./PaxHeaders.26529/libinfinity-0.7.10000644000000000000000000000013213055210765013667 xustar0030 mtime=1488261621.184067593 30 atime=1488261588.724139668 30 ctime=1488261621.184067593 libinfinity-0.7.1/0000755000175000017500000000000013055210765014341 5ustar00arminarmin00000000000000libinfinity-0.7.1/PaxHeaders.26529/depcomp0000644000000000000000000000013013036062711015152 xustar0029 mtime=1484285385.23189705 29 atime=1484285385.23189705 30 ctime=1488261588.780139546 libinfinity-0.7.1/depcomp0000755000175000017500000005601613036062711015721 0ustar00arminarmin00000000000000#! /bin/sh # depcomp - compile a program generating dependencies as side-effects scriptversion=2013-05-30.07; # UTC # Copyright (C) 1999-2014 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # Originally written by Alexandre Oliva . case $1 in '') echo "$0: No command. Try '$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: depcomp [--help] [--version] PROGRAM [ARGS] Run PROGRAMS ARGS to compile a file, generating dependencies as side-effects. Environment variables: depmode Dependency tracking mode. source Source file read by 'PROGRAMS ARGS'. object Object file output by 'PROGRAMS ARGS'. DEPDIR directory where to store dependencies. depfile Dependency file to output. tmpdepfile Temporary file to use when outputting dependencies. libtool Whether libtool is used (yes/no). Report bugs to . EOF exit $? ;; -v | --v*) echo "depcomp $scriptversion" exit $? ;; esac # Get the directory component of the given path, and save it in the # global variables '$dir'. Note that this directory component will # be either empty or ending with a '/' character. This is deliberate. set_dir_from () { case $1 in */*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;; *) dir=;; esac } # Get the suffix-stripped basename of the given path, and save it the # global variable '$base'. set_base_from () { base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'` } # If no dependency file was actually created by the compiler invocation, # we still have to create a dummy depfile, to avoid errors with the # Makefile "include basename.Plo" scheme. make_dummy_depfile () { echo "#dummy" > "$depfile" } # Factor out some common post-processing of the generated depfile. # Requires the auxiliary global variable '$tmpdepfile' to be set. aix_post_process_depfile () { # If the compiler actually managed to produce a dependency file, # post-process it. if test -f "$tmpdepfile"; then # Each line is of the form 'foo.o: dependency.h'. # Do two passes, one to just change these to # $object: dependency.h # and one to simply output # dependency.h: # which is needed to avoid the deleted-header problem. { sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile" sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile" } > "$depfile" rm -f "$tmpdepfile" else make_dummy_depfile fi } # A tabulation character. tab=' ' # A newline character. nl=' ' # Character ranges might be problematic outside the C locale. # These definitions help. upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ lower=abcdefghijklmnopqrstuvwxyz digits=0123456789 alpha=${upper}${lower} if test -z "$depmode" || test -z "$source" || test -z "$object"; then echo "depcomp: Variables source, object and depmode must be set" 1>&2 exit 1 fi # Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. depfile=${depfile-`echo "$object" | sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} rm -f "$tmpdepfile" # Avoid interferences from the environment. gccflag= dashmflag= # Some modes work just like other modes, but use different flags. We # parameterize here, but still list the modes in the big case below, # to make depend.m4 easier to write. Note that we *cannot* use a case # here, because this file can only contain one case statement. if test "$depmode" = hp; then # HP compiler uses -M and no extra arg. gccflag=-M depmode=gcc fi if test "$depmode" = dashXmstdout; then # This is just like dashmstdout with a different argument. dashmflag=-xM depmode=dashmstdout fi cygpath_u="cygpath -u -f -" if test "$depmode" = msvcmsys; then # This is just like msvisualcpp but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvisualcpp fi if test "$depmode" = msvc7msys; then # This is just like msvc7 but w/o cygpath translation. # Just convert the backslash-escaped backslashes to single forward # slashes to satisfy depend.m4 cygpath_u='sed s,\\\\,/,g' depmode=msvc7 fi if test "$depmode" = xlc; then # IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information. gccflag=-qmakedep=gcc,-MF depmode=gcc fi case "$depmode" in gcc3) ## gcc 3 implements dependency tracking that does exactly what ## we want. Yay! Note: for some reason libtool 1.4 doesn't like ## it if -MD -MP comes after the -MF stuff. Hmm. ## Unfortunately, FreeBSD c89 acceptance of flags depends upon ## the command line argument order; so add the flags where they ## appear in depend2.am. Note that the slowdown incurred here ## affects only configure: in makefiles, %FASTDEP% shortcuts this. for arg do case $arg in -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; *) set fnord "$@" "$arg" ;; esac shift # fnord shift # $arg done "$@" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi mv "$tmpdepfile" "$depfile" ;; gcc) ## Note that this doesn't just cater to obsosete pre-3.x GCC compilers. ## but also to in-use compilers like IMB xlc/xlC and the HP C compiler. ## (see the conditional assignment to $gccflag above). ## There are various ways to get dependency output from gcc. Here's ## why we pick this rather obscure method: ## - Don't want to use -MD because we'd like the dependencies to end ## up in a subdir. Having to rename by hand is ugly. ## (We might end up doing this anyway to support other compilers.) ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like ## -MM, not -M (despite what the docs say). Also, it might not be ## supported by the other compilers which use the 'gcc' depmode. ## - Using -M directly means running the compiler twice (even worse ## than renaming). if test -z "$gccflag"; then gccflag=-MD, fi "$@" -Wp,"$gccflag$tmpdepfile" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # The second -e expression handles DOS-style file names with drive # letters. sed -e 's/^[^:]*: / /' \ -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" ## This next piece of magic avoids the "deleted header file" problem. ## The problem is that when a header file which appears in a .P file ## is deleted, the dependency causes make to die (because there is ## typically no way to rebuild the header). We avoid this by adding ## dummy dependencies for each header file. Too bad gcc doesn't do ## this for us directly. ## Some versions of gcc put a space before the ':'. On the theory ## that the space means something, we add a space to the output as ## well. hp depmode also adds that space, but also prefixes the VPATH ## to the object. Take care to not repeat it in the output. ## Some versions of the HPUX 10.20 sed can't process this invocation ## correctly. Breaking it into two sed invocations is a workaround. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; sgi) if test "$libtool" = yes; then "$@" "-Wp,-MDupdate,$tmpdepfile" else "$@" -MDupdate "$tmpdepfile" fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files echo "$object : \\" > "$depfile" # Clip off the initial element (the dependent). Don't try to be # clever and replace this with sed code, as IRIX sed won't handle # lines with more than a fixed number of characters (4096 in # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; # the IRIX cc adds comments like '#:fec' to the end of the # dependency line. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \ | tr "$nl" ' ' >> "$depfile" echo >> "$depfile" # The second pass generates a dummy entry for each header file. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ >> "$depfile" else make_dummy_depfile fi rm -f "$tmpdepfile" ;; xlc) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; aix) # The C for AIX Compiler uses -M and outputs the dependencies # in a .u file. In older versions, this file always lives in the # current directory. Also, the AIX compiler puts '$object:' at the # start of each line; $object doesn't have directory information. # Version 6 uses the directory in both cases. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then tmpdepfile1=$dir$base.u tmpdepfile2=$base.u tmpdepfile3=$dir.libs/$base.u "$@" -Wc,-M else tmpdepfile1=$dir$base.u tmpdepfile2=$dir$base.u tmpdepfile3=$dir$base.u "$@" -M fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done aix_post_process_depfile ;; tcc) # tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26 # FIXME: That version still under development at the moment of writing. # Make that this statement remains true also for stable, released # versions. # It will wrap lines (doesn't matter whether long or short) with a # trailing '\', as in: # # foo.o : \ # foo.c \ # foo.h \ # # It will put a trailing '\' even on the last line, and will use leading # spaces rather than leading tabs (at least since its commit 0394caf7 # "Emit spaces for -MD"). "$@" -MD -MF "$tmpdepfile" stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each non-empty line is of the form 'foo.o : \' or ' dep.h \'. # We have to change lines of the first kind to '$object: \'. sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile" # And for each line of the second kind, we have to emit a 'dep.h:' # dummy dependency, to avoid the deleted-header problem. sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile" rm -f "$tmpdepfile" ;; ## The order of this option in the case statement is important, since the ## shell code in configure will try each of these formats in the order ## listed in this file. A plain '-MD' option would be understood by many ## compilers, so we must ensure this comes after the gcc and icc options. pgcc) # Portland's C compiler understands '-MD'. # Will always output deps to 'file.d' where file is the root name of the # source file under compilation, even if file resides in a subdirectory. # The object file name does not affect the name of the '.d' file. # pgcc 10.2 will output # foo.o: sub/foo.c sub/foo.h # and will wrap long lines using '\' : # foo.o: sub/foo.c ... \ # sub/foo.h ... \ # ... set_dir_from "$object" # Use the source, not the object, to determine the base name, since # that's sadly what pgcc will do too. set_base_from "$source" tmpdepfile=$base.d # For projects that build the same source file twice into different object # files, the pgcc approach of using the *source* file root name can cause # problems in parallel builds. Use a locking strategy to avoid stomping on # the same $tmpdepfile. lockdir=$base.d-lock trap " echo '$0: caught signal, cleaning up...' >&2 rmdir '$lockdir' exit 1 " 1 2 13 15 numtries=100 i=$numtries while test $i -gt 0; do # mkdir is a portable test-and-set. if mkdir "$lockdir" 2>/dev/null; then # This process acquired the lock. "$@" -MD stat=$? # Release the lock. rmdir "$lockdir" break else # If the lock is being held by a different process, wait # until the winning process is done or we timeout. while test -d "$lockdir" && test $i -gt 0; do sleep 1 i=`expr $i - 1` done fi i=`expr $i - 1` done trap - 1 2 13 15 if test $i -le 0; then echo "$0: failed to acquire lock after $numtries attempts" >&2 echo "$0: check lockdir '$lockdir'" >&2 exit 1 fi if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" # Each line is of the form `foo.o: dependent.h', # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. # Do two passes, one to just change these to # `$object: dependent.h' and one to simply `dependent.h:'. sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this invocation # correctly. Breaking it into two sed invocations is a workaround. sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; hp2) # The "hp" stanza above does not work with aCC (C++) and HP's ia64 # compilers, which have integrated preprocessors. The correct option # to use with these is +Maked; it writes dependencies to a file named # 'foo.d', which lands next to the object file, wherever that # happens to be. # Much of this is similar to the tru64 case; see comments there. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then tmpdepfile1=$dir$base.d tmpdepfile2=$dir.libs/$base.d "$@" -Wc,+Maked else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d "$@" +Maked fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" do test -f "$tmpdepfile" && break done if test -f "$tmpdepfile"; then sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile" # Add 'dependent.h:' lines. sed -ne '2,${ s/^ *// s/ \\*$// s/$/:/ p }' "$tmpdepfile" >> "$depfile" else make_dummy_depfile fi rm -f "$tmpdepfile" "$tmpdepfile2" ;; tru64) # The Tru64 compiler uses -MD to generate dependencies as a side # effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'. # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put # dependencies in 'foo.d' instead, so we check for that too. # Subdirectories are respected. set_dir_from "$object" set_base_from "$object" if test "$libtool" = yes; then # Libtool generates 2 separate objects for the 2 libraries. These # two compilations output dependencies in $dir.libs/$base.o.d and # in $dir$base.o.d. We have to check for both files, because # one of the two compilations can be disabled. We should prefer # $dir$base.o.d over $dir.libs/$base.o.d because the latter is # automatically cleaned when .libs/ is deleted, while ignoring # the former would cause a distcleancheck panic. tmpdepfile1=$dir$base.o.d # libtool 1.5 tmpdepfile2=$dir.libs/$base.o.d # Likewise. tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504 "$@" -Wc,-MD else tmpdepfile1=$dir$base.d tmpdepfile2=$dir$base.d tmpdepfile3=$dir$base.d "$@" -MD fi stat=$? if test $stat -ne 0; then rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" exit $stat fi for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" do test -f "$tmpdepfile" && break done # Same post-processing that is required for AIX mode. aix_post_process_depfile ;; msvc7) if test "$libtool" = yes; then showIncludes=-Wc,-showIncludes else showIncludes=-showIncludes fi "$@" $showIncludes > "$tmpdepfile" stat=$? grep -v '^Note: including file: ' "$tmpdepfile" if test $stat -ne 0; then rm -f "$tmpdepfile" exit $stat fi rm -f "$depfile" echo "$object : \\" > "$depfile" # The first sed program below extracts the file names and escapes # backslashes for cygpath. The second sed program outputs the file # name when reading, but also accumulates all include files in the # hold buffer in order to output them again at the end. This only # works with sed implementations that can handle large buffers. sed < "$tmpdepfile" -n ' /^Note: including file: *\(.*\)/ { s//\1/ s/\\/\\\\/g p }' | $cygpath_u | sort -u | sed -n ' s/ /\\ /g s/\(.*\)/'"$tab"'\1 \\/p s/.\(.*\) \\/\1:/ H $ { s/.*/'"$tab"'/ G p }' >> "$depfile" echo >> "$depfile" # make sure the fragment doesn't end with a backslash rm -f "$tmpdepfile" ;; msvc7msys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; #nosideeffect) # This comment above is used by automake to tell side-effect # dependency tracking mechanisms from slower ones. dashmstdout) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout, regardless of -o. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove '-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done test -z "$dashmflag" && dashmflag=-M # Require at least two characters before searching for ':' # in the target name. This is to cope with DOS-style filenames: # a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise. "$@" $dashmflag | sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile" rm -f "$depfile" cat < "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process this sed invocation # correctly. Breaking it into two sed invocations is a workaround. tr ' ' "$nl" < "$tmpdepfile" \ | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; dashXmstdout) # This case only exists to satisfy depend.m4. It is never actually # run, as this mode is specially recognized in the preamble. exit 1 ;; makedepend) "$@" || exit $? # Remove any Libtool call if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # X makedepend shift cleared=no eat=no for arg do case $cleared in no) set ""; shift cleared=yes ;; esac if test $eat = yes; then eat=no continue fi case "$arg" in -D*|-I*) set fnord "$@" "$arg"; shift ;; # Strip any option that makedepend may not understand. Remove # the object too, otherwise makedepend will parse it as a source file. -arch) eat=yes ;; -*|$object) ;; *) set fnord "$@" "$arg"; shift ;; esac done obj_suffix=`echo "$object" | sed 's/^.*\././'` touch "$tmpdepfile" ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" rm -f "$depfile" # makedepend may prepend the VPATH from the source file name to the object. # No need to regex-escape $object, excess matching of '.' is harmless. sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile" # Some versions of the HPUX 10.20 sed can't process the last invocation # correctly. Breaking it into two sed invocations is a workaround. sed '1,2d' "$tmpdepfile" \ | tr ' ' "$nl" \ | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \ | sed -e 's/$/ :/' >> "$depfile" rm -f "$tmpdepfile" "$tmpdepfile".bak ;; cpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi # Remove '-o $object'. IFS=" " for arg do case $arg in -o) shift ;; $object) shift ;; *) set fnord "$@" "$arg" shift # fnord shift # $arg ;; esac done "$@" -E \ | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ | sed '$ s: \\$::' > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" cat < "$tmpdepfile" >> "$depfile" sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" rm -f "$tmpdepfile" ;; msvisualcpp) # Important note: in order to support this mode, a compiler *must* # always write the preprocessed file to stdout. "$@" || exit $? # Remove the call to Libtool. if test "$libtool" = yes; then while test "X$1" != 'X--mode=compile'; do shift done shift fi IFS=" " for arg do case "$arg" in -o) shift ;; $object) shift ;; "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") set fnord "$@" shift shift ;; *) set fnord "$@" "$arg" shift shift ;; esac done "$@" -E 2>/dev/null | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile" rm -f "$depfile" echo "$object : \\" > "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile" echo "$tab" >> "$depfile" sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile" rm -f "$tmpdepfile" ;; msvcmsys) # This case exists only to let depend.m4 do its work. It works by # looking at the text of this script. This case will never be run, # since it is checked for above. exit 1 ;; none) exec "$@" ;; *) echo "Unknown depmode $depmode" 1>&2 exit 1 ;; esac exit 0 # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: libinfinity-0.7.1/PaxHeaders.26529/libinftextgtk.pc.in0000644000000000000000000000013113034342512017406 xustar0030 mtime=1483851082.049718536 30 atime=1483851082.049718536 29 ctime=1488261588.76013959 libinfinity-0.7.1/libinftextgtk.pc.in0000644000175000017500000000062613034342512020145 0ustar00arminarmin00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: libinftextgtk Description: Infinote text processing GTK+ UI functionality Requires: libinfinity-@LIBINFINITY_API_VERSION@ libinftext-@LIBINFINITY_API_VERSION@ @gtk_requirement@ Version: @VERSION@ Libs: -L${libdir} -linftextgtk-@LIBINFINITY_API_VERSION@ Cflags: -I${includedir}/libinftextgtk-@LIBINFINITY_API_VERSION@ libinfinity-0.7.1/PaxHeaders.26529/configure.ac0000644000000000000000000000013213051240623016065 xustar0030 mtime=1487225235.440756142 30 atime=1487225235.436756128 30 ctime=1488261588.752139607 libinfinity-0.7.1/configure.ac0000644000175000017500000002606513051240623016630 0ustar00arminarmin00000000000000m4_define([libinfinity_version], [0.7.1]) m4_define([libinfinity_api_version], [0.7]) m4_define([libinfinity_libtool_version], [0:0:0]) AC_PREREQ(2.60) AC_INIT([libinfinity], [libinfinity_version], [armin@arbur.net]) AM_INIT_AUTOMAKE([-Wall -Wno-portability dist-bzip2 check-news foreign tar-pax subdir-objects]) m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES]) AM_MAINTAINER_MODE AC_CONFIG_SRCDIR([libinfinity/common/inf-init.c]) AC_CONFIG_HEADER([config.h libinfinity/inf-config.h]) LIBINFINITY_VERSION=libinfinity_version LIBINFINITY_API_VERSION=libinfinity_api_version LIBINFINITY_LIBTOOL_VERSION=libinfinity_libtool_version AC_SUBST(LIBINFINITY_VERSION) AC_SUBST(LIBINFINITY_API_VERSION) AC_SUBST(LIBINFINITY_LIBTOOL_VERSION) AC_CANONICAL_HOST AM_SILENT_RULES([yes]) # Remove -Wno-strict-prototypes for the feature tests has_strict_prototypes="" if (echo $CFLAGS | grep -- -Wstrict-prototype) then has_strict_prototypes="true" old_CFLAGS=$CFLAGS CFLAGS="$CFLAGS -Wno-strict-prototypes" fi # Make GNU and POSIX extensions such as readdir_r, O_NOFOLLOW and # fdopendir available AC_USE_SYSTEM_EXTENSIONS AC_LANG(C) AC_PROG_CC AC_PROG_CPP AC_PROG_INSTALL AC_PROG_LN_S AC_PROG_MAKE_SET AM_PROG_AR AC_PROG_LIBTOOL # Seems to be required for building a binary from multiple source files # automake complains without it in infinoted/. AM_PROG_CC_C_O ################################### # Gtk-Doc ################################### AC_CONFIG_MACRO_DIR(m4) GTK_DOC_CHECK(1.4) ################################### # Platform checks ################################### case "$host_os" in *mingw*) platform='win32' ;; *) platform='unix' ;; esac AM_CONDITIONAL([WIN32], test "$platform" = "win32") # Check for MSG_NOSIGNAL AC_MSG_CHECKING(for MSG_NOSIGNAL) AC_TRY_COMPILE([#include ], [ int f = MSG_NOSIGNAL; ], [ AC_MSG_RESULT(yes) AC_DEFINE(HAVE_MSG_NOSIGNAL, 1, [Define this symbol if you have MSG_NOSIGNAL]) ], [ AC_MSG_RESULT(no)] ) # Check for SO_REUSEADDR AC_MSG_CHECKING(for SO_REUSEADDR) AC_TRY_COMPILE([#include #include ], [ int f = SO_REUSEADDR; printf("%d\n", f); ], [ AC_MSG_RESULT(yes) AC_DEFINE(HAVE_SO_REUSEADDR, 1, [Define this symbol if you have SO_REUSEADDR]) ], [ AC_MSG_RESULT(no)] ) # Check for dirent.d_type AC_MSG_CHECKING(for d_type) AC_TRY_COMPILE([#include #include ], [ struct dirent d; printf("%d\n", d.d_type); ], [ AC_MSG_RESULT(yes) AC_DEFINE(HAVE_D_TYPE, 1, [Define this symbol if your struct dirent has the d_type field])], [ AC_MSG_RESULT(no)] ) # Check for O_NOFOLLOW AC_MSG_CHECKING(for O_NOFOLLOW) AC_TRY_COMPILE([#include #include #include ], [ printf("%d\n", O_NOFOLLOW); ], [ AC_MSG_RESULT(yes) AC_DEFINE(HAVE_O_NOFOLLOW, 1, [Define this symbol if the O_NOFOLLOW flag is supported on your system])], [ AC_MSG_RESULT(no)] ) ################################### # Check for regular dependencies ################################### infinity_libraries='glib-2.0 >= 2.38 gobject-2.0 >= 2.38 gmodule-2.0 >= 2.38 libxml-2.0 gnutls >= 2.12.0 libgsasl >= 0.2.21' PKG_CHECK_MODULES([infinity], [$infinity_libraries]) PKG_CHECK_MODULES([inftext], [glib-2.0 >= 2.38 gobject-2.0 >= 2.38 libxml-2.0]) if test $platform = 'win32'; then infinity_LIBS="$infinity_LIBS -lws2_32 -ldnsapi" else # Check whether we need libresolv for res_query() # Can't use AC_SEARCH_LIBS because res_query is a macro defined in # resolv.h AC_MSG_CHECKING(for res_query) AC_TRY_LINK( [ #include #include #include #include ], [res_query(NULL, 0, 0, NULL, 0);], [ # res_init() available in libc AC_MSG_RESULT(yes) ], [ LIBS="-lresolv" AC_TRY_LINK( [ #include #include #include #include ], [res_query(NULL, 0, 0, NULL, 0);], [ AC_MSG_RESULT(in libresolv) LIBS="" infinity_LIBS="$infinity_LIBS -lresolv" # res_init available in libresolv ], [AC_MSG_ERROR(res_query not provided by either libc or libresolv)] ) ] ) fi ################################### # libinftextgtk optional package ################################### AC_ARG_WITH([inftextgtk], AS_HELP_STRING([--with-inftextgtk], [Builds the libinftextgtk library [[default=auto]]]), [with_inftextgtk=$withval], [with_inftextgtk=auto]) gtk_requirement="gtk+-3.0 >= 3.10.0" if test "x$with_inftextgtk" = "xauto" then PKG_CHECK_MODULES([inftextgtk], [$gtk_requirement], [with_inftextgtk=yes], [with_inftextgtk=no]) elif test "x$with_inftextgtk" = "xyes" then PKG_CHECK_MODULES([inftextgtk], [$gtk_requirement]) fi if test "x$with_inftextgtk" = "xyes" then AC_CHECK_LIB([m], [atan2], [inftextgtk_LIBS="$inftextgtk_LIBS -lm"], AC_MSG_ERROR(libm not found)) fi AM_CONDITIONAL([WITH_INFTEXTGTK], test "x$with_inftextgtk" = "xyes") AC_SUBST(gtk_requirement) ############################### # libinfgtk optional package ############################### AC_ARG_WITH([infgtk], AS_HELP_STRING([--with-infgtk], [Builds the libinfgtk library [[default=auto]]]), [with_infgtk=$withval], [with_infgtk=auto]) if test "x$with_infgtk" = "xauto" then PKG_CHECK_MODULES([infgtk], [$gtk_requirement], [with_infgtk=yes], [with_infgtk=no]) elif test "x$with_infgtk" = "xyes" then PKG_CHECK_MODULES([infgtk], [$gtk_requirement]) fi AM_CONDITIONAL([WITH_INFGTK], test "x$with_infgtk" = "xyes") ############################### # infinoted optional package ############################### AC_ARG_WITH([infinoted], AS_HELP_STRING([--with-infinoted], [Build the infinote standalone server [[default=yes]]]), [with_infinoted=$withval], [with_infinoted=yes]) if test "x$with_infinoted" = "xyes" then PKG_CHECK_MODULES([infinoted], [glib-2.0 >= 2.38 gobject-2.0 >= 2.38 gmodule-2.0 >= 2.38 gnutls >= 2.12.0]) fi AM_CONDITIONAL([WITH_INFINOTED], test "x$with_infinoted" = "xyes") #################### # Check for avahi #################### AC_ARG_WITH([avahi], AS_HELP_STRING([--with-avahi], [Enables avahi support [[default=auto]]]), [use_avahi=$withval], [use_avahi=auto]) if test "x$use_avahi" = "xauto" then PKG_CHECK_MODULES([avahi], [avahi-client], [use_avahi=yes], [use_avahi=no]) elif test "x$use_avahi" = "xyes" then PKG_CHECK_MODULES([avahi], [avahi-client]) fi if test "x$use_avahi" = "xyes" then AC_DEFINE([LIBINFINITY_HAVE_AVAHI], 1, [Whether avahi support is enabled]) fi AM_CONDITIONAL([LIBINFINITY_HAVE_AVAHI], test "x$use_avahi" = "xyes") #################### # Check for gio #################### AC_ARG_WITH([gio], AS_HELP_STRING([--with-gio], [Enables avahi support [[default=auto]]]), [use_gio=$withval], [use_gio=auto]) if test "x$use_gio" = "xauto" then PKG_CHECK_MODULES([gio], [gio-2.0 >= 2.40], [use_gio=yes], [use_gio=no]) elif test "x$use_avahi" = "xyes" then PKG_CHECK_MODULES([gio], [gio-2.0 >= 2.40]) fi if test "x$use_gio" = "xyes" then AC_DEFINE([LIBINFINITY_HAVE_GIO], 1, [Whether gio support is enabled]) fi AM_CONDITIONAL([LIBINFINITY_HAVE_GIO], test "x$use_gio" = "xyes") #################### # Check for libdaemon #################### AC_ARG_WITH([libdaemon], AS_HELP_STRING([--with-libdaemon], [Enables daemonizing support in infinoted [[default=auto]]]), [use_libdaemon=$withval], [use_libdaemon=auto]) if test "x$use_libdaemon" = "xauto" then PKG_CHECK_MODULES([libdaemon], [libdaemon], [use_libdaemon=yes], [use_libdaemon=no]) elif test "x$use_libdaemon" = "xyes" then PKG_CHECK_MODULES([libdaemon], [libdaemon]) fi if test "x$use_libdaemon" = "xyes" then AC_DEFINE([LIBINFINITY_HAVE_LIBDAEMON], 1, [Whether libdaemon support is enabled]) fi AM_CONDITIONAL([LIBINFINITY_HAVE_LIBDAEMON], test "x$use_libdaemon" = "xyes") ################# # Check for pam # ################# AC_MSG_CHECKING(for pam) AC_CHECK_LIB([ pam ], [ pam_start ], [ AC_MSG_RESULT(yes) AC_DEFINE(LIBINFINITY_HAVE_PAM, 1, [Define this symbol if you have pam]) use_pam=yes infinity_LIBS="$infinity_LIBS -lpam" ], [ AC_MSG_RESULT(no) use_pam=no ] ) # Check for PAM_FAIL_DELAY AC_MSG_CHECKING(for PAM_FAIL_DELAY) AC_TRY_COMPILE([#include #include ], [ int f = PAM_FAIL_DELAY; printf("%d\n", f); ], [ AC_MSG_RESULT(yes) AC_DEFINE(HAVE_PAM_FAIL_DELAY, 1, [Define this symbol if your pam has PAM_FAIL_DELAY])], [ AC_MSG_RESULT(no)] ) ############ # gettext ############ GETTEXT_PACKAGE="libinfinity-libinfinity_api_version" AC_SUBST(GETTEXT_PACKAGE) AC_DEFINE_UNQUOTED([GETTEXT_PACKAGE], ["$GETTEXT_PACKAGE"], [The domain name to use with gettext.]) ALL_LINGUAS="`grep -v '^#' "$srcdir/po/LINGUAS" | tr '\n' ' '`" AM_GLIB_GNU_GETTEXT AM_GLIB_DEFINE_LOCALEDIR(INF_LOCALEDIR) ########### # GObject Introspection ########### GOBJECT_INTROSPECTION_CHECK([1.0]) ########### # Output ########### if test -n $has_strict_prototypes then CFLAGS=$old_CFLAGS fi AC_CONFIG_FILES([ Makefile libinfinity/Makefile libinftext/Makefile libinfgtk/Makefile libinftextgtk/Makefile infinoted/Makefile infinoted/plugins/Makefile pixmaps/Makefile pixmaps/16x16/Makefile pixmaps/22x22/Makefile pixmaps/scalable/Makefile test/Makefile test/util/Makefile test/session/Makefile test/cleanup/Makefile test/certs/Makefile docs/Makefile docs/reference/Makefile docs/reference/version.xml.in docs/reference/api_version.xml.in docs/reference/libinfinity/Makefile docs/reference/libinftext/Makefile docs/reference/libinfgtk/Makefile docs/reference/libinftextgtk/Makefile docs/reference/libinfinoted-plugin-manager/Makefile po/Makefile.in ]) # These are separate for the macros to be expanded # (note no square brackets) AC_CONFIG_FILES( libinfinity-libinfinity_api_version.pc:libinfinity.pc.in libinftext-libinfinity_api_version.pc:libinftext.pc.in libinfgtk-libinfinity_api_version.pc:libinfgtk.pc.in libinftextgtk-libinfinity_api_version.pc:libinftextgtk.pc.in libinfinoted-plugin-manager-libinfinity_api_version.pc:libinfinoted-plugin-manager.pc.in ) AC_OUTPUT echo " Build optional packages: libinfgtk: $with_infgtk libinftextgtk: $with_inftextgtk infinoted: $with_infinoted Enable support for: avahi: $use_avahi libdaemon: $use_libdaemon pam: $use_pam " # vim:set et: libinfinity-0.7.1/PaxHeaders.26529/AUTHORS0000644000000000000000000000013213034342512014650 xustar0030 mtime=1483851082.013718339 30 atime=1483851082.013718339 30 ctime=1488261588.764139581 libinfinity-0.7.1/AUTHORS0000644000175000017500000000114613034342512015404 0ustar00arminarmin00000000000000infinote ======== This program and associated libraries are licensed under the GNU Lesser General Public License (LGPL) version 2.1 or any later version. A copy of the license is included in the distribution. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. Copyright (C) 2007-2015 Armin Burgmeier Authors: * Armin Burgmeier Artists: * Benjamin Herr libinfinity-0.7.1/PaxHeaders.26529/install-sh0000644000000000000000000000013213036062707015610 xustar0030 mtime=1484285383.715895807 30 atime=1484285383.715895807 30 ctime=1488261588.780139546 libinfinity-0.7.1/install-sh0000755000175000017500000003546313036062707016360 0ustar00arminarmin00000000000000#!/bin/sh # install - install a program, script, or datafile scriptversion=2014-09-12.12; # UTC # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the # following copyright and license. # # Copyright (C) 1994 X Consortium # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to # deal in the Software without restriction, including without limitation the # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or # sell copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name of the X Consortium shall not # be used in advertising or otherwise to promote the sale, use or other deal- # ings in this Software without prior written authorization from the X Consor- # tium. # # # FSF changes to this file are in the public domain. # # Calling this script install-sh is preferred over install.sh, to prevent # 'make' implicit rules from creating a file called install from it # when there is no Makefile. # # This script is compatible with the BSD install script, but was written # from scratch. tab=' ' nl=' ' IFS=" $tab$nl" # Set DOITPROG to "echo" to test this script. doit=${DOITPROG-} doit_exec=${doit:-exec} # Put in absolute file names if you don't have them in your path; # or use environment vars. chgrpprog=${CHGRPPROG-chgrp} chmodprog=${CHMODPROG-chmod} chownprog=${CHOWNPROG-chown} cmpprog=${CMPPROG-cmp} cpprog=${CPPROG-cp} mkdirprog=${MKDIRPROG-mkdir} mvprog=${MVPROG-mv} rmprog=${RMPROG-rm} stripprog=${STRIPPROG-strip} posix_mkdir= # Desired mode of installed file. mode=0755 chgrpcmd= chmodcmd=$chmodprog chowncmd= mvcmd=$mvprog rmcmd="$rmprog -f" stripcmd= src= dst= dir_arg= dst_arg= copy_on_change=false is_target_a_directory=possibly usage="\ Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE or: $0 [OPTION]... SRCFILES... DIRECTORY or: $0 [OPTION]... -t DIRECTORY SRCFILES... or: $0 [OPTION]... -d DIRECTORIES... In the 1st form, copy SRCFILE to DSTFILE. In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. In the 4th, create DIRECTORIES. Options: --help display this help and exit. --version display version info and exit. -c (ignored) -C install only if different (preserve the last data modification time) -d create directories instead of installing files. -g GROUP $chgrpprog installed files to GROUP. -m MODE $chmodprog installed files to MODE. -o USER $chownprog installed files to USER. -s $stripprog installed files. -t DIRECTORY install into DIRECTORY. -T report an error if DSTFILE is a directory. Environment variables override the default commands: CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG " while test $# -ne 0; do case $1 in -c) ;; -C) copy_on_change=true;; -d) dir_arg=true;; -g) chgrpcmd="$chgrpprog $2" shift;; --help) echo "$usage"; exit $?;; -m) mode=$2 case $mode in *' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*) echo "$0: invalid mode: $mode" >&2 exit 1;; esac shift;; -o) chowncmd="$chownprog $2" shift;; -s) stripcmd=$stripprog;; -t) is_target_a_directory=always dst_arg=$2 # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac shift;; -T) is_target_a_directory=never;; --version) echo "$0 $scriptversion"; exit $?;; --) shift break;; -*) echo "$0: invalid option: $1" >&2 exit 1;; *) break;; esac shift done # We allow the use of options -d and -T together, by making -d # take the precedence; this is for compatibility with GNU install. if test -n "$dir_arg"; then if test -n "$dst_arg"; then echo "$0: target directory not allowed when installing a directory." >&2 exit 1 fi fi if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then # When -d is used, all remaining arguments are directories to create. # When -t is used, the destination is already specified. # Otherwise, the last argument is the destination. Remove it from $@. for arg do if test -n "$dst_arg"; then # $@ is not empty: it contains at least $arg. set fnord "$@" "$dst_arg" shift # fnord fi shift # arg dst_arg=$arg # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac done fi if test $# -eq 0; then if test -z "$dir_arg"; then echo "$0: no input file specified." >&2 exit 1 fi # It's OK to call 'install-sh -d' without argument. # This can happen when creating conditional directories. exit 0 fi if test -z "$dir_arg"; then if test $# -gt 1 || test "$is_target_a_directory" = always; then if test ! -d "$dst_arg"; then echo "$0: $dst_arg: Is not a directory." >&2 exit 1 fi fi fi if test -z "$dir_arg"; then do_exit='(exit $ret); exit $ret' trap "ret=129; $do_exit" 1 trap "ret=130; $do_exit" 2 trap "ret=141; $do_exit" 13 trap "ret=143; $do_exit" 15 # Set umask so as not to create temps with too-generous modes. # However, 'strip' requires both read and write access to temps. case $mode in # Optimize common cases. *644) cp_umask=133;; *755) cp_umask=22;; *[0-7]) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw='% 200' fi cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; *) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw=,u+rw fi cp_umask=$mode$u_plus_rw;; esac fi for src do # Protect names problematic for 'test' and other utilities. case $src in -* | [=\(\)!]) src=./$src;; esac if test -n "$dir_arg"; then dst=$src dstdir=$dst test -d "$dstdir" dstdir_status=$? else # Waiting for this to be detected by the "$cpprog $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if test ! -f "$src" && test ! -d "$src"; then echo "$0: $src does not exist." >&2 exit 1 fi if test -z "$dst_arg"; then echo "$0: no destination specified." >&2 exit 1 fi dst=$dst_arg # If destination is a directory, append the input filename; won't work # if double slashes aren't ignored. if test -d "$dst"; then if test "$is_target_a_directory" = never; then echo "$0: $dst_arg: Is a directory" >&2 exit 1 fi dstdir=$dst dst=$dstdir/`basename "$src"` dstdir_status=0 else dstdir=`dirname "$dst"` test -d "$dstdir" dstdir_status=$? fi fi obsolete_mkdir_used=false if test $dstdir_status != 0; then case $posix_mkdir in '') # Create intermediate dirs using mode 755 as modified by the umask. # This is like FreeBSD 'install' as of 1997-10-28. umask=`umask` case $stripcmd.$umask in # Optimize common cases. *[2367][2367]) mkdir_umask=$umask;; .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; *[0-7]) mkdir_umask=`expr $umask + 22 \ - $umask % 100 % 40 + $umask % 20 \ - $umask % 10 % 4 + $umask % 2 `;; *) mkdir_umask=$umask,go-w;; esac # With -d, create the new directory with the user-specified mode. # Otherwise, rely on $mkdir_umask. if test -n "$dir_arg"; then mkdir_mode=-m$mode else mkdir_mode= fi posix_mkdir=false case $umask in *[123567][0-7][0-7]) # POSIX mkdir -p sets u+wx bits regardless of umask, which # is incompatible with FreeBSD 'install' when (umask & 300) != 0. ;; *) # $RANDOM is not portable (e.g. dash); use it when possible to # lower collision chance tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0 # As "mkdir -p" follows symlinks and we work in /tmp possibly; so # create the $tmpdir first (and fail if unsuccessful) to make sure # that nobody tries to guess the $tmpdir name. if (umask $mkdir_umask && $mkdirprog $mkdir_mode "$tmpdir" && exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1 then if test -z "$dir_arg" || { # Check for POSIX incompatibilities with -m. # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or # other-writable bit of parent directory when it shouldn't. # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. test_tmpdir="$tmpdir/a" ls_ld_tmpdir=`ls -ld "$test_tmpdir"` case $ls_ld_tmpdir in d????-?r-*) different_mode=700;; d????-?--*) different_mode=755;; *) false;; esac && $mkdirprog -m$different_mode -p -- "$test_tmpdir" && { ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"` test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" } } then posix_mkdir=: fi rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" else # Remove any dirs left behind by ancient mkdir implementations. rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null fi trap '' 0;; esac;; esac if $posix_mkdir && ( umask $mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" ) then : else # The umask is ridiculous, or mkdir does not conform to POSIX, # or it failed possibly due to a race condition. Create the # directory the slow way, step by step, checking for races as we go. case $dstdir in /*) prefix='/';; [-=\(\)!]*) prefix='./';; *) prefix='';; esac oIFS=$IFS IFS=/ set -f set fnord $dstdir shift set +f IFS=$oIFS prefixes= for d do test X"$d" = X && continue prefix=$prefix$d if test -d "$prefix"; then prefixes= else if $posix_mkdir; then (umask=$mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break # Don't fail if two instances are running concurrently. test -d "$prefix" || exit 1 else case $prefix in *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; *) qprefix=$prefix;; esac prefixes="$prefixes '$qprefix'" fi fi prefix=$prefix/ done if test -n "$prefixes"; then # Don't fail if two instances are running concurrently. (umask $mkdir_umask && eval "\$doit_exec \$mkdirprog $prefixes") || test -d "$dstdir" || exit 1 obsolete_mkdir_used=true fi fi fi if test -n "$dir_arg"; then { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 else # Make a couple of temp file names in the proper directory. dsttmp=$dstdir/_inst.$$_ rmtmp=$dstdir/_rm.$$_ # Trap to clean up those temp files at exit. trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 # Copy the file name to the temp name. (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && # and set any options; do chmod last to preserve setuid bits. # # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $cpprog $src $dsttmp" command. # { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && # If -C, don't bother to copy if it wouldn't change the file. if $copy_on_change && old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && set -f && set X $old && old=:$2:$4:$5:$6 && set X $new && new=:$2:$4:$5:$6 && set +f && test "$old" = "$new" && $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 then rm -f "$dsttmp" else # Rename the file to the real destination. $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || # The rename failed, perhaps because mv can't rename something else # to itself, or perhaps because mv is so ancient that it does not # support -f. { # Now remove or move aside any old file at destination location. # We try this two ways since rm can't unlink itself on some # systems and the destination file might be busy for other # reasons. In this case, the final cleanup might fail but the new # file should still install successfully. { test ! -f "$dst" || $doit $rmcmd -f "$dst" 2>/dev/null || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } } || { echo "$0: cannot unlink or rename $dst" >&2 (exit 1); exit 1 } } && # Now rename the file to the real destination. $doit $mvcmd "$dsttmp" "$dst" } fi || exit 1 trap '' 0 fi done # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: libinfinity-0.7.1/PaxHeaders.26529/pixmaps0000644000000000000000000000013213055210725015207 xustar0030 mtime=1488261589.624137701 30 atime=1488261589.544137876 30 ctime=1488261589.624137701 libinfinity-0.7.1/pixmaps/0000755000175000017500000000000013055210725016016 5ustar00arminarmin00000000000000libinfinity-0.7.1/pixmaps/PaxHeaders.26529/16x160000644000000000000000000000013213055210725015774 xustar0030 mtime=1488261589.596137762 30 atime=1488261589.572137815 30 ctime=1488261589.596137762 libinfinity-0.7.1/pixmaps/16x16/0000755000175000017500000000000013055210725016603 5ustar00arminarmin00000000000000libinfinity-0.7.1/pixmaps/16x16/PaxHeaders.26529/infinote.png0000644000000000000000000000013012400102201020346 xustar0029 mtime=1409320065.13113192 29 atime=1409320065.13113192 30 ctime=1488261589.596137762 libinfinity-0.7.1/pixmaps/16x16/infinote.png0000644000175000017500000000156112400102201021105 0ustar00arminarmin00000000000000‰PNG  IHDRísO/sBIT|dˆ pHYs × ×B(›xtEXtSoftwarewww.inkscape.org›î<îIDAT(‘•ÓÏOiðgÞyßwÞ:ý¡¶)ÕMÝ©©’E”z {`³$v/ê`âE/þDﻫL4Æ`Òƒò#ÞôbHÌÙÀn¶± ¤KØÅ,v¦3Ö±ÑË>çïóI¾‡Gº:rýñÚN²ƒãÕùÇÓ?/âFúáþ?YíÒ‘ˆÿ­ÛL?³Ýåɯ–Ëå@©Tº3;;k7===ä›CCú_çXÕ&ô·=ÁÀ€Š}ªÀ9ÇÌÌL½£££>77gƒÁ5MÓx™Ïç‡äx<žLýÔ=ÒÖò¯òþ?óùa¬ç7Ñ{ÀH$‚ÕÕU©··WŠÇã,›Í†R©ïììü6›Ínp8|&úšîǵ+6Ú!°Ï/¼¥[[[hjjÂÄÄt]G.—ƒã8ÒÒÒ’âóù†©"!„€mÛ‚ââEŒÝÖÿ>|Ø„ëÖà8 ÃÀöö6ººº°°°€r¹ Çã%²,G)¥`ŒsÎ9‘C8ÓÝxü4M«rÎŽã`ll ¦iÂu]pÎýDá¯V«`Œ5 œs(Š]×]B(¥p]o^<Ç©?3…÷ „(cL°0Æ@)…,Ë „À4MH’EQ þñü÷îâ\¹‚õ`†Ô²¬’ªª°m» ”‚‚@ sóúÞ,âûåu,‡ö#}²Fì8P*I¥RÙQ²,ï?!ZÙåƒO§1¸²g'šQûåv¢- „ÀuÝ©ÕjyÓ4!ËòH¹dàÈAS’< ΞÆêà0nþzªªB˲ R,s†a€BHòû« ì£Ý˜<÷#Þ†¢ˆÅb( èëëC2™„eY[r(Úöz½©D"ø¼ÌCëwmH´¶crj ãããÈd2Ð4 ¦iÖlÛþ8??Yª×뽉D.!hÃP$ õz®¬¬„=¤ëúR±XÌ)ŠrÀëõ>L§Ó>|I&sûâ…IEND®B`‚libinfinity-0.7.1/pixmaps/16x16/PaxHeaders.26529/Makefile.in0000644000000000000000000000013213051241010020101 xustar0030 mtime=1487225352.441150762 30 atime=1487225352.441150762 30 ctime=1488261589.596137762 libinfinity-0.7.1/pixmaps/16x16/Makefile.in0000644000175000017500000003756513051241010020653 0ustar00arminarmin00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 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__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) 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@ subdir = pixmaps/16x16 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/gtk-doc.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/libinfinity/inf-config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(icondir)" DATA = $(icon_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ 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@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIRNAME = @DATADIRNAME@ 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@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ GTKDOC_CHECK = @GTKDOC_CHECK@ GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ GTKDOC_MKPDF = @GTKDOC_MKPDF@ GTKDOC_REBASE = @GTKDOC_REBASE@ HTML_DIR = @HTML_DIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INSTOBJEXT = @INSTOBJEXT@ INTLLIBS = @INTLLIBS@ INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBINFINITY_API_VERSION = @LIBINFINITY_API_VERSION@ LIBINFINITY_LIBTOOL_VERSION = @LIBINFINITY_LIBTOOL_VERSION@ LIBINFINITY_VERSION = @LIBINFINITY_VERSION@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGFMT_OPTS = @MSGFMT_OPTS@ 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@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ 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@ avahi_CFLAGS = @avahi_CFLAGS@ avahi_LIBS = @avahi_LIBS@ 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@ gio_CFLAGS = @gio_CFLAGS@ gio_LIBS = @gio_LIBS@ gtk_requirement = @gtk_requirement@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infgtk_CFLAGS = @infgtk_CFLAGS@ infgtk_LIBS = @infgtk_LIBS@ infinity_CFLAGS = @infinity_CFLAGS@ infinity_LIBS = @infinity_LIBS@ infinoted_CFLAGS = @infinoted_CFLAGS@ infinoted_LIBS = @infinoted_LIBS@ infodir = @infodir@ inftext_CFLAGS = @inftext_CFLAGS@ inftext_LIBS = @inftext_LIBS@ inftextgtk_CFLAGS = @inftextgtk_CFLAGS@ inftextgtk_LIBS = @inftextgtk_LIBS@ install_sh = @install_sh@ libdaemon_CFLAGS = @libdaemon_CFLAGS@ libdaemon_LIBS = @libdaemon_LIBS@ 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@ runstatedir = @runstatedir@ 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@ icondir = $(datadir)/icons/hicolor/16x16/apps icon_DATA = infinote.png EXTRA_DIST = $(icon_DATA) all: all-am .SUFFIXES: $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(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) --foreign pixmaps/16x16/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign pixmaps/16x16/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: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-iconDATA: $(icon_DATA) @$(NORMAL_INSTALL) @list='$(icon_DATA)'; test -n "$(icondir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(icondir)'"; \ $(MKDIR_P) "$(DESTDIR)$(icondir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(icondir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(icondir)" || exit $$?; \ done uninstall-iconDATA: @$(NORMAL_UNINSTALL) @list='$(icon_DATA)'; test -n "$(icondir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(icondir)'; $(am__uninstall_files_from_dir) tags TAGS: ctags CTAGS: cscope cscopelist: 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: check-am all-am: Makefile $(DATA) installdirs: for dir in "$(DESTDIR)$(icondir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: 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: 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." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-iconDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: 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 -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-iconDATA .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool 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-iconDATA install-info install-info-am \ install-man install-pdf install-pdf-am install-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ ps ps-am tags-am uninstall uninstall-am uninstall-iconDATA .PRECIOUS: Makefile # 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: libinfinity-0.7.1/pixmaps/16x16/PaxHeaders.26529/Makefile.am0000644000000000000000000000013012400102201020061 xustar0029 mtime=1409320065.13113192 29 atime=1409320065.13113192 30 ctime=1488261589.592137771 libinfinity-0.7.1/pixmaps/16x16/Makefile.am0000644000175000017500000000014212400102201020612 0ustar00arminarmin00000000000000icondir = $(datadir)/icons/hicolor/16x16/apps icon_DATA = infinote.png EXTRA_DIST = $(icon_DATA) libinfinity-0.7.1/pixmaps/PaxHeaders.26529/Makefile.in0000644000000000000000000000013013051241010017312 xustar0029 mtime=1487225352.49715094 29 atime=1487225352.49715094 30 ctime=1488261589.568137823 libinfinity-0.7.1/pixmaps/Makefile.in0000644000175000017500000005072013051241010020052 0ustar00arminarmin00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 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__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) 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@ subdir = pixmaps ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/gtk-doc.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/libinfinity/inf-config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ 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@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIRNAME = @DATADIRNAME@ 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@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ GTKDOC_CHECK = @GTKDOC_CHECK@ GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ GTKDOC_MKPDF = @GTKDOC_MKPDF@ GTKDOC_REBASE = @GTKDOC_REBASE@ HTML_DIR = @HTML_DIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INSTOBJEXT = @INSTOBJEXT@ INTLLIBS = @INTLLIBS@ INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBINFINITY_API_VERSION = @LIBINFINITY_API_VERSION@ LIBINFINITY_LIBTOOL_VERSION = @LIBINFINITY_LIBTOOL_VERSION@ LIBINFINITY_VERSION = @LIBINFINITY_VERSION@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGFMT_OPTS = @MSGFMT_OPTS@ 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@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ 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@ avahi_CFLAGS = @avahi_CFLAGS@ avahi_LIBS = @avahi_LIBS@ 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@ gio_CFLAGS = @gio_CFLAGS@ gio_LIBS = @gio_LIBS@ gtk_requirement = @gtk_requirement@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infgtk_CFLAGS = @infgtk_CFLAGS@ infgtk_LIBS = @infgtk_LIBS@ infinity_CFLAGS = @infinity_CFLAGS@ infinity_LIBS = @infinity_LIBS@ infinoted_CFLAGS = @infinoted_CFLAGS@ infinoted_LIBS = @infinoted_LIBS@ infodir = @infodir@ inftext_CFLAGS = @inftext_CFLAGS@ inftext_LIBS = @inftext_LIBS@ inftextgtk_CFLAGS = @inftextgtk_CFLAGS@ inftextgtk_LIBS = @inftextgtk_LIBS@ install_sh = @install_sh@ libdaemon_CFLAGS = @libdaemon_CFLAGS@ libdaemon_LIBS = @libdaemon_LIBS@ 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@ runstatedir = @runstatedir@ 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@ SUBDIRS = 16x16 22x22 scalable gtk_update_icon_cache = gtk-update-icon-cache -f -t $(datadir)/icons/hicolor all: all-recursive .SUFFIXES: $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(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) --foreign pixmaps/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign pixmaps/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: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ 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-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ 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" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files 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 @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive 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: 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." clean: clean-recursive clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-recursive -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) install-data-hook install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) uninstall-hook .MAKE: $(am__recursive_targets) install-am install-data-am \ install-strip uninstall-am .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-am clean clean-generic clean-libtool cscopelist-am ctags \ ctags-am distclean 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-data-hook 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-ps install-ps-am install-strip installcheck \ installcheck-am installdirs installdirs-am maintainer-clean \ maintainer-clean-generic mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \ uninstall-am uninstall-hook .PRECIOUS: Makefile install-data-hook: update-icon-cache uninstall-hook: update-icon-cache update-icon-cache: @-if test -z "$(DESTDIR)"; then \ echo "Updating Gtk icon cache."; \ $(gtk_update_icon_cache); \ else \ echo "*** Icon cache not updated. After (un)install, run this:"; \ echo "*** $(gtk_update_icon_cache)"; \ fi # 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: libinfinity-0.7.1/pixmaps/PaxHeaders.26529/Makefile.am0000644000000000000000000000013012400102201017274 xustar0029 mtime=1409320065.13113192 29 atime=1409320065.13113192 30 ctime=1488261589.568137823 libinfinity-0.7.1/pixmaps/Makefile.am0000644000175000017500000000065312400102201020034 0ustar00arminarmin00000000000000SUBDIRS = 16x16 22x22 scalable gtk_update_icon_cache = gtk-update-icon-cache -f -t $(datadir)/icons/hicolor install-data-hook: update-icon-cache uninstall-hook: update-icon-cache update-icon-cache: @-if test -z "$(DESTDIR)"; then \ echo "Updating Gtk icon cache."; \ $(gtk_update_icon_cache); \ else \ echo "*** Icon cache not updated. After (un)install, run this:"; \ echo "*** $(gtk_update_icon_cache)"; \ fi libinfinity-0.7.1/pixmaps/PaxHeaders.26529/scalable0000644000000000000000000000013013055210725016753 xustar0029 mtime=1488261589.65213764 30 atime=1488261589.624137701 29 ctime=1488261589.65213764 libinfinity-0.7.1/pixmaps/scalable/0000755000175000017500000000000013055210725017564 5ustar00arminarmin00000000000000libinfinity-0.7.1/pixmaps/scalable/PaxHeaders.26529/Makefile.in0000644000000000000000000000013213051241010021062 xustar0030 mtime=1487225352.525151029 30 atime=1487225352.525151029 30 ctime=1488261589.648137648 libinfinity-0.7.1/pixmaps/scalable/Makefile.in0000644000175000017500000003760113051241010021623 0ustar00arminarmin00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 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__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) 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@ subdir = pixmaps/scalable ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/gtk-doc.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/libinfinity/inf-config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(icondir)" DATA = $(icon_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ 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@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIRNAME = @DATADIRNAME@ 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@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ GTKDOC_CHECK = @GTKDOC_CHECK@ GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ GTKDOC_MKPDF = @GTKDOC_MKPDF@ GTKDOC_REBASE = @GTKDOC_REBASE@ HTML_DIR = @HTML_DIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INSTOBJEXT = @INSTOBJEXT@ INTLLIBS = @INTLLIBS@ INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBINFINITY_API_VERSION = @LIBINFINITY_API_VERSION@ LIBINFINITY_LIBTOOL_VERSION = @LIBINFINITY_LIBTOOL_VERSION@ LIBINFINITY_VERSION = @LIBINFINITY_VERSION@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGFMT_OPTS = @MSGFMT_OPTS@ 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@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ 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@ avahi_CFLAGS = @avahi_CFLAGS@ avahi_LIBS = @avahi_LIBS@ 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@ gio_CFLAGS = @gio_CFLAGS@ gio_LIBS = @gio_LIBS@ gtk_requirement = @gtk_requirement@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infgtk_CFLAGS = @infgtk_CFLAGS@ infgtk_LIBS = @infgtk_LIBS@ infinity_CFLAGS = @infinity_CFLAGS@ infinity_LIBS = @infinity_LIBS@ infinoted_CFLAGS = @infinoted_CFLAGS@ infinoted_LIBS = @infinoted_LIBS@ infodir = @infodir@ inftext_CFLAGS = @inftext_CFLAGS@ inftext_LIBS = @inftext_LIBS@ inftextgtk_CFLAGS = @inftextgtk_CFLAGS@ inftextgtk_LIBS = @inftextgtk_LIBS@ install_sh = @install_sh@ libdaemon_CFLAGS = @libdaemon_CFLAGS@ libdaemon_LIBS = @libdaemon_LIBS@ 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@ runstatedir = @runstatedir@ 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@ icondir = $(datadir)/icons/hicolor/scalable/apps icon_DATA = infinote.svg EXTRA_DIST = $(icon_DATA) all: all-am .SUFFIXES: $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(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) --foreign pixmaps/scalable/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign pixmaps/scalable/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: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-iconDATA: $(icon_DATA) @$(NORMAL_INSTALL) @list='$(icon_DATA)'; test -n "$(icondir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(icondir)'"; \ $(MKDIR_P) "$(DESTDIR)$(icondir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(icondir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(icondir)" || exit $$?; \ done uninstall-iconDATA: @$(NORMAL_UNINSTALL) @list='$(icon_DATA)'; test -n "$(icondir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(icondir)'; $(am__uninstall_files_from_dir) tags TAGS: ctags CTAGS: cscope cscopelist: 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: check-am all-am: Makefile $(DATA) installdirs: for dir in "$(DESTDIR)$(icondir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: 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: 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." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-iconDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: 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 -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-iconDATA .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool 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-iconDATA install-info install-info-am \ install-man install-pdf install-pdf-am install-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ ps ps-am tags-am uninstall uninstall-am uninstall-iconDATA .PRECIOUS: Makefile # 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: libinfinity-0.7.1/pixmaps/scalable/PaxHeaders.26529/Makefile.am0000644000000000000000000000013012400102201021042 xustar0029 mtime=1409320065.13113192 29 atime=1409320065.13113192 30 ctime=1488261589.648137648 libinfinity-0.7.1/pixmaps/scalable/Makefile.am0000644000175000017500000000014512400102201021576 0ustar00arminarmin00000000000000icondir = $(datadir)/icons/hicolor/scalable/apps icon_DATA = infinote.svg EXTRA_DIST = $(icon_DATA) libinfinity-0.7.1/pixmaps/scalable/PaxHeaders.26529/infinote.svg0000644000000000000000000000013012400102201021342 xustar0029 mtime=1409320065.13113192 29 atime=1409320065.13113192 30 ctime=1488261589.656137631 libinfinity-0.7.1/pixmaps/scalable/infinote.svg0000644000175000017500000011526312400102201022106 0ustar00arminarmin00000000000000 image/svg+xml libinfinity-0.7.1/pixmaps/PaxHeaders.26529/22x220000644000000000000000000000013213055210725015766 xustar0030 mtime=1488261589.624137701 30 atime=1488261589.600137753 30 ctime=1488261589.624137701 libinfinity-0.7.1/pixmaps/22x22/0000755000175000017500000000000013055210725016575 5ustar00arminarmin00000000000000libinfinity-0.7.1/pixmaps/22x22/PaxHeaders.26529/infinote.png0000644000000000000000000000013012400102201020340 xustar0029 mtime=1409320065.13113192 29 atime=1409320065.13113192 30 ctime=1488261589.624137701 libinfinity-0.7.1/pixmaps/22x22/infinote.png0000644000175000017500000000261312400102201021076 0ustar00arminarmin00000000000000‰PNG  IHDRÄ´l;sBIT|dˆ pHYs--+Ü ôtEXtSoftwarewww.inkscape.org›î<IDAT8­•]lTdžŸ™9sŽÏzÝõîz1nä¥@@¸MdA[¥IY#Y)Qš‚“È¥æ¢J{*~ÔFŠ*¥ªb!U⢮Ԫå¢U*EJ©ÊEÒÉìE@Â&¶@ÿ@`ÿÛ»^Û볜³Ó‹h-C“^e¤Ñ\}ϼó|£qèå×~¿êGŸüÜÏœíû_ÐŽ®éߓǚ‡g_}ýÀ ?;ŸÉdÂ_X¼¸ÿ—o<ólWau—ø|eCߊm]PÓŸWdŒ±<Ïk.•J'ÏŸ?á3ÁÆ|çÇo,¬>ùóñ…n’͉~žyzŒ]ߨþ?áp˜ÞÞ^ºººÌ… ÌÜÜֺܼAÜ39??ÿÝl6û¡¨Ê|ÇOÄÅ“›‹Æf÷ò—>Çßÿ6Èòò2¾ïãû>Æ._¾LGG===âĉ²¥¥%±gÏž»wïvúúúZ“Éä_d&“©s]wG"ÙÈ¡C[yá›o­û’×Ê»C?á½þPJ¡µ&‹qéÒ%öíÛGoo/wïÞeaak×®ÑÝÝM2™¤½½=–Édž’@ssssP,xfïcüðÅë|9þ6M”Ø¿3`äæÐZ …ð<ÁÁAnß¾ÍÀÀ©TŠ©©)†††8zô(étºÑuÝ]ЋŴïû(¥PJÑöÕ/±i³Çø?0ºàsùêûlÙÞ†ëºH)Éår!XZZbÛ¶mT*®\¹‚RŠ[·n‡³€!˲ÖÀJ)¢Q›]Ow ¥dÇSRJ´Öh­ñ}ÿÓÎ A{{;[¶la``­5žç¡”JKÇqZ‰„«”²¬¦Ö˲p]Çq˜œœ$šJ¥R»v$“I:;;ñ<˲BA‹‡·F"j‰×'—R"¥D‚;wîJ¥X]]]ƒ,..ây ùqü†G ´ cLT*¥Ò‘Hä §¯)˜˜˜ •Jqÿþ}´ÖØ¶ÍØëœ9ô¯]½A§½„Y˜Ã²,mc®ëR.—?3µRj-ñÊÊ ±X 皦r4 üƒù–oNRyâQ¤”Òr¥R Û¶‘R~®!6l ŸÏ‹jµJSnŒ®FÙ¼T¦,Úú( × áß›¸oyž7V,I¥Rk‡á5pkk+ƒß7mã7Å÷‡?¡ÎÆÂ.C{;ù`~™M‘(¾ïS­VËrqqq¤P(ø5Àúu½k­5¦8˳WÅ+ݦÎÎmLð¯½Â¾×…ã8X–E(¥¦,àÞììì²"R»7²æyäúEzŠ%ÊBðæö4Ÿl‚Ñ$'OžÄ¶m”RApGù™™™ÕZqíØ§>óÖŸ ‹Eú¾µƒß|ýqŠ™ocl‡‘‘†‡‡‰Çã šššð&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) 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@ subdir = pixmaps/22x22 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/gtk-doc.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/libinfinity/inf-config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(icondir)" DATA = $(icon_DATA) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ 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@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIRNAME = @DATADIRNAME@ 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@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ GTKDOC_CHECK = @GTKDOC_CHECK@ GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ GTKDOC_MKPDF = @GTKDOC_MKPDF@ GTKDOC_REBASE = @GTKDOC_REBASE@ HTML_DIR = @HTML_DIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INSTOBJEXT = @INSTOBJEXT@ INTLLIBS = @INTLLIBS@ INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBINFINITY_API_VERSION = @LIBINFINITY_API_VERSION@ LIBINFINITY_LIBTOOL_VERSION = @LIBINFINITY_LIBTOOL_VERSION@ LIBINFINITY_VERSION = @LIBINFINITY_VERSION@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGFMT_OPTS = @MSGFMT_OPTS@ 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@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ 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@ avahi_CFLAGS = @avahi_CFLAGS@ avahi_LIBS = @avahi_LIBS@ 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@ gio_CFLAGS = @gio_CFLAGS@ gio_LIBS = @gio_LIBS@ gtk_requirement = @gtk_requirement@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infgtk_CFLAGS = @infgtk_CFLAGS@ infgtk_LIBS = @infgtk_LIBS@ infinity_CFLAGS = @infinity_CFLAGS@ infinity_LIBS = @infinity_LIBS@ infinoted_CFLAGS = @infinoted_CFLAGS@ infinoted_LIBS = @infinoted_LIBS@ infodir = @infodir@ inftext_CFLAGS = @inftext_CFLAGS@ inftext_LIBS = @inftext_LIBS@ inftextgtk_CFLAGS = @inftextgtk_CFLAGS@ inftextgtk_LIBS = @inftextgtk_LIBS@ install_sh = @install_sh@ libdaemon_CFLAGS = @libdaemon_CFLAGS@ libdaemon_LIBS = @libdaemon_LIBS@ 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@ runstatedir = @runstatedir@ 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@ icondir = $(datadir)/icons/hicolor/22x22/apps icon_DATA = infinote.png EXTRA_DIST = $(icon_DATA) all: all-am .SUFFIXES: $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(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) --foreign pixmaps/22x22/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign pixmaps/22x22/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: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-iconDATA: $(icon_DATA) @$(NORMAL_INSTALL) @list='$(icon_DATA)'; test -n "$(icondir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(icondir)'"; \ $(MKDIR_P) "$(DESTDIR)$(icondir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(icondir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(icondir)" || exit $$?; \ done uninstall-iconDATA: @$(NORMAL_UNINSTALL) @list='$(icon_DATA)'; test -n "$(icondir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(icondir)'; $(am__uninstall_files_from_dir) tags TAGS: ctags CTAGS: cscope cscopelist: 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: check-am all-am: Makefile $(DATA) installdirs: for dir in "$(DESTDIR)$(icondir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: 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: 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." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-iconDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: 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 -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-iconDATA .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool 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-iconDATA install-info install-info-am \ install-man install-pdf install-pdf-am install-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ ps ps-am tags-am uninstall uninstall-am uninstall-iconDATA .PRECIOUS: Makefile # 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: libinfinity-0.7.1/pixmaps/22x22/PaxHeaders.26529/Makefile.am0000644000000000000000000000012712400102201020061 xustar0029 mtime=1409320065.13113192 29 atime=1409320065.13113192 29 ctime=1488261589.62013771 libinfinity-0.7.1/pixmaps/22x22/Makefile.am0000644000175000017500000000014212400102201020604 0ustar00arminarmin00000000000000icondir = $(datadir)/icons/hicolor/22x22/apps icon_DATA = infinote.png EXTRA_DIST = $(icon_DATA) libinfinity-0.7.1/PaxHeaders.26529/aclocal.m40000644000000000000000000000013213051241006015433 xustar0030 mtime=1487225350.569144803 30 atime=1487225350.569144803 30 ctime=1488261588.752139607 libinfinity-0.7.1/aclocal.m40000644000175000017500000021750513051241006016177 0ustar00arminarmin00000000000000# generated automatically by aclocal 1.15 -*- Autoconf -*- # Copyright (C) 1996-2014 Free Software Foundation, Inc. # This file 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. m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, [m4_warning([this file was generated for autoconf 2.69. You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically 'autoreconf'.])]) # Copyright (C) 1995-2002 Free Software Foundation, Inc. # Copyright (C) 2001-2003,2004 Red Hat, Inc. # # This file is free software, distributed under the terms of the GNU # General Public License. As a special exception to the GNU General # Public License, this file may be distributed as part of a program # that contains a configuration script generated by Autoconf, under # the same distribution terms as the rest of that program. # # This file can be copied and used freely without restrictions. It can # be used in projects which are not available under the GNU Public License # but which still want to provide support for the GNU gettext functionality. # # Macro to add for using GNU gettext. # Ulrich Drepper , 1995, 1996 # # Modified to never use included libintl. # Owen Taylor , 12/15/1998 # # Major rework to remove unused code # Owen Taylor , 12/11/2002 # # Added better handling of ALL_LINGUAS from GNU gettext version # written by Bruno Haible, Owen Taylor 5/30/3002 # # Modified to require ngettext # Matthias Clasen 08/06/2004 # # We need this here as well, since someone might use autoconf-2.5x # to configure GLib then an older version to configure a package # using AM_GLIB_GNU_GETTEXT AC_PREREQ(2.53) dnl dnl We go to great lengths to make sure that aclocal won't dnl try to pull in the installed version of these macros dnl when running aclocal in the glib directory. dnl m4_copy([AC_DEFUN],[glib_DEFUN]) m4_copy([AC_REQUIRE],[glib_REQUIRE]) dnl dnl At the end, if we're not within glib, we'll define the public dnl definitions in terms of our private definitions. dnl # GLIB_LC_MESSAGES #-------------------- glib_DEFUN([GLIB_LC_MESSAGES], [AC_CHECK_HEADERS([locale.h]) if test $ac_cv_header_locale_h = yes; then AC_CACHE_CHECK([for LC_MESSAGES], am_cv_val_LC_MESSAGES, [AC_TRY_LINK([#include ], [return LC_MESSAGES], am_cv_val_LC_MESSAGES=yes, am_cv_val_LC_MESSAGES=no)]) if test $am_cv_val_LC_MESSAGES = yes; then AC_DEFINE(HAVE_LC_MESSAGES, 1, [Define if your file defines LC_MESSAGES.]) fi fi]) # GLIB_PATH_PROG_WITH_TEST #---------------------------- dnl GLIB_PATH_PROG_WITH_TEST(VARIABLE, PROG-TO-CHECK-FOR, dnl TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]]) glib_DEFUN([GLIB_PATH_PROG_WITH_TEST], [# Extract the first word of "$2", so it can be a program name with args. set dummy $2; ac_word=[$]2 AC_MSG_CHECKING([for $ac_word]) AC_CACHE_VAL(ac_cv_path_$1, [case "[$]$1" in /*) ac_cv_path_$1="[$]$1" # Let the user override the test with a path. ;; *) IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" for ac_dir in ifelse([$5], , $PATH, [$5]); do test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$ac_word; then if [$3]; then ac_cv_path_$1="$ac_dir/$ac_word" break fi fi done IFS="$ac_save_ifs" dnl If no 4th arg is given, leave the cache variable unset, dnl so AC_PATH_PROGS will keep looking. ifelse([$4], , , [ test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4" ])dnl ;; esac])dnl $1="$ac_cv_path_$1" if test ifelse([$4], , [-n "[$]$1"], ["[$]$1" != "$4"]); then AC_MSG_RESULT([$]$1) else AC_MSG_RESULT(no) fi AC_SUBST($1)dnl ]) # GLIB_WITH_NLS #----------------- glib_DEFUN([GLIB_WITH_NLS], dnl NLS is obligatory [USE_NLS=yes AC_SUBST(USE_NLS) gt_cv_have_gettext=no CATOBJEXT=NONE XGETTEXT=: INTLLIBS= AC_CHECK_HEADER(libintl.h, [gt_cv_func_dgettext_libintl="no" libintl_extra_libs="" # # First check in libc # AC_CACHE_CHECK([for ngettext in libc], gt_cv_func_ngettext_libc, [AC_TRY_LINK([ #include ], [return !ngettext ("","", 1)], gt_cv_func_ngettext_libc=yes, gt_cv_func_ngettext_libc=no) ]) if test "$gt_cv_func_ngettext_libc" = "yes" ; then AC_CACHE_CHECK([for dgettext in libc], gt_cv_func_dgettext_libc, [AC_TRY_LINK([ #include ], [return !dgettext ("","")], gt_cv_func_dgettext_libc=yes, gt_cv_func_dgettext_libc=no) ]) fi if test "$gt_cv_func_ngettext_libc" = "yes" ; then AC_CHECK_FUNCS(bind_textdomain_codeset) fi # # If we don't have everything we want, check in libintl # if test "$gt_cv_func_dgettext_libc" != "yes" \ || test "$gt_cv_func_ngettext_libc" != "yes" \ || test "$ac_cv_func_bind_textdomain_codeset" != "yes" ; then AC_CHECK_LIB(intl, bindtextdomain, [AC_CHECK_LIB(intl, ngettext, [AC_CHECK_LIB(intl, dgettext, gt_cv_func_dgettext_libintl=yes)])]) if test "$gt_cv_func_dgettext_libintl" != "yes" ; then AC_MSG_CHECKING([if -liconv is needed to use gettext]) AC_MSG_RESULT([]) AC_CHECK_LIB(intl, ngettext, [AC_CHECK_LIB(intl, dcgettext, [gt_cv_func_dgettext_libintl=yes libintl_extra_libs=-liconv], :,-liconv)], :,-liconv) fi # # If we found libintl, then check in it for bind_textdomain_codeset(); # we'll prefer libc if neither have bind_textdomain_codeset(), # and both have dgettext and ngettext # if test "$gt_cv_func_dgettext_libintl" = "yes" ; then glib_save_LIBS="$LIBS" LIBS="$LIBS -lintl $libintl_extra_libs" unset ac_cv_func_bind_textdomain_codeset AC_CHECK_FUNCS(bind_textdomain_codeset) LIBS="$glib_save_LIBS" if test "$ac_cv_func_bind_textdomain_codeset" = "yes" ; then gt_cv_func_dgettext_libc=no else if test "$gt_cv_func_dgettext_libc" = "yes" \ && test "$gt_cv_func_ngettext_libc" = "yes"; then gt_cv_func_dgettext_libintl=no fi fi fi fi if test "$gt_cv_func_dgettext_libc" = "yes" \ || test "$gt_cv_func_dgettext_libintl" = "yes"; then gt_cv_have_gettext=yes fi if test "$gt_cv_func_dgettext_libintl" = "yes"; then INTLLIBS="-lintl $libintl_extra_libs" fi if test "$gt_cv_have_gettext" = "yes"; then AC_DEFINE(HAVE_GETTEXT,1, [Define if the GNU gettext() function is already present or preinstalled.]) GLIB_PATH_PROG_WITH_TEST(MSGFMT, msgfmt, [test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"], no)dnl if test "$MSGFMT" != "no"; then glib_save_LIBS="$LIBS" LIBS="$LIBS $INTLLIBS" AC_CHECK_FUNCS(dcgettext) MSGFMT_OPTS= AC_MSG_CHECKING([if msgfmt accepts -c]) GLIB_RUN_PROG([$MSGFMT -c -o /dev/null],[ msgid "" msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Project-Id-Version: test 1.0\n" "PO-Revision-Date: 2007-02-15 12:01+0100\n" "Last-Translator: test \n" "Language-Team: C \n" "MIME-Version: 1.0\n" "Content-Transfer-Encoding: 8bit\n" ], [MSGFMT_OPTS=-c; AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no])]) AC_SUBST(MSGFMT_OPTS) AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT) GLIB_PATH_PROG_WITH_TEST(XGETTEXT, xgettext, [test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"], :) AC_TRY_LINK(, [extern int _nl_msg_cat_cntr; return _nl_msg_cat_cntr], [CATOBJEXT=.gmo DATADIRNAME=share], [case $host in *-*-solaris*) dnl On Solaris, if bind_textdomain_codeset is in libc, dnl GNU format message catalog is always supported, dnl since both are added to the libc all together. dnl Hence, we'd like to go with DATADIRNAME=share and dnl and CATOBJEXT=.gmo in this case. AC_CHECK_FUNC(bind_textdomain_codeset, [CATOBJEXT=.gmo DATADIRNAME=share], [CATOBJEXT=.mo DATADIRNAME=lib]) ;; *-*-openbsd*) CATOBJEXT=.mo DATADIRNAME=share ;; *) CATOBJEXT=.mo DATADIRNAME=lib ;; esac]) LIBS="$glib_save_LIBS" INSTOBJEXT=.mo else gt_cv_have_gettext=no fi fi ]) if test "$gt_cv_have_gettext" = "yes" ; then AC_DEFINE(ENABLE_NLS, 1, [always defined to indicate that i18n is enabled]) fi dnl Test whether we really found GNU xgettext. if test "$XGETTEXT" != ":"; then dnl If it is not GNU xgettext we define it as : so that the dnl Makefiles still can work. if $XGETTEXT --omit-header /dev/null 2> /dev/null; then : ; else AC_MSG_RESULT( [found xgettext program is not GNU xgettext; ignore it]) XGETTEXT=":" fi fi # We need to process the po/ directory. POSUB=po AC_OUTPUT_COMMANDS( [case "$CONFIG_FILES" in *po/Makefile.in*) sed -e "/POTFILES =/r po/POTFILES" po/Makefile.in > po/Makefile esac]) dnl These rules are solely for the distribution goal. While doing this dnl we only have to keep exactly one list of the available catalogs dnl in configure.ac. for lang in $ALL_LINGUAS; do GMOFILES="$GMOFILES $lang.gmo" POFILES="$POFILES $lang.po" done dnl Make all variables we use known to autoconf. AC_SUBST(CATALOGS) AC_SUBST(CATOBJEXT) AC_SUBST(DATADIRNAME) AC_SUBST(GMOFILES) AC_SUBST(INSTOBJEXT) AC_SUBST(INTLLIBS) AC_SUBST(PO_IN_DATADIR_TRUE) AC_SUBST(PO_IN_DATADIR_FALSE) AC_SUBST(POFILES) AC_SUBST(POSUB) ]) # AM_GLIB_GNU_GETTEXT # ------------------- # Do checks necessary for use of gettext. If a suitable implementation # of gettext is found in either in libintl or in the C library, # it will set INTLLIBS to the libraries needed for use of gettext # and AC_DEFINE() HAVE_GETTEXT and ENABLE_NLS. (The shell variable # gt_cv_have_gettext will be set to "yes".) It will also call AC_SUBST() # on various variables needed by the Makefile.in.in installed by # glib-gettextize. dnl AU_DEFUN([GLIB_GNU_GETTEXT], [AC_REQUIRE([AC_PROG_CC])dnl GLIB_LC_MESSAGES GLIB_WITH_NLS if test "$gt_cv_have_gettext" = "yes"; then if test "x$ALL_LINGUAS" = "x"; then LINGUAS= else AC_MSG_CHECKING(for catalogs to be installed) NEW_LINGUAS= for presentlang in $ALL_LINGUAS; do useit=no if test "%UNSET%" != "${LINGUAS-%UNSET%}"; then desiredlanguages="$LINGUAS" else desiredlanguages="$ALL_LINGUAS" fi for desiredlang in $desiredlanguages; do # Use the presentlang catalog if desiredlang is # a. equal to presentlang, or # b. a variant of presentlang (because in this case, # presentlang can be used as a fallback for messages # which are not translated in the desiredlang catalog). case "$desiredlang" in "$presentlang"*) useit=yes;; esac done if test $useit = yes; then NEW_LINGUAS="$NEW_LINGUAS $presentlang" fi done LINGUAS=$NEW_LINGUAS AC_MSG_RESULT($LINGUAS) fi dnl Construct list of names of catalog files to be constructed. if test -n "$LINGUAS"; then for lang in $LINGUAS; do CATALOGS="$CATALOGS $lang$CATOBJEXT"; done fi fi dnl If the AC_CONFIG_AUX_DIR macro for autoconf is used we possibly dnl find the mkinstalldirs script in another subdir but ($top_srcdir). dnl Try to locate is. MKINSTALLDIRS= if test -n "$ac_aux_dir"; then MKINSTALLDIRS="$ac_aux_dir/mkinstalldirs" fi if test -z "$MKINSTALLDIRS"; then MKINSTALLDIRS="\$(top_srcdir)/mkinstalldirs" fi AC_SUBST(MKINSTALLDIRS) dnl Generate list of files to be processed by xgettext which will dnl be included in po/Makefile. test -d po || mkdir po if test "x$srcdir" != "x."; then if test "x`echo $srcdir | sed 's@/.*@@'`" = "x"; then posrcprefix="$srcdir/" else posrcprefix="../$srcdir/" fi else posrcprefix="../" fi rm -f po/POTFILES sed -e "/^#/d" -e "/^\$/d" -e "s,.*, $posrcprefix& \\\\," -e "\$s/\(.*\) \\\\/\1/" \ < $srcdir/po/POTFILES.in > po/POTFILES ], [[$0: This macro is deprecated. You should use upstream gettext instead.]]) # AM_GLIB_DEFINE_LOCALEDIR(VARIABLE) # ------------------------------- # Define VARIABLE to the location where catalog files will # be installed by po/Makefile. glib_DEFUN([GLIB_DEFINE_LOCALEDIR], [glib_REQUIRE([GLIB_GNU_GETTEXT])dnl glib_save_prefix="$prefix" glib_save_exec_prefix="$exec_prefix" glib_save_datarootdir="$datarootdir" test "x$prefix" = xNONE && prefix=$ac_default_prefix test "x$exec_prefix" = xNONE && exec_prefix=$prefix datarootdir=`eval echo "${datarootdir}"` if test "x$CATOBJEXT" = "x.mo" ; then localedir=`eval echo "${libdir}/locale"` else localedir=`eval echo "${datadir}/locale"` fi prefix="$glib_save_prefix" exec_prefix="$glib_save_exec_prefix" datarootdir="$glib_save_datarootdir" AC_DEFINE_UNQUOTED($1, "$localedir", [Define the location where the catalogs will be installed]) ]) dnl dnl Now the definitions that aclocal will find dnl ifdef(glib_configure_ac,[],[ AC_DEFUN([AM_GLIB_GNU_GETTEXT],[GLIB_GNU_GETTEXT($@)]) AC_DEFUN([AM_GLIB_DEFINE_LOCALEDIR],[GLIB_DEFINE_LOCALEDIR($@)]) ])dnl # GLIB_RUN_PROG(PROGRAM, TEST-FILE, [ACTION-IF-PASS], [ACTION-IF-FAIL]) # # Create a temporary file with TEST-FILE as its contents and pass the # file name to PROGRAM. Perform ACTION-IF-PASS if PROGRAM exits with # 0 and perform ACTION-IF-FAIL for any other exit status. AC_DEFUN([GLIB_RUN_PROG], [cat >conftest.foo <<_ACEOF $2 _ACEOF if AC_RUN_LOG([$1 conftest.foo]); then m4_ifval([$3], [$3], [:]) m4_ifvaln([$4], [else $4])dnl echo "$as_me: failed input was:" >&AS_MESSAGE_LOG_FD sed 's/^/| /' conftest.foo >&AS_MESSAGE_LOG_FD fi]) dnl -*- mode: autoconf -*- dnl Copyright 2009 Johan Dahlin dnl dnl This file is free software; the author(s) gives unlimited dnl permission to copy and/or distribute it, with or without dnl modifications, as long as this notice is preserved. dnl # serial 1 m4_define([_GOBJECT_INTROSPECTION_CHECK_INTERNAL], [ AC_BEFORE([AC_PROG_LIBTOOL],[$0])dnl setup libtool first AC_BEFORE([AM_PROG_LIBTOOL],[$0])dnl setup libtool first AC_BEFORE([LT_INIT],[$0])dnl setup libtool first dnl enable/disable introspection m4_if([$2], [require], [dnl enable_introspection=yes ],[dnl AC_ARG_ENABLE(introspection, AS_HELP_STRING([--enable-introspection[=@<:@no/auto/yes@:>@]], [Enable introspection for this build]),, [enable_introspection=auto]) ])dnl AC_MSG_CHECKING([for gobject-introspection]) dnl presence/version checking AS_CASE([$enable_introspection], [no], [dnl found_introspection="no (disabled, use --enable-introspection to enable)" ],dnl [yes],[dnl PKG_CHECK_EXISTS([gobject-introspection-1.0],, AC_MSG_ERROR([gobject-introspection-1.0 is not installed])) PKG_CHECK_EXISTS([gobject-introspection-1.0 >= $1], found_introspection=yes, AC_MSG_ERROR([You need to have gobject-introspection >= $1 installed to build AC_PACKAGE_NAME])) ],dnl [auto],[dnl PKG_CHECK_EXISTS([gobject-introspection-1.0 >= $1], found_introspection=yes, found_introspection=no) dnl Canonicalize enable_introspection enable_introspection=$found_introspection ],dnl [dnl AC_MSG_ERROR([invalid argument passed to --enable-introspection, should be one of @<:@no/auto/yes@:>@]) ])dnl AC_MSG_RESULT([$found_introspection]) INTROSPECTION_SCANNER= INTROSPECTION_COMPILER= INTROSPECTION_GENERATE= INTROSPECTION_GIRDIR= INTROSPECTION_TYPELIBDIR= if test "x$found_introspection" = "xyes"; then INTROSPECTION_SCANNER=`$PKG_CONFIG --variable=g_ir_scanner gobject-introspection-1.0` INTROSPECTION_COMPILER=`$PKG_CONFIG --variable=g_ir_compiler gobject-introspection-1.0` INTROSPECTION_GENERATE=`$PKG_CONFIG --variable=g_ir_generate gobject-introspection-1.0` INTROSPECTION_GIRDIR=`$PKG_CONFIG --variable=girdir gobject-introspection-1.0` INTROSPECTION_TYPELIBDIR="$($PKG_CONFIG --variable=typelibdir gobject-introspection-1.0)" INTROSPECTION_CFLAGS=`$PKG_CONFIG --cflags gobject-introspection-1.0` INTROSPECTION_LIBS=`$PKG_CONFIG --libs gobject-introspection-1.0` INTROSPECTION_MAKEFILE=`$PKG_CONFIG --variable=datadir gobject-introspection-1.0`/gobject-introspection-1.0/Makefile.introspection fi AC_SUBST(INTROSPECTION_SCANNER) AC_SUBST(INTROSPECTION_COMPILER) AC_SUBST(INTROSPECTION_GENERATE) AC_SUBST(INTROSPECTION_GIRDIR) AC_SUBST(INTROSPECTION_TYPELIBDIR) AC_SUBST(INTROSPECTION_CFLAGS) AC_SUBST(INTROSPECTION_LIBS) AC_SUBST(INTROSPECTION_MAKEFILE) AM_CONDITIONAL(HAVE_INTROSPECTION, test "x$found_introspection" = "xyes") ]) dnl Usage: dnl GOBJECT_INTROSPECTION_CHECK([minimum-g-i-version]) AC_DEFUN([GOBJECT_INTROSPECTION_CHECK], [ _GOBJECT_INTROSPECTION_CHECK_INTERNAL([$1]) ]) dnl Usage: dnl GOBJECT_INTROSPECTION_REQUIRE([minimum-g-i-version]) AC_DEFUN([GOBJECT_INTROSPECTION_REQUIRE], [ _GOBJECT_INTROSPECTION_CHECK_INTERNAL([$1], [require]) ]) dnl pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- dnl serial 11 (pkg-config-0.29) dnl dnl Copyright © 2004 Scott James Remnant . dnl Copyright © 2012-2015 Dan Nicholson dnl dnl This program is free software; you can redistribute it and/or modify dnl it under the terms of the GNU General Public License as published by dnl the Free Software Foundation; either version 2 of the License, or dnl (at your option) any later version. dnl dnl This program is distributed in the hope that it will be useful, but dnl WITHOUT ANY WARRANTY; without even the implied warranty of dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU dnl General Public License for more details. dnl dnl You should have received a copy of the GNU General Public License dnl along with this program; if not, write to the Free Software dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA dnl 02111-1307, USA. dnl dnl As a special exception to the GNU General Public License, if you dnl distribute this file as part of a program that contains a dnl configuration script generated by Autoconf, you may include it under dnl the same distribution terms that you use for the rest of that dnl program. dnl PKG_PREREQ(MIN-VERSION) dnl ----------------------- dnl Since: 0.29 dnl dnl Verify that the version of the pkg-config macros are at least dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's dnl installed version of pkg-config, this checks the developer's version dnl of pkg.m4 when generating configure. dnl dnl To ensure that this macro is defined, also add: dnl m4_ifndef([PKG_PREREQ], dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])]) dnl dnl See the "Since" comment for each macro you use to see what version dnl of the macros you require. m4_defun([PKG_PREREQ], [m4_define([PKG_MACROS_VERSION], [0.29]) m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1, [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) ])dnl PKG_PREREQ dnl PKG_PROG_PKG_CONFIG([MIN-VERSION]) dnl ---------------------------------- dnl Since: 0.16 dnl dnl Search for the pkg-config tool and set the PKG_CONFIG variable to dnl first found in the path. Checks that the version of pkg-config found dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is dnl used since that's the first version where most current features of dnl pkg-config existed. AC_DEFUN([PKG_PROG_PKG_CONFIG], [m4_pattern_forbid([^_?PKG_[A-Z_]+$]) m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) fi if test -n "$PKG_CONFIG"; then _pkg_min_version=m4_default([$1], [0.9.0]) AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) PKG_CONFIG="" fi fi[]dnl ])dnl PKG_PROG_PKG_CONFIG dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) dnl ------------------------------------------------------------------- dnl Since: 0.18 dnl dnl Check to see whether a particular set of modules exists. Similar to dnl PKG_CHECK_MODULES(), but does not set variables or print errors. dnl dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) dnl only at the first occurence in configure.ac, so if the first place dnl it's called might be skipped (such as if it is within an "if", you dnl have to call PKG_CHECK_EXISTS manually AC_DEFUN([PKG_CHECK_EXISTS], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl if test -n "$PKG_CONFIG" && \ AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then m4_default([$2], [:]) m4_ifvaln([$3], [else $3])dnl fi]) dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) dnl --------------------------------------------- dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting dnl pkg_failed based on the result. m4_define([_PKG_CONFIG], [if test -n "$$1"; then pkg_cv_[]$1="$$1" elif test -n "$PKG_CONFIG"; then PKG_CHECK_EXISTS([$3], [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes ], [pkg_failed=yes]) else pkg_failed=untried fi[]dnl ])dnl _PKG_CONFIG dnl _PKG_SHORT_ERRORS_SUPPORTED dnl --------------------------- dnl Internal check to see if pkg-config supports short errors. AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], [AC_REQUIRE([PKG_PROG_PKG_CONFIG]) if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi[]dnl ])dnl _PKG_SHORT_ERRORS_SUPPORTED dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], dnl [ACTION-IF-NOT-FOUND]) dnl -------------------------------------------------------------- dnl Since: 0.4.0 dnl dnl Note that if there is a possibility the first call to dnl PKG_CHECK_MODULES might not happen, you should be sure to include an dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac AC_DEFUN([PKG_CHECK_MODULES], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl pkg_failed=no AC_MSG_CHECKING([for $1]) _PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) _PKG_CONFIG([$1][_LIBS], [libs], [$2]) m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS and $1[]_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details.]) if test $pkg_failed = yes; then AC_MSG_RESULT([no]) _PKG_SHORT_ERRORS_SUPPORTED if test $_pkg_short_errors_supported = yes; then $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` else $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD m4_default([$4], [AC_MSG_ERROR( [Package requirements ($2) were not met: $$1_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. _PKG_TEXT])[]dnl ]) elif test $pkg_failed = untried; then AC_MSG_RESULT([no]) m4_default([$4], [AC_MSG_FAILURE( [The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. _PKG_TEXT To get pkg-config, see .])[]dnl ]) else $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS $1[]_LIBS=$pkg_cv_[]$1[]_LIBS AC_MSG_RESULT([yes]) $3 fi[]dnl ])dnl PKG_CHECK_MODULES dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], dnl [ACTION-IF-NOT-FOUND]) dnl --------------------------------------------------------------------- dnl Since: 0.29 dnl dnl Checks for existence of MODULES and gathers its build flags with dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags dnl and VARIABLE-PREFIX_LIBS from --libs. dnl dnl Note that if there is a possibility the first call to dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to dnl include an explicit call to PKG_PROG_PKG_CONFIG in your dnl configure.ac. AC_DEFUN([PKG_CHECK_MODULES_STATIC], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl _save_PKG_CONFIG=$PKG_CONFIG PKG_CONFIG="$PKG_CONFIG --static" PKG_CHECK_MODULES($@) PKG_CONFIG=$_save_PKG_CONFIG[]dnl ])dnl PKG_CHECK_MODULES_STATIC dnl PKG_INSTALLDIR([DIRECTORY]) dnl ------------------------- dnl Since: 0.27 dnl dnl Substitutes the variable pkgconfigdir as the location where a module dnl should install pkg-config .pc files. By default the directory is dnl $libdir/pkgconfig, but the default can be changed by passing dnl DIRECTORY. The user can override through the --with-pkgconfigdir dnl parameter. AC_DEFUN([PKG_INSTALLDIR], [m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) m4_pushdef([pkg_description], [pkg-config installation directory @<:@]pkg_default[@:>@]) AC_ARG_WITH([pkgconfigdir], [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, [with_pkgconfigdir=]pkg_default) AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) m4_popdef([pkg_default]) m4_popdef([pkg_description]) ])dnl PKG_INSTALLDIR dnl PKG_NOARCH_INSTALLDIR([DIRECTORY]) dnl -------------------------------- dnl Since: 0.27 dnl dnl Substitutes the variable noarch_pkgconfigdir as the location where a dnl module should install arch-independent pkg-config .pc files. By dnl default the directory is $datadir/pkgconfig, but the default can be dnl changed by passing DIRECTORY. The user can override through the dnl --with-noarch-pkgconfigdir parameter. AC_DEFUN([PKG_NOARCH_INSTALLDIR], [m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) m4_pushdef([pkg_description], [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) AC_ARG_WITH([noarch-pkgconfigdir], [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, [with_noarch_pkgconfigdir=]pkg_default) AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) m4_popdef([pkg_default]) m4_popdef([pkg_description]) ])dnl PKG_NOARCH_INSTALLDIR dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) dnl ------------------------------------------- dnl Since: 0.28 dnl dnl Retrieves the value of the pkg-config variable for the given module. AC_DEFUN([PKG_CHECK_VAR], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl _PKG_CONFIG([$1], [variable="][$3]["], [$2]) AS_VAR_COPY([$1], [pkg_cv_][$1]) AS_VAR_IF([$1], [""], [$5], [$4])dnl ])dnl PKG_CHECK_VAR # Copyright (C) 2002-2014 Free Software Foundation, Inc. # # This file 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. # AM_AUTOMAKE_VERSION(VERSION) # ---------------------------- # Automake X.Y traces this macro to ensure aclocal.m4 has been # generated from the m4 files accompanying Automake X.Y. # (This private macro should not be called outside this file.) AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version='1.15' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. m4_if([$1], [1.15], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) # _AM_AUTOCONF_VERSION(VERSION) # ----------------------------- # aclocal traces this macro to find the Autoconf version. # This is a private macro too. Using m4_define simplifies # the logic in aclocal, which can simply ignore this definition. m4_define([_AM_AUTOCONF_VERSION], []) # AM_SET_CURRENT_AUTOMAKE_VERSION # ------------------------------- # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], [AM_AUTOMAKE_VERSION([1.15])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) # Copyright (C) 2011-2014 Free Software Foundation, Inc. # # This file 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. # AM_PROG_AR([ACT-IF-FAIL]) # ------------------------- # Try to determine the archiver interface, and trigger the ar-lib wrapper # if it is needed. If the detection of archiver interface fails, run # ACT-IF-FAIL (default is to abort configure with a proper error message). AC_DEFUN([AM_PROG_AR], [AC_BEFORE([$0], [LT_INIT])dnl AC_BEFORE([$0], [AC_PROG_LIBTOOL])dnl AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([ar-lib])dnl AC_CHECK_TOOLS([AR], [ar lib "link -lib"], [false]) : ${AR=ar} AC_CACHE_CHECK([the archiver ($AR) interface], [am_cv_ar_interface], [AC_LANG_PUSH([C]) am_cv_ar_interface=ar AC_COMPILE_IFELSE([AC_LANG_SOURCE([[int some_variable = 0;]])], [am_ar_try='$AR cru libconftest.a conftest.$ac_objext >&AS_MESSAGE_LOG_FD' AC_TRY_EVAL([am_ar_try]) if test "$ac_status" -eq 0; then am_cv_ar_interface=ar else am_ar_try='$AR -NOLOGO -OUT:conftest.lib conftest.$ac_objext >&AS_MESSAGE_LOG_FD' AC_TRY_EVAL([am_ar_try]) if test "$ac_status" -eq 0; then am_cv_ar_interface=lib else am_cv_ar_interface=unknown fi fi rm -f conftest.lib libconftest.a ]) AC_LANG_POP([C])]) case $am_cv_ar_interface in ar) ;; lib) # Microsoft lib, so override with the ar-lib wrapper script. # FIXME: It is wrong to rewrite AR. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__AR in this case, # and then we could set am__AR="$am_aux_dir/ar-lib \$(AR)" or something # similar. AR="$am_aux_dir/ar-lib $AR" ;; unknown) m4_default([$1], [AC_MSG_ERROR([could not determine $AR interface])]) ;; esac AC_SUBST([AR])dnl ]) # AM_AUX_DIR_EXPAND -*- Autoconf -*- # Copyright (C) 2001-2014 Free Software Foundation, Inc. # # This file 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. # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets # $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to # '$srcdir', '$srcdir/..', or '$srcdir/../..'. # # Of course, Automake must honor this variable whenever it calls a # tool from the auxiliary directory. The problem is that $srcdir (and # therefore $ac_aux_dir as well) can be either absolute or relative, # depending on how configure is run. This is pretty annoying, since # it makes $ac_aux_dir quite unusable in subdirectories: in the top # source directory, any form will work fine, but in subdirectories a # relative path needs to be adjusted first. # # $ac_aux_dir/missing # fails when called from a subdirectory if $ac_aux_dir is relative # $top_srcdir/$ac_aux_dir/missing # fails if $ac_aux_dir is absolute, # fails when called from a subdirectory in a VPATH build with # a relative $ac_aux_dir # # The reason of the latter failure is that $top_srcdir and $ac_aux_dir # are both prefixed by $srcdir. In an in-source build this is usually # harmless because $srcdir is '.', but things will broke when you # start a VPATH build or use an absolute $srcdir. # # So we could use something similar to $top_srcdir/$ac_aux_dir/missing, # iff we strip the leading $srcdir from $ac_aux_dir. That would be: # am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` # and then we would define $MISSING as # MISSING="\${SHELL} $am_aux_dir/missing" # This will work as long as MISSING is not called from configure, because # unfortunately $(top_srcdir) has no meaning in configure. # However there are other variables, like CC, which are often used in # configure, and could therefore not use this "fixed" $ac_aux_dir. # # Another solution, used here, is to always expand $ac_aux_dir to an # absolute PATH. The drawback is that using absolute paths prevent a # configured tree to be moved without reconfiguration. AC_DEFUN([AM_AUX_DIR_EXPAND], [AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl # Expand $ac_aux_dir to an absolute path. am_aux_dir=`cd "$ac_aux_dir" && pwd` ]) # AM_CONDITIONAL -*- Autoconf -*- # Copyright (C) 1997-2014 Free Software Foundation, Inc. # # This file 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. # AM_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- # Define a conditional. AC_DEFUN([AM_CONDITIONAL], [AC_PREREQ([2.52])dnl m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl AC_SUBST([$1_TRUE])dnl AC_SUBST([$1_FALSE])dnl _AM_SUBST_NOTMAKE([$1_TRUE])dnl _AM_SUBST_NOTMAKE([$1_FALSE])dnl m4_define([_AM_COND_VALUE_$1], [$2])dnl if $2; then $1_TRUE= $1_FALSE='#' else $1_TRUE='#' $1_FALSE= fi AC_CONFIG_COMMANDS_PRE( [if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then AC_MSG_ERROR([[conditional "$1" was never defined. Usually this means the macro was only invoked conditionally.]]) fi])]) # Copyright (C) 1999-2014 Free Software Foundation, Inc. # # This file 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. # There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be # written in clear, in which case automake, when reading aclocal.m4, # will think it sees a *use*, and therefore will trigger all it's # C support machinery. Also note that it means that autoscan, seeing # CC etc. in the Makefile, will ask for an AC_PROG_CC use... # _AM_DEPENDENCIES(NAME) # ---------------------- # See how the compiler implements dependency checking. # NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC". # We try a few techniques and use that to set a single cache variable. # # We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was # modified to invoke _AM_DEPENDENCIES(CC); we would have a circular # dependency, and given that the user is not expected to run this macro, # just rely on AC_PROG_CC. AC_DEFUN([_AM_DEPENDENCIES], [AC_REQUIRE([AM_SET_DEPDIR])dnl AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl AC_REQUIRE([AM_MAKE_INCLUDE])dnl AC_REQUIRE([AM_DEP_TRACK])dnl m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], [$1], [CXX], [depcc="$CXX" am_compiler_list=], [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], [$1], [UPC], [depcc="$UPC" am_compiler_list=], [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'], [depcc="$$1" am_compiler_list=]) AC_CACHE_CHECK([dependency style of $depcc], [am_cv_$1_dependencies_compiler_type], [if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_$1_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` fi am__universal=false m4_case([$1], [CC], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac], [CXX], [case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac]) for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_$1_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_$1_dependencies_compiler_type=none fi ]) AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) AM_CONDITIONAL([am__fastdep$1], [ test "x$enable_dependency_tracking" != xno \ && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) ]) # AM_SET_DEPDIR # ------------- # Choose a directory name for dependency files. # This macro is AC_REQUIREd in _AM_DEPENDENCIES. AC_DEFUN([AM_SET_DEPDIR], [AC_REQUIRE([AM_SET_LEADING_DOT])dnl AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl ]) # AM_DEP_TRACK # ------------ AC_DEFUN([AM_DEP_TRACK], [AC_ARG_ENABLE([dependency-tracking], [dnl AS_HELP_STRING( [--enable-dependency-tracking], [do not reject slow dependency extractors]) AS_HELP_STRING( [--disable-dependency-tracking], [speeds up one-time build])]) if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) AC_SUBST([AMDEPBACKSLASH])dnl _AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl AC_SUBST([am__nodep])dnl _AM_SUBST_NOTMAKE([am__nodep])dnl ]) # Generate code to set up dependency tracking. -*- Autoconf -*- # Copyright (C) 1999-2014 Free Software Foundation, Inc. # # This file 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. # _AM_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], [{ # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named 'Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`AS_DIRNAME("$mf")` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running 'make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "$am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`AS_DIRNAME(["$file"])` AS_MKDIR_P([$dirpart/$fdir]) # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ])# _AM_OUTPUT_DEPENDENCY_COMMANDS # AM_OUTPUT_DEPENDENCY_COMMANDS # ----------------------------- # This macro should only be invoked once -- use via AC_REQUIRE. # # This code is only required when automatic dependency tracking # is enabled. FIXME. This creates each '.P' file that we will # need in order to bootstrap the dependency handling code. AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AC_CONFIG_COMMANDS([depfiles], [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) ]) # Do all the work for Automake. -*- Autoconf -*- # Copyright (C) 1996-2014 Free Software Foundation, Inc. # # This file 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 macro actually does too much. Some checks are only needed if # your package does certain things. But this isn't really a big deal. dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O. m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC]) [_AM_PROG_CC_C_O ]) # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) # AM_INIT_AUTOMAKE([OPTIONS]) # ----------------------------------------------- # The call with PACKAGE and VERSION arguments is the old style # call (pre autoconf-2.50), which is being phased out. PACKAGE # and VERSION should now be passed to AC_INIT and removed from # the call to AM_INIT_AUTOMAKE. # We support both call styles for the transition. After # the next Automake release, Autoconf can make the AC_INIT # arguments mandatory, and then we can depend on a new Autoconf # release and drop the old call support. AC_DEFUN([AM_INIT_AUTOMAKE], [AC_PREREQ([2.65])dnl dnl Autoconf wants to disallow AM_ names. We explicitly allow dnl the ones we care about. m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl AC_REQUIRE([AC_PROG_INSTALL])dnl if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl # test to see if srcdir already configured if test -f $srcdir/config.status; then AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi AC_SUBST([CYGPATH_W]) # Define the identity of the package. dnl Distinguish between old-style and new-style calls. m4_ifval([$2], [AC_DIAGNOSE([obsolete], [$0: two- and three-arguments forms are deprecated.]) m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl AC_SUBST([PACKAGE], [$1])dnl AC_SUBST([VERSION], [$2])], [_AM_SET_OPTIONS([$1])dnl dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. m4_if( m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]), [ok:ok],, [m4_fatal([AC_INIT should be called with package and version arguments])])dnl AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl _AM_IF_OPTION([no-define],, [AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl # Some tools Automake needs. AC_REQUIRE([AM_SANITY_CHECK])dnl AC_REQUIRE([AC_ARG_PROGRAM])dnl AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) AM_MISSING_PROG([AUTOCONF], [autoconf]) AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) AM_MISSING_PROG([AUTOHEADER], [autoheader]) AM_MISSING_PROG([MAKEINFO], [makeinfo]) AC_REQUIRE([AM_PROG_INSTALL_SH])dnl AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl AC_REQUIRE([AC_PROG_MKDIR_P])dnl # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # AC_SUBST([mkdir_p], ['$(MKDIR_P)']) # We need awk for the "check" target (and possibly the TAP driver). The # system "awk" is bad on some platforms. AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AM_SET_LEADING_DOT])dnl _AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], [_AM_PROG_TAR([v7])])]) _AM_IF_OPTION([no-dependencies],, [AC_PROVIDE_IFELSE([AC_PROG_CC], [_AM_DEPENDENCIES([CC])], [m4_define([AC_PROG_CC], m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_CXX], [_AM_DEPENDENCIES([CXX])], [m4_define([AC_PROG_CXX], m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJC], [_AM_DEPENDENCIES([OBJC])], [m4_define([AC_PROG_OBJC], m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], [_AM_DEPENDENCIES([OBJCXX])], [m4_define([AC_PROG_OBJCXX], m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl ]) AC_REQUIRE([AM_SILENT_RULES])dnl dnl The testsuite driver may need to know about EXEEXT, so add the dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below. AC_CONFIG_COMMANDS_PRE(dnl [m4_provide_if([_AM_COMPILER_EXEEXT], [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl # POSIX will say in a future version that running "rm -f" with no argument # is OK; and we want to be able to make that assumption in our Makefile # recipes. So use an aggressive probe to check that the usage we want is # actually supported "in the wild" to an acceptable degree. # See automake bug#10828. # To make any issue more visible, cause the running configure to be aborted # by default if the 'rm' program in use doesn't match our expectations; the # user can still override this though. if rm -f && rm -fr && rm -rf; then : OK; else cat >&2 <<'END' Oops! Your 'rm' program seems unable to run without file operands specified on the command line, even when the '-f' option is present. This is contrary to the behaviour of most rm programs out there, and not conforming with the upcoming POSIX standard: Please tell bug-automake@gnu.org about your system, including the value of your $PATH and any error possibly output before this message. This can help us improve future automake versions. END if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then echo 'Configuration will proceed anyway, since you have set the' >&2 echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 echo >&2 else cat >&2 <<'END' Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation that behaves properly: . If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM to "yes", and re-run configure. END AC_MSG_ERROR([Your 'rm' program is bad, sorry.]) fi fi dnl The trailing newline in this macro's definition is deliberate, for dnl backward compatibility and to allow trailing 'dnl'-style comments dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841. ]) dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further dnl mangled by Autoconf and run in a shell conditional statement. m4_define([_AC_COMPILER_EXEEXT], m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) # When config.status generates a header, we must update the stamp-h file. # This file resides in the same directory as the config header # that is generated. The stamp files are numbered to have different names. # Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the # loop where config.status creates the headers, so we can generate # our stamp files there. AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], [# Compute $1's index in $config_headers. _am_arg=$1 _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) # Copyright (C) 2001-2014 Free Software Foundation, Inc. # # This file 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. # AM_PROG_INSTALL_SH # ------------------ # Define $install_sh. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl if test x"${install_sh+set}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi AC_SUBST([install_sh])]) # Copyright (C) 2003-2014 Free Software Foundation, Inc. # # This file 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. # Check whether the underlying file-system supports filenames # with a leading dot. For instance MS-DOS doesn't. AC_DEFUN([AM_SET_LEADING_DOT], [rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null AC_SUBST([am__leading_dot])]) # Add --enable-maintainer-mode option to configure. -*- Autoconf -*- # From Jim Meyering # Copyright (C) 1996-2014 Free Software Foundation, Inc. # # This file 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. # AM_MAINTAINER_MODE([DEFAULT-MODE]) # ---------------------------------- # Control maintainer-specific portions of Makefiles. # Default is to disable them, unless 'enable' is passed literally. # For symmetry, 'disable' may be passed as well. Anyway, the user # can override the default with the --enable/--disable switch. AC_DEFUN([AM_MAINTAINER_MODE], [m4_case(m4_default([$1], [disable]), [enable], [m4_define([am_maintainer_other], [disable])], [disable], [m4_define([am_maintainer_other], [enable])], [m4_define([am_maintainer_other], [enable]) m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])]) AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles]) dnl maintainer-mode's default is 'disable' unless 'enable' is passed AC_ARG_ENABLE([maintainer-mode], [AS_HELP_STRING([--]am_maintainer_other[-maintainer-mode], am_maintainer_other[ make rules and dependencies not useful (and sometimes confusing) to the casual installer])], [USE_MAINTAINER_MODE=$enableval], [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes])) AC_MSG_RESULT([$USE_MAINTAINER_MODE]) AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes]) MAINT=$MAINTAINER_MODE_TRUE AC_SUBST([MAINT])dnl ] ) # Check to see how 'make' treats includes. -*- Autoconf -*- # Copyright (C) 2001-2014 Free Software Foundation, Inc. # # This file 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. # AM_MAKE_INCLUDE() # ----------------- # Check to see how make treats includes. AC_DEFUN([AM_MAKE_INCLUDE], [am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. AC_MSG_CHECKING([for style of include used by $am_make]) am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # Ignore all kinds of additional output from 'make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi AC_SUBST([am__include]) AC_SUBST([am__quote]) AC_MSG_RESULT([$_am_result]) rm -f confinc confmf ]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- # Copyright (C) 1997-2014 Free Software Foundation, Inc. # # This file 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. # AM_MISSING_PROG(NAME, PROGRAM) # ------------------------------ AC_DEFUN([AM_MISSING_PROG], [AC_REQUIRE([AM_MISSING_HAS_RUN]) $1=${$1-"${am_missing_run}$2"} AC_SUBST($1)]) # AM_MISSING_HAS_RUN # ------------------ # Define MISSING if not defined so far and test if it is modern enough. # If it is, set am_missing_run to use it, otherwise, to nothing. AC_DEFUN([AM_MISSING_HAS_RUN], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([missing])dnl if test x"${MISSING+set}" != xset; then case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --is-lightweight"; then am_missing_run="$MISSING " else am_missing_run= AC_MSG_WARN(['missing' script is too old or missing]) fi ]) # Helper functions for option handling. -*- Autoconf -*- # Copyright (C) 2001-2014 Free Software Foundation, Inc. # # This file 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. # _AM_MANGLE_OPTION(NAME) # ----------------------- AC_DEFUN([_AM_MANGLE_OPTION], [[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) # _AM_SET_OPTION(NAME) # -------------------- # Set option NAME. Presently that only means defining a flag for this option. AC_DEFUN([_AM_SET_OPTION], [m4_define(_AM_MANGLE_OPTION([$1]), [1])]) # _AM_SET_OPTIONS(OPTIONS) # ------------------------ # OPTIONS is a space-separated list of Automake options. AC_DEFUN([_AM_SET_OPTIONS], [m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) # _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) # ------------------------------------------- # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) # Copyright (C) 1999-2014 Free Software Foundation, Inc. # # This file 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. # _AM_PROG_CC_C_O # --------------- # Like AC_PROG_CC_C_O, but changed for automake. We rewrite AC_PROG_CC # to automatically call this. AC_DEFUN([_AM_PROG_CC_C_O], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([compile])dnl AC_LANG_PUSH([C])dnl AC_CACHE_CHECK( [whether $CC understands -c and -o together], [am_cv_prog_cc_c_o], [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])]) # Make sure it works both with $CC and with simple cc. # Following AC_PROG_CC_C_O, we do the test twice because some # compilers refuse to overwrite an existing .o file with -o, # though they will create one. am_cv_prog_cc_c_o=yes for am_i in 1 2; do if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \ && test -f conftest2.$ac_objext; then : OK else am_cv_prog_cc_c_o=no break fi done rm -f core conftest* unset am_i]) if test "$am_cv_prog_cc_c_o" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi AC_LANG_POP([C])]) # For backward compatibility. AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) # Copyright (C) 2001-2014 Free Software Foundation, Inc. # # This file 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. # AM_RUN_LOG(COMMAND) # ------------------- # Run COMMAND, save the exit status in ac_status, and log it. # (This has been adapted from Autoconf's _AC_RUN_LOG macro.) AC_DEFUN([AM_RUN_LOG], [{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD (exit $ac_status); }]) # Check to make sure that the build environment is sane. -*- Autoconf -*- # Copyright (C) 1996-2014 Free Software Foundation, Inc. # # This file 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. # AM_SANITY_CHECK # --------------- AC_DEFUN([AM_SANITY_CHECK], [AC_MSG_CHECKING([whether build environment is sane]) # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[[\\\"\#\$\&\'\`$am_lf]]*) AC_MSG_ERROR([unsafe absolute working directory name]);; esac case $srcdir in *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; esac # Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$[*]" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$[*]" != "X $srcdir/configure conftest.file" \ && test "$[*]" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken alias in your environment]) fi if test "$[2]" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$[2]" = conftest.file ) then # Ok. : else AC_MSG_ERROR([newly created file is older than distributed files! Check your system clock]) fi AC_MSG_RESULT([yes]) # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi AC_CONFIG_COMMANDS_PRE( [AC_MSG_CHECKING([that generated files are newer than configure]) if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi AC_MSG_RESULT([done])]) rm -f conftest.file ]) # Copyright (C) 2009-2014 Free Software Foundation, Inc. # # This file 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. # AM_SILENT_RULES([DEFAULT]) # -------------------------- # Enable less verbose build rules; with the default set to DEFAULT # ("yes" being less verbose, "no" or empty being verbose). AC_DEFUN([AM_SILENT_RULES], [AC_ARG_ENABLE([silent-rules], [dnl AS_HELP_STRING( [--enable-silent-rules], [less verbose build output (undo: "make V=1")]) AS_HELP_STRING( [--disable-silent-rules], [verbose build output (undo: "make V=0")])dnl ]) case $enable_silent_rules in @%:@ ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; esac dnl dnl A few 'make' implementations (e.g., NonStop OS and NextStep) dnl do not support nested variable expansions. dnl See automake bug#9928 and bug#10237. am_make=${MAKE-make} AC_CACHE_CHECK([whether $am_make supports nested variables], [am_cv_make_support_nested_variables], [if AS_ECHO([['TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi]) if test $am_cv_make_support_nested_variables = yes; then dnl Using '$V' instead of '$(V)' breaks IRIX make. AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AC_SUBST([AM_V])dnl AM_SUBST_NOTMAKE([AM_V])dnl AC_SUBST([AM_DEFAULT_V])dnl AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl AC_SUBST([AM_DEFAULT_VERBOSITY])dnl AM_BACKSLASH='\' AC_SUBST([AM_BACKSLASH])dnl _AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl ]) # Copyright (C) 2001-2014 Free Software Foundation, Inc. # # This file 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. # AM_PROG_INSTALL_STRIP # --------------------- # One issue with vendor 'install' (even GNU) is that you can't # specify the program used to strip binaries. This is especially # annoying in cross-compiling environments, where the build's strip # is unlikely to handle the host's binaries. # Fortunately install-sh will honor a STRIPPROG variable, so we # always use install-sh in "make install-strip", and initialize # STRIPPROG with the value of the STRIP variable (set by the user). AC_DEFUN([AM_PROG_INSTALL_STRIP], [AC_REQUIRE([AM_PROG_INSTALL_SH])dnl # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. if test "$cross_compiling" != no; then AC_CHECK_TOOL([STRIP], [strip], :) fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) # Copyright (C) 2006-2014 Free Software Foundation, Inc. # # This file 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. # _AM_SUBST_NOTMAKE(VARIABLE) # --------------------------- # Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. # This macro is traced by Automake. AC_DEFUN([_AM_SUBST_NOTMAKE]) # AM_SUBST_NOTMAKE(VARIABLE) # -------------------------- # Public sister of _AM_SUBST_NOTMAKE. AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) # Check how to create a tarball. -*- Autoconf -*- # Copyright (C) 2004-2014 Free Software Foundation, Inc. # # This file 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. # _AM_PROG_TAR(FORMAT) # -------------------- # Check how to create a tarball in format FORMAT. # FORMAT should be one of 'v7', 'ustar', or 'pax'. # # Substitute a variable $(am__tar) that is a command # writing to stdout a FORMAT-tarball containing the directory # $tardir. # tardir=directory && $(am__tar) > result.tar # # Substitute a variable $(am__untar) that extract such # a tarball read from stdin. # $(am__untar) < result.tar # AC_DEFUN([_AM_PROG_TAR], [# Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AC_SUBST([AMTAR], ['$${TAR-tar}']) # We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' m4_if([$1], [v7], [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], [m4_case([$1], [ustar], [# The POSIX 1988 'ustar' format is defined with fixed-size fields. # There is notably a 21 bits limit for the UID and the GID. In fact, # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 # and bug#13588). am_max_uid=2097151 # 2^21 - 1 am_max_gid=$am_max_uid # The $UID and $GID variables are not portable, so we need to resort # to the POSIX-mandated id(1) utility. Errors in the 'id' calls # below are definitely unexpected, so allow the users to see them # (that is, avoid stderr redirection). am_uid=`id -u || echo unknown` am_gid=`id -g || echo unknown` AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) if test $am_uid -le $am_max_uid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) if test $am_gid -le $am_max_gid; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) _am_tools=none fi], [pax], [], [m4_fatal([Unknown tar format])]) AC_MSG_CHECKING([how to create a $1 tar archive]) # Go ahead even if we have the value already cached. We do so because we # need to set the values for the 'am__tar' and 'am__untar' variables. _am_tools=${am_cv_prog_tar_$1-$_am_tools} for _am_tool in $_am_tools; do case $_am_tool in gnutar) for _am_tar in tar gnutar gtar; do AM_RUN_LOG([$_am_tar --version]) && break done am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' am__untar="$_am_tar -xf -" ;; plaintar) # Must skip GNU tar: if it does not support --format= it doesn't create # ustar tarball either. (tar --version) >/dev/null 2>&1 && continue am__tar='tar chf - "$$tardir"' am__tar_='tar chf - "$tardir"' am__untar='tar xf -' ;; pax) am__tar='pax -L -x $1 -w "$$tardir"' am__tar_='pax -L -x $1 -w "$tardir"' am__untar='pax -r' ;; cpio) am__tar='find "$$tardir" -print | cpio -o -H $1 -L' am__tar_='find "$tardir" -print | cpio -o -H $1 -L' am__untar='cpio -i -H $1 -d' ;; none) am__tar=false am__tar_=false am__untar=false ;; esac # If the value was cached, stop now. We just wanted to have am__tar # and am__untar set. test -n "${am_cv_prog_tar_$1}" && break # tar/untar a dummy directory, and stop if the command works. rm -rf conftest.dir mkdir conftest.dir echo GrepMe > conftest.dir/file AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) rm -rf conftest.dir if test -s conftest.tar; then AM_RUN_LOG([$am__untar /dev/null 2>&1 && break fi done rm -rf conftest.dir AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) AC_MSG_RESULT([$am_cv_prog_tar_$1])]) AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR m4_include([m4/gtk-doc.m4]) m4_include([m4/libtool.m4]) m4_include([m4/ltoptions.m4]) m4_include([m4/ltsugar.m4]) m4_include([m4/ltversion.m4]) m4_include([m4/lt~obsolete.m4]) libinfinity-0.7.1/PaxHeaders.26529/po0000644000000000000000000000013213055210765014150 xustar0030 mtime=1488261621.324067277 30 atime=1488261621.184067593 30 ctime=1488261621.324067277 libinfinity-0.7.1/po/0000755000175000017500000000000013055210765014757 5ustar00arminarmin00000000000000libinfinity-0.7.1/po/PaxHeaders.26529/ca.gmo0000644000000000000000000000013213034545201015305 xustar0030 mtime=1483917953.495214847 30 atime=1483917953.495214847 30 ctime=1488261621.324067277 libinfinity-0.7.1/po/ca.gmo0000644000175000017500000000307013034545201016037 0ustar00arminarmin00000000000000Þ•¼\ÐÑ ã í û  ? ^ k u € Žœ±¶»ÊÛäëöâ ø  " /T9 Ž ˜ ¢ ¬¹ÈÞãéü   Certificate ChainConnectedConnecting...DIRECTORYDisconnectedExpires On:Failed to auto-save session "%s": %s Will retry in %u seconds.FingerprintsIssued ByIssued On:Not connectedOrganization:Organizational Unit:PORTSendSerial Number:Synchronizing...Validity_View CertificateProject-Id-Version: libinfinity Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=glib&keywords=I18N+L10N&component=general POT-Creation-Date: 2017-01-08 15:20-0800 PO-Revision-Date: 2009-12-10 07:26+0000 Last-Translator: David Planella Language-Team: Catalan Language: ca MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Launchpad-Export-Date: 2009-12-19 18:32+0000 X-Generator: Launchpad (build Unknown) Cadena de certificatsConnectatS'està connectant...DIRECTORIDesconnectatVenç el:Ha fallat el desament de la sessió «%s»: %s Es tornarà a intentar en %u segons.EmpremtesEmès perEmès el:No connectatOrganització:Unitat organitzativa:PORTEnviaNúmero de sèrie:S'està sincronitzant...Validesa_Visualitza el certificatlibinfinity-0.7.1/po/PaxHeaders.26529/de.po0000644000000000000000000000013213034544707015160 xustar0030 mtime=1483917767.602911315 30 atime=1483917767.602911315 30 ctime=1488261621.324067277 libinfinity-0.7.1/po/de.po0000644000175000017500000024034013034544707015715 0ustar00arminarmin00000000000000# German translation for libinfinity # Copyright (c) 2009 Rosetta Contributors and Canonical Ltd 2009 # This file is distributed under the same license as the libinfinity package. # FIRST AUTHOR , 2009. # msgid "" msgstr "" "Project-Id-Version: libinfinity\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=glib&keywords=I18N+L10N&component=general\n" "POT-Creation-Date: 2017-01-08 15:20-0800\n" "PO-Revision-Date: 2009-11-28 11:36+0000\n" "Last-Translator: Armin Burgmeier \n" "Language-Team: German \n" "Language: de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Launchpad-Export-Date: 2009-12-19 18:32+0000\n" "X-Generator: Launchpad (build Unknown)\n" #: ../infinoted/infinoted-config-reload.c:122 #, c-format msgid "Changing the listen address at runtime is not supported" msgstr "" #: ../infinoted/infinoted-config-reload.c:439 #, c-format msgid "Failed to re-load plugins: %s" msgstr "" #: ../infinoted/infinoted-config-reload.c:445 msgid "" "Plugins are disabled. Please fix the problem and reload configuration again." msgstr "" #: ../infinoted/infinoted-dh-params.c:83 msgid "Generating 2048 bit Diffie-Hellman parameters..." msgstr "Erzeuge 2048-bit Diffie-Hellman-Parameter…" #. Translators: fork as in "fork into the background" #: ../infinoted/infinoted-main.c:77 msgid "Failed to fork" msgstr "" #: ../infinoted/infinoted-main.c:93 msgid "Failed to wait for daemonized child's return value" msgstr "" #: ../infinoted/infinoted-main.c:102 ../infinoted/infinoted-main.c:120 msgid "Failed to create PID file" msgstr "" #: ../infinoted/infinoted-options.c:48 msgid "If set, write the server log to the given file, in addition to stdout" msgstr "" #: ../infinoted/infinoted-options.c:50 #, fuzzy msgid "LOG-FILE" msgstr "SCHLÜSSELDATEI" #: ../infinoted/infinoted-options.c:58 msgid "" "Path to the server's private key. Must be the key with which the given " "certificate was signed. Not needed when security-policy is set to \"no-tls\"." msgstr "" #: ../infinoted/infinoted-options.c:61 msgid "KEY-FILE" msgstr "SCHLÜSSELDATEI" #: ../infinoted/infinoted-options.c:69 msgid "" "Path to the server's certificate. Must be signed with the given key file. " "Not needed when security-policy is set to \"no-tls\"." msgstr "" #: ../infinoted/infinoted-options.c:71 ../infinoted/infinoted-options.c:85 #, fuzzy msgid "CERT-FILE" msgstr "ZERTIFIKATSDATEI" #: ../infinoted/infinoted-options.c:79 msgid "" "Optional file which contains the issuer certificate of the server " "certificate, and the issuer's issuer, and so on. This option can be used " "when the issuer certificates are not stored in the same file as the server " "certificate. If the issuer certificates are not available the server will " "still run, but not show the issuer certificates to connecting clients." msgstr "" #: ../infinoted/infinoted-options.c:93 msgid "The TCP port number to listen on." msgstr "" #: ../infinoted/infinoted-options.c:94 msgid "PORT" msgstr "PORT" #: ../infinoted/infinoted-options.c:102 msgid "The IP address to listen on." msgstr "" #: ../infinoted/infinoted-options.c:103 msgid "ADDRESS" msgstr "" #: ../infinoted/infinoted-options.c:111 msgid "" "Whether to use Transport Layer Security (TLS) or not. Allowed values are " "\"no-tls\", \"allow-tls\" or \"require-tls\". When TLS is allowed or " "required, a server certificate must be provided. Infinoted has a built-in " "option to create a self-signed certificate with the --create-key and --" "create-certificate command line options. When TLS is allowed but not " "required, clients may choose not to use TLS. It is strongly encouraged to " "always require TLS. [Default=require-tls]" msgstr "" #: ../infinoted/infinoted-options.c:119 msgid "no-tls|allow-tls|require-tls" msgstr "" #: ../infinoted/infinoted-options.c:127 msgid "" "The directory which infinoted uses to permanantly store all documents on the " "server, and where they are read from after a server restart. [Default=~/." "infinote]" msgstr "" #: ../infinoted/infinoted-options.c:130 #: ../infinoted/plugins/infinoted-plugin-directory-sync.c:603 #: ../infinoted/plugins/infinoted-plugin-traffic-logging.c:326 msgid "DIRECTORY" msgstr "VERZEICHNIS" #: ../infinoted/infinoted-options.c:138 msgid "" "Additional plugins to load. This option can be specified more than once to " "load multiple plugins. Plugin options can be configured in the configuration " "file (one section for each plugin), or with the --plugin-parameter option. " "[Default=note-text]" msgstr "" #: ../infinoted/infinoted-options.c:142 msgid "PLUGIN-NAME" msgstr "" #: ../infinoted/infinoted-options.c:150 msgid "" "If set, require clients to enter a password before being allowed to connect " "to the server. This option cannot be combined with --pam-service." msgstr "" #: ../infinoted/infinoted-options.c:153 msgid "Password" msgstr "" #: ../infinoted/infinoted-options.c:162 msgid "" "Authenticate clients using the given PAM service. This option cannot be " "combined with --password. Clients are requested to send their user name and " "then enter the password for their account on the server machine with the " "same name." msgstr "" #: ../infinoted/infinoted-options.c:166 msgid "SERVICE" msgstr "" #: ../infinoted/infinoted-options.c:174 msgid "" "If set, only the given username is allowed to connect to the server. This " "option can be given multiple times to allow multiple users." msgstr "" #: ../infinoted/infinoted-options.c:177 msgid "USER" msgstr "" #: ../infinoted/infinoted-options.c:185 msgid "" "If set, only users belonging to the given group are allowed to connect to " "the server. This option can be given multiple times to allow multiple groups." msgstr "" #: ../infinoted/infinoted-options.c:188 msgid "GROUPS" msgstr "" #: ../infinoted/infinoted-options.c:215 msgid "Cannot use both server password and system authentication." msgstr "" #: ../infinoted/infinoted-options.c:228 msgid "Need a pam service to authenticate users." msgstr "" #: ../infinoted/infinoted-options.c:248 msgid "WARNING: Requiring password through unencrypted connection." msgstr "" #: ../infinoted/infinoted-options.c:258 msgid "" "Creating a new private key also requires creating a new certificate signed " "with it." msgstr "" "Einen neuen privaten Schlüssel zu erstellen erfordert auch ein zugehöriges " "Zertifikat zu erstellen das damit signiert ist." #: ../infinoted/infinoted-options.c:271 msgid "" "No private key file given. If you don't have a suitable key file, either " "create one using the --create-key command line argument, or disable TLS by " "setting the security policy to \"no-tls\"." msgstr "" "Es wurde keine private Schlüsseldatei angegeben. Wenn keine passende Datei " "vorliegt können Sie entweder eine mit dem Kommandozeilen-Argument --create-" "key erstellen oder TLS durch Setzen der Sicherheitsrichtlinie auf »no-tls« " "deaktivieren." #: ../infinoted/infinoted-options.c:285 msgid "" "No certificate file given. If you don't have a suitable certificate file, " "either create one using the --create-certificate command line agument, or " "disable TLS via by setting the security policy to \"no-tls\"." msgstr "" "Keine Zertifikatsdatei angegeben. Wenn keine passende Datei vorliegt können " "Sie entweder eine mit dem Kommandozeilen-Argument --create-certificate " "erstellen oder TLS durch Setzen der Sicherheitsrichtlinie auf »no-tls« " "deaktivieren." #: ../infinoted/infinoted-options.c:329 #, c-format msgid "Error reading configuration file \"%s\": " msgstr "" #: ../infinoted/infinoted-options.c:387 ../infinoted/infinoted-options.c:431 #: ../infinoted/infinoted-options.c:505 #, c-format msgid "The option \"%s\" can only be given once" msgstr "" #: ../infinoted/infinoted-options.c:416 #, c-format msgid "\"%s\" cannot be interpreted as a boolean value" msgstr "" #: ../infinoted/infinoted-options.c:446 #, c-format msgid "\"%s\" is not a number" msgstr "" #: ../infinoted/infinoted-options.c:458 #, fuzzy, c-format msgid "Could not read the number \"%s\": %s" msgstr "Das Verzeichnis »%s« konnte nicht erstellt werden: %s" #: ../infinoted/infinoted-options.c:471 #, c-format msgid "Number \"%s\" is too small" msgstr "" #: ../infinoted/infinoted-options.c:483 #, c-format msgid "Number \"%s\" is too large" msgstr "" #: ../infinoted/infinoted-options.c:693 msgid "Configuration file to load, instead of the default configuration file" msgstr "" #: ../infinoted/infinoted-options.c:695 msgid "CONFIG-FILE" msgstr "" #: ../infinoted/infinoted-options.c:699 msgid "" "Creates a new random private key. The new key will be stored at the given " "location for the server's private key." msgstr "" #: ../infinoted/infinoted-options.c:705 msgid "" "Creates a new self-signed certificate signed with the given private key. The " "certificate is stored at the given location for the server's certificate." msgstr "" #: ../infinoted/infinoted-options.c:712 msgid "" "Allows one to override configuration entries for plugins from the command " "line. The syntax is --plugin-parameter=plugin:key:value, where plugin is the " "name of the plugin for which to override a configuration parameter, key is " "the parameter which to override and value is the new value of the parameter" msgstr "" #: ../infinoted/infinoted-options.c:717 msgid "PLUGIN:PARAMETER:VALUE" msgstr "" #: ../infinoted/infinoted-options.c:722 msgid "Daemonize the server, i.e. run it in the background" msgstr "" #: ../infinoted/infinoted-options.c:726 msgid "Kill a running daemon and exit" msgstr "" #: ../infinoted/infinoted-options.c:731 msgid "Display version information and exit" msgstr "" #: ../infinoted/infinoted-options.c:790 msgid "Infinoted Options" msgstr "" #: ../infinoted/infinoted-options.c:791 msgid "Main Program Options" msgstr "" #: ../infinoted/infinoted-options.c:800 msgid "infinote dedicated server" msgstr "" #: ../infinoted/infinoted-options.c:835 msgid "Could not kill daemon" msgstr "" #: ../infinoted/infinoted-pam.c:100 msgid "Entry not found" msgstr "" #: ../infinoted/infinoted-pam.c:106 #, fuzzy, c-format msgid "Error while checking groups of user \"%s\", %s: %s." msgstr "Fehler beim Speichern der Aufnahme für die Sitzung »%s« nach »%s«: %s" #: ../infinoted/infinoted-pam.c:144 msgid "looking up user information" msgstr "" #: ../infinoted/infinoted-pam.c:155 #, c-format msgid "looking up group %ld" msgstr "" #: ../infinoted/infinoted-pam.c:170 #, c-format msgid "looking up group \"%s\"" msgstr "" #: ../infinoted/infinoted-parameter.c:145 #, c-format msgid "The parameter \"%s\" is required" msgstr "" #: ../infinoted/infinoted-parameter.c:514 #, c-format msgid "\"%d\" is not a valid port number. Port numbers range from 1 to 65535" msgstr "" "»%d« ist keine gültige Portnummer. Gültige Portnummern liegen zwischen 1 und " "65535" #: ../infinoted/infinoted-parameter.c:562 msgid "Invalid IP address" msgstr "" #: ../infinoted/infinoted-parameter.c:601 msgid "Number must not be negative" msgstr "" #: ../infinoted/infinoted-parameter.c:640 msgid "Number must be positive" msgstr "" #: ../infinoted/infinoted-parameter.c:697 #, c-format msgid "" "\"%s\" is not a valid security policy. Allowed values are \"no-tls\", " "\"allow-tls\" or \"require-tls\"" msgstr "" "»%s« ist keine gültige Sicherheitsrichtlinie. Mögliche Werte sind »no-tls«, " "»allow-tls« oder »require-tls«" #: ../infinoted/infinoted-parameter.c:769 #, c-format msgid "\"%s\" is not a valid value. Allowed values are: %s." msgstr "" #: ../infinoted/infinoted-plugin-manager.c:490 #, fuzzy, c-format msgid "Loaded plugin \"%s\" from \"%s\"" msgstr "Erweiterung »%s« (%s) geladen" #: ../infinoted/infinoted-plugin-manager.c:534 #, fuzzy, c-format msgid "Unloaded plugin \"%s\" from \"%s\"" msgstr "Erweiterung »%s« (%s) geladen" #: ../infinoted/infinoted-run.c:394 #, c-format msgid "Failed to generate Diffie-Hellman parameters: %s" msgstr "" #: ../infinoted/infinoted-run.c:414 #, c-format msgid "IPv6 Server running on port %u" msgstr "Der IPv6-Server läuft auf dem Port %u" #: ../infinoted/infinoted-run.c:437 #, c-format msgid "IPv4 Server running on port %u" msgstr "Der IPv4-Server läuft auf dem Port %u" #: ../infinoted/infinoted-run.c:458 #, c-format msgid "Failed to start server: %s" msgstr "" #: ../infinoted/infinoted-run.c:476 msgid "Infinoted shutting down..." msgstr "" #: ../infinoted/infinoted-signal.c:58 msgid "" "Error on signal handler connection; signal handlers have been removed from " "now on" msgstr "" #: ../infinoted/infinoted-signal.c:77 #, c-format msgid "Configuration reload failed: %s" msgstr "" #: ../infinoted/infinoted-signal.c:86 msgid "Configuration reloaded" msgstr "" #: ../infinoted/infinoted-signal.c:146 msgid "" "For config reloading to work libinfinity needs to be compiled with libdaemon " "support" msgstr "" #. TODO: Open the key file beforehand #: ../infinoted/infinoted-startup.c:62 #, fuzzy msgid "Generating 4096 bit RSA private key..." msgstr "Erzeuge einen 2048-bit starken privaten RSA-Schlüssel…" #: ../infinoted/infinoted-startup.c:104 msgid "Generating self-signed certificate..." msgstr "Erzeuge ein selbstsigniertes Zertifikat…" #: ../infinoted/infinoted-startup.c:321 #, c-format msgid "User %s failed to log in from %s: PAM authentication failed" msgstr "" #: ../infinoted/infinoted-startup.c:341 #, c-format msgid "User %s failed to log in from %s: PAM user not allowed" msgstr "" #: ../infinoted/infinoted-startup.c:361 #, c-format msgid "User %s logged in from %s via PAM" msgstr "" #: ../infinoted/infinoted-startup.c:392 #, c-format msgid "User %s logged in from %s via password" msgstr "" #: ../infinoted/infinoted-startup.c:403 #, c-format msgid "User %s failed to log in from %s: wrong password" msgstr "" #: ../infinoted/plugins/infinoted-plugin-autosave.c:151 #, c-format msgid "" "Failed to auto-save session \"%s\": %s\n" "\n" "Will retry in %u seconds." msgstr "" "Die Sitzung »%s« konnte nicht automatisch gespeichert werden: %s\n" "\n" "In %u Sekunden wird ein erneuter Versuch unternommen." #: ../infinoted/plugins/infinoted-plugin-autosave.c:191 #, fuzzy, c-format msgid "Could not execute autosave hook: \"%s\"" msgstr "Das Verzeichnis »%s« konnte nicht erstellt werden: %s" #: ../infinoted/plugins/infinoted-plugin-autosave.c:328 msgid "" "Interval, in seconds, after which to save documents into the root directory. " "Documents are also stored to disk when there has been no user logged into " "them for 60 seconds." msgstr "" #: ../infinoted/plugins/infinoted-plugin-autosave.c:331 #: ../infinoted/plugins/infinoted-plugin-directory-sync.c:613 msgid "SECONDS" msgstr "" #: ../infinoted/plugins/infinoted-plugin-autosave.c:339 #: ../infinoted/plugins/infinoted-plugin-directory-sync.c:621 msgid "Command to run after having saved a document." msgstr "" #: ../infinoted/plugins/infinoted-plugin-autosave.c:340 #: ../infinoted/plugins/infinoted-plugin-directory-sync.c:622 msgid "PROGRAM" msgstr "" #: ../infinoted/plugins/infinoted-plugin-autosave.c:352 msgid "" "Periodically saves the content of all documents to disk. If this plugin is " "not enabled, infinoted only moves a document to permanent storage 60 seconds " "after the last user left the document." msgstr "" #: ../infinoted/plugins/infinoted-plugin-certificate-auth.c:77 #, c-format msgid "Failed to set permissions for super user: %s" msgstr "" #: ../infinoted/plugins/infinoted-plugin-certificate-auth.c:97 #, c-format msgid "" "Failed to remove super user on server shutdown. This should not be a problem " "since the account is not made persistent, however might point to an " "inconsistency in the server setup. The error message was: %s" msgstr "" #: ../infinoted/plugins/infinoted-plugin-certificate-auth.c:226 msgid "" "The certificate-auth plugin can only be used when TLS is enabled and a " "server certificate has been set." msgstr "" #: ../infinoted/plugins/infinoted-plugin-certificate-auth.c:243 #, c-format msgid "File \"%s\" does not contain any CA certificates" msgstr "" #: ../infinoted/plugins/infinoted-plugin-certificate-auth.c:288 msgid "The given CA key does not match with any of the CA certificates" msgstr "" #: ../infinoted/plugins/infinoted-plugin-certificate-auth.c:321 msgid "Cannot generate a superuser certificate without CA key" msgstr "" #: ../infinoted/plugins/infinoted-plugin-certificate-auth.c:330 msgid "Creating 4096-bit RSA private key for the super user account..." msgstr "" #: ../infinoted/plugins/infinoted-plugin-certificate-auth.c:358 msgid "Super User" msgstr "" #: ../infinoted/plugins/infinoted-plugin-certificate-auth.c:598 msgid "" "The trusted CA or list of trusted CAs. Only clients presenting a certificate " "signed by one of these CAs are accepted." msgstr "" #: ../infinoted/plugins/infinoted-plugin-certificate-auth.c:600 msgid "CA-LIST" msgstr "" #: ../infinoted/plugins/infinoted-plugin-certificate-auth.c:608 msgid "" "If given, this is the private key for one of the CA certificates in the list " "given by the \"ca-list\" parameter. In this case, the server itself acts as " "a CA and can issue certificates to clients. This can be used to allow " "clients to create their own accounts." msgstr "" #: ../infinoted/plugins/infinoted-plugin-certificate-auth.c:612 msgid "CA-KEY" msgstr "" #: ../infinoted/plugins/infinoted-plugin-certificate-auth.c:620 msgid "" "If this value is set to false, then clients that cannot authenticate " "themselves with a valid certificate are rejected and the connection is " "closed. If it is set to true, the connection will be accepted, but the " "client will only have unauthenticated access to the server. [Default: false]" msgstr "" #: ../infinoted/plugins/infinoted-plugin-certificate-auth.c:633 msgid "" "Filename to which to write a short-lived super-user private key and " "certificate. The user is deleted when the infinoted server goes down or the " "plugin is re-loaded. This option can only be given when the \"ca-key\" " "parameter is set." msgstr "" #: ../infinoted/plugins/infinoted-plugin-certificate-auth.c:637 msgid "FILENAME" msgstr "" #: ../infinoted/plugins/infinoted-plugin-certificate-auth.c:645 msgid "" "Flags to be used when verifying a client certificate. Each of these flags " "weakens the security, and so should be set only when absolutely necessary, " "and it should be done with care. [Default: disable-ca-sign]" msgstr "" #: ../infinoted/plugins/infinoted-plugin-certificate-auth.c:649 msgid "flag1;flag2;[...]" msgstr "" #: ../infinoted/plugins/infinoted-plugin-certificate-auth.c:661 msgid "" "Allows clients to authenticate themselves with client-side certificates. If " "authentication is successful, the certificate ID is used to log the user " "into its account." msgstr "" #: ../infinoted/plugins/infinoted-plugin-dbus.c:1188 #, fuzzy, c-format msgid "" "\"%s\" is not a valid bus type. Allowed values are \"system\" or \"session\"" msgstr "" "»%s« ist keine gültige Sicherheitsrichtlinie. Mögliche Werte sind »no-tls«, " "»allow-tls« oder »require-tls«" #: ../infinoted/plugins/infinoted-plugin-dbus.c:1207 msgid "" "The bus type to use, either \"session\" or \"system\". [default=session]" msgstr "" #: ../infinoted/plugins/infinoted-plugin-dbus.c:1209 msgid "TYPE" msgstr "" #: ../infinoted/plugins/infinoted-plugin-dbus.c:1217 msgid "The name to own on the bus. [default=org.infinote.infinoted]" msgstr "" #: ../infinoted/plugins/infinoted-plugin-dbus.c:1218 msgid "NAME" msgstr "" #: ../infinoted/plugins/infinoted-plugin-dbus.c:1230 msgid "Exports infinoted functionality on D-Bus" msgstr "" #: ../infinoted/plugins/infinoted-plugin-directory-sync.c:93 #, c-format msgid "Failed to convert path \"%s\" from UTF-8 to %s: " msgstr "" #: ../infinoted/plugins/infinoted-plugin-directory-sync.c:199 #, fuzzy, c-format msgid "Failed to remove directory \"%s\": " msgstr "Das Verzeichnis »%s« konnte nicht erstellt werden: %s" #: ../infinoted/plugins/infinoted-plugin-directory-sync.c:255 #, fuzzy, c-format msgid "Failed to create directory for path \"%s\": " msgstr "Das Verzeichnis »%s« konnte nicht erstellt werden: %s" #: ../infinoted/plugins/infinoted-plugin-directory-sync.c:283 #, c-format msgid "Failed to write session for path \"%s\": " msgstr "" #: ../infinoted/plugins/infinoted-plugin-directory-sync.c:315 #, c-format msgid "Failed to execute hook \"%s\": " msgstr "" #: ../infinoted/plugins/infinoted-plugin-directory-sync.c:347 #, c-format msgid "" "%s\n" "\tWill retry in %u seconds" msgstr "" #: ../infinoted/plugins/infinoted-plugin-directory-sync.c:358 #, c-format msgid "%s" msgstr "" #: ../infinoted/plugins/infinoted-plugin-directory-sync.c:522 #, c-format msgid "Node \"%s\" contains invalid characters" msgstr "" #: ../infinoted/plugins/infinoted-plugin-directory-sync.c:602 #, fuzzy msgid "The directory into which to store the directory tree in text form." msgstr "Das Verzeichnis in dem die Dokumente gespeichert werden sollen" #: ../infinoted/plugins/infinoted-plugin-directory-sync.c:611 #, fuzzy msgid "" "Interval, in seconds, after which to save documents into the given directory." msgstr "" "Zeitabstand in Sekunden in dem Dokumente automatisch gespeichert werden, " "oder 0 um automatische Speicherung abzuschalten" #: ../infinoted/plugins/infinoted-plugin-directory-sync.c:634 msgid "" "Periodically saves the content of all documents into a custom directory, " "without any infinote metadata such as which user wrote what text. This " "option can be used to (automatically) process the files on the server by " "standard tools that operate on normal UTF-8 encoded text files" msgstr "" #: ../infinoted/plugins/infinoted-plugin-document-stream.c:669 msgid "Not a text or chat node" msgstr "" #: ../infinoted/plugins/infinoted-plugin-document-stream.c:1503 msgid "Allows streaming of document changes to external programs" msgstr "" #: ../infinoted/plugins/infinoted-plugin-linekeeper.c:317 #, c-format msgid "Could not join LineKeeper user for document: %s\n" msgstr "" #: ../infinoted/plugins/infinoted-plugin-linekeeper.c:549 msgid "The number of empty lines to keep at the end of the document." msgstr "" #: ../infinoted/plugins/infinoted-plugin-linekeeper.c:550 msgid "LINES" msgstr "" #: ../infinoted/plugins/infinoted-plugin-linekeeper.c:562 msgid "" "This plugin makes sure that at the end of every document there is always a " "fixed number of empty lines." msgstr "" #: ../infinoted/plugins/infinoted-plugin-logging.c:224 #, c-format msgid "when executing request \"%s\" from user %s (%s) in document %s" msgstr "" #: ../infinoted/plugins/infinoted-plugin-logging.c:285 #, c-format msgid "Error from connection %s: %s" msgstr "" #: ../infinoted/plugins/infinoted-plugin-logging.c:322 #, c-format msgid "in document %s from connection %s. The request was: %s" msgstr "" #: ../infinoted/plugins/infinoted-plugin-logging.c:336 #, c-format msgid "Session error: %s" msgstr "" #: ../infinoted/plugins/infinoted-plugin-logging.c:449 #: ../infinoted/plugins/infinoted-plugin-logging.c:517 #: ../infinoted/plugins/infinoted-plugin-traffic-logging.c:237 #, fuzzy, c-format msgid "%s connected" msgstr "Verbindung getrennt" #: ../infinoted/plugins/infinoted-plugin-logging.c:566 #, c-format msgid "Unsuccessful connection attempt from %s" msgstr "" #: ../infinoted/plugins/infinoted-plugin-logging.c:574 #, fuzzy, c-format msgid "%s disconnected" msgstr "Verbindung getrennt" #: ../infinoted/plugins/infinoted-plugin-logging.c:711 msgid "Whether to write a log message when a new user connects or disconnects." msgstr "" #: ../infinoted/plugins/infinoted-plugin-logging.c:721 msgid "" "Whether to write a log message when an error with a connection is detected, " "usually leading to disconnection of the user." msgstr "" #: ../infinoted/plugins/infinoted-plugin-logging.c:731 msgid "" "Whether to write a log message when a session cannot process a client " "request, mostly caused by invalid client requests." msgstr "" #: ../infinoted/plugins/infinoted-plugin-logging.c:741 msgid "" "Whether to write an additional line into the log when a message occurs " "during transformation of an adOPTed request. This is mostly used for " "debugging purposes to find problems in the server implementation itself." msgstr "" #: ../infinoted/plugins/infinoted-plugin-logging.c:757 msgid "" "This plugin writes extra information into the infinoted log. By default all " "extra information is logged, but individual events can be turned off with " "the plugin options." msgstr "" #: ../infinoted/plugins/infinoted-plugin-note-chat.c:166 #: ../infinoted/plugins/infinoted-plugin-note-text.c:172 #, c-format msgid "There is a already a plugin which handles sessions of type \"%s\"" msgstr "" #: ../infinoted/plugins/infinoted-plugin-note-chat.c:211 msgid "Adds support to handle chat documents." msgstr "" #: ../infinoted/plugins/infinoted-plugin-note-text.c:217 msgid "Adds support to handle plain text documents." msgstr "" #: ../infinoted/plugins/infinoted-plugin-record.c:71 #, c-format msgid "" "Could not create record file for session \"%s\": Could not generate unused " "record file in directory \"%s\"" msgstr "" "Die Aufnahmedatei für die Sitzung »%s« konnte nicht erstellt werden, da " "keine unbenutzte Aufnahmedatei im Verzeichnis »%s« erzeugt werden konnte" #: ../infinoted/plugins/infinoted-plugin-record.c:88 #, c-format msgid "Could not create directory \"%s\": %s" msgstr "Das Verzeichnis »%s« konnte nicht erstellt werden: %s" #: ../infinoted/plugins/infinoted-plugin-record.c:104 #, c-format msgid "Error while writing record for session \"%s\" into \"%s\": %s" msgstr "Fehler beim Speichern der Aufnahme für die Sitzung »%s« nach »%s«: %s" #: ../infinoted/plugins/infinoted-plugin-record.c:221 msgid "" "Creates a recording of each session that can be replayed later. The records " "are created in the ~/.infinoted-records directory." msgstr "" #: ../infinoted/plugins/infinoted-plugin-traffic-logging.c:136 #, fuzzy, c-format msgid "Connection error: %s" msgstr "Unsichere Verbindung" #: ../infinoted/plugins/infinoted-plugin-traffic-logging.c:211 #, c-format msgid "" "Failed to create directory \"%s\": %s\n" "Traffic logging for connection \"%s\" is disabled." msgstr "" #: ../infinoted/plugins/infinoted-plugin-traffic-logging.c:228 #, c-format msgid "" "Failed to open file \"%s\": %s\n" "Traffic logging for connection \"%s\" is disabled." msgstr "" #: ../infinoted/plugins/infinoted-plugin-traffic-logging.c:300 msgid "Log closed" msgstr "" #: ../infinoted/plugins/infinoted-plugin-traffic-logging.c:325 msgid "The directory into which to write the log files." msgstr "" #: ../infinoted/plugins/infinoted-plugin-traffic-logging.c:338 msgid "" "This plugin writes a dump of all network traffic between the server and the " "client into a file. Note that the traffic written to the log files is " "unencrypted. It is meant to be used as a diagnostic tool for debugging, and " "it should never be used in a production environment as it is a severe " "privacy issue." msgstr "" #: ../infinoted/plugins/infinoted-plugin-transformation-protection.c:105 #, c-format msgid "" "In document \"%s\": Attempt to transform request \"%s\" to current state \"%s" "\" (vdiff=%u) by user \"%s\" (id=%u, conn=%s). Maximum allowed is %u; the " "connection has been unsubscribed." msgstr "" #: ../infinoted/plugins/infinoted-plugin-transformation-protection.c:216 msgid "" "The maximum number of individual transformations to allow. If a client makes " "a request that would require more than this number of transformations, the " "request is rejected and the client is unsubscribed from the session." msgstr "" #: ../infinoted/plugins/infinoted-plugin-transformation-protection.c:220 msgid "DIFF" msgstr "" #: ../infinoted/plugins/infinoted-plugin-transformation-protection.c:232 msgid "" "This plugin tries to protect the server from malicious clients that send " "formally valid requests but would take the server a long time to process, " "making in unresponsive to other requests. This is only possible if sessions " "use the \"central\" communication method. At the moment this is the only " "method available, so the plugin can always be used. Currently the plugin " "rejects requests that were made in a state too far behind the current state. " "However, additional criteria might be implemented in future versions." msgstr "" #: ../infinoted/plugins/util/infinoted-plugin-util-navigate-browser.c:137 #, c-format msgid "The path \"%.*s\" does not exist" msgstr "" #. should be const... #: ../infinoted/plugins/util/infinoted-plugin-util-navigate-browser.c:170 #, c-format msgid "Failed to explore path \"%.*s\": " msgstr "" #: ../infinoted/plugins/util/infinoted-plugin-util-navigate-browser.c:213 #, c-format msgid "The path \"%.*s\" does not exist or is not a directory" msgstr "" #: ../infinoted/plugins/util/infinoted-plugin-util-navigate-browser.c:284 #, c-format msgid "The path \"%.*s\" is not an absolute path" msgstr "" #: ../libinfgtk/inf-gtk-account-creation-dialog.c:198 #: ../libinfgtk/inf-gtk-account-creation-dialog.c:206 #, fuzzy msgid "Not connected to a server" msgstr "Nicht verbunden" #: ../libinfgtk/inf-gtk-account-creation-dialog.c:226 msgid "Permissions to create an account are not granted" msgstr "" #: ../libinfgtk/inf-gtk-account-creation-dialog.c:265 msgid "" "A private key is being generated. This process might take a few seconds..." msgstr "" #: ../libinfgtk/inf-gtk-account-creation-dialog.c:275 msgid "" "New account is being requested from the server. Usually, this should not " "take very long." msgstr "" #: ../libinfgtk/inf-gtk-browser-store.c:685 msgid "Disconnected" msgstr "Verbindung getrennt" #: ../libinfgtk/inf-gtk-browser-view.c:2197 msgid "Exploring..." msgstr "Erkunde…" #: ../libinfgtk/inf-gtk-browser-view.c:2236 msgid "Synchronizing..." msgstr "Synchronisiere…" #: ../libinfgtk/inf-gtk-browser-view.c:2319 msgid "Not connected" msgstr "Nicht verbunden" #: ../libinfgtk/inf-gtk-browser-view.c:2330 msgid "Connecting..." msgstr "Verbindung wird hergestellt ..." #: ../libinfgtk/inf-gtk-browser-view.c:2340 msgid "Connected" msgstr "Verbunden" #: ../libinfgtk/inf-gtk-certificate-dialog.c:109 #, c-format msgid "The connection to host \"%s\" is not considered secure" msgstr "Die Verbindung zu »%s« wird als unsicher eingestuft" #: ../libinfgtk/inf-gtk-certificate-dialog.c:130 #, fuzzy msgid "The host has presented a new certificate." msgstr "Das Zertifikat des Servers" #: ../libinfgtk/inf-gtk-certificate-dialog.c:139 msgid "" "Its previous certificate has expired or is closed to expiration. Please make " "sure that you trust the new certificate." msgstr "" #: ../libinfgtk/inf-gtk-certificate-dialog.c:146 msgid "The host has presented an unexpected certificate!" msgstr "" #: ../libinfgtk/inf-gtk-certificate-dialog.c:155 msgid "" "This means someone might be eavesdropping on the connection. Please only " "continue if you expected this message, otherwise please contact the server " "administrator." msgstr "" #: ../libinfgtk/inf-gtk-certificate-dialog.c:165 msgid "" "The server certificate cannot be verified automatically. Please make sure " "that you trust this host before proceeding." msgstr "" #: ../libinfgtk/inf-gtk-certificate-dialog.c:176 msgid "The issuer of the certificate is not known." msgstr "" #: ../libinfgtk/inf-gtk-certificate-dialog.c:189 #, c-format msgid "" "The hostname of the server, \"%s\", does not match the hostname the " "certificate is issued to, \"%s\"." msgstr "" "Der Name des Servers, »%s«, passt nicht zu dem Namen »%s« auf den das " "Zertifikat ausgestellt ist." #: ../libinfgtk/inf-gtk-certificate-dialog.c:342 msgid "" msgstr "" #: ../libinfgtk/inf-gtk-certificate-manager.c:226 msgid "_Cancel connection" msgstr "Verbindung abbre_chen" #: ../libinfgtk/inf-gtk-certificate-manager.c:232 msgid "C_ontinue connection" msgstr "Verbindung f_ortsetzen" #: ../libinfgtk/inf-gtk-certificate-manager.c:237 #, c-format msgid "" "Do you want to continue the connection to host \"%s\"? If you choose to " "continue, this certificate will be trusted in the future when connecting to " "this host." msgstr "" #: ../libinfgtk/inf-gtk-certificate-view.c:72 msgid "" msgstr "" #: ../libinfgtk/inf-gtk-chat.c:202 #, c-format msgid "%s has joined" msgstr "%s ist beigetreten" #: ../libinfgtk/inf-gtk-chat.c:209 #, c-format msgid "%s has left" msgstr "%s ist gegangen" #. Then, show a menu item to remove an account. #: ../libinfgtk/inf-gtk-permissions-dialog.c:1879 msgid "_Delete Account" msgstr "" #: ../libinfgtk/inf-gtk-permissions-dialog.c:2312 #, fuzzy msgid "No node selected" msgstr "Nicht verbunden" #: ../libinfgtk/inf-gtk-permissions-dialog.c:2318 #, c-format msgid "Permissions for %s" msgstr "" #: ../libinfgtk/inf-gtk-permissions-dialog.c:2496 msgid "" "Permission is not granted to modify the permission list. It is read-" "only." msgstr "" #: ../libinfgtk/inf-gtk-permissions-dialog.c:2520 msgid "Permission is granted to modify the permission list." msgstr "" #: ../libinfgtk/inf-gtk-permissions-dialog.c:2530 #, c-format msgid "Server Error: %s" msgstr "" #: ../libinfgtk/inf-gtk-permissions-dialog.c:2538 msgid "Querying current permissions for this node from the server..." msgstr "" #: ../libinfgtk/inf-gtk-permissions-dialog.c:2544 msgid "" "Permission is not granted to query the permission list for this node " "from the server. Showing only default permissions and permissions for the " "own account." msgstr "" #: ../libinfgtk/inf-gtk-permissions-dialog.c:2551 msgid "" "Permissions are granted to query the full permission list from the " "server. Showing all permissions." msgstr "" #: ../libinfgtk/resources/ui/infgtkaccountcreationdialog.ui:12 msgid "Create New Account" msgstr "" #: ../libinfgtk/resources/ui/infgtkaccountcreationdialog.ui:75 #, fuzzy msgid "Account Name:" msgstr "Common-Name:" #: ../libinfgtk/resources/ui/infgtkaccountcreationdialog.ui:98 msgid "Create _Account" msgstr "" #: ../libinfgtk/resources/ui/infgtkaclsheetview.ui:31 msgid "Permission" msgstr "" #: ../libinfgtk/resources/ui/infgtkaclsheetview.ui:43 msgid "Default" msgstr "" #: ../libinfgtk/resources/ui/infgtkaclsheetview.ui:55 msgid "Yes" msgstr "" #: ../libinfgtk/resources/ui/infgtkaclsheetview.ui:67 msgid "No" msgstr "" #: ../libinfgtk/resources/ui/infgtkcertificatedialog.ui:14 #, fuzzy msgid "Connection Not Secure" msgstr "Unsichere Verbindung" #: ../libinfgtk/resources/ui/infgtkcertificatedialog.ui:138 msgid "Certificate Chain" msgstr "Zertifikatskette" #: ../libinfgtk/resources/ui/infgtkcertificatedialog.ui:172 msgid "_View Certificate" msgstr "_Zertifikat anzeigen" #: ../libinfgtk/resources/ui/infgtkcertificateview.ui:11 msgid "Issued To" msgstr "Ausgestellt an" #: ../libinfgtk/resources/ui/infgtkcertificateview.ui:26 #: ../libinfgtk/resources/ui/infgtkcertificateview.ui:134 msgid "Common Name:" msgstr "Common-Name:" #: ../libinfgtk/resources/ui/infgtkcertificateview.ui:48 #: ../libinfgtk/resources/ui/infgtkcertificateview.ui:156 msgid "Organization:" msgstr "Organisation:" #: ../libinfgtk/resources/ui/infgtkcertificateview.ui:70 #: ../libinfgtk/resources/ui/infgtkcertificateview.ui:178 msgid "Organizational Unit:" msgstr "Organisationseinheit:" #: ../libinfgtk/resources/ui/infgtkcertificateview.ui:92 msgid "Serial Number:" msgstr "Seriennummer:" #: ../libinfgtk/resources/ui/infgtkcertificateview.ui:119 msgid "Issued By" msgstr "Ausgestellt von" #: ../libinfgtk/resources/ui/infgtkcertificateview.ui:200 msgid "Validity" msgstr "Gültigkeit" #: ../libinfgtk/resources/ui/infgtkcertificateview.ui:215 msgid "Issued On:" msgstr "Ausgestellt am:" #: ../libinfgtk/resources/ui/infgtkcertificateview.ui:237 msgid "Expires On:" msgstr "Läuft aus:" #: ../libinfgtk/resources/ui/infgtkcertificateview.ui:259 msgid "Fingerprints" msgstr "Fingerabdrücke" #: ../libinfgtk/resources/ui/infgtkcertificateview.ui:274 #, fuzzy msgid "SHA-1 Fingerprint:" msgstr "SHA1-Fingerabdruck:" #: ../libinfgtk/resources/ui/infgtkcertificateview.ui:301 #, fuzzy msgid "SHA-256 Fingerprint:" msgstr "SHA1-Fingerabdruck:" #: ../libinfgtk/resources/ui/infgtkcertificateview.ui:333 msgid "Signature" msgstr "" #: ../libinfgtk/resources/ui/infgtkcertificateview.ui:348 msgid "Signature Algorithm:" msgstr "" #: ../libinfgtk/resources/ui/infgtkchat.ui:93 msgid "Send" msgstr "" #: ../libinfgtk/resources/ui/infgtkpermissionsdialog.ui:121 #, fuzzy msgid "Accounts" msgstr "Common-Name:" #: ../libinfinity/adopted/inf-adopted-algorithm.c:1013 #, c-format msgid "Failed to apply request \"%s\" from user \"%s\" at state \"%s\": " msgstr "" #: ../libinfinity/adopted/inf-adopted-algorithm.c:1899 #, c-format msgid "" "The request \"%s\" from user \"%s\" is an UNDO request but there is no " "request to be undone." msgstr "" #: ../libinfinity/adopted/inf-adopted-algorithm.c:1920 #, c-format msgid "" "The request \"%s\" from user \"%s\" is a REDO request but there is no " "request to be redone." msgstr "" #: ../libinfinity/adopted/inf-adopted-session.c:160 #, c-format msgid "Request has index '%u', but index '%u' was expected" msgstr "" #: ../libinfinity/adopted/inf-adopted-session.c:181 msgid "Undo received, but no previous request found" msgstr "" #: ../libinfinity/adopted/inf-adopted-session.c:197 msgid "Redo received, but no previous request found" msgstr "" #: ../libinfinity/adopted/inf-adopted-session.c:238 #, c-format msgid "No such user with user ID '%u'" msgstr "" #: ../libinfinity/adopted/inf-adopted-session.c:481 msgid "The request was rejected via the API" msgstr "" #: ../libinfinity/adopted/inf-adopted-session.c:1173 #: ../libinfinity/common/inf-chat-session.c:468 #: ../libinfinity/common/inf-session.c:782 ../libinftext/inf-text-session.c:949 msgid "User did not join from this connection" msgstr "" #: ../libinfinity/adopted/inf-adopted-session.c:1223 #, c-format msgid "" "Request \"%s\" by user \"%s\" is not consecutive with respect to previously " "received request \"%s\"" msgstr "" #: ../libinfinity/adopted/inf-adopted-session.c:1436 msgid "\"time\" attribute in user message is missing" msgstr "" #: ../libinfinity/adopted/inf-adopted-session.c:1884 msgid "Operation for request missing" msgstr "" #. Error writing record `': #: ../libinfinity/adopted/inf-adopted-session-record.c:95 #, fuzzy, c-format msgid "Error writing record \"%s\": %s" msgstr "Fehler beim Speichern der Aufnahme für die Sitzung »%s« nach »%s«: %s" #: ../libinfinity/adopted/inf-adopted-session-replay.c:164 msgid "Unexpected end of recording" msgstr "" #: ../libinfinity/adopted/inf-adopted-session-replay.c:356 msgid "Document is not a session recording" msgstr "" #: ../libinfinity/adopted/inf-adopted-session-replay.c:371 msgid "Session type of the recording does not match" msgstr "" #: ../libinfinity/adopted/inf-adopted-session-replay.c:391 msgid "Initial session state missing in recording" msgstr "" #: ../libinfinity/adopted/inf-adopted-session-replay.c:465 msgid "Session switched to running without having finished playing the initial" msgstr "" #: ../libinfinity/adopted/inf-adopted-session-replay.c:485 msgid "Superfluous XML in initial session section" msgstr "" #: ../libinfinity/adopted/inf-adopted-session-replay.c:498 msgid "Session is still in synchronizing state after having played the initial" msgstr "" #: ../libinfinity/adopted/inf-adopted-session-replay.c:892 msgid "Superfluous XML in requests section" msgstr "" #: ../libinfinity/adopted/inf-adopted-session-replay.c:919 #: ../libinfinity/common/inf-chat-session.c:269 #, c-format msgid "No such user with ID \"%u\"" msgstr "" #: ../libinfinity/adopted/inf-adopted-session-replay.c:992 #, c-format msgid "Unexpected node \"%s\" in requests section" msgstr "" #: ../libinfinity/adopted/inf-adopted-state-vector.c:730 msgid "Expected \":\" after ID" msgstr "" #: ../libinfinity/adopted/inf-adopted-state-vector.c:744 #, c-format msgid "ID '%u' already occured before" msgstr "" #: ../libinfinity/adopted/inf-adopted-state-vector.c:761 #, c-format msgid "Expected ';' or end of string after component of ID '%u'" msgstr "" #: ../libinfinity/client/infc-browser.c:784 msgid "The node to subscribe to has been removed" msgstr "" #: ../libinfinity/client/infc-browser.c:811 #: ../libinfinity/client/infc-browser.c:839 msgid "" "The subdirectory into which the new node should have been created has been " "removed" msgstr "" #: ../libinfinity/client/infc-browser.c:990 msgid "Permissions to explore this node have been revoked" msgstr "" #: ../libinfinity/client/infc-browser.c:1030 #: ../libinfinity/client/infc-browser.c:1059 msgid "Permissions to explore the parent node have been revoked" msgstr "" #: ../libinfinity/client/infc-browser.c:1354 msgid "" "The server did not send an initial welcome message. This means that the " "server is running a lower version of the software which is incompatible to " "the client. Consider downgrading the client, or ask the server " "administrators to upgrade their software." msgstr "" #: ../libinfinity/client/infc-browser.c:1635 #, c-format msgid "" "This session requires communication method `%s' which is not installed for " "network `%s'" msgstr "" #: ../libinfinity/client/infc-browser.c:2448 #, c-format msgid "There is no such node with ID %u" msgstr "" #: ../libinfinity/client/infc-browser.c:2580 #, c-format msgid "" "The request contains a sequence number refering to a request of type '%s', " "but a request of either 'explore-node' or 'add-node' was expected." msgstr "" #: ../libinfinity/client/infc-browser.c:2831 msgid "" "The server uses an older version of the protocol which is no longer " "supported by this client. Consider using an earlier version of it, or ask " "the server administrators to upgrade their software." msgstr "" #: ../libinfinity/client/infc-browser.c:2844 msgid "" "The server uses a newer version of the protocol which is not supported by " "this client. Consider upgrading your client." msgstr "" #: ../libinfinity/client/infc-browser.c:3005 msgid "Node to explore does no longer exist" msgstr "" #: ../libinfinity/client/infc-browser.c:3016 msgid "Node to explore is not a subdirectory" msgstr "" #: ../libinfinity/client/infc-browser.c:3027 msgid "Node to explore is already explored" msgstr "" #: ../libinfinity/client/infc-browser.c:3072 msgid "Not all nodes were received before explore-end was received" msgstr "" #: ../libinfinity/client/infc-browser.c:3134 #: ../libinfinity/client/infc-browser.c:3358 #, c-format msgid "Node with ID \"%u\" exists already" msgstr "" #: ../libinfinity/client/infc-browser.c:3157 msgid "The parent node has not been explored yet" msgstr "" #: ../libinfinity/client/infc-browser.c:3232 msgid "Explored nodes cannot be initially be subscribed to" msgstr "" #: ../libinfinity/client/infc-browser.c:3247 #, c-format msgid "Note type \"%s\" not known" msgstr "" #: ../libinfinity/client/infc-browser.c:3402 msgid "Received sync-in without having requested one" msgstr "" #: ../libinfinity/client/infc-browser.c:3422 #, c-format msgid "Expected note type \"%s\" for sync-in, but received \"%s\"" msgstr "" #: ../libinfinity/client/infc-browser.c:3578 #, c-format msgid "Note type '%s' is not supported" msgstr "" #: ../libinfinity/client/infc-browser.c:3592 msgid "Already subscribed to this session" msgstr "" #: ../libinfinity/client/infc-browser.c:3648 msgid "Already subscribed to the chat session" msgstr "" #: ../libinfinity/client/infc-browser.c:3870 msgid "Not all users have been transmitted before user-list-end was received" msgstr "" #: ../libinfinity/client/infc-browser.c:4149 #, c-format msgid "" "Unknown account ID \"%s\" in server reply of \"%s\". Typically, this means " "the server claimed it notified us about new connections as soon as they are " "available, but it did not do so." msgstr "" #: ../libinfinity/client/infc-browser.c:4411 #, fuzzy msgid "No certificate request has been made" msgstr "Das SZertifikats des Servers hat sich geändert!" #: ../libinfinity/client/infc-browser.c:4438 #: ../libinfinity/client/infc-browser.c:4468 #, fuzzy msgid "No certificate provided" msgstr "Das Zertifikat ist ungültig!" #: ../libinfinity/client/infc-browser.c:4486 msgid "Cannot verify the certificate without server certificate" msgstr "" #: ../libinfinity/client/infc-browser.c:4536 #, c-format msgid "Server sent an invalid certificate (%s)" msgstr "" #: ../libinfinity/client/infc-browser.c:4643 #: ../libinfinity/server/infd-directory.c:3306 msgid "The default account cannot be removed" msgstr "" #: ../libinfinity/client/infc-browser.c:4796 #, c-format msgid "" "The request contains a sequence number refering to a request of type '%s', " "but a request of either 'query-acl' or 'set-acl' was expected." msgstr "" #: ../libinfinity/client/infc-browser.c:4969 #, c-format msgid "Error comes from unknown error domain '%s' (code %u)" msgstr "" #: ../libinfinity/client/infc-browser.c:5193 #, c-format msgid "Received unexpected network message \"%s\"" msgstr "" #: ../libinfinity/client/infc-browser.c:5216 #: ../libinfinity/client/infc-session-proxy.c:989 #, c-format msgid "Server reply could not be processed: %s" msgstr "" #: ../libinfinity/client/infc-request-manager.c:126 msgid "Sequence identifier causes overflow" msgstr "" #: ../libinfinity/client/infc-request-manager.c:138 msgid "Sequence components are not separated by '/'" msgstr "" #: ../libinfinity/client/infc-request-manager.c:152 msgid "Sequence number causes overflow" msgstr "" #: ../libinfinity/client/infc-request-manager.c:164 msgid "Trailing characters after sequence number" msgstr "" #: ../libinfinity/client/infc-request-manager.c:735 #, c-format msgid "No such sequence number %u" msgstr "" #: ../libinfinity/client/infc-request-manager.c:748 #, c-format msgid "" "The request contains a sequence number refering to a request of type '%s', " "but a request of type '%s' was expected" msgstr "" #: ../libinfinity/client/infc-request-manager.c:803 msgid "The request does not contain a sequence number, but one is required" msgstr "" #: ../libinfinity/client/infc-session-proxy.c:524 #, c-format msgid "Error comes from unknown error domain \"%s\" (code %u)" msgstr "" #: ../libinfinity/client/infc-session-proxy.c:666 msgid "Request does not contain required attribute \"id\"" msgstr "" #: ../libinfinity/client/infc-session-proxy.c:684 #: ../libinfinity/common/inf-session.c:768 #, c-format msgid "No such user with ID %u" msgstr "" #: ../libinfinity/common/inf-acl.c:763 msgid "ACL field must be either \"yes\" or \"no\"" msgstr "" #: ../libinfinity/common/inf-acl.c:1273 #, c-format msgid "Permissions for account ID \"%s\" defined more than once" msgstr "" #: ../libinfinity/common/inf-async-operation.c:115 msgid "" "InfIo object was deleted without InfAsyncOperation being freed! This is a " "programming error that leaves the program in an inconsistent state. " "Therefore, the program is aborted. Please fix your code." msgstr "" #: ../libinfinity/common/inf-chat-session.c:90 msgid "An invalid message type was sent" msgstr "" #: ../libinfinity/common/inf-chat-session.c:92 msgid "A user with the requested ID does not exist" msgstr "" #: ../libinfinity/common/inf-chat-session.c:94 msgid "An unknown chat session error has occured" msgstr "" #: ../libinfinity/common/inf-chat-session.c:96 #: ../libinfinity/common/inf-error.c:84 ../libinfinity/common/inf-error.c:131 #: ../libinfinity/common/inf-session.c:233 msgid "An error with unknown error code occured" msgstr "" #: ../libinfinity/common/inf-chat-session.c:360 #, c-format msgid "%s --- %s has joined\n" msgstr "" #: ../libinfinity/common/inf-chat-session.c:363 #, c-format msgid "%s --- %s has left\n" msgstr "" #: ../libinfinity/common/inf-chat-session.c:421 #, c-format msgid "%s --- %u users total\n" msgstr "" #: ../libinfinity/common/inf-chat-session.c:1244 #, c-format msgid "%s --- Log closed\n" msgstr "" #: ../libinfinity/common/inf-chat-session.c:1258 #, c-format msgid "%s --- Log opened\n" msgstr "" #: ../libinfinity/common/inf-discovery-avahi.c:542 #, c-format msgid "" "Avahi service browser is in failure state. Services of type '%s' are no " "longer discovered.\n" "\n" "The failure was: %s\n" msgstr "" #: ../libinfinity/common/inf-discovery-avahi.c:629 #, c-format msgid "" "Avahi entry group is in failure state. The service '%s' of type '%s' is no " "longer published.\n" "\n" "The failure was: %s\n" msgstr "" #: ../libinfinity/common/inf-discovery-avahi.c:839 #, c-format msgid "" "Failed to start Avahi client. Service discovery or publishing will not be " "possible.\n" "\n" "The occurred failure was: %s" msgstr "" #: ../libinfinity/common/inf-discovery-avahi.c:882 #, c-format msgid "" "Avahi client is in failure state. Service discovery or publishing is no " "longer possible.\n" "\n" "The occured failure was: %s\n" msgstr "" #. Translators: This is " (via on #. *
)", for example "ck (via eth0 on IPv4)". #: ../libinfinity/common/inf-discovery-avahi.c:1465 #, c-format msgid "%s (via %s on IPv4)" msgstr "" #: ../libinfinity/common/inf-discovery-avahi.c:1466 #, c-format msgid "%s (via %s on IPv6)" msgstr "" #: ../libinfinity/common/inf-error.c:68 msgid "Received error from an unknown domain" msgstr "" #: ../libinfinity/common/inf-error.c:70 msgid "Failed to process server reply" msgstr "" #: ../libinfinity/common/inf-error.c:72 msgid "Server reply contains invalid sequence number" msgstr "" #: ../libinfinity/common/inf-error.c:74 msgid "A required attribute was not set in request" msgstr "" #: ../libinfinity/common/inf-error.c:76 msgid "An attribute did not have valid content" msgstr "" #: ../libinfinity/common/inf-error.c:78 msgid "An attribute contained an invalid number" msgstr "" #: ../libinfinity/common/inf-error.c:80 msgid "Not authorized" msgstr "" #: ../libinfinity/common/inf-error.c:82 msgid "An unknown request error occured" msgstr "" #: ../libinfinity/common/inf-error.c:117 msgid "Name is already in use" msgstr "" #: ../libinfinity/common/inf-error.c:119 msgid "'id' attribute provided in request" msgstr "" #: ../libinfinity/common/inf-error.c:121 msgid "There is no user with the given ID" msgstr "" #: ../libinfinity/common/inf-error.c:123 msgid "'status' attribute is 'unavailable' in join or rejoin request" msgstr "" #: ../libinfinity/common/inf-error.c:125 msgid "User did not join via this connection" msgstr "" #: ../libinfinity/common/inf-error.c:127 msgid "'status' attribute has invalid value" msgstr "" #: ../libinfinity/common/inf-error.c:129 msgid "An unknown user error occured" msgstr "" #: ../libinfinity/common/inf-error.c:164 msgid "Server did not send an initial welcome message" msgstr "" #: ../libinfinity/common/inf-error.c:166 msgid "The server and client use different protocol versions" msgstr "" #: ../libinfinity/common/inf-error.c:168 msgid "A node with this name exists already" msgstr "" #: ../libinfinity/common/inf-error.c:170 msgid "Invalid node name" msgstr "" #: ../libinfinity/common/inf-error.c:172 msgid "Node does not exist" msgstr "" #: ../libinfinity/common/inf-error.c:174 msgid "No previous subscription request present" msgstr "" #: ../libinfinity/common/inf-error.c:176 msgid "The chat is disabled on the server side" msgstr "" #: ../libinfinity/common/inf-error.c:178 msgid "Node is not a subdirectory" msgstr "" #: ../libinfinity/common/inf-error.c:180 msgid "Node is not a note" msgstr "" #: ../libinfinity/common/inf-error.c:182 msgid "The node type is not supported by the server" msgstr "" #: ../libinfinity/common/inf-error.c:184 #: ../libinfinity/server/infd-directory.c:5948 msgid "The root node cannot be removed" msgstr "" #: ../libinfinity/common/inf-error.c:186 msgid "Subdirectory is not explored" msgstr "" #: ../libinfinity/common/inf-error.c:188 msgid "Subdirectory has already been explored" msgstr "" #: ../libinfinity/common/inf-error.c:190 msgid "Note type is not supported" msgstr "" #: ../libinfinity/common/inf-error.c:192 msgid "Connection is already subscribed to this session" msgstr "" #: ../libinfinity/common/inf-error.c:194 #: ../libinfinity/server/infd-directory.c:6212 msgid "The requesting connection is not subscribed to the session" msgstr "" #: ../libinfinity/common/inf-error.c:196 msgid "" "The server started to send explored nodes before telling howmany nodes to " "expect" msgstr "" #: ../libinfinity/common/inf-error.c:199 msgid "Server sent more explored nodes then announced" msgstr "" #: ../libinfinity/common/inf-error.c:201 msgid "Server sent not as much explored nodes as announced" msgstr "" #: ../libinfinity/common/inf-error.c:203 msgid "" "The session does not support the network through which the connection " "attempt is being made." msgstr "" #: ../libinfinity/common/inf-error.c:206 msgid "The session uses an unsupported communication method" msgstr "" #: ../libinfinity/common/inf-error.c:208 msgid "The requested operation is not supported by the server" msgstr "" #: ../libinfinity/common/inf-error.c:210 msgid "Received sync-in message without having requested a sync-in" msgstr "" #: ../libinfinity/common/inf-error.c:212 msgid "Client rejected subscription" msgstr "" #: ../libinfinity/common/inf-error.c:214 msgid "Unexpected XML message" msgstr "" #: ../libinfinity/common/inf-error.c:216 msgid "Server does not have a background storage" msgstr "" #: ../libinfinity/common/inf-error.c:218 #, fuzzy msgid "The certificate is invalid or not trusted" msgstr "Dem Aussteller des Zertifikats wird nicht vertraut." #: ../libinfinity/common/inf-error.c:220 msgid "The account list has already been queried before" msgstr "" #: ../libinfinity/common/inf-error.c:222 msgid "The account list has not been queried" msgstr "" #: ../libinfinity/common/inf-error.c:224 msgid "An account with this ID exists already" msgstr "" #: ../libinfinity/common/inf-error.c:226 msgid "There is no such account with the given ID" msgstr "" #: ../libinfinity/common/inf-error.c:228 msgid "The ACL has already been queried" msgstr "" #: ../libinfinity/common/inf-error.c:230 msgid "The ACL has not been queried" msgstr "" #: ../libinfinity/common/inf-error.c:232 msgid "An unknown directory error has occured" msgstr "" #: ../libinfinity/common/inf-error.c:234 ../libinfinity/common/inf-error.c:277 msgid "An error with unknown code has occured" msgstr "" #: ../libinfinity/common/inf-error.c:268 msgid "User did not provide valid credentials." msgstr "" #: ../libinfinity/common/inf-error.c:270 msgid "User is not permitted to connect to this server." msgstr "" #: ../libinfinity/common/inf-error.c:272 msgid "Authentication was temporarily interrupted on the server side." msgstr "" #: ../libinfinity/common/inf-error.c:275 msgid "An error cocured while checking user permissions." msgstr "" #: ../libinfinity/common/inf-error.c:351 #, fuzzy msgid "The certificate was revoked" msgstr "Das Zertifikat ist ungültig!" #: ../libinfinity/common/inf-error.c:353 #, fuzzy msgid "The certificate was not signed by a trusted CA" msgstr "Dem Aussteller des Zertifikats wird nicht vertraut." #: ../libinfinity/common/inf-error.c:355 #, fuzzy msgid "The signer of the certificate is not a CA" msgstr "Das Zertifikat ist ungültig!" #: ../libinfinity/common/inf-error.c:357 #, fuzzy msgid "The certificate uses an insecure algorithm" msgstr "Das Zertifikat ist ungültig!" #: ../libinfinity/common/inf-error.c:359 #, fuzzy msgid "The certificate is not yet activated" msgstr "Das Zertifikat ist ungültig!" #: ../libinfinity/common/inf-error.c:361 #, fuzzy msgid "The certificate has expired" msgstr "Das Zertifikat ist selbstsigniert." #: ../libinfinity/common/inf-error.c:363 #, fuzzy msgid "The certificate is invalid" msgstr "Das Zertifikat ist ungültig!" #: ../libinfinity/common/inf-name-resolver.c:205 msgid "The reply from the DNS server is incomplete" msgstr "" #: ../libinfinity/common/inf-name-resolver.c:742 #, c-format msgid "" "Failure during SRV record lookup: %s\n" "Will go on with normal A/AAAA lookup" msgstr "" #: ../libinfinity/common/inf-protocol.c:85 msgid "Major part of version number causes overflow" msgstr "" #: ../libinfinity/common/inf-protocol.c:97 msgid "Version number parts are not separated by '.'" msgstr "" #: ../libinfinity/common/inf-protocol.c:111 msgid "Minor part of version number causes overflow" msgstr "" #: ../libinfinity/common/inf-protocol.c:123 msgid "Trailing characters after version number" msgstr "" #: ../libinfinity/common/inf-session.c:198 msgid "Unexpectedly got an XML message in presync" msgstr "" #: ../libinfinity/common/inf-session.c:200 msgid "Got unexpected XML node during synchronization" msgstr "" #: ../libinfinity/common/inf-session.c:202 msgid "'id' attribute in user message is missing" msgstr "" #: ../libinfinity/common/inf-session.c:204 msgid "User ID is already in use" msgstr "" #: ../libinfinity/common/inf-session.c:206 msgid "'name' attribute in user message is missing" msgstr "" #: ../libinfinity/common/inf-session.c:208 msgid "User Name is already in use" msgstr "" #: ../libinfinity/common/inf-session.c:210 msgid "The connection was closed unexpectedly" msgstr "" #: ../libinfinity/common/inf-session.c:212 msgid "The sender cancelled the synchronization" msgstr "" #: ../libinfinity/common/inf-session.c:214 msgid "The receiver cancelled the synchronization" msgstr "" #: ../libinfinity/common/inf-session.c:216 msgid "Got begin-of-sync message, but synchronization is already in progress" msgstr "" #: ../libinfinity/common/inf-session.c:219 msgid "begin-of-sync message does not contain the number of messages to expect" msgstr "" #: ../libinfinity/common/inf-session.c:222 msgid "Got end-of-sync message, but synchronization is still in progress" msgstr "" #: ../libinfinity/common/inf-session.c:225 msgid "Expected begin-of-sync message as first message during synchronization" msgstr "" #: ../libinfinity/common/inf-session.c:228 msgid "Expected end-of-sync message as last message during synchronization" msgstr "" #: ../libinfinity/common/inf-session.c:231 msgid "An unknown synchronization error has occured" msgstr "" #. TODO: Add a possibilty for sub classes to register their error domains #. * that can occur in process_xml_sync. Maybe via a translate_error_sync #. * vfunc. #: ../libinfinity/common/inf-session.c:247 msgid "An error with unknown error domain occured" msgstr "" #: ../libinfinity/common/inf-session.c:937 #, c-format msgid "Received unhandled XML message '%s'" msgstr "" #: ../libinfinity/common/inf-session.c:1467 #, c-format msgid "Unexpectedly received XML message \"%s\" in presync" msgstr "" #: ../libinfinity/common/inf-session.c:1576 #, c-format msgid "Received unexpected XML message \"%s\" while synchronizing" msgstr "" #: ../libinfinity/common/inf-tcp-connection.c:1039 #, c-format msgid "Interface `%s' does not exist" msgstr "" #: ../libinfinity/common/inf-tcp-connection.c:1100 #, c-format msgid "Failed to retrieve local address: %s" msgstr "" #: ../libinfinity/common/inf-tcp-connection.c:1118 #, c-format msgid "Failed to retrieve local port: %s" msgstr "" #. TODO: We can probably implement this using GetInterfaceInfo() #: ../libinfinity/common/inf-tcp-connection.c:1134 msgid "The device-name property is not implemented on Win32" msgstr "" #. Failed to get name for device : #: ../libinfinity/common/inf-tcp-connection.c:1147 #, c-format msgid "Failed to get name for device %u: %s" msgstr "" #: ../libinfinity/common/inf-user.c:497 #, c-format msgid "Invalid user status: '%s'" msgstr "" #: ../libinfinity/common/inf-xml-util.c:60 #: ../libinfinity/common/inf-xml-util.c:117 #: ../libinfinity/common/inf-xml-util.c:236 #, c-format msgid "Attribute '%s' does not contain a valid number" msgstr "" #: ../libinfinity/common/inf-xml-util.c:72 #: ../libinfinity/common/inf-xml-util.c:129 #: ../libinfinity/common/inf-xml-util.c:160 #: ../libinfinity/common/inf-xml-util.c:204 #: ../libinfinity/common/inf-xml-util.c:249 #, c-format msgid "Attribute '%s' causes overflow (%s)" msgstr "" #: ../libinfinity/common/inf-xml-util.c:85 #: ../libinfinity/common/inf-xml-util.c:173 #: ../libinfinity/common/inf-xml-util.c:262 #, c-format msgid "Attribute '%s' causes underflow (%s)" msgstr "" #: ../libinfinity/common/inf-xml-util.c:454 #, c-format msgid "Request '%s' does not contain required attribute '%s'" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:400 msgid "The entity has sent XML that cannot be processed" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:402 msgid "" "The entity has sent a namespace prefix that is unsupported, or has sent no " "namespace prefix on an element that requires such a prefix" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:406 msgid "" "The server is closing the active stream for this entity because a new stream " "has been initiated that conflicts with the existing stream" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:410 msgid "" "The entity has not generated any traffic over the stream for some period of " "time" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:413 msgid "" "The value of the 'to' attribute provided by the initiating entity in the " "stream header corresponds to a hostname that is no longer hosted by the " "server" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:417 msgid "" "The value of the 'to' attribute provided by the initiating entity in the " "stream header does not correspond to a hostname that is hosted by the server" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:421 msgid "A stanza sent between two servers lacks a 'to' or 'from'attribute" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:424 msgid "" "The server has experienced a misconfiguration or an otherwise-undefined " "internal error that prevents it from servicing the stream" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:428 msgid "" "The JID or hostname provided in a 'from' address does not match an " "authorized JID or validated domain negotiated between servers via SASL or " "dialback, or between a client and a server via authentication and resource " "binding" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:433 msgid "" "The stream ID or dialback ID is invalid or does not match an ID previously " "provided" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:436 msgid "" "The streams namespace is something other than \"http://etherx.jabber.org/" "streams\" or the dialback namespace name is something other than \"jabber:" "server:dialback\"" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:440 msgid "" "The entity has sent invalid XML over the stream to a server that performs " "validation" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:443 msgid "" "The entity has attempted to send data before the stream has been " "authenticated, or otherwise is not authorized to perform an action related " "to stream negotiation" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:447 msgid "The entity has violated some local service policy" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:449 msgid "" "The server is unable to properly connect to a remote entity that is required " "for authentication or authorization" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:452 msgid "The server lacks the system resources necessary to service the stream" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:455 msgid "The entity has attempted to send restricted XML features" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:457 msgid "" "The server will not provide service to the initiating entity but is " "redirecting traffic to another host" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:460 msgid "The server is being shut down and all active streams are being closed" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:464 msgid "The error condition is not one of those defined by the other conditions" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:467 msgid "" "The initiating entity has encoded the stream in an encoding that is not " "supported by the server" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:470 msgid "" "The initiating entity has sent a first-level child of the stream that is not " "supported by the server." msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:473 msgid "" "The value of the 'version' attribute provided by the initiating entity in " "the stream header specifies a version of XMPP that is not supported by the " "server" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:477 msgid "The initiating entity has sent XML that is not well-formed" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:522 msgid "" "The receiving entity acknowledged an element sent by the initiating " "entity" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:525 msgid "" "The data provided by the initiating entity could not be processed because " "the Base64 encoding is incorrect" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:528 msgid "" "The authzid provided by the initiating entity is invalid, either because it " "is incorrectly formatted or because the initiating entity does not have " "permissions to authorize that ID" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:533 msgid "" "The initiating entity did not provide a mechanism or requested a mechanism " "that is not supported by the receiving entity" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:536 msgid "" "The mechanism requsted by the initiating entity is weaker than server policy " "permits for that initiating entity" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:539 msgid "" "The authentication failed because the initiating entity did not provide " "valid credentials" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:542 msgid "" "The authentication failed because of a temporary error condition within the " "receiving entity" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:545 msgid "An unknown authentication error has occured" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:1314 msgid "The server did not provide a certificate" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:2109 msgid "Stream is not yet secured with TLS" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:2176 msgid "Stream is not yet authorized" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:2304 msgid "The server does not offer a suitable authentication mechanism" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:2349 msgid "The server does not support transport layer security (TLS)" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:2372 msgid "The server requires transport layer security (TLS)" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:2406 msgid "The server does not provide any authentication mechanism" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:2464 msgid "The server cannot perform the TLS handshake" msgstr "" #. XML Warning from : #: ../libinfinity/common/inf-xmpp-connection.c:2946 #, c-format msgid "XML warning from %s: %s\n" msgstr "" #. The server sent something which is not XML #: ../libinfinity/common/inf-xmpp-connection.c:2990 msgid "Remote site is not an XMPP server" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:4606 msgid "The server certificate is not trusted" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:4614 #, fuzzy, c-format msgid "The server certificate is not trusted: %s" msgstr "Dem Aussteller des Zertifikats wird nicht vertraut." #: ../libinfinity/common/inf-xmpp-connection.c:4626 #, fuzzy msgid "The client certificate is not trusted" msgstr "Dem Aussteller des Zertifikats wird nicht vertraut." #: ../libinfinity/common/inf-xmpp-connection.c:4634 #, fuzzy, c-format msgid "The client certificate is not trusted: %s" msgstr "Dem Aussteller des Zertifikats wird nicht vertraut." #: ../libinfinity/server/infd-account-storage.c:333 msgid "The account backend does not support acount listing" msgstr "" #: ../libinfinity/server/infd-account-storage.c:387 msgid "The account backend does not support adding accounts" msgstr "" #: ../libinfinity/server/infd-account-storage.c:427 msgid "The account backend does not support removing accounts" msgstr "" #: ../libinfinity/server/infd-account-storage.c:471 msgid "The account backend does not support logging in with a certificate" msgstr "" #: ../libinfinity/server/infd-account-storage.c:522 msgid "The account backend does not support logging in with a password" msgstr "" #: ../libinfinity/server/infd-account-storage.c:573 msgid "The account backend does not support changing the certificate" msgstr "" #: ../libinfinity/server/infd-account-storage.c:619 msgid "The account backend does not support changing the password" msgstr "" #: ../libinfinity/server/infd-chat-filesystem-format.c:145 #: ../libinfinity/server/infd-filesystem-storage.c:269 #: ../libinftext/inf-text-filesystem-format.c:368 #, c-format msgid "Error parsing XML in file \"%s\": [%d]: %s" msgstr "" #: ../libinfinity/server/infd-chat-filesystem-format.c:162 #: ../libinftext/inf-text-filesystem-format.c:385 #, c-format msgid "Error processing file \"%s\": %s" msgstr "" #: ../libinfinity/server/infd-chat-filesystem-format.c:164 msgid "The document is not a chat session" msgstr "" #: ../libinfinity/server/infd-directory.c:431 #, c-format msgid "" "Failed to save note \"%s\": %s\n" "\n" "Keeping it in memory. Another save attempt will be made when the server is " "shut down." msgstr "" #: ../libinfinity/server/infd-directory.c:955 #, c-format msgid "Failed to login client \"%s\" by certificate: %s" msgstr "" #: ../libinfinity/server/infd-directory.c:1000 #, c-format msgid "" "Failed to write ACL for node \"%s\": %s\n" "The new ACL is applied but will be lost after a server re-start. This is a " "possible security problem. Please fix the problem with the storage!" msgstr "" #: ../libinfinity/server/infd-directory.c:1198 #, c-format msgid "Failed to look up accounts in account storage: %s" msgstr "" #: ../libinfinity/server/infd-directory.c:1690 #, c-format msgid "" "Failed to read the ACL for the root node: %s\n" "In order not to compromise security all permissions have been revoked for " "all users. The infinote server is likely not very usable in this " "configuration, so please check the storage system, fix the problem and re-" "start the server." msgstr "" #: ../libinfinity/server/infd-directory.c:2086 #, c-format msgid "" "Could not write session \"%s\" to storage: %s\n" "\n" "All changes since the document das been saved are lost." msgstr "" #: ../libinfinity/server/infd-directory.c:2901 msgid "Server does not support issuing certificates" msgstr "" #: ../libinfinity/server/infd-directory.c:3014 #, fuzzy msgid "The certificate request has no common name set" msgstr "Das SZertifikats des Servers hat sich geändert!" #: ../libinfinity/server/infd-directory.c:3069 #, c-format msgid "There is already a transient account with name \"%s\"" msgstr "" #: ../libinfinity/server/infd-directory.c:3132 msgid "This server does not support creating accounts" msgstr "" #: ../libinfinity/server/infd-directory.c:3333 #: ../libinfinity/server/infd-directory.c:11245 #: ../libinfinity/server/infd-filesystem-account-storage.c:1264 #: ../libinfinity/server/infd-filesystem-account-storage.c:1446 #: ../libinfinity/server/infd-filesystem-account-storage.c:1560 #, c-format msgid "There is no such account with ID \"%s\"" msgstr "" #: ../libinfinity/server/infd-directory.c:3389 msgid "This server does not support removing accounts" msgstr "" #: ../libinfinity/server/infd-directory.c:3730 #, c-format msgid "" "Session \"%s\" could not be saved: %s\n" "Another attempt will be made when the session is unused for a while or the " "server is shut down." msgstr "" #: ../libinfinity/server/infd-directory.c:4254 #, c-format msgid "Name \"%s\" is an invalid name: contains non-printable characters" msgstr "" #: ../libinfinity/server/infd-directory.c:4272 #, c-format msgid "Name \"%s\" is an invalid name: contains only space characters" msgstr "" #: ../libinfinity/server/infd-directory.c:4285 #, c-format msgid "Name \"%s\" is an invalid name: contains \"/\"" msgstr "" #: ../libinfinity/server/infd-directory.c:4300 #, c-format msgid "A node with name \"%s\" exists already" msgstr "" #: ../libinfinity/server/infd-directory.c:5221 #: ../libinfinity/server/infd-session-proxy.c:419 msgid "Permission denied" msgstr "" #: ../libinfinity/server/infd-directory.c:5368 #, c-format msgid "Failed to look up account: %s. Logging out user..." msgstr "" #: ../libinfinity/server/infd-directory.c:5438 msgid "No subscription request for the server chat" msgstr "" #: ../libinfinity/server/infd-directory.c:5457 #, c-format msgid "No subscription request with ID %u" msgstr "" #: ../libinfinity/server/infd-directory.c:5524 #, c-format msgid "Node with ID \"%u\" is not a subdirectory node" msgstr "" #: ../libinfinity/server/infd-directory.c:5536 #, c-format msgid "Node with ID \"%u\" has unsupported type \"%s\"" msgstr "" #: ../libinfinity/server/infd-directory.c:5547 #, c-format msgid "Node with ID \"%u\" is not a leaf node" msgstr "" #: ../libinfinity/server/infd-directory.c:6187 #: ../libinfinity/server/infd-directory.c:11330 msgid "No background storage available" msgstr "" #: ../libinfinity/server/infd-directory.c:6310 msgid "The chat is disabled" msgstr "" #: ../libinfinity/server/infd-directory.c:6419 #, fuzzy msgid "No certificate request provided" msgstr "Das Zertifikat ist ungültig!" #: ../libinfinity/server/infd-directory.c:6950 msgid "The ACL for this node has already been queried" msgstr "" #: ../libinfinity/server/infd-directory.c:7037 msgid "The ACL for this node has not been queried yet" msgstr "" #: ../libinfinity/server/infd-directory.c:7063 msgid "The set-acl request does not have any ACL provided" msgstr "" #: ../libinfinity/server/infd-directory.c:7079 #: ../libinfinity/server/infd-directory.c:10454 msgid "This server does not support the requested permissions" msgstr "" #: ../libinfinity/server/infd-directory.c:7346 msgid "The node to be subscribed to has been removed" msgstr "" #: ../libinfinity/server/infd-directory.c:7467 #: ../libinfinity/server/infd-directory.c:7582 msgid "The parent node of the node to be added has been removed" msgstr "" #: ../libinfinity/server/infd-directory.c:7667 msgid "Client did not acknowledge initial subscription" msgstr "" #: ../libinfinity/server/infd-directory.c:7989 #, c-format msgid "Failed to explore the root directory of the new storage: %s" msgstr "" #: ../libinfinity/server/infd-directory.c:8080 #, c-format msgid "" "Failed to lookup account IDs on account storage change: %s. Demoting clients " "to default account." msgstr "" #: ../libinfinity/server/infd-directory.c:8160 #, c-format msgid "Failed to obtain account list from account storage: %s" msgstr "" #: ../libinfinity/server/infd-directory.c:8292 #: ../libinfinity/server/infd-directory.c:8377 #, c-format msgid "Failed to look up accounts in new account storage: %s" msgstr "" #: ../libinfinity/server/infd-filesystem-account-storage.c:189 msgid "" "If one of \"password-hash\" or \"password-salt\" is provided, the other must " "be provided as well." msgstr "" #: ../libinfinity/server/infd-filesystem-account-storage.c:216 msgid "The length of the password salt is incorrect, it should be 32 bytes" msgstr "" #: ../libinfinity/server/infd-filesystem-account-storage.c:247 #, c-format msgid "The length of the password hash is incorrect, it should be %u bytes" msgstr "" #: ../libinfinity/server/infd-filesystem-account-storage.c:541 #, c-format msgid "Duplicate account ID \"%s\" in file \"%s\"" msgstr "" #: ../libinfinity/server/infd-filesystem-account-storage.c:585 #, c-format msgid "" "Accounts \"%s\" and \"%s\" have the same name. This is not supported by " "InfdFilesystemAccountStorage." msgstr "" #: ../libinfinity/server/infd-filesystem-account-storage.c:606 #, c-format msgid "" "Accounts \"%s\" and \"%s\" have the same certificate with DN=%s. This is not " "supported by InfdFilesystemAccountStorage." msgstr "" #: ../libinfinity/server/infd-filesystem-account-storage.c:904 #, c-format msgid "Failed to read accounts from filesystem: %s" msgstr "" #: ../libinfinity/server/infd-filesystem-account-storage.c:1094 #, c-format msgid "There is already an account with name \"%s\"" msgstr "" #: ../libinfinity/server/infd-filesystem-account-storage.c:1107 msgid "The account name is too long" msgstr "" #: ../libinfinity/server/infd-filesystem-account-storage.c:1124 #, c-format msgid "There is already an account with a certificate with DN=\"%s\"" msgstr "" #: ../libinfinity/server/infd-filesystem-account-storage.c:1145 #, c-format msgid "There is already an account with a certificate with fingerprint=\"%s\"" msgstr "" #: ../libinfinity/server/infd-filesystem-account-storage.c:1197 #, c-format msgid "Could not generate a unique ID for account with name \"%s\"" msgstr "" #: ../libinfinity/server/infd-filesystem-account-storage.c:1464 #, c-format msgid "The certificate with DN=%s is already in use by another account" msgstr "" #: ../libinfinity/server/infd-filesystem-storage.c:78 msgid "The path does not start with \"/\"" msgstr "" #: ../libinfinity/server/infd-filesystem-storage.c:92 msgid "The path contains invalid components" msgstr "" #: ../libinfinity/server/infd-filesystem-storage.c:122 #, c-format msgid "Failed to convert root directory to filename encoding: %s" msgstr "" #: ../libinfinity/server/infd-filesystem-storage.c:141 #, c-format msgid "" "Failed to create root directory: %s\n" "Subsequent storage operations will most likely fail\n" msgstr "" #: ../libinfinity/server/infd-filesystem-storage.c:284 #, c-format msgid "Error processing file \"%s\": Toplevel tag is not \"%s\"" msgstr "" #: ../libinfinity/server/infd-session-proxy.c:299 msgid "Request does not contain required attribute \"name\"" msgstr "" #: ../libinfinity/server/infd-session-proxy.c:317 #, c-format msgid "Name \"%s\" already in use" msgstr "" #: ../libinfinity/server/infd-session-proxy.c:359 msgid "\"status\" attribute is \"unavailable\" in user join request" msgstr "" #: ../libinftext/inf-text-default-delete-operation.c:271 #: ../libinftext/inf-text-remote-delete-operation.c:380 msgid "Attempt to remove text from after the end of the document" msgstr "" #: ../libinftext/inf-text-default-insert-operation.c:223 msgid "Attempt to insert text after the end of the document" msgstr "" #: ../libinftext/inf-text-filesystem-format.c:99 #, c-format msgid "User with ID %u exists already" msgstr "" #: ../libinftext/inf-text-filesystem-format.c:113 #, c-format msgid "User with name \"%s\" exists already" msgstr "" #: ../libinftext/inf-text-filesystem-format.c:193 #, c-format msgid "User with ID \"%u\" does not exist" msgstr "" #: ../libinftext/inf-text-filesystem-format.c:387 msgid "The document is not a text session" msgstr "" #: ../libinftext/inf-text-filesystem-format.c:403 #: ../libinftext/inf-text-filesystem-format.c:413 #, c-format msgid "Error processing file \"%s\": " msgstr "" #: ../libinftext/inf-text-move-operation.c:228 msgid "Attempt to move cursor or selection beyond the end of the document" msgstr "" #: ../libinftext/inf-text-session.c:935 ../libinftext/inf-text-session.c:1081 #, c-format msgid "No such user with ID '%u'" msgstr "" #: ../libinftext/inf-text-session.c:963 #, c-format msgid "Invalid hue value: '%g'" msgstr "" #: ../libinftext/inf-text-session.c:1276 msgid "\"caret\" attribute in user message is missing" msgstr "" #~ msgid "MD5 Fingerprint:" #~ msgstr "MD5-Fingerabdruck:" #~ msgid "General" #~ msgstr "Allgemeines" #~ msgid "The server's private key" #~ msgstr "Die private Schlüsseldatei des Servers" #~ msgid "Creates a new random private key" #~ msgstr "Erstellt einen neuen zufälligen privaten Schlüssel" #~ msgid "Creates a new self-signed certificate using the given key" #~ msgstr "" #~ "Erstellt ein neues selbstsigniertes Zertifikat mit Hilfe des angegeben " #~ "Schlüssels" #~ msgid "INTERVAL" #~ msgstr "INTERVALL" #~ msgid "Could not create record file directory \"%s\": %s" #~ msgstr "" #~ "Das Verzeichnis für die Aufnahmedateien »%s« konnte nicht erstellt " #~ "werden: %s" #~ msgid "The previous certificate of the server has expired." #~ msgstr "Das vorherige Zertifikat des Servers ist abgelaufen." #~ msgid "" #~ "It is possible that the connection to the server is being hijacked. It is " #~ "also possible that the host just has got a new certificate. However, " #~ "please only continue the connection if you expected this warning." #~ msgstr "" #~ "Es ist möglich dass die Verbindung zum Server abgehört oder manipuliert " #~ "wird. Es kann aber auch sein dass der Server einfach ein neues Zertifikat " #~ "installiert hat. Fahren Sie in jedem Fall bitte nur fort wenn Sie diese " #~ "Warnung erwartet haben." #~ msgid "The certificate has expired. The expiration date was %s" #~ msgstr "Das Zertifikat ist abgelaufen. Das Ablaufdatum war %s" #~ msgid "The certificate has not yet been activated. Activation date is %s" #~ msgstr "" #~ "Das Zertifikat wurde noch nicht aktiviert. Das Aktivierungsdatum ist %s" #~ msgid "Do you want to continue the connection to host %s?" #~ msgstr "Wollen Sie die Verbindung zu %s fortsetzen?" libinfinity-0.7.1/po/PaxHeaders.26529/ca.po0000644000000000000000000000013213034544707015153 xustar0030 mtime=1483917767.602911315 30 atime=1483917767.602911315 30 ctime=1488261621.324067277 libinfinity-0.7.1/po/ca.po0000644000175000017500000022677713034544707015732 0ustar00arminarmin00000000000000# Catalan translation for libinfinity # Copyright (c) 2009 Rosetta Contributors and Canonical Ltd 2009 # This file is distributed under the same license as the libinfinity package. # FIRST AUTHOR , 2009. # msgid "" msgstr "" "Project-Id-Version: libinfinity\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=glib&keywords=I18N+L10N&component=general\n" "POT-Creation-Date: 2017-01-08 15:20-0800\n" "PO-Revision-Date: 2009-12-10 07:26+0000\n" "Last-Translator: David Planella \n" "Language-Team: Catalan \n" "Language: ca\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Launchpad-Export-Date: 2009-12-19 18:32+0000\n" "X-Generator: Launchpad (build Unknown)\n" #: ../infinoted/infinoted-config-reload.c:122 #, c-format msgid "Changing the listen address at runtime is not supported" msgstr "" #: ../infinoted/infinoted-config-reload.c:439 #, c-format msgid "Failed to re-load plugins: %s" msgstr "" #: ../infinoted/infinoted-config-reload.c:445 msgid "" "Plugins are disabled. Please fix the problem and reload configuration again." msgstr "" #: ../infinoted/infinoted-dh-params.c:83 msgid "Generating 2048 bit Diffie-Hellman parameters..." msgstr "" #. Translators: fork as in "fork into the background" #: ../infinoted/infinoted-main.c:77 msgid "Failed to fork" msgstr "" #: ../infinoted/infinoted-main.c:93 msgid "Failed to wait for daemonized child's return value" msgstr "" #: ../infinoted/infinoted-main.c:102 ../infinoted/infinoted-main.c:120 msgid "Failed to create PID file" msgstr "" #: ../infinoted/infinoted-options.c:48 msgid "If set, write the server log to the given file, in addition to stdout" msgstr "" #: ../infinoted/infinoted-options.c:50 msgid "LOG-FILE" msgstr "" #: ../infinoted/infinoted-options.c:58 msgid "" "Path to the server's private key. Must be the key with which the given " "certificate was signed. Not needed when security-policy is set to \"no-tls\"." msgstr "" #: ../infinoted/infinoted-options.c:61 msgid "KEY-FILE" msgstr "" #: ../infinoted/infinoted-options.c:69 msgid "" "Path to the server's certificate. Must be signed with the given key file. " "Not needed when security-policy is set to \"no-tls\"." msgstr "" #: ../infinoted/infinoted-options.c:71 ../infinoted/infinoted-options.c:85 msgid "CERT-FILE" msgstr "" #: ../infinoted/infinoted-options.c:79 msgid "" "Optional file which contains the issuer certificate of the server " "certificate, and the issuer's issuer, and so on. This option can be used " "when the issuer certificates are not stored in the same file as the server " "certificate. If the issuer certificates are not available the server will " "still run, but not show the issuer certificates to connecting clients." msgstr "" #: ../infinoted/infinoted-options.c:93 #, fuzzy msgid "The TCP port number to listen on." msgstr "El número de port on escoltar" #: ../infinoted/infinoted-options.c:94 msgid "PORT" msgstr "PORT" #: ../infinoted/infinoted-options.c:102 #, fuzzy msgid "The IP address to listen on." msgstr "El número de port on escoltar" #: ../infinoted/infinoted-options.c:103 msgid "ADDRESS" msgstr "" #: ../infinoted/infinoted-options.c:111 msgid "" "Whether to use Transport Layer Security (TLS) or not. Allowed values are " "\"no-tls\", \"allow-tls\" or \"require-tls\". When TLS is allowed or " "required, a server certificate must be provided. Infinoted has a built-in " "option to create a self-signed certificate with the --create-key and --" "create-certificate command line options. When TLS is allowed but not " "required, clients may choose not to use TLS. It is strongly encouraged to " "always require TLS. [Default=require-tls]" msgstr "" #: ../infinoted/infinoted-options.c:119 msgid "no-tls|allow-tls|require-tls" msgstr "" #: ../infinoted/infinoted-options.c:127 msgid "" "The directory which infinoted uses to permanantly store all documents on the " "server, and where they are read from after a server restart. [Default=~/." "infinote]" msgstr "" #: ../infinoted/infinoted-options.c:130 #: ../infinoted/plugins/infinoted-plugin-directory-sync.c:603 #: ../infinoted/plugins/infinoted-plugin-traffic-logging.c:326 msgid "DIRECTORY" msgstr "DIRECTORI" #: ../infinoted/infinoted-options.c:138 msgid "" "Additional plugins to load. This option can be specified more than once to " "load multiple plugins. Plugin options can be configured in the configuration " "file (one section for each plugin), or with the --plugin-parameter option. " "[Default=note-text]" msgstr "" #: ../infinoted/infinoted-options.c:142 msgid "PLUGIN-NAME" msgstr "" #: ../infinoted/infinoted-options.c:150 msgid "" "If set, require clients to enter a password before being allowed to connect " "to the server. This option cannot be combined with --pam-service." msgstr "" #: ../infinoted/infinoted-options.c:153 msgid "Password" msgstr "" #: ../infinoted/infinoted-options.c:162 msgid "" "Authenticate clients using the given PAM service. This option cannot be " "combined with --password. Clients are requested to send their user name and " "then enter the password for their account on the server machine with the " "same name." msgstr "" #: ../infinoted/infinoted-options.c:166 msgid "SERVICE" msgstr "" #: ../infinoted/infinoted-options.c:174 msgid "" "If set, only the given username is allowed to connect to the server. This " "option can be given multiple times to allow multiple users." msgstr "" #: ../infinoted/infinoted-options.c:177 msgid "USER" msgstr "" #: ../infinoted/infinoted-options.c:185 msgid "" "If set, only users belonging to the given group are allowed to connect to " "the server. This option can be given multiple times to allow multiple groups." msgstr "" #: ../infinoted/infinoted-options.c:188 msgid "GROUPS" msgstr "" #: ../infinoted/infinoted-options.c:215 msgid "Cannot use both server password and system authentication." msgstr "" #: ../infinoted/infinoted-options.c:228 msgid "Need a pam service to authenticate users." msgstr "" #: ../infinoted/infinoted-options.c:248 msgid "WARNING: Requiring password through unencrypted connection." msgstr "" #: ../infinoted/infinoted-options.c:258 msgid "" "Creating a new private key also requires creating a new certificate signed " "with it." msgstr "" #: ../infinoted/infinoted-options.c:271 msgid "" "No private key file given. If you don't have a suitable key file, either " "create one using the --create-key command line argument, or disable TLS by " "setting the security policy to \"no-tls\"." msgstr "" #: ../infinoted/infinoted-options.c:285 msgid "" "No certificate file given. If you don't have a suitable certificate file, " "either create one using the --create-certificate command line agument, or " "disable TLS via by setting the security policy to \"no-tls\"." msgstr "" #: ../infinoted/infinoted-options.c:329 #, c-format msgid "Error reading configuration file \"%s\": " msgstr "" #: ../infinoted/infinoted-options.c:387 ../infinoted/infinoted-options.c:431 #: ../infinoted/infinoted-options.c:505 #, c-format msgid "The option \"%s\" can only be given once" msgstr "" #: ../infinoted/infinoted-options.c:416 #, c-format msgid "\"%s\" cannot be interpreted as a boolean value" msgstr "" #: ../infinoted/infinoted-options.c:446 #, c-format msgid "\"%s\" is not a number" msgstr "" #: ../infinoted/infinoted-options.c:458 #, c-format msgid "Could not read the number \"%s\": %s" msgstr "" #: ../infinoted/infinoted-options.c:471 #, c-format msgid "Number \"%s\" is too small" msgstr "" #: ../infinoted/infinoted-options.c:483 #, c-format msgid "Number \"%s\" is too large" msgstr "" #: ../infinoted/infinoted-options.c:693 msgid "Configuration file to load, instead of the default configuration file" msgstr "" #: ../infinoted/infinoted-options.c:695 msgid "CONFIG-FILE" msgstr "" #: ../infinoted/infinoted-options.c:699 msgid "" "Creates a new random private key. The new key will be stored at the given " "location for the server's private key." msgstr "" #: ../infinoted/infinoted-options.c:705 msgid "" "Creates a new self-signed certificate signed with the given private key. The " "certificate is stored at the given location for the server's certificate." msgstr "" #: ../infinoted/infinoted-options.c:712 msgid "" "Allows one to override configuration entries for plugins from the command " "line. The syntax is --plugin-parameter=plugin:key:value, where plugin is the " "name of the plugin for which to override a configuration parameter, key is " "the parameter which to override and value is the new value of the parameter" msgstr "" #: ../infinoted/infinoted-options.c:717 msgid "PLUGIN:PARAMETER:VALUE" msgstr "" #: ../infinoted/infinoted-options.c:722 msgid "Daemonize the server, i.e. run it in the background" msgstr "" #: ../infinoted/infinoted-options.c:726 msgid "Kill a running daemon and exit" msgstr "" #: ../infinoted/infinoted-options.c:731 msgid "Display version information and exit" msgstr "" #: ../infinoted/infinoted-options.c:790 msgid "Infinoted Options" msgstr "" #: ../infinoted/infinoted-options.c:791 msgid "Main Program Options" msgstr "" #: ../infinoted/infinoted-options.c:800 msgid "infinote dedicated server" msgstr "" #: ../infinoted/infinoted-options.c:835 msgid "Could not kill daemon" msgstr "" #: ../infinoted/infinoted-pam.c:100 msgid "Entry not found" msgstr "" #: ../infinoted/infinoted-pam.c:106 #, c-format msgid "Error while checking groups of user \"%s\", %s: %s." msgstr "" #: ../infinoted/infinoted-pam.c:144 msgid "looking up user information" msgstr "" #: ../infinoted/infinoted-pam.c:155 #, c-format msgid "looking up group %ld" msgstr "" #: ../infinoted/infinoted-pam.c:170 #, c-format msgid "looking up group \"%s\"" msgstr "" #: ../infinoted/infinoted-parameter.c:145 #, c-format msgid "The parameter \"%s\" is required" msgstr "" #: ../infinoted/infinoted-parameter.c:514 #, c-format msgid "\"%d\" is not a valid port number. Port numbers range from 1 to 65535" msgstr "" #: ../infinoted/infinoted-parameter.c:562 msgid "Invalid IP address" msgstr "" #: ../infinoted/infinoted-parameter.c:601 msgid "Number must not be negative" msgstr "" #: ../infinoted/infinoted-parameter.c:640 msgid "Number must be positive" msgstr "" #: ../infinoted/infinoted-parameter.c:697 #, c-format msgid "" "\"%s\" is not a valid security policy. Allowed values are \"no-tls\", " "\"allow-tls\" or \"require-tls\"" msgstr "" #: ../infinoted/infinoted-parameter.c:769 #, c-format msgid "\"%s\" is not a valid value. Allowed values are: %s." msgstr "" #: ../infinoted/infinoted-plugin-manager.c:490 #, c-format msgid "Loaded plugin \"%s\" from \"%s\"" msgstr "" #: ../infinoted/infinoted-plugin-manager.c:534 #, c-format msgid "Unloaded plugin \"%s\" from \"%s\"" msgstr "" #: ../infinoted/infinoted-run.c:394 #, c-format msgid "Failed to generate Diffie-Hellman parameters: %s" msgstr "" #: ../infinoted/infinoted-run.c:414 #, c-format msgid "IPv6 Server running on port %u" msgstr "" #: ../infinoted/infinoted-run.c:437 #, c-format msgid "IPv4 Server running on port %u" msgstr "" #: ../infinoted/infinoted-run.c:458 #, c-format msgid "Failed to start server: %s" msgstr "" #: ../infinoted/infinoted-run.c:476 msgid "Infinoted shutting down..." msgstr "" #: ../infinoted/infinoted-signal.c:58 msgid "" "Error on signal handler connection; signal handlers have been removed from " "now on" msgstr "" #: ../infinoted/infinoted-signal.c:77 #, c-format msgid "Configuration reload failed: %s" msgstr "" #: ../infinoted/infinoted-signal.c:86 msgid "Configuration reloaded" msgstr "" #: ../infinoted/infinoted-signal.c:146 msgid "" "For config reloading to work libinfinity needs to be compiled with libdaemon " "support" msgstr "" #. TODO: Open the key file beforehand #: ../infinoted/infinoted-startup.c:62 msgid "Generating 4096 bit RSA private key..." msgstr "" #: ../infinoted/infinoted-startup.c:104 msgid "Generating self-signed certificate..." msgstr "" #: ../infinoted/infinoted-startup.c:321 #, c-format msgid "User %s failed to log in from %s: PAM authentication failed" msgstr "" #: ../infinoted/infinoted-startup.c:341 #, c-format msgid "User %s failed to log in from %s: PAM user not allowed" msgstr "" #: ../infinoted/infinoted-startup.c:361 #, c-format msgid "User %s logged in from %s via PAM" msgstr "" #: ../infinoted/infinoted-startup.c:392 #, c-format msgid "User %s logged in from %s via password" msgstr "" #: ../infinoted/infinoted-startup.c:403 #, c-format msgid "User %s failed to log in from %s: wrong password" msgstr "" #: ../infinoted/plugins/infinoted-plugin-autosave.c:151 #, c-format msgid "" "Failed to auto-save session \"%s\": %s\n" "\n" "Will retry in %u seconds." msgstr "" "Ha fallat el desament de la sessió «%s»: %s\n" "\n" "Es tornarà a intentar en %u segons." #: ../infinoted/plugins/infinoted-plugin-autosave.c:191 #, c-format msgid "Could not execute autosave hook: \"%s\"" msgstr "" #: ../infinoted/plugins/infinoted-plugin-autosave.c:328 msgid "" "Interval, in seconds, after which to save documents into the root directory. " "Documents are also stored to disk when there has been no user logged into " "them for 60 seconds." msgstr "" #: ../infinoted/plugins/infinoted-plugin-autosave.c:331 #: ../infinoted/plugins/infinoted-plugin-directory-sync.c:613 msgid "SECONDS" msgstr "" #: ../infinoted/plugins/infinoted-plugin-autosave.c:339 #: ../infinoted/plugins/infinoted-plugin-directory-sync.c:621 msgid "Command to run after having saved a document." msgstr "" #: ../infinoted/plugins/infinoted-plugin-autosave.c:340 #: ../infinoted/plugins/infinoted-plugin-directory-sync.c:622 msgid "PROGRAM" msgstr "" #: ../infinoted/plugins/infinoted-plugin-autosave.c:352 msgid "" "Periodically saves the content of all documents to disk. If this plugin is " "not enabled, infinoted only moves a document to permanent storage 60 seconds " "after the last user left the document." msgstr "" #: ../infinoted/plugins/infinoted-plugin-certificate-auth.c:77 #, c-format msgid "Failed to set permissions for super user: %s" msgstr "" #: ../infinoted/plugins/infinoted-plugin-certificate-auth.c:97 #, c-format msgid "" "Failed to remove super user on server shutdown. This should not be a problem " "since the account is not made persistent, however might point to an " "inconsistency in the server setup. The error message was: %s" msgstr "" #: ../infinoted/plugins/infinoted-plugin-certificate-auth.c:226 msgid "" "The certificate-auth plugin can only be used when TLS is enabled and a " "server certificate has been set." msgstr "" #: ../infinoted/plugins/infinoted-plugin-certificate-auth.c:243 #, fuzzy, c-format msgid "File \"%s\" does not contain any CA certificates" msgstr "El camí «%s» no conté cap connector de notes" #: ../infinoted/plugins/infinoted-plugin-certificate-auth.c:288 msgid "The given CA key does not match with any of the CA certificates" msgstr "" #: ../infinoted/plugins/infinoted-plugin-certificate-auth.c:321 msgid "Cannot generate a superuser certificate without CA key" msgstr "" #: ../infinoted/plugins/infinoted-plugin-certificate-auth.c:330 msgid "Creating 4096-bit RSA private key for the super user account..." msgstr "" #: ../infinoted/plugins/infinoted-plugin-certificate-auth.c:358 msgid "Super User" msgstr "" #: ../infinoted/plugins/infinoted-plugin-certificate-auth.c:598 msgid "" "The trusted CA or list of trusted CAs. Only clients presenting a certificate " "signed by one of these CAs are accepted." msgstr "" #: ../infinoted/plugins/infinoted-plugin-certificate-auth.c:600 msgid "CA-LIST" msgstr "" #: ../infinoted/plugins/infinoted-plugin-certificate-auth.c:608 msgid "" "If given, this is the private key for one of the CA certificates in the list " "given by the \"ca-list\" parameter. In this case, the server itself acts as " "a CA and can issue certificates to clients. This can be used to allow " "clients to create their own accounts." msgstr "" #: ../infinoted/plugins/infinoted-plugin-certificate-auth.c:612 msgid "CA-KEY" msgstr "" #: ../infinoted/plugins/infinoted-plugin-certificate-auth.c:620 msgid "" "If this value is set to false, then clients that cannot authenticate " "themselves with a valid certificate are rejected and the connection is " "closed. If it is set to true, the connection will be accepted, but the " "client will only have unauthenticated access to the server. [Default: false]" msgstr "" #: ../infinoted/plugins/infinoted-plugin-certificate-auth.c:633 msgid "" "Filename to which to write a short-lived super-user private key and " "certificate. The user is deleted when the infinoted server goes down or the " "plugin is re-loaded. This option can only be given when the \"ca-key\" " "parameter is set." msgstr "" #: ../infinoted/plugins/infinoted-plugin-certificate-auth.c:637 msgid "FILENAME" msgstr "" #: ../infinoted/plugins/infinoted-plugin-certificate-auth.c:645 msgid "" "Flags to be used when verifying a client certificate. Each of these flags " "weakens the security, and so should be set only when absolutely necessary, " "and it should be done with care. [Default: disable-ca-sign]" msgstr "" #: ../infinoted/plugins/infinoted-plugin-certificate-auth.c:649 msgid "flag1;flag2;[...]" msgstr "" #: ../infinoted/plugins/infinoted-plugin-certificate-auth.c:661 msgid "" "Allows clients to authenticate themselves with client-side certificates. If " "authentication is successful, the certificate ID is used to log the user " "into its account." msgstr "" #: ../infinoted/plugins/infinoted-plugin-dbus.c:1188 #, c-format msgid "" "\"%s\" is not a valid bus type. Allowed values are \"system\" or \"session\"" msgstr "" #: ../infinoted/plugins/infinoted-plugin-dbus.c:1207 msgid "" "The bus type to use, either \"session\" or \"system\". [default=session]" msgstr "" #: ../infinoted/plugins/infinoted-plugin-dbus.c:1209 msgid "TYPE" msgstr "" #: ../infinoted/plugins/infinoted-plugin-dbus.c:1217 msgid "The name to own on the bus. [default=org.infinote.infinoted]" msgstr "" #: ../infinoted/plugins/infinoted-plugin-dbus.c:1218 msgid "NAME" msgstr "" #: ../infinoted/plugins/infinoted-plugin-dbus.c:1230 msgid "Exports infinoted functionality on D-Bus" msgstr "" #: ../infinoted/plugins/infinoted-plugin-directory-sync.c:93 #, c-format msgid "Failed to convert path \"%s\" from UTF-8 to %s: " msgstr "" #: ../infinoted/plugins/infinoted-plugin-directory-sync.c:199 #, c-format msgid "Failed to remove directory \"%s\": " msgstr "" #: ../infinoted/plugins/infinoted-plugin-directory-sync.c:255 #, c-format msgid "Failed to create directory for path \"%s\": " msgstr "" #: ../infinoted/plugins/infinoted-plugin-directory-sync.c:283 #, c-format msgid "Failed to write session for path \"%s\": " msgstr "" #: ../infinoted/plugins/infinoted-plugin-directory-sync.c:315 #, c-format msgid "Failed to execute hook \"%s\": " msgstr "" #: ../infinoted/plugins/infinoted-plugin-directory-sync.c:347 #, c-format msgid "" "%s\n" "\tWill retry in %u seconds" msgstr "" #: ../infinoted/plugins/infinoted-plugin-directory-sync.c:358 #, c-format msgid "%s" msgstr "" #: ../infinoted/plugins/infinoted-plugin-directory-sync.c:522 #, c-format msgid "Node \"%s\" contains invalid characters" msgstr "" #: ../infinoted/plugins/infinoted-plugin-directory-sync.c:602 msgid "The directory into which to store the directory tree in text form." msgstr "" #: ../infinoted/plugins/infinoted-plugin-directory-sync.c:611 msgid "" "Interval, in seconds, after which to save documents into the given directory." msgstr "" #: ../infinoted/plugins/infinoted-plugin-directory-sync.c:634 msgid "" "Periodically saves the content of all documents into a custom directory, " "without any infinote metadata such as which user wrote what text. This " "option can be used to (automatically) process the files on the server by " "standard tools that operate on normal UTF-8 encoded text files" msgstr "" #: ../infinoted/plugins/infinoted-plugin-document-stream.c:669 msgid "Not a text or chat node" msgstr "" #: ../infinoted/plugins/infinoted-plugin-document-stream.c:1503 msgid "Allows streaming of document changes to external programs" msgstr "" #: ../infinoted/plugins/infinoted-plugin-linekeeper.c:317 #, c-format msgid "Could not join LineKeeper user for document: %s\n" msgstr "" #: ../infinoted/plugins/infinoted-plugin-linekeeper.c:549 msgid "The number of empty lines to keep at the end of the document." msgstr "" #: ../infinoted/plugins/infinoted-plugin-linekeeper.c:550 msgid "LINES" msgstr "" #: ../infinoted/plugins/infinoted-plugin-linekeeper.c:562 msgid "" "This plugin makes sure that at the end of every document there is always a " "fixed number of empty lines." msgstr "" #: ../infinoted/plugins/infinoted-plugin-logging.c:224 #, c-format msgid "when executing request \"%s\" from user %s (%s) in document %s" msgstr "" #: ../infinoted/plugins/infinoted-plugin-logging.c:285 #, c-format msgid "Error from connection %s: %s" msgstr "" #: ../infinoted/plugins/infinoted-plugin-logging.c:322 #, c-format msgid "in document %s from connection %s. The request was: %s" msgstr "" #: ../infinoted/plugins/infinoted-plugin-logging.c:336 #, c-format msgid "Session error: %s" msgstr "" #: ../infinoted/plugins/infinoted-plugin-logging.c:449 #: ../infinoted/plugins/infinoted-plugin-logging.c:517 #: ../infinoted/plugins/infinoted-plugin-traffic-logging.c:237 #, fuzzy, c-format msgid "%s connected" msgstr "Desconnectat" #: ../infinoted/plugins/infinoted-plugin-logging.c:566 #, c-format msgid "Unsuccessful connection attempt from %s" msgstr "" #: ../infinoted/plugins/infinoted-plugin-logging.c:574 #, fuzzy, c-format msgid "%s disconnected" msgstr "Desconnectat" #: ../infinoted/plugins/infinoted-plugin-logging.c:711 msgid "Whether to write a log message when a new user connects or disconnects." msgstr "" #: ../infinoted/plugins/infinoted-plugin-logging.c:721 msgid "" "Whether to write a log message when an error with a connection is detected, " "usually leading to disconnection of the user." msgstr "" #: ../infinoted/plugins/infinoted-plugin-logging.c:731 msgid "" "Whether to write a log message when a session cannot process a client " "request, mostly caused by invalid client requests." msgstr "" #: ../infinoted/plugins/infinoted-plugin-logging.c:741 msgid "" "Whether to write an additional line into the log when a message occurs " "during transformation of an adOPTed request. This is mostly used for " "debugging purposes to find problems in the server implementation itself." msgstr "" #: ../infinoted/plugins/infinoted-plugin-logging.c:757 msgid "" "This plugin writes extra information into the infinoted log. By default all " "extra information is logged, but individual events can be turned off with " "the plugin options." msgstr "" #: ../infinoted/plugins/infinoted-plugin-note-chat.c:166 #: ../infinoted/plugins/infinoted-plugin-note-text.c:172 #, c-format msgid "There is a already a plugin which handles sessions of type \"%s\"" msgstr "" #: ../infinoted/plugins/infinoted-plugin-note-chat.c:211 msgid "Adds support to handle chat documents." msgstr "" #: ../infinoted/plugins/infinoted-plugin-note-text.c:217 msgid "Adds support to handle plain text documents." msgstr "" #: ../infinoted/plugins/infinoted-plugin-record.c:71 #, c-format msgid "" "Could not create record file for session \"%s\": Could not generate unused " "record file in directory \"%s\"" msgstr "" #: ../infinoted/plugins/infinoted-plugin-record.c:88 #, c-format msgid "Could not create directory \"%s\": %s" msgstr "" #: ../infinoted/plugins/infinoted-plugin-record.c:104 #, c-format msgid "Error while writing record for session \"%s\" into \"%s\": %s" msgstr "" #: ../infinoted/plugins/infinoted-plugin-record.c:221 msgid "" "Creates a recording of each session that can be replayed later. The records " "are created in the ~/.infinoted-records directory." msgstr "" #: ../infinoted/plugins/infinoted-plugin-traffic-logging.c:136 #, c-format msgid "Connection error: %s" msgstr "" #: ../infinoted/plugins/infinoted-plugin-traffic-logging.c:211 #, c-format msgid "" "Failed to create directory \"%s\": %s\n" "Traffic logging for connection \"%s\" is disabled." msgstr "" #: ../infinoted/plugins/infinoted-plugin-traffic-logging.c:228 #, c-format msgid "" "Failed to open file \"%s\": %s\n" "Traffic logging for connection \"%s\" is disabled." msgstr "" #: ../infinoted/plugins/infinoted-plugin-traffic-logging.c:300 msgid "Log closed" msgstr "" #: ../infinoted/plugins/infinoted-plugin-traffic-logging.c:325 msgid "The directory into which to write the log files." msgstr "" #: ../infinoted/plugins/infinoted-plugin-traffic-logging.c:338 msgid "" "This plugin writes a dump of all network traffic between the server and the " "client into a file. Note that the traffic written to the log files is " "unencrypted. It is meant to be used as a diagnostic tool for debugging, and " "it should never be used in a production environment as it is a severe " "privacy issue." msgstr "" #: ../infinoted/plugins/infinoted-plugin-transformation-protection.c:105 #, c-format msgid "" "In document \"%s\": Attempt to transform request \"%s\" to current state \"%s" "\" (vdiff=%u) by user \"%s\" (id=%u, conn=%s). Maximum allowed is %u; the " "connection has been unsubscribed." msgstr "" #: ../infinoted/plugins/infinoted-plugin-transformation-protection.c:216 msgid "" "The maximum number of individual transformations to allow. If a client makes " "a request that would require more than this number of transformations, the " "request is rejected and the client is unsubscribed from the session." msgstr "" #: ../infinoted/plugins/infinoted-plugin-transformation-protection.c:220 msgid "DIFF" msgstr "" #: ../infinoted/plugins/infinoted-plugin-transformation-protection.c:232 msgid "" "This plugin tries to protect the server from malicious clients that send " "formally valid requests but would take the server a long time to process, " "making in unresponsive to other requests. This is only possible if sessions " "use the \"central\" communication method. At the moment this is the only " "method available, so the plugin can always be used. Currently the plugin " "rejects requests that were made in a state too far behind the current state. " "However, additional criteria might be implemented in future versions." msgstr "" #: ../infinoted/plugins/util/infinoted-plugin-util-navigate-browser.c:137 #, c-format msgid "The path \"%.*s\" does not exist" msgstr "" #. should be const... #: ../infinoted/plugins/util/infinoted-plugin-util-navigate-browser.c:170 #, c-format msgid "Failed to explore path \"%.*s\": " msgstr "" #: ../infinoted/plugins/util/infinoted-plugin-util-navigate-browser.c:213 #, c-format msgid "The path \"%.*s\" does not exist or is not a directory" msgstr "" #: ../infinoted/plugins/util/infinoted-plugin-util-navigate-browser.c:284 #, c-format msgid "The path \"%.*s\" is not an absolute path" msgstr "" #: ../libinfgtk/inf-gtk-account-creation-dialog.c:198 #: ../libinfgtk/inf-gtk-account-creation-dialog.c:206 #, fuzzy msgid "Not connected to a server" msgstr "No connectat" #: ../libinfgtk/inf-gtk-account-creation-dialog.c:226 msgid "Permissions to create an account are not granted" msgstr "" #: ../libinfgtk/inf-gtk-account-creation-dialog.c:265 msgid "" "A private key is being generated. This process might take a few seconds..." msgstr "" #: ../libinfgtk/inf-gtk-account-creation-dialog.c:275 msgid "" "New account is being requested from the server. Usually, this should not " "take very long." msgstr "" #: ../libinfgtk/inf-gtk-browser-store.c:685 msgid "Disconnected" msgstr "Desconnectat" #: ../libinfgtk/inf-gtk-browser-view.c:2197 msgid "Exploring..." msgstr "" #: ../libinfgtk/inf-gtk-browser-view.c:2236 msgid "Synchronizing..." msgstr "S'està sincronitzant..." #: ../libinfgtk/inf-gtk-browser-view.c:2319 msgid "Not connected" msgstr "No connectat" #: ../libinfgtk/inf-gtk-browser-view.c:2330 msgid "Connecting..." msgstr "S'està connectant..." #: ../libinfgtk/inf-gtk-browser-view.c:2340 msgid "Connected" msgstr "Connectat" #: ../libinfgtk/inf-gtk-certificate-dialog.c:109 #, c-format msgid "The connection to host \"%s\" is not considered secure" msgstr "" #: ../libinfgtk/inf-gtk-certificate-dialog.c:130 msgid "The host has presented a new certificate." msgstr "" #: ../libinfgtk/inf-gtk-certificate-dialog.c:139 msgid "" "Its previous certificate has expired or is closed to expiration. Please make " "sure that you trust the new certificate." msgstr "" #: ../libinfgtk/inf-gtk-certificate-dialog.c:146 msgid "The host has presented an unexpected certificate!" msgstr "" #: ../libinfgtk/inf-gtk-certificate-dialog.c:155 msgid "" "This means someone might be eavesdropping on the connection. Please only " "continue if you expected this message, otherwise please contact the server " "administrator." msgstr "" #: ../libinfgtk/inf-gtk-certificate-dialog.c:165 msgid "" "The server certificate cannot be verified automatically. Please make sure " "that you trust this host before proceeding." msgstr "" #: ../libinfgtk/inf-gtk-certificate-dialog.c:176 msgid "The issuer of the certificate is not known." msgstr "" #: ../libinfgtk/inf-gtk-certificate-dialog.c:189 #, c-format msgid "" "The hostname of the server, \"%s\", does not match the hostname the " "certificate is issued to, \"%s\"." msgstr "" #: ../libinfgtk/inf-gtk-certificate-dialog.c:342 msgid "" msgstr "" #: ../libinfgtk/inf-gtk-certificate-manager.c:226 msgid "_Cancel connection" msgstr "" #: ../libinfgtk/inf-gtk-certificate-manager.c:232 msgid "C_ontinue connection" msgstr "" #: ../libinfgtk/inf-gtk-certificate-manager.c:237 #, c-format msgid "" "Do you want to continue the connection to host \"%s\"? If you choose to " "continue, this certificate will be trusted in the future when connecting to " "this host." msgstr "" #: ../libinfgtk/inf-gtk-certificate-view.c:72 msgid "" msgstr "" #: ../libinfgtk/inf-gtk-chat.c:202 #, c-format msgid "%s has joined" msgstr "" #: ../libinfgtk/inf-gtk-chat.c:209 #, c-format msgid "%s has left" msgstr "" #. Then, show a menu item to remove an account. #: ../libinfgtk/inf-gtk-permissions-dialog.c:1879 msgid "_Delete Account" msgstr "" #: ../libinfgtk/inf-gtk-permissions-dialog.c:2312 #, fuzzy msgid "No node selected" msgstr "No connectat" #: ../libinfgtk/inf-gtk-permissions-dialog.c:2318 #, c-format msgid "Permissions for %s" msgstr "" #: ../libinfgtk/inf-gtk-permissions-dialog.c:2496 msgid "" "Permission is not granted to modify the permission list. It is read-" "only." msgstr "" #: ../libinfgtk/inf-gtk-permissions-dialog.c:2520 msgid "Permission is granted to modify the permission list." msgstr "" #: ../libinfgtk/inf-gtk-permissions-dialog.c:2530 #, c-format msgid "Server Error: %s" msgstr "" #: ../libinfgtk/inf-gtk-permissions-dialog.c:2538 msgid "Querying current permissions for this node from the server..." msgstr "" #: ../libinfgtk/inf-gtk-permissions-dialog.c:2544 msgid "" "Permission is not granted to query the permission list for this node " "from the server. Showing only default permissions and permissions for the " "own account." msgstr "" #: ../libinfgtk/inf-gtk-permissions-dialog.c:2551 msgid "" "Permissions are granted to query the full permission list from the " "server. Showing all permissions." msgstr "" #: ../libinfgtk/resources/ui/infgtkaccountcreationdialog.ui:12 msgid "Create New Account" msgstr "" #: ../libinfgtk/resources/ui/infgtkaccountcreationdialog.ui:75 msgid "Account Name:" msgstr "" #: ../libinfgtk/resources/ui/infgtkaccountcreationdialog.ui:98 msgid "Create _Account" msgstr "" #: ../libinfgtk/resources/ui/infgtkaclsheetview.ui:31 msgid "Permission" msgstr "" #: ../libinfgtk/resources/ui/infgtkaclsheetview.ui:43 msgid "Default" msgstr "" #: ../libinfgtk/resources/ui/infgtkaclsheetview.ui:55 msgid "Yes" msgstr "" #: ../libinfgtk/resources/ui/infgtkaclsheetview.ui:67 msgid "No" msgstr "" #: ../libinfgtk/resources/ui/infgtkcertificatedialog.ui:14 msgid "Connection Not Secure" msgstr "" #: ../libinfgtk/resources/ui/infgtkcertificatedialog.ui:138 msgid "Certificate Chain" msgstr "Cadena de certificats" #: ../libinfgtk/resources/ui/infgtkcertificatedialog.ui:172 msgid "_View Certificate" msgstr "_Visualitza el certificat" #: ../libinfgtk/resources/ui/infgtkcertificateview.ui:11 #, fuzzy msgid "Issued To" msgstr "Emès per" #: ../libinfgtk/resources/ui/infgtkcertificateview.ui:26 #: ../libinfgtk/resources/ui/infgtkcertificateview.ui:134 msgid "Common Name:" msgstr "" #: ../libinfgtk/resources/ui/infgtkcertificateview.ui:48 #: ../libinfgtk/resources/ui/infgtkcertificateview.ui:156 msgid "Organization:" msgstr "Organització:" #: ../libinfgtk/resources/ui/infgtkcertificateview.ui:70 #: ../libinfgtk/resources/ui/infgtkcertificateview.ui:178 msgid "Organizational Unit:" msgstr "Unitat organitzativa:" #: ../libinfgtk/resources/ui/infgtkcertificateview.ui:92 msgid "Serial Number:" msgstr "Número de sèrie:" #: ../libinfgtk/resources/ui/infgtkcertificateview.ui:119 msgid "Issued By" msgstr "Emès per" #: ../libinfgtk/resources/ui/infgtkcertificateview.ui:200 msgid "Validity" msgstr "Validesa" #: ../libinfgtk/resources/ui/infgtkcertificateview.ui:215 msgid "Issued On:" msgstr "Emès el:" #: ../libinfgtk/resources/ui/infgtkcertificateview.ui:237 msgid "Expires On:" msgstr "Venç el:" #: ../libinfgtk/resources/ui/infgtkcertificateview.ui:259 msgid "Fingerprints" msgstr "Empremtes" #: ../libinfgtk/resources/ui/infgtkcertificateview.ui:274 #, fuzzy msgid "SHA-1 Fingerprint:" msgstr "Empremta SHA1:" #: ../libinfgtk/resources/ui/infgtkcertificateview.ui:301 #, fuzzy msgid "SHA-256 Fingerprint:" msgstr "Empremta SHA1:" #: ../libinfgtk/resources/ui/infgtkcertificateview.ui:333 msgid "Signature" msgstr "" #: ../libinfgtk/resources/ui/infgtkcertificateview.ui:348 msgid "Signature Algorithm:" msgstr "" #: ../libinfgtk/resources/ui/infgtkchat.ui:93 msgid "Send" msgstr "Envia" #: ../libinfgtk/resources/ui/infgtkpermissionsdialog.ui:121 msgid "Accounts" msgstr "" #: ../libinfinity/adopted/inf-adopted-algorithm.c:1013 #, c-format msgid "Failed to apply request \"%s\" from user \"%s\" at state \"%s\": " msgstr "" #: ../libinfinity/adopted/inf-adopted-algorithm.c:1899 #, c-format msgid "" "The request \"%s\" from user \"%s\" is an UNDO request but there is no " "request to be undone." msgstr "" #: ../libinfinity/adopted/inf-adopted-algorithm.c:1920 #, c-format msgid "" "The request \"%s\" from user \"%s\" is a REDO request but there is no " "request to be redone." msgstr "" #: ../libinfinity/adopted/inf-adopted-session.c:160 #, c-format msgid "Request has index '%u', but index '%u' was expected" msgstr "" #: ../libinfinity/adopted/inf-adopted-session.c:181 msgid "Undo received, but no previous request found" msgstr "" #: ../libinfinity/adopted/inf-adopted-session.c:197 msgid "Redo received, but no previous request found" msgstr "" #: ../libinfinity/adopted/inf-adopted-session.c:238 #, c-format msgid "No such user with user ID '%u'" msgstr "" #: ../libinfinity/adopted/inf-adopted-session.c:481 msgid "The request was rejected via the API" msgstr "" #: ../libinfinity/adopted/inf-adopted-session.c:1173 #: ../libinfinity/common/inf-chat-session.c:468 #: ../libinfinity/common/inf-session.c:782 ../libinftext/inf-text-session.c:949 msgid "User did not join from this connection" msgstr "" #: ../libinfinity/adopted/inf-adopted-session.c:1223 #, c-format msgid "" "Request \"%s\" by user \"%s\" is not consecutive with respect to previously " "received request \"%s\"" msgstr "" #: ../libinfinity/adopted/inf-adopted-session.c:1436 msgid "\"time\" attribute in user message is missing" msgstr "" #: ../libinfinity/adopted/inf-adopted-session.c:1884 msgid "Operation for request missing" msgstr "" #. Error writing record `': #: ../libinfinity/adopted/inf-adopted-session-record.c:95 #, c-format msgid "Error writing record \"%s\": %s" msgstr "" #: ../libinfinity/adopted/inf-adopted-session-replay.c:164 msgid "Unexpected end of recording" msgstr "" #: ../libinfinity/adopted/inf-adopted-session-replay.c:356 msgid "Document is not a session recording" msgstr "" #: ../libinfinity/adopted/inf-adopted-session-replay.c:371 msgid "Session type of the recording does not match" msgstr "" #: ../libinfinity/adopted/inf-adopted-session-replay.c:391 msgid "Initial session state missing in recording" msgstr "" #: ../libinfinity/adopted/inf-adopted-session-replay.c:465 msgid "Session switched to running without having finished playing the initial" msgstr "" #: ../libinfinity/adopted/inf-adopted-session-replay.c:485 msgid "Superfluous XML in initial session section" msgstr "" #: ../libinfinity/adopted/inf-adopted-session-replay.c:498 msgid "Session is still in synchronizing state after having played the initial" msgstr "" #: ../libinfinity/adopted/inf-adopted-session-replay.c:892 msgid "Superfluous XML in requests section" msgstr "" #: ../libinfinity/adopted/inf-adopted-session-replay.c:919 #: ../libinfinity/common/inf-chat-session.c:269 #, c-format msgid "No such user with ID \"%u\"" msgstr "" #: ../libinfinity/adopted/inf-adopted-session-replay.c:992 #, c-format msgid "Unexpected node \"%s\" in requests section" msgstr "" #: ../libinfinity/adopted/inf-adopted-state-vector.c:730 msgid "Expected \":\" after ID" msgstr "" #: ../libinfinity/adopted/inf-adopted-state-vector.c:744 #, c-format msgid "ID '%u' already occured before" msgstr "" #: ../libinfinity/adopted/inf-adopted-state-vector.c:761 #, c-format msgid "Expected ';' or end of string after component of ID '%u'" msgstr "" #: ../libinfinity/client/infc-browser.c:784 msgid "The node to subscribe to has been removed" msgstr "" #: ../libinfinity/client/infc-browser.c:811 #: ../libinfinity/client/infc-browser.c:839 msgid "" "The subdirectory into which the new node should have been created has been " "removed" msgstr "" #: ../libinfinity/client/infc-browser.c:990 msgid "Permissions to explore this node have been revoked" msgstr "" #: ../libinfinity/client/infc-browser.c:1030 #: ../libinfinity/client/infc-browser.c:1059 msgid "Permissions to explore the parent node have been revoked" msgstr "" #: ../libinfinity/client/infc-browser.c:1354 msgid "" "The server did not send an initial welcome message. This means that the " "server is running a lower version of the software which is incompatible to " "the client. Consider downgrading the client, or ask the server " "administrators to upgrade their software." msgstr "" #: ../libinfinity/client/infc-browser.c:1635 #, c-format msgid "" "This session requires communication method `%s' which is not installed for " "network `%s'" msgstr "" #: ../libinfinity/client/infc-browser.c:2448 #, c-format msgid "There is no such node with ID %u" msgstr "" #: ../libinfinity/client/infc-browser.c:2580 #, c-format msgid "" "The request contains a sequence number refering to a request of type '%s', " "but a request of either 'explore-node' or 'add-node' was expected." msgstr "" #: ../libinfinity/client/infc-browser.c:2831 msgid "" "The server uses an older version of the protocol which is no longer " "supported by this client. Consider using an earlier version of it, or ask " "the server administrators to upgrade their software." msgstr "" #: ../libinfinity/client/infc-browser.c:2844 msgid "" "The server uses a newer version of the protocol which is not supported by " "this client. Consider upgrading your client." msgstr "" #: ../libinfinity/client/infc-browser.c:3005 msgid "Node to explore does no longer exist" msgstr "" #: ../libinfinity/client/infc-browser.c:3016 msgid "Node to explore is not a subdirectory" msgstr "" #: ../libinfinity/client/infc-browser.c:3027 msgid "Node to explore is already explored" msgstr "" #: ../libinfinity/client/infc-browser.c:3072 msgid "Not all nodes were received before explore-end was received" msgstr "" #: ../libinfinity/client/infc-browser.c:3134 #: ../libinfinity/client/infc-browser.c:3358 #, c-format msgid "Node with ID \"%u\" exists already" msgstr "" #: ../libinfinity/client/infc-browser.c:3157 msgid "The parent node has not been explored yet" msgstr "" #: ../libinfinity/client/infc-browser.c:3232 msgid "Explored nodes cannot be initially be subscribed to" msgstr "" #: ../libinfinity/client/infc-browser.c:3247 #, c-format msgid "Note type \"%s\" not known" msgstr "" #: ../libinfinity/client/infc-browser.c:3402 msgid "Received sync-in without having requested one" msgstr "" #: ../libinfinity/client/infc-browser.c:3422 #, c-format msgid "Expected note type \"%s\" for sync-in, but received \"%s\"" msgstr "" #: ../libinfinity/client/infc-browser.c:3578 #, c-format msgid "Note type '%s' is not supported" msgstr "" #: ../libinfinity/client/infc-browser.c:3592 msgid "Already subscribed to this session" msgstr "" #: ../libinfinity/client/infc-browser.c:3648 msgid "Already subscribed to the chat session" msgstr "" #: ../libinfinity/client/infc-browser.c:3870 msgid "Not all users have been transmitted before user-list-end was received" msgstr "" #: ../libinfinity/client/infc-browser.c:4149 #, c-format msgid "" "Unknown account ID \"%s\" in server reply of \"%s\". Typically, this means " "the server claimed it notified us about new connections as soon as they are " "available, but it did not do so." msgstr "" #: ../libinfinity/client/infc-browser.c:4411 msgid "No certificate request has been made" msgstr "" #: ../libinfinity/client/infc-browser.c:4438 #: ../libinfinity/client/infc-browser.c:4468 #, fuzzy msgid "No certificate provided" msgstr "Cadena de certificats" #: ../libinfinity/client/infc-browser.c:4486 msgid "Cannot verify the certificate without server certificate" msgstr "" #: ../libinfinity/client/infc-browser.c:4536 #, c-format msgid "Server sent an invalid certificate (%s)" msgstr "" #: ../libinfinity/client/infc-browser.c:4643 #: ../libinfinity/server/infd-directory.c:3306 msgid "The default account cannot be removed" msgstr "" #: ../libinfinity/client/infc-browser.c:4796 #, c-format msgid "" "The request contains a sequence number refering to a request of type '%s', " "but a request of either 'query-acl' or 'set-acl' was expected." msgstr "" #: ../libinfinity/client/infc-browser.c:4969 #, c-format msgid "Error comes from unknown error domain '%s' (code %u)" msgstr "" #: ../libinfinity/client/infc-browser.c:5193 #, c-format msgid "Received unexpected network message \"%s\"" msgstr "" #: ../libinfinity/client/infc-browser.c:5216 #: ../libinfinity/client/infc-session-proxy.c:989 #, c-format msgid "Server reply could not be processed: %s" msgstr "" #: ../libinfinity/client/infc-request-manager.c:126 msgid "Sequence identifier causes overflow" msgstr "" #: ../libinfinity/client/infc-request-manager.c:138 msgid "Sequence components are not separated by '/'" msgstr "" #: ../libinfinity/client/infc-request-manager.c:152 msgid "Sequence number causes overflow" msgstr "" #: ../libinfinity/client/infc-request-manager.c:164 msgid "Trailing characters after sequence number" msgstr "" #: ../libinfinity/client/infc-request-manager.c:735 #, c-format msgid "No such sequence number %u" msgstr "" #: ../libinfinity/client/infc-request-manager.c:748 #, c-format msgid "" "The request contains a sequence number refering to a request of type '%s', " "but a request of type '%s' was expected" msgstr "" #: ../libinfinity/client/infc-request-manager.c:803 msgid "The request does not contain a sequence number, but one is required" msgstr "" #: ../libinfinity/client/infc-session-proxy.c:524 #, c-format msgid "Error comes from unknown error domain \"%s\" (code %u)" msgstr "" #: ../libinfinity/client/infc-session-proxy.c:666 msgid "Request does not contain required attribute \"id\"" msgstr "" #: ../libinfinity/client/infc-session-proxy.c:684 #: ../libinfinity/common/inf-session.c:768 #, c-format msgid "No such user with ID %u" msgstr "" #: ../libinfinity/common/inf-acl.c:763 msgid "ACL field must be either \"yes\" or \"no\"" msgstr "" #: ../libinfinity/common/inf-acl.c:1273 #, c-format msgid "Permissions for account ID \"%s\" defined more than once" msgstr "" #: ../libinfinity/common/inf-async-operation.c:115 msgid "" "InfIo object was deleted without InfAsyncOperation being freed! This is a " "programming error that leaves the program in an inconsistent state. " "Therefore, the program is aborted. Please fix your code." msgstr "" #: ../libinfinity/common/inf-chat-session.c:90 msgid "An invalid message type was sent" msgstr "" #: ../libinfinity/common/inf-chat-session.c:92 msgid "A user with the requested ID does not exist" msgstr "" #: ../libinfinity/common/inf-chat-session.c:94 msgid "An unknown chat session error has occured" msgstr "" #: ../libinfinity/common/inf-chat-session.c:96 #: ../libinfinity/common/inf-error.c:84 ../libinfinity/common/inf-error.c:131 #: ../libinfinity/common/inf-session.c:233 msgid "An error with unknown error code occured" msgstr "" #: ../libinfinity/common/inf-chat-session.c:360 #, c-format msgid "%s --- %s has joined\n" msgstr "" #: ../libinfinity/common/inf-chat-session.c:363 #, c-format msgid "%s --- %s has left\n" msgstr "" #: ../libinfinity/common/inf-chat-session.c:421 #, c-format msgid "%s --- %u users total\n" msgstr "" #: ../libinfinity/common/inf-chat-session.c:1244 #, c-format msgid "%s --- Log closed\n" msgstr "" #: ../libinfinity/common/inf-chat-session.c:1258 #, c-format msgid "%s --- Log opened\n" msgstr "" #: ../libinfinity/common/inf-discovery-avahi.c:542 #, c-format msgid "" "Avahi service browser is in failure state. Services of type '%s' are no " "longer discovered.\n" "\n" "The failure was: %s\n" msgstr "" #: ../libinfinity/common/inf-discovery-avahi.c:629 #, c-format msgid "" "Avahi entry group is in failure state. The service '%s' of type '%s' is no " "longer published.\n" "\n" "The failure was: %s\n" msgstr "" #: ../libinfinity/common/inf-discovery-avahi.c:839 #, c-format msgid "" "Failed to start Avahi client. Service discovery or publishing will not be " "possible.\n" "\n" "The occurred failure was: %s" msgstr "" #: ../libinfinity/common/inf-discovery-avahi.c:882 #, c-format msgid "" "Avahi client is in failure state. Service discovery or publishing is no " "longer possible.\n" "\n" "The occured failure was: %s\n" msgstr "" #. Translators: This is " (via on #. *
)", for example "ck (via eth0 on IPv4)". #: ../libinfinity/common/inf-discovery-avahi.c:1465 #, c-format msgid "%s (via %s on IPv4)" msgstr "" #: ../libinfinity/common/inf-discovery-avahi.c:1466 #, c-format msgid "%s (via %s on IPv6)" msgstr "" #: ../libinfinity/common/inf-error.c:68 msgid "Received error from an unknown domain" msgstr "" #: ../libinfinity/common/inf-error.c:70 msgid "Failed to process server reply" msgstr "" #: ../libinfinity/common/inf-error.c:72 msgid "Server reply contains invalid sequence number" msgstr "" #: ../libinfinity/common/inf-error.c:74 msgid "A required attribute was not set in request" msgstr "" #: ../libinfinity/common/inf-error.c:76 msgid "An attribute did not have valid content" msgstr "" #: ../libinfinity/common/inf-error.c:78 msgid "An attribute contained an invalid number" msgstr "" #: ../libinfinity/common/inf-error.c:80 msgid "Not authorized" msgstr "" #: ../libinfinity/common/inf-error.c:82 msgid "An unknown request error occured" msgstr "" #: ../libinfinity/common/inf-error.c:117 msgid "Name is already in use" msgstr "" #: ../libinfinity/common/inf-error.c:119 msgid "'id' attribute provided in request" msgstr "" #: ../libinfinity/common/inf-error.c:121 msgid "There is no user with the given ID" msgstr "" #: ../libinfinity/common/inf-error.c:123 msgid "'status' attribute is 'unavailable' in join or rejoin request" msgstr "" #: ../libinfinity/common/inf-error.c:125 msgid "User did not join via this connection" msgstr "" #: ../libinfinity/common/inf-error.c:127 msgid "'status' attribute has invalid value" msgstr "" #: ../libinfinity/common/inf-error.c:129 msgid "An unknown user error occured" msgstr "" #: ../libinfinity/common/inf-error.c:164 msgid "Server did not send an initial welcome message" msgstr "" #: ../libinfinity/common/inf-error.c:166 msgid "The server and client use different protocol versions" msgstr "" #: ../libinfinity/common/inf-error.c:168 msgid "A node with this name exists already" msgstr "" #: ../libinfinity/common/inf-error.c:170 msgid "Invalid node name" msgstr "" #: ../libinfinity/common/inf-error.c:172 msgid "Node does not exist" msgstr "" #: ../libinfinity/common/inf-error.c:174 msgid "No previous subscription request present" msgstr "" #: ../libinfinity/common/inf-error.c:176 msgid "The chat is disabled on the server side" msgstr "" #: ../libinfinity/common/inf-error.c:178 msgid "Node is not a subdirectory" msgstr "" #: ../libinfinity/common/inf-error.c:180 msgid "Node is not a note" msgstr "" #: ../libinfinity/common/inf-error.c:182 msgid "The node type is not supported by the server" msgstr "" #: ../libinfinity/common/inf-error.c:184 #: ../libinfinity/server/infd-directory.c:5948 msgid "The root node cannot be removed" msgstr "" #: ../libinfinity/common/inf-error.c:186 msgid "Subdirectory is not explored" msgstr "" #: ../libinfinity/common/inf-error.c:188 msgid "Subdirectory has already been explored" msgstr "" #: ../libinfinity/common/inf-error.c:190 msgid "Note type is not supported" msgstr "" #: ../libinfinity/common/inf-error.c:192 msgid "Connection is already subscribed to this session" msgstr "" #: ../libinfinity/common/inf-error.c:194 #: ../libinfinity/server/infd-directory.c:6212 msgid "The requesting connection is not subscribed to the session" msgstr "" #: ../libinfinity/common/inf-error.c:196 msgid "" "The server started to send explored nodes before telling howmany nodes to " "expect" msgstr "" #: ../libinfinity/common/inf-error.c:199 msgid "Server sent more explored nodes then announced" msgstr "" #: ../libinfinity/common/inf-error.c:201 msgid "Server sent not as much explored nodes as announced" msgstr "" #: ../libinfinity/common/inf-error.c:203 msgid "" "The session does not support the network through which the connection " "attempt is being made." msgstr "" #: ../libinfinity/common/inf-error.c:206 msgid "The session uses an unsupported communication method" msgstr "" #: ../libinfinity/common/inf-error.c:208 msgid "The requested operation is not supported by the server" msgstr "" #: ../libinfinity/common/inf-error.c:210 msgid "Received sync-in message without having requested a sync-in" msgstr "" #: ../libinfinity/common/inf-error.c:212 msgid "Client rejected subscription" msgstr "" #: ../libinfinity/common/inf-error.c:214 msgid "Unexpected XML message" msgstr "" #: ../libinfinity/common/inf-error.c:216 msgid "Server does not have a background storage" msgstr "" #: ../libinfinity/common/inf-error.c:218 msgid "The certificate is invalid or not trusted" msgstr "" #: ../libinfinity/common/inf-error.c:220 msgid "The account list has already been queried before" msgstr "" #: ../libinfinity/common/inf-error.c:222 msgid "The account list has not been queried" msgstr "" #: ../libinfinity/common/inf-error.c:224 msgid "An account with this ID exists already" msgstr "" #: ../libinfinity/common/inf-error.c:226 msgid "There is no such account with the given ID" msgstr "" #: ../libinfinity/common/inf-error.c:228 msgid "The ACL has already been queried" msgstr "" #: ../libinfinity/common/inf-error.c:230 msgid "The ACL has not been queried" msgstr "" #: ../libinfinity/common/inf-error.c:232 msgid "An unknown directory error has occured" msgstr "" #: ../libinfinity/common/inf-error.c:234 ../libinfinity/common/inf-error.c:277 msgid "An error with unknown code has occured" msgstr "" #: ../libinfinity/common/inf-error.c:268 msgid "User did not provide valid credentials." msgstr "" #: ../libinfinity/common/inf-error.c:270 msgid "User is not permitted to connect to this server." msgstr "" #: ../libinfinity/common/inf-error.c:272 msgid "Authentication was temporarily interrupted on the server side." msgstr "" #: ../libinfinity/common/inf-error.c:275 msgid "An error cocured while checking user permissions." msgstr "" #: ../libinfinity/common/inf-error.c:351 msgid "The certificate was revoked" msgstr "" #: ../libinfinity/common/inf-error.c:353 msgid "The certificate was not signed by a trusted CA" msgstr "" #: ../libinfinity/common/inf-error.c:355 msgid "The signer of the certificate is not a CA" msgstr "" #: ../libinfinity/common/inf-error.c:357 msgid "The certificate uses an insecure algorithm" msgstr "" #: ../libinfinity/common/inf-error.c:359 msgid "The certificate is not yet activated" msgstr "" #: ../libinfinity/common/inf-error.c:361 #, fuzzy msgid "The certificate has expired" msgstr "Cadena de certificats" #: ../libinfinity/common/inf-error.c:363 #, fuzzy msgid "The certificate is invalid" msgstr "Cadena de certificats" #: ../libinfinity/common/inf-name-resolver.c:205 msgid "The reply from the DNS server is incomplete" msgstr "" #: ../libinfinity/common/inf-name-resolver.c:742 #, c-format msgid "" "Failure during SRV record lookup: %s\n" "Will go on with normal A/AAAA lookup" msgstr "" #: ../libinfinity/common/inf-protocol.c:85 msgid "Major part of version number causes overflow" msgstr "" #: ../libinfinity/common/inf-protocol.c:97 msgid "Version number parts are not separated by '.'" msgstr "" #: ../libinfinity/common/inf-protocol.c:111 msgid "Minor part of version number causes overflow" msgstr "" #: ../libinfinity/common/inf-protocol.c:123 msgid "Trailing characters after version number" msgstr "" #: ../libinfinity/common/inf-session.c:198 msgid "Unexpectedly got an XML message in presync" msgstr "" #: ../libinfinity/common/inf-session.c:200 msgid "Got unexpected XML node during synchronization" msgstr "" #: ../libinfinity/common/inf-session.c:202 msgid "'id' attribute in user message is missing" msgstr "" #: ../libinfinity/common/inf-session.c:204 msgid "User ID is already in use" msgstr "" #: ../libinfinity/common/inf-session.c:206 msgid "'name' attribute in user message is missing" msgstr "" #: ../libinfinity/common/inf-session.c:208 msgid "User Name is already in use" msgstr "" #: ../libinfinity/common/inf-session.c:210 msgid "The connection was closed unexpectedly" msgstr "" #: ../libinfinity/common/inf-session.c:212 msgid "The sender cancelled the synchronization" msgstr "" #: ../libinfinity/common/inf-session.c:214 msgid "The receiver cancelled the synchronization" msgstr "" #: ../libinfinity/common/inf-session.c:216 msgid "Got begin-of-sync message, but synchronization is already in progress" msgstr "" #: ../libinfinity/common/inf-session.c:219 msgid "begin-of-sync message does not contain the number of messages to expect" msgstr "" #: ../libinfinity/common/inf-session.c:222 msgid "Got end-of-sync message, but synchronization is still in progress" msgstr "" #: ../libinfinity/common/inf-session.c:225 msgid "Expected begin-of-sync message as first message during synchronization" msgstr "" #: ../libinfinity/common/inf-session.c:228 msgid "Expected end-of-sync message as last message during synchronization" msgstr "" #: ../libinfinity/common/inf-session.c:231 msgid "An unknown synchronization error has occured" msgstr "" #. TODO: Add a possibilty for sub classes to register their error domains #. * that can occur in process_xml_sync. Maybe via a translate_error_sync #. * vfunc. #: ../libinfinity/common/inf-session.c:247 msgid "An error with unknown error domain occured" msgstr "" #: ../libinfinity/common/inf-session.c:937 #, c-format msgid "Received unhandled XML message '%s'" msgstr "" #: ../libinfinity/common/inf-session.c:1467 #, c-format msgid "Unexpectedly received XML message \"%s\" in presync" msgstr "" #: ../libinfinity/common/inf-session.c:1576 #, c-format msgid "Received unexpected XML message \"%s\" while synchronizing" msgstr "" #: ../libinfinity/common/inf-tcp-connection.c:1039 #, c-format msgid "Interface `%s' does not exist" msgstr "" #: ../libinfinity/common/inf-tcp-connection.c:1100 #, c-format msgid "Failed to retrieve local address: %s" msgstr "" #: ../libinfinity/common/inf-tcp-connection.c:1118 #, c-format msgid "Failed to retrieve local port: %s" msgstr "" #. TODO: We can probably implement this using GetInterfaceInfo() #: ../libinfinity/common/inf-tcp-connection.c:1134 msgid "The device-name property is not implemented on Win32" msgstr "" #. Failed to get name for device : #: ../libinfinity/common/inf-tcp-connection.c:1147 #, c-format msgid "Failed to get name for device %u: %s" msgstr "" #: ../libinfinity/common/inf-user.c:497 #, c-format msgid "Invalid user status: '%s'" msgstr "" #: ../libinfinity/common/inf-xml-util.c:60 #: ../libinfinity/common/inf-xml-util.c:117 #: ../libinfinity/common/inf-xml-util.c:236 #, c-format msgid "Attribute '%s' does not contain a valid number" msgstr "" #: ../libinfinity/common/inf-xml-util.c:72 #: ../libinfinity/common/inf-xml-util.c:129 #: ../libinfinity/common/inf-xml-util.c:160 #: ../libinfinity/common/inf-xml-util.c:204 #: ../libinfinity/common/inf-xml-util.c:249 #, c-format msgid "Attribute '%s' causes overflow (%s)" msgstr "" #: ../libinfinity/common/inf-xml-util.c:85 #: ../libinfinity/common/inf-xml-util.c:173 #: ../libinfinity/common/inf-xml-util.c:262 #, c-format msgid "Attribute '%s' causes underflow (%s)" msgstr "" #: ../libinfinity/common/inf-xml-util.c:454 #, c-format msgid "Request '%s' does not contain required attribute '%s'" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:400 msgid "The entity has sent XML that cannot be processed" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:402 msgid "" "The entity has sent a namespace prefix that is unsupported, or has sent no " "namespace prefix on an element that requires such a prefix" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:406 msgid "" "The server is closing the active stream for this entity because a new stream " "has been initiated that conflicts with the existing stream" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:410 msgid "" "The entity has not generated any traffic over the stream for some period of " "time" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:413 msgid "" "The value of the 'to' attribute provided by the initiating entity in the " "stream header corresponds to a hostname that is no longer hosted by the " "server" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:417 msgid "" "The value of the 'to' attribute provided by the initiating entity in the " "stream header does not correspond to a hostname that is hosted by the server" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:421 msgid "A stanza sent between two servers lacks a 'to' or 'from'attribute" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:424 msgid "" "The server has experienced a misconfiguration or an otherwise-undefined " "internal error that prevents it from servicing the stream" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:428 msgid "" "The JID or hostname provided in a 'from' address does not match an " "authorized JID or validated domain negotiated between servers via SASL or " "dialback, or between a client and a server via authentication and resource " "binding" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:433 msgid "" "The stream ID or dialback ID is invalid or does not match an ID previously " "provided" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:436 msgid "" "The streams namespace is something other than \"http://etherx.jabber.org/" "streams\" or the dialback namespace name is something other than \"jabber:" "server:dialback\"" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:440 msgid "" "The entity has sent invalid XML over the stream to a server that performs " "validation" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:443 msgid "" "The entity has attempted to send data before the stream has been " "authenticated, or otherwise is not authorized to perform an action related " "to stream negotiation" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:447 msgid "The entity has violated some local service policy" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:449 msgid "" "The server is unable to properly connect to a remote entity that is required " "for authentication or authorization" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:452 msgid "The server lacks the system resources necessary to service the stream" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:455 msgid "The entity has attempted to send restricted XML features" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:457 msgid "" "The server will not provide service to the initiating entity but is " "redirecting traffic to another host" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:460 msgid "The server is being shut down and all active streams are being closed" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:464 msgid "The error condition is not one of those defined by the other conditions" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:467 msgid "" "The initiating entity has encoded the stream in an encoding that is not " "supported by the server" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:470 msgid "" "The initiating entity has sent a first-level child of the stream that is not " "supported by the server." msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:473 msgid "" "The value of the 'version' attribute provided by the initiating entity in " "the stream header specifies a version of XMPP that is not supported by the " "server" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:477 msgid "The initiating entity has sent XML that is not well-formed" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:522 msgid "" "The receiving entity acknowledged an element sent by the initiating " "entity" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:525 msgid "" "The data provided by the initiating entity could not be processed because " "the Base64 encoding is incorrect" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:528 msgid "" "The authzid provided by the initiating entity is invalid, either because it " "is incorrectly formatted or because the initiating entity does not have " "permissions to authorize that ID" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:533 msgid "" "The initiating entity did not provide a mechanism or requested a mechanism " "that is not supported by the receiving entity" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:536 msgid "" "The mechanism requsted by the initiating entity is weaker than server policy " "permits for that initiating entity" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:539 msgid "" "The authentication failed because the initiating entity did not provide " "valid credentials" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:542 msgid "" "The authentication failed because of a temporary error condition within the " "receiving entity" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:545 msgid "An unknown authentication error has occured" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:1314 msgid "The server did not provide a certificate" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:2109 msgid "Stream is not yet secured with TLS" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:2176 msgid "Stream is not yet authorized" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:2304 msgid "The server does not offer a suitable authentication mechanism" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:2349 msgid "The server does not support transport layer security (TLS)" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:2372 msgid "The server requires transport layer security (TLS)" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:2406 msgid "The server does not provide any authentication mechanism" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:2464 msgid "The server cannot perform the TLS handshake" msgstr "" #. XML Warning from : #: ../libinfinity/common/inf-xmpp-connection.c:2946 #, c-format msgid "XML warning from %s: %s\n" msgstr "" #. The server sent something which is not XML #: ../libinfinity/common/inf-xmpp-connection.c:2990 msgid "Remote site is not an XMPP server" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:4606 msgid "The server certificate is not trusted" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:4614 #, c-format msgid "The server certificate is not trusted: %s" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:4626 msgid "The client certificate is not trusted" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:4634 #, c-format msgid "The client certificate is not trusted: %s" msgstr "" #: ../libinfinity/server/infd-account-storage.c:333 msgid "The account backend does not support acount listing" msgstr "" #: ../libinfinity/server/infd-account-storage.c:387 msgid "The account backend does not support adding accounts" msgstr "" #: ../libinfinity/server/infd-account-storage.c:427 msgid "The account backend does not support removing accounts" msgstr "" #: ../libinfinity/server/infd-account-storage.c:471 msgid "The account backend does not support logging in with a certificate" msgstr "" #: ../libinfinity/server/infd-account-storage.c:522 msgid "The account backend does not support logging in with a password" msgstr "" #: ../libinfinity/server/infd-account-storage.c:573 msgid "The account backend does not support changing the certificate" msgstr "" #: ../libinfinity/server/infd-account-storage.c:619 msgid "The account backend does not support changing the password" msgstr "" #: ../libinfinity/server/infd-chat-filesystem-format.c:145 #: ../libinfinity/server/infd-filesystem-storage.c:269 #: ../libinftext/inf-text-filesystem-format.c:368 #, c-format msgid "Error parsing XML in file \"%s\": [%d]: %s" msgstr "" #: ../libinfinity/server/infd-chat-filesystem-format.c:162 #: ../libinftext/inf-text-filesystem-format.c:385 #, c-format msgid "Error processing file \"%s\": %s" msgstr "" #: ../libinfinity/server/infd-chat-filesystem-format.c:164 msgid "The document is not a chat session" msgstr "" #: ../libinfinity/server/infd-directory.c:431 #, c-format msgid "" "Failed to save note \"%s\": %s\n" "\n" "Keeping it in memory. Another save attempt will be made when the server is " "shut down." msgstr "" #: ../libinfinity/server/infd-directory.c:955 #, c-format msgid "Failed to login client \"%s\" by certificate: %s" msgstr "" #: ../libinfinity/server/infd-directory.c:1000 #, c-format msgid "" "Failed to write ACL for node \"%s\": %s\n" "The new ACL is applied but will be lost after a server re-start. This is a " "possible security problem. Please fix the problem with the storage!" msgstr "" #: ../libinfinity/server/infd-directory.c:1198 #, c-format msgid "Failed to look up accounts in account storage: %s" msgstr "" #: ../libinfinity/server/infd-directory.c:1690 #, c-format msgid "" "Failed to read the ACL for the root node: %s\n" "In order not to compromise security all permissions have been revoked for " "all users. The infinote server is likely not very usable in this " "configuration, so please check the storage system, fix the problem and re-" "start the server." msgstr "" #: ../libinfinity/server/infd-directory.c:2086 #, c-format msgid "" "Could not write session \"%s\" to storage: %s\n" "\n" "All changes since the document das been saved are lost." msgstr "" #: ../libinfinity/server/infd-directory.c:2901 msgid "Server does not support issuing certificates" msgstr "" #: ../libinfinity/server/infd-directory.c:3014 msgid "The certificate request has no common name set" msgstr "" #: ../libinfinity/server/infd-directory.c:3069 #, c-format msgid "There is already a transient account with name \"%s\"" msgstr "" #: ../libinfinity/server/infd-directory.c:3132 msgid "This server does not support creating accounts" msgstr "" #: ../libinfinity/server/infd-directory.c:3333 #: ../libinfinity/server/infd-directory.c:11245 #: ../libinfinity/server/infd-filesystem-account-storage.c:1264 #: ../libinfinity/server/infd-filesystem-account-storage.c:1446 #: ../libinfinity/server/infd-filesystem-account-storage.c:1560 #, c-format msgid "There is no such account with ID \"%s\"" msgstr "" #: ../libinfinity/server/infd-directory.c:3389 msgid "This server does not support removing accounts" msgstr "" #: ../libinfinity/server/infd-directory.c:3730 #, c-format msgid "" "Session \"%s\" could not be saved: %s\n" "Another attempt will be made when the session is unused for a while or the " "server is shut down." msgstr "" #: ../libinfinity/server/infd-directory.c:4254 #, c-format msgid "Name \"%s\" is an invalid name: contains non-printable characters" msgstr "" #: ../libinfinity/server/infd-directory.c:4272 #, c-format msgid "Name \"%s\" is an invalid name: contains only space characters" msgstr "" #: ../libinfinity/server/infd-directory.c:4285 #, c-format msgid "Name \"%s\" is an invalid name: contains \"/\"" msgstr "" #: ../libinfinity/server/infd-directory.c:4300 #, c-format msgid "A node with name \"%s\" exists already" msgstr "" #: ../libinfinity/server/infd-directory.c:5221 #: ../libinfinity/server/infd-session-proxy.c:419 msgid "Permission denied" msgstr "" #: ../libinfinity/server/infd-directory.c:5368 #, c-format msgid "Failed to look up account: %s. Logging out user..." msgstr "" #: ../libinfinity/server/infd-directory.c:5438 msgid "No subscription request for the server chat" msgstr "" #: ../libinfinity/server/infd-directory.c:5457 #, c-format msgid "No subscription request with ID %u" msgstr "" #: ../libinfinity/server/infd-directory.c:5524 #, c-format msgid "Node with ID \"%u\" is not a subdirectory node" msgstr "" #: ../libinfinity/server/infd-directory.c:5536 #, c-format msgid "Node with ID \"%u\" has unsupported type \"%s\"" msgstr "" #: ../libinfinity/server/infd-directory.c:5547 #, c-format msgid "Node with ID \"%u\" is not a leaf node" msgstr "" #: ../libinfinity/server/infd-directory.c:6187 #: ../libinfinity/server/infd-directory.c:11330 msgid "No background storage available" msgstr "" #: ../libinfinity/server/infd-directory.c:6310 msgid "The chat is disabled" msgstr "" #: ../libinfinity/server/infd-directory.c:6419 msgid "No certificate request provided" msgstr "" #: ../libinfinity/server/infd-directory.c:6950 msgid "The ACL for this node has already been queried" msgstr "" #: ../libinfinity/server/infd-directory.c:7037 msgid "The ACL for this node has not been queried yet" msgstr "" #: ../libinfinity/server/infd-directory.c:7063 msgid "The set-acl request does not have any ACL provided" msgstr "" #: ../libinfinity/server/infd-directory.c:7079 #: ../libinfinity/server/infd-directory.c:10454 msgid "This server does not support the requested permissions" msgstr "" #: ../libinfinity/server/infd-directory.c:7346 msgid "The node to be subscribed to has been removed" msgstr "" #: ../libinfinity/server/infd-directory.c:7467 #: ../libinfinity/server/infd-directory.c:7582 msgid "The parent node of the node to be added has been removed" msgstr "" #: ../libinfinity/server/infd-directory.c:7667 msgid "Client did not acknowledge initial subscription" msgstr "" #: ../libinfinity/server/infd-directory.c:7989 #, c-format msgid "Failed to explore the root directory of the new storage: %s" msgstr "" #: ../libinfinity/server/infd-directory.c:8080 #, c-format msgid "" "Failed to lookup account IDs on account storage change: %s. Demoting clients " "to default account." msgstr "" #: ../libinfinity/server/infd-directory.c:8160 #, c-format msgid "Failed to obtain account list from account storage: %s" msgstr "" #: ../libinfinity/server/infd-directory.c:8292 #: ../libinfinity/server/infd-directory.c:8377 #, c-format msgid "Failed to look up accounts in new account storage: %s" msgstr "" #: ../libinfinity/server/infd-filesystem-account-storage.c:189 msgid "" "If one of \"password-hash\" or \"password-salt\" is provided, the other must " "be provided as well." msgstr "" #: ../libinfinity/server/infd-filesystem-account-storage.c:216 msgid "The length of the password salt is incorrect, it should be 32 bytes" msgstr "" #: ../libinfinity/server/infd-filesystem-account-storage.c:247 #, c-format msgid "The length of the password hash is incorrect, it should be %u bytes" msgstr "" #: ../libinfinity/server/infd-filesystem-account-storage.c:541 #, c-format msgid "Duplicate account ID \"%s\" in file \"%s\"" msgstr "" #: ../libinfinity/server/infd-filesystem-account-storage.c:585 #, c-format msgid "" "Accounts \"%s\" and \"%s\" have the same name. This is not supported by " "InfdFilesystemAccountStorage." msgstr "" #: ../libinfinity/server/infd-filesystem-account-storage.c:606 #, c-format msgid "" "Accounts \"%s\" and \"%s\" have the same certificate with DN=%s. This is not " "supported by InfdFilesystemAccountStorage." msgstr "" #: ../libinfinity/server/infd-filesystem-account-storage.c:904 #, c-format msgid "Failed to read accounts from filesystem: %s" msgstr "" #: ../libinfinity/server/infd-filesystem-account-storage.c:1094 #, c-format msgid "There is already an account with name \"%s\"" msgstr "" #: ../libinfinity/server/infd-filesystem-account-storage.c:1107 #, fuzzy msgid "The account name is too long" msgstr "El número de port on escoltar" #: ../libinfinity/server/infd-filesystem-account-storage.c:1124 #, c-format msgid "There is already an account with a certificate with DN=\"%s\"" msgstr "" #: ../libinfinity/server/infd-filesystem-account-storage.c:1145 #, c-format msgid "There is already an account with a certificate with fingerprint=\"%s\"" msgstr "" #: ../libinfinity/server/infd-filesystem-account-storage.c:1197 #, c-format msgid "Could not generate a unique ID for account with name \"%s\"" msgstr "" #: ../libinfinity/server/infd-filesystem-account-storage.c:1464 #, c-format msgid "The certificate with DN=%s is already in use by another account" msgstr "" #: ../libinfinity/server/infd-filesystem-storage.c:78 msgid "The path does not start with \"/\"" msgstr "" #: ../libinfinity/server/infd-filesystem-storage.c:92 msgid "The path contains invalid components" msgstr "" #: ../libinfinity/server/infd-filesystem-storage.c:122 #, c-format msgid "Failed to convert root directory to filename encoding: %s" msgstr "" #: ../libinfinity/server/infd-filesystem-storage.c:141 #, c-format msgid "" "Failed to create root directory: %s\n" "Subsequent storage operations will most likely fail\n" msgstr "" #: ../libinfinity/server/infd-filesystem-storage.c:284 #, c-format msgid "Error processing file \"%s\": Toplevel tag is not \"%s\"" msgstr "" #: ../libinfinity/server/infd-session-proxy.c:299 msgid "Request does not contain required attribute \"name\"" msgstr "" #: ../libinfinity/server/infd-session-proxy.c:317 #, c-format msgid "Name \"%s\" already in use" msgstr "" #: ../libinfinity/server/infd-session-proxy.c:359 msgid "\"status\" attribute is \"unavailable\" in user join request" msgstr "" #: ../libinftext/inf-text-default-delete-operation.c:271 #: ../libinftext/inf-text-remote-delete-operation.c:380 msgid "Attempt to remove text from after the end of the document" msgstr "" #: ../libinftext/inf-text-default-insert-operation.c:223 msgid "Attempt to insert text after the end of the document" msgstr "" #: ../libinftext/inf-text-filesystem-format.c:99 #, c-format msgid "User with ID %u exists already" msgstr "" #: ../libinftext/inf-text-filesystem-format.c:113 #, c-format msgid "User with name \"%s\" exists already" msgstr "" #: ../libinftext/inf-text-filesystem-format.c:193 #, c-format msgid "User with ID \"%u\" does not exist" msgstr "" #: ../libinftext/inf-text-filesystem-format.c:387 msgid "The document is not a text session" msgstr "" #: ../libinftext/inf-text-filesystem-format.c:403 #: ../libinftext/inf-text-filesystem-format.c:413 #, c-format msgid "Error processing file \"%s\": " msgstr "" #: ../libinftext/inf-text-move-operation.c:228 msgid "Attempt to move cursor or selection beyond the end of the document" msgstr "" #: ../libinftext/inf-text-session.c:935 ../libinftext/inf-text-session.c:1081 #, c-format msgid "No such user with ID '%u'" msgstr "" #: ../libinftext/inf-text-session.c:963 #, c-format msgid "Invalid hue value: '%g'" msgstr "" #: ../libinftext/inf-text-session.c:1276 msgid "\"caret\" attribute in user message is missing" msgstr "" #~ msgid "MD5 Fingerprint:" #~ msgstr "Empremta MD5:" #~ msgid "General" #~ msgstr "General" #~ msgid "INTERVAL" #~ msgstr "INTERVAL" libinfinity-0.7.1/po/PaxHeaders.26529/de.gmo0000644000000000000000000000013213034545201015312 xustar0030 mtime=1483917953.519214882 30 atime=1483917953.519214882 30 ctime=1488261621.324067277 libinfinity-0.7.1/po/de.gmo0000644000175000017500000001156613034545201016055 0ustar00arminarmin00000000000000Þ•*l;¼¨C©^í L Zfƒ˜ ª · Á#ÏfóSZ ® ¸9Å ÿ ? X0e%–¼Û ú  Ï"¼ò ¯ ½Ëàåô4 a: œ ¥ ¸ óÊ V¾ t Š  #­ Ñ è ù   70 •h |þ {‡J› æ òyýw,‡*´&ß&-=M\êlòWJ Zh~ ƒ‘5£eÙ ?Ka  %'! "#  $*&() "%d" is not a valid port number. Port numbers range from 1 to 65535"%s" is not a valid security policy. Allowed values are "no-tls", "allow-tls" or "require-tls"%s has joined%s has leftC_ontinue connectionCertificate ChainCommon Name:ConnectedConnecting...Could not create directory "%s": %sCould not create record file for session "%s": Could not generate unused record file in directory "%s"Creating a new private key also requires creating a new certificate signed with it.DIRECTORYDisconnectedError while writing record for session "%s" into "%s": %sExpires On:Exploring...Failed to auto-save session "%s": %s Will retry in %u seconds.FingerprintsGenerating 2048 bit Diffie-Hellman parameters...Generating self-signed certificate...IPv4 Server running on port %uIPv6 Server running on port %uIssued ByIssued On:Issued ToKEY-FILENo certificate file given. If you don't have a suitable certificate file, either create one using the --create-certificate command line agument, or disable TLS via by setting the security policy to "no-tls".No private key file given. If you don't have a suitable key file, either create one using the --create-key command line argument, or disable TLS by setting the security policy to "no-tls".Not connectedOrganization:Organizational Unit:PORTSerial Number:Synchronizing...The connection to host "%s" is not considered secureThe hostname of the server, "%s", does not match the hostname the certificate is issued to, "%s".Validity_Cancel connection_View CertificateProject-Id-Version: libinfinity Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=glib&keywords=I18N+L10N&component=general POT-Creation-Date: 2017-01-08 15:20-0800 PO-Revision-Date: 2009-11-28 11:36+0000 Last-Translator: Armin Burgmeier Language-Team: German Language: de MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Launchpad-Export-Date: 2009-12-19 18:32+0000 X-Generator: Launchpad (build Unknown) »%d« ist keine gültige Portnummer. Gültige Portnummern liegen zwischen 1 und 65535»%s« ist keine gültige Sicherheitsrichtlinie. Mögliche Werte sind »no-tls«, »allow-tls« oder »require-tls«%s ist beigetreten%s ist gegangenVerbindung f_ortsetzenZertifikatsketteCommon-Name:VerbundenVerbindung wird hergestellt ...Das Verzeichnis »%s« konnte nicht erstellt werden: %sDie Aufnahmedatei für die Sitzung »%s« konnte nicht erstellt werden, da keine unbenutzte Aufnahmedatei im Verzeichnis »%s« erzeugt werden konnteEinen neuen privaten Schlüssel zu erstellen erfordert auch ein zugehöriges Zertifikat zu erstellen das damit signiert ist.VERZEICHNISVerbindung getrenntFehler beim Speichern der Aufnahme für die Sitzung »%s« nach »%s«: %sLäuft aus:Erkunde…Die Sitzung »%s« konnte nicht automatisch gespeichert werden: %s In %u Sekunden wird ein erneuter Versuch unternommen.FingerabdrückeErzeuge 2048-bit Diffie-Hellman-Parameter…Erzeuge ein selbstsigniertes Zertifikat…Der IPv4-Server läuft auf dem Port %uDer IPv6-Server läuft auf dem Port %uAusgestellt vonAusgestellt am:Ausgestellt anSCHLÜSSELDATEIKeine Zertifikatsdatei angegeben. Wenn keine passende Datei vorliegt können Sie entweder eine mit dem Kommandozeilen-Argument --create-certificate erstellen oder TLS durch Setzen der Sicherheitsrichtlinie auf »no-tls« deaktivieren.Es wurde keine private Schlüsseldatei angegeben. Wenn keine passende Datei vorliegt können Sie entweder eine mit dem Kommandozeilen-Argument --create-key erstellen oder TLS durch Setzen der Sicherheitsrichtlinie auf »no-tls« deaktivieren.Nicht verbundenOrganisation:Organisationseinheit:PORTSeriennummer:Synchronisiere…Die Verbindung zu »%s« wird als unsicher eingestuftDer Name des Servers, »%s«, passt nicht zu dem Namen »%s« auf den das Zertifikat ausgestellt ist.GültigkeitVerbindung abbre_chen_Zertifikat anzeigenlibinfinity-0.7.1/po/PaxHeaders.26529/ChangeLog0000644000000000000000000000013012400102201015747 xustar0029 mtime=1409320065.13113192 29 atime=1409320065.13113192 30 ctime=1488261621.320067286 libinfinity-0.7.1/po/ChangeLog0000644000175000017500000000153012400102201016502 0ustar00arminarmin000000000000002011-03-27 Armin Burgmeier * libinfinity-0.6.pot: Moved from libinfinity-0.5.pot after release. 2009-12-19 Armin Burgmeier * libinfinity-0.5.pot: Moved from libinfinity-0.4.pot after release. 2009-12-19 Armin Burgmeier * ca.po: * de.po: Update from Launchpad. 2009-12-19 Armin Burgmeier * libinfinity-0.4.pot: Added, to allow synchronization with launchpad. * POTFILES.in: Updated. 2008-10-16 Armin Burgmeier * POTFILES.in: Updated. 2008-09-18 Armin Burgmeier * POTFILES.in: Updated. 2008-09-17 Armin Burgmeier * de.po: Initial German translation with a single string translated... only used to test gettext usage in infinote. * POTFILES.in: List all files containing translatable strings. libinfinity-0.7.1/po/PaxHeaders.26529/Makefile.in.in0000644000000000000000000000013213036062665016702 xustar0030 mtime=1484285365.651881236 30 atime=1484285365.651881236 30 ctime=1488261621.320067286 libinfinity-0.7.1/po/Makefile.in.in0000644000175000017500000001760413036062665017444 0ustar00arminarmin00000000000000# Makefile for program source directory in GNU NLS utilities package. # Copyright (C) 1995, 1996, 1997 by Ulrich Drepper # # This file file be copied and used freely without restrictions. It can # be used in projects which are not available under the GNU Public License # but which still want to provide support for the GNU gettext functionality. # Please note that the actual code is *not* freely available. # # - Modified by Owen Taylor to use GETTEXT_PACKAGE # instead of PACKAGE and to look for po2tbl in ./ not in intl/ # # - Modified by jacob berkman to install # Makefile.in.in and po2tbl.sed.in for use with glib-gettextize GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ PACKAGE = @PACKAGE@ VERSION = @VERSION@ SHELL = @SHELL@ @SET_MAKE@ srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ prefix = @prefix@ exec_prefix = @exec_prefix@ datarootdir = @datarootdir@ datadir = @datadir@ libdir = @libdir@ localedir = $(libdir)/locale gnulocaledir = $(datadir)/locale gettextsrcdir = $(datadir)/glib-2.0/gettext/po subdir = po INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ MKINSTALLDIRS = mkdir -p CC = @CC@ GENCAT = @GENCAT@ GMSGFMT = @GMSGFMT@ MSGFMT = @MSGFMT@ MSGFMT_OPTS = @MSGFMT_OPTS@ XGETTEXT = @XGETTEXT@ MSGMERGE = msgmerge DEFS = @DEFS@ CFLAGS = @CFLAGS@ CPPFLAGS = @CPPFLAGS@ INCLUDES = -I.. -I$(top_srcdir)/intl COMPILE = $(CC) -c $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) $(XCFLAGS) SOURCES = POFILES = @POFILES@ GMOFILES = @GMOFILES@ DISTFILES = LINGUAS ChangeLog Makefile.in.in POTFILES.in $(GETTEXT_PACKAGE).pot \ $(POFILES) $(GMOFILES) $(SOURCES) POTFILES = \ CATALOGS = @CATALOGS@ CATOBJEXT = @CATOBJEXT@ INSTOBJEXT = @INSTOBJEXT@ .SUFFIXES: .SUFFIXES: .c .o .po .pox .gmo .mo .msg .cat .c.o: $(COMPILE) $< .po.pox: $(MAKE) $(GETTEXT_PACKAGE).pot $(MSGMERGE) $< $(srcdir)/$(GETTEXT_PACKAGE).pot -o $*.pox .po.mo: $(MSGFMT) -o $@ $< .po.gmo: $(AM_V_GEN) file=$(srcdir)/`echo $* | sed 's,.*/,,'`.gmo \ && rm -f $$file && $(GMSGFMT) $(MSGFMT_OPTS) -o $$file $< .po.cat: sed -f ../intl/po2msg.sed < $< > $*.msg \ && rm -f $@ && $(GENCAT) $@ $*.msg all: all-@USE_NLS@ all-yes: $(CATALOGS) all-no: $(srcdir)/$(GETTEXT_PACKAGE).pot: $(POTFILES) $(XGETTEXT) --default-domain=$(GETTEXT_PACKAGE) \ --msgid-bugs-address='http://bugzilla.gnome.org/enter_bug.cgi?product=glib&keywords=I18N+L10N&component=general' \ --add-comments --keyword=_ --keyword=N_ \ --keyword=C_:1c,2 \ --keyword=NC_:1c,2 \ --keyword=g_dcgettext:2 \ --keyword=g_dngettext:2,3 \ --keyword=g_dpgettext2:2c,3 \ --flag=N_:1:pass-c-format \ --flag=C_:2:pass-c-format \ --flag=NC_:2:pass-c-format \ --flag=g_dngettext:2:pass-c-format \ --flag=g_strdup_printf:1:c-format \ --flag=g_string_printf:2:c-format \ --flag=g_string_append_printf:2:c-format \ --flag=g_error_new:3:c-format \ --flag=g_set_error:4:c-format \ --flag=g_markup_printf_escaped:1:c-format \ --flag=g_log:3:c-format \ --flag=g_print:1:c-format \ --flag=g_printerr:1:c-format \ --flag=g_printf:1:c-format \ --flag=g_fprintf:2:c-format \ --flag=g_sprintf:2:c-format \ --flag=g_snprintf:3:c-format \ --flag=g_scanner_error:2:c-format \ --flag=g_scanner_warn:2:c-format \ $(POTFILES) \ && test ! -f $(GETTEXT_PACKAGE).po \ || ( rm -f $(srcdir)/$(GETTEXT_PACKAGE).pot \ && mv $(GETTEXT_PACKAGE).po $(srcdir)/$(GETTEXT_PACKAGE).pot ) install: install-exec install-data install-exec: install-data: install-data-@USE_NLS@ install-data-no: all install-data-yes: all $(MKINSTALLDIRS) $(DESTDIR)$(datadir); \ catalogs='$(CATALOGS)'; \ for cat in $$catalogs; do \ cat=`basename $$cat`; \ case "$$cat" in \ *.gmo) destdir=$(gnulocaledir);; \ *) destdir=$(localedir);; \ esac; \ lang=`echo $$cat | sed 's/\$(CATOBJEXT)$$//'`; \ dir=$(DESTDIR)$$destdir/$$lang/LC_MESSAGES; \ $(MKINSTALLDIRS) $$dir; \ if test -r $$cat; then \ $(INSTALL_DATA) $$cat $$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT); \ echo "installing $$cat as $$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT)"; \ else \ $(INSTALL_DATA) $(srcdir)/$$cat $$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT); \ echo "installing $(srcdir)/$$cat as" \ "$$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT)"; \ fi; \ if test -r $$cat.m; then \ $(INSTALL_DATA) $$cat.m $$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT).m; \ echo "installing $$cat.m as $$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT).m"; \ else \ if test -r $(srcdir)/$$cat.m ; then \ $(INSTALL_DATA) $(srcdir)/$$cat.m \ $$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT).m; \ echo "installing $(srcdir)/$$cat as" \ "$$dir/$(GETTEXT_PACKAGE)$(INSTOBJEXT).m"; \ else \ true; \ fi; \ fi; \ done if test "$(PACKAGE)" = "glib"; then \ $(MKINSTALLDIRS) $(DESTDIR)$(gettextsrcdir); \ $(INSTALL_DATA) $(srcdir)/Makefile.in.in \ $(DESTDIR)$(gettextsrcdir)/Makefile.in.in; \ else \ : ; \ fi # Define this as empty until I found a useful application. installcheck: uninstall: catalogs='$(CATALOGS)'; \ for cat in $$catalogs; do \ cat=`basename $$cat`; \ lang=`echo $$cat | sed 's/\$(CATOBJEXT)$$//'`; \ rm -f $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE)$(INSTOBJEXT); \ rm -f $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE)$(INSTOBJEXT).m; \ rm -f $(DESTDIR)$(gnulocaledir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE)$(INSTOBJEXT); \ rm -f $(DESTDIR)$(gnulocaledir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE)$(INSTOBJEXT).m; \ done if test "$(PACKAGE)" = "glib"; then \ rm -f $(DESTDIR)$(gettextsrcdir)/Makefile.in.in; \ fi check: all dvi info tags TAGS ID: mostlyclean: rm -f core core.* *.pox $(GETTEXT_PACKAGE).po *.old.po cat-id-tbl.tmp rm -fr *.o clean: mostlyclean distclean: clean rm -f Makefile Makefile.in POTFILES *.mo *.msg *.cat *.cat.m maintainer-clean: distclean @echo "This command is intended for maintainers to use;" @echo "it deletes files that may require special tools to rebuild." rm -f $(GMOFILES) distdir = ../$(GETTEXT_PACKAGE)-$(VERSION)/$(subdir) dist distdir: $(DISTFILES) dists="$(DISTFILES)"; \ for file in $$dists; do \ ln $(srcdir)/$$file $(distdir) 2> /dev/null \ || cp -p $(srcdir)/$$file $(distdir); \ done update-po: Makefile $(MAKE) $(GETTEXT_PACKAGE).pot tmpdir=`pwd`; \ cd $(srcdir); \ catalogs='$(CATALOGS)'; \ for cat in $$catalogs; do \ cat=`basename $$cat`; \ lang=`echo $$cat | sed 's/\$(CATOBJEXT)$$//'`; \ echo "$$lang:"; \ if $(MSGMERGE) $$lang.po $(GETTEXT_PACKAGE).pot -o $$tmpdir/$$lang.new.po; then \ if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \ rm -f $$tmpdir/$$lang.new.po; \ else \ if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \ :; \ else \ echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \ rm -f $$tmpdir/$$lang.new.po; \ exit 1; \ fi; \ fi; \ else \ echo "msgmerge for $$cat failed!"; \ rm -f $$tmpdir/$$lang.new.po; \ fi; \ done # POTFILES is created from POTFILES.in by stripping comments, empty lines # and Intltool tags (enclosed in square brackets), and appending a full # relative path to them POTFILES: POTFILES.in ( if test 'x$(srcdir)' != 'x.'; then \ posrcprefix='$(top_srcdir)/'; \ else \ posrcprefix="../"; \ fi; \ rm -f $@-t $@ \ && (sed -e '/^#/d' \ -e "s/^\[.*\] +//" \ -e '/^[ ]*$$/d' \ -e "s@.*@ $$posrcprefix& \\\\@" < $(srcdir)/$@.in \ | sed -e '$$s/\\$$//') > $@-t \ && chmod a-w $@-t \ && mv $@-t $@ ) Makefile: Makefile.in.in ../config.status POTFILES cd .. \ && $(SHELL) ./config.status $(subdir)/$@.in # Tell versions [3.59,3.63) of GNU make not to export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: libinfinity-0.7.1/po/PaxHeaders.26529/libinfinity-0.7.pot0000644000000000000000000000013213055210765017573 xustar0030 mtime=1488261621.316067296 30 atime=1488261621.304067322 30 ctime=1488261621.324067277 libinfinity-0.7.1/po/libinfinity-0.7.pot0000644000175000017500000022503213055210765020331 0ustar00arminarmin00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?" "product=glib&keywords=I18N+L10N&component=general\n" "POT-Creation-Date: 2017-02-27 22:00-0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" #: ../infinoted/infinoted-config-reload.c:122 msgid "Changing the listen address at runtime is not supported" msgstr "" #: ../infinoted/infinoted-config-reload.c:439 #, c-format msgid "Failed to re-load plugins: %s" msgstr "" #: ../infinoted/infinoted-config-reload.c:445 msgid "" "Plugins are disabled. Please fix the problem and reload configuration again." msgstr "" #: ../infinoted/infinoted-dh-params.c:83 msgid "Generating 2048 bit Diffie-Hellman parameters..." msgstr "" #. Translators: fork as in "fork into the background" #: ../infinoted/infinoted-main.c:77 msgid "Failed to fork" msgstr "" #: ../infinoted/infinoted-main.c:93 msgid "Failed to wait for daemonized child's return value" msgstr "" #: ../infinoted/infinoted-main.c:102 ../infinoted/infinoted-main.c:120 msgid "Failed to create PID file" msgstr "" #: ../infinoted/infinoted-options.c:48 msgid "If set, write the server log to the given file, in addition to stdout" msgstr "" #: ../infinoted/infinoted-options.c:50 msgid "LOG-FILE" msgstr "" #: ../infinoted/infinoted-options.c:58 msgid "" "Path to the server's private key. Must be the key with which the given " "certificate was signed. Not needed when security-policy is set to \"no-tls\"." msgstr "" #: ../infinoted/infinoted-options.c:61 msgid "KEY-FILE" msgstr "" #: ../infinoted/infinoted-options.c:69 msgid "" "Path to the server's certificate. Must be signed with the given key file. " "Not needed when security-policy is set to \"no-tls\"." msgstr "" #: ../infinoted/infinoted-options.c:71 ../infinoted/infinoted-options.c:85 msgid "CERT-FILE" msgstr "" #: ../infinoted/infinoted-options.c:79 msgid "" "Optional file which contains the issuer certificate of the server " "certificate, and the issuer's issuer, and so on. This option can be used " "when the issuer certificates are not stored in the same file as the server " "certificate. If the issuer certificates are not available the server will " "still run, but not show the issuer certificates to connecting clients." msgstr "" #: ../infinoted/infinoted-options.c:93 msgid "The TCP port number to listen on." msgstr "" #: ../infinoted/infinoted-options.c:94 msgid "PORT" msgstr "" #: ../infinoted/infinoted-options.c:102 msgid "The IP address to listen on." msgstr "" #: ../infinoted/infinoted-options.c:103 msgid "ADDRESS" msgstr "" #: ../infinoted/infinoted-options.c:111 msgid "" "Whether to use Transport Layer Security (TLS) or not. Allowed values are " "\"no-tls\", \"allow-tls\" or \"require-tls\". When TLS is allowed or " "required, a server certificate must be provided. Infinoted has a built-in " "option to create a self-signed certificate with the --create-key and --" "create-certificate command line options. When TLS is allowed but not " "required, clients may choose not to use TLS. It is strongly encouraged to " "always require TLS. [Default=require-tls]" msgstr "" #: ../infinoted/infinoted-options.c:119 msgid "no-tls|allow-tls|require-tls" msgstr "" #: ../infinoted/infinoted-options.c:127 msgid "" "The directory which infinoted uses to permanantly store all documents on the " "server, and where they are read from after a server restart. [Default=~/." "infinote]" msgstr "" #: ../infinoted/infinoted-options.c:130 #: ../infinoted/plugins/infinoted-plugin-directory-sync.c:603 #: ../infinoted/plugins/infinoted-plugin-traffic-logging.c:326 msgid "DIRECTORY" msgstr "" #: ../infinoted/infinoted-options.c:138 msgid "" "Additional plugins to load. This option can be specified more than once to " "load multiple plugins. Plugin options can be configured in the configuration " "file (one section for each plugin), or with the --plugin-parameter option. " "[Default=note-text]" msgstr "" #: ../infinoted/infinoted-options.c:142 msgid "PLUGIN-NAME" msgstr "" #: ../infinoted/infinoted-options.c:150 msgid "" "If set, require clients to enter a password before being allowed to connect " "to the server. This option cannot be combined with --pam-service." msgstr "" #: ../infinoted/infinoted-options.c:153 msgid "Password" msgstr "" #: ../infinoted/infinoted-options.c:162 msgid "" "Authenticate clients using the given PAM service. This option cannot be " "combined with --password. Clients are requested to send their user name and " "then enter the password for their account on the server machine with the " "same name." msgstr "" #: ../infinoted/infinoted-options.c:166 msgid "SERVICE" msgstr "" #: ../infinoted/infinoted-options.c:174 msgid "" "If set, only the given username is allowed to connect to the server. This " "option can be given multiple times to allow multiple users." msgstr "" #: ../infinoted/infinoted-options.c:177 msgid "USER" msgstr "" #: ../infinoted/infinoted-options.c:185 msgid "" "If set, only users belonging to the given group are allowed to connect to " "the server. This option can be given multiple times to allow multiple groups." msgstr "" #: ../infinoted/infinoted-options.c:188 msgid "GROUPS" msgstr "" #: ../infinoted/infinoted-options.c:215 msgid "Cannot use both server password and system authentication." msgstr "" #: ../infinoted/infinoted-options.c:228 msgid "Need a pam service to authenticate users." msgstr "" #: ../infinoted/infinoted-options.c:248 msgid "WARNING: Requiring password through unencrypted connection." msgstr "" #: ../infinoted/infinoted-options.c:258 msgid "" "Creating a new private key also requires creating a new certificate signed " "with it." msgstr "" #: ../infinoted/infinoted-options.c:271 msgid "" "No private key file given. If you don't have a suitable key file, either " "create one using the --create-key command line argument, or disable TLS by " "setting the security policy to \"no-tls\"." msgstr "" #: ../infinoted/infinoted-options.c:285 msgid "" "No certificate file given. If you don't have a suitable certificate file, " "either create one using the --create-certificate command line agument, or " "disable TLS via by setting the security policy to \"no-tls\"." msgstr "" #: ../infinoted/infinoted-options.c:329 #, c-format msgid "Error reading configuration file \"%s\": " msgstr "" #: ../infinoted/infinoted-options.c:387 ../infinoted/infinoted-options.c:431 #: ../infinoted/infinoted-options.c:505 #, c-format msgid "The option \"%s\" can only be given once" msgstr "" #: ../infinoted/infinoted-options.c:416 #, c-format msgid "\"%s\" cannot be interpreted as a boolean value" msgstr "" #: ../infinoted/infinoted-options.c:446 #, c-format msgid "\"%s\" is not a number" msgstr "" #: ../infinoted/infinoted-options.c:458 #, c-format msgid "Could not read the number \"%s\": %s" msgstr "" #: ../infinoted/infinoted-options.c:471 #, c-format msgid "Number \"%s\" is too small" msgstr "" #: ../infinoted/infinoted-options.c:483 #, c-format msgid "Number \"%s\" is too large" msgstr "" #: ../infinoted/infinoted-options.c:693 msgid "Configuration file to load, instead of the default configuration file" msgstr "" #: ../infinoted/infinoted-options.c:695 msgid "CONFIG-FILE" msgstr "" #: ../infinoted/infinoted-options.c:699 msgid "" "Creates a new random private key. The new key will be stored at the given " "location for the server's private key." msgstr "" #: ../infinoted/infinoted-options.c:705 msgid "" "Creates a new self-signed certificate signed with the given private key. The " "certificate is stored at the given location for the server's certificate." msgstr "" #: ../infinoted/infinoted-options.c:712 msgid "" "Allows one to override configuration entries for plugins from the command " "line. The syntax is --plugin-parameter=plugin:key:value, where plugin is the " "name of the plugin for which to override a configuration parameter, key is " "the parameter which to override and value is the new value of the parameter" msgstr "" #: ../infinoted/infinoted-options.c:717 msgid "PLUGIN:PARAMETER:VALUE" msgstr "" #: ../infinoted/infinoted-options.c:722 msgid "Daemonize the server, i.e. run it in the background" msgstr "" #: ../infinoted/infinoted-options.c:726 msgid "Kill a running daemon and exit" msgstr "" #: ../infinoted/infinoted-options.c:731 msgid "Display version information and exit" msgstr "" #: ../infinoted/infinoted-options.c:790 msgid "Infinoted Options" msgstr "" #: ../infinoted/infinoted-options.c:791 msgid "Main Program Options" msgstr "" #: ../infinoted/infinoted-options.c:800 msgid "infinote dedicated server" msgstr "" #: ../infinoted/infinoted-options.c:835 msgid "Could not kill daemon" msgstr "" #: ../infinoted/infinoted-pam.c:100 msgid "Entry not found" msgstr "" #: ../infinoted/infinoted-pam.c:106 #, c-format msgid "Error while checking groups of user \"%s\", %s: %s." msgstr "" #: ../infinoted/infinoted-pam.c:144 msgid "looking up user information" msgstr "" #: ../infinoted/infinoted-pam.c:155 #, c-format msgid "looking up group %ld" msgstr "" #: ../infinoted/infinoted-pam.c:170 #, c-format msgid "looking up group \"%s\"" msgstr "" #: ../infinoted/infinoted-parameter.c:145 #, c-format msgid "The parameter \"%s\" is required" msgstr "" #: ../infinoted/infinoted-parameter.c:514 #, c-format msgid "\"%d\" is not a valid port number. Port numbers range from 1 to 65535" msgstr "" #: ../infinoted/infinoted-parameter.c:562 msgid "Invalid IP address" msgstr "" #: ../infinoted/infinoted-parameter.c:601 msgid "Number must not be negative" msgstr "" #: ../infinoted/infinoted-parameter.c:640 msgid "Number must be positive" msgstr "" #: ../infinoted/infinoted-parameter.c:697 #, c-format msgid "" "\"%s\" is not a valid security policy. Allowed values are \"no-tls\", " "\"allow-tls\" or \"require-tls\"" msgstr "" #: ../infinoted/infinoted-parameter.c:769 #, c-format msgid "\"%s\" is not a valid value. Allowed values are: %s." msgstr "" #: ../infinoted/infinoted-plugin-manager.c:490 #, c-format msgid "Loaded plugin \"%s\" from \"%s\"" msgstr "" #: ../infinoted/infinoted-plugin-manager.c:534 #, c-format msgid "Unloaded plugin \"%s\" from \"%s\"" msgstr "" #: ../infinoted/infinoted-run.c:394 #, c-format msgid "Failed to generate Diffie-Hellman parameters: %s" msgstr "" #: ../infinoted/infinoted-run.c:414 #, c-format msgid "IPv6 Server running on port %u" msgstr "" #: ../infinoted/infinoted-run.c:437 #, c-format msgid "IPv4 Server running on port %u" msgstr "" #: ../infinoted/infinoted-run.c:458 #, c-format msgid "Failed to start server: %s" msgstr "" #: ../infinoted/infinoted-run.c:476 msgid "Infinoted shutting down..." msgstr "" #: ../infinoted/infinoted-signal.c:58 msgid "" "Error on signal handler connection; signal handlers have been removed from " "now on" msgstr "" #: ../infinoted/infinoted-signal.c:77 #, c-format msgid "Configuration reload failed: %s" msgstr "" #: ../infinoted/infinoted-signal.c:86 msgid "Configuration reloaded" msgstr "" #: ../infinoted/infinoted-signal.c:146 msgid "" "For config reloading to work libinfinity needs to be compiled with libdaemon " "support" msgstr "" #. TODO: Open the key file beforehand #: ../infinoted/infinoted-startup.c:62 msgid "Generating 4096 bit RSA private key..." msgstr "" #: ../infinoted/infinoted-startup.c:104 msgid "Generating self-signed certificate..." msgstr "" #: ../infinoted/infinoted-startup.c:321 #, c-format msgid "User %s failed to log in from %s: PAM authentication failed" msgstr "" #: ../infinoted/infinoted-startup.c:341 #, c-format msgid "User %s failed to log in from %s: PAM user not allowed" msgstr "" #: ../infinoted/infinoted-startup.c:361 #, c-format msgid "User %s logged in from %s via PAM" msgstr "" #: ../infinoted/infinoted-startup.c:392 #, c-format msgid "User %s logged in from %s via password" msgstr "" #: ../infinoted/infinoted-startup.c:403 #, c-format msgid "User %s failed to log in from %s: wrong password" msgstr "" #: ../infinoted/plugins/infinoted-plugin-autosave.c:151 #, c-format msgid "" "Failed to auto-save session \"%s\": %s\n" "\n" "Will retry in %u seconds." msgstr "" #: ../infinoted/plugins/infinoted-plugin-autosave.c:191 #, c-format msgid "Could not execute autosave hook: \"%s\"" msgstr "" #: ../infinoted/plugins/infinoted-plugin-autosave.c:328 msgid "" "Interval, in seconds, after which to save documents into the root directory. " "Documents are also stored to disk when there has been no user logged into " "them for 60 seconds." msgstr "" #: ../infinoted/plugins/infinoted-plugin-autosave.c:331 #: ../infinoted/plugins/infinoted-plugin-directory-sync.c:613 msgid "SECONDS" msgstr "" #: ../infinoted/plugins/infinoted-plugin-autosave.c:339 #: ../infinoted/plugins/infinoted-plugin-directory-sync.c:621 msgid "Command to run after having saved a document." msgstr "" #: ../infinoted/plugins/infinoted-plugin-autosave.c:340 #: ../infinoted/plugins/infinoted-plugin-directory-sync.c:622 msgid "PROGRAM" msgstr "" #: ../infinoted/plugins/infinoted-plugin-autosave.c:352 msgid "" "Periodically saves the content of all documents to disk. If this plugin is " "not enabled, infinoted only moves a document to permanent storage 60 seconds " "after the last user left the document." msgstr "" #: ../infinoted/plugins/infinoted-plugin-certificate-auth.c:77 #, c-format msgid "Failed to set permissions for super user: %s" msgstr "" #: ../infinoted/plugins/infinoted-plugin-certificate-auth.c:97 #, c-format msgid "" "Failed to remove super user on server shutdown. This should not be a problem " "since the account is not made persistent, however might point to an " "inconsistency in the server setup. The error message was: %s" msgstr "" #: ../infinoted/plugins/infinoted-plugin-certificate-auth.c:226 msgid "" "The certificate-auth plugin can only be used when TLS is enabled and a " "server certificate has been set." msgstr "" #: ../infinoted/plugins/infinoted-plugin-certificate-auth.c:243 #, c-format msgid "File \"%s\" does not contain any CA certificates" msgstr "" #: ../infinoted/plugins/infinoted-plugin-certificate-auth.c:288 msgid "The given CA key does not match with any of the CA certificates" msgstr "" #: ../infinoted/plugins/infinoted-plugin-certificate-auth.c:321 msgid "Cannot generate a superuser certificate without CA key" msgstr "" #: ../infinoted/plugins/infinoted-plugin-certificate-auth.c:330 msgid "Creating 4096-bit RSA private key for the super user account..." msgstr "" #: ../infinoted/plugins/infinoted-plugin-certificate-auth.c:358 msgid "Super User" msgstr "" #: ../infinoted/plugins/infinoted-plugin-certificate-auth.c:598 msgid "" "The trusted CA or list of trusted CAs. Only clients presenting a certificate " "signed by one of these CAs are accepted." msgstr "" #: ../infinoted/plugins/infinoted-plugin-certificate-auth.c:600 msgid "CA-LIST" msgstr "" #: ../infinoted/plugins/infinoted-plugin-certificate-auth.c:608 msgid "" "If given, this is the private key for one of the CA certificates in the list " "given by the \"ca-list\" parameter. In this case, the server itself acts as " "a CA and can issue certificates to clients. This can be used to allow " "clients to create their own accounts." msgstr "" #: ../infinoted/plugins/infinoted-plugin-certificate-auth.c:612 msgid "CA-KEY" msgstr "" #: ../infinoted/plugins/infinoted-plugin-certificate-auth.c:620 msgid "" "If this value is set to false, then clients that cannot authenticate " "themselves with a valid certificate are rejected and the connection is " "closed. If it is set to true, the connection will be accepted, but the " "client will only have unauthenticated access to the server. [Default: false]" msgstr "" #: ../infinoted/plugins/infinoted-plugin-certificate-auth.c:633 msgid "" "Filename to which to write a short-lived super-user private key and " "certificate. The user is deleted when the infinoted server goes down or the " "plugin is re-loaded. This option can only be given when the \"ca-key\" " "parameter is set." msgstr "" #: ../infinoted/plugins/infinoted-plugin-certificate-auth.c:637 msgid "FILENAME" msgstr "" #: ../infinoted/plugins/infinoted-plugin-certificate-auth.c:645 msgid "" "Flags to be used when verifying a client certificate. Each of these flags " "weakens the security, and so should be set only when absolutely necessary, " "and it should be done with care. [Default: disable-ca-sign]" msgstr "" #: ../infinoted/plugins/infinoted-plugin-certificate-auth.c:649 msgid "flag1;flag2;[...]" msgstr "" #: ../infinoted/plugins/infinoted-plugin-certificate-auth.c:661 msgid "" "Allows clients to authenticate themselves with client-side certificates. If " "authentication is successful, the certificate ID is used to log the user " "into its account." msgstr "" #: ../infinoted/plugins/infinoted-plugin-dbus.c:1188 #, c-format msgid "" "\"%s\" is not a valid bus type. Allowed values are \"system\" or \"session\"" msgstr "" #: ../infinoted/plugins/infinoted-plugin-dbus.c:1207 msgid "" "The bus type to use, either \"session\" or \"system\". [default=session]" msgstr "" #: ../infinoted/plugins/infinoted-plugin-dbus.c:1209 msgid "TYPE" msgstr "" #: ../infinoted/plugins/infinoted-plugin-dbus.c:1217 msgid "The name to own on the bus. [default=org.infinote.infinoted]" msgstr "" #: ../infinoted/plugins/infinoted-plugin-dbus.c:1218 msgid "NAME" msgstr "" #: ../infinoted/plugins/infinoted-plugin-dbus.c:1230 msgid "Exports infinoted functionality on D-Bus" msgstr "" #: ../infinoted/plugins/infinoted-plugin-directory-sync.c:93 #, c-format msgid "Failed to convert path \"%s\" from UTF-8 to %s: " msgstr "" #: ../infinoted/plugins/infinoted-plugin-directory-sync.c:199 #, c-format msgid "Failed to remove directory \"%s\": " msgstr "" #: ../infinoted/plugins/infinoted-plugin-directory-sync.c:255 #, c-format msgid "Failed to create directory for path \"%s\": " msgstr "" #: ../infinoted/plugins/infinoted-plugin-directory-sync.c:283 #, c-format msgid "Failed to write session for path \"%s\": " msgstr "" #: ../infinoted/plugins/infinoted-plugin-directory-sync.c:315 #, c-format msgid "Failed to execute hook \"%s\": " msgstr "" #: ../infinoted/plugins/infinoted-plugin-directory-sync.c:347 #, c-format msgid "" "%s\n" "\tWill retry in %u seconds" msgstr "" #: ../infinoted/plugins/infinoted-plugin-directory-sync.c:358 #, c-format msgid "%s" msgstr "" #: ../infinoted/plugins/infinoted-plugin-directory-sync.c:522 #, c-format msgid "Node \"%s\" contains invalid characters" msgstr "" #: ../infinoted/plugins/infinoted-plugin-directory-sync.c:602 msgid "The directory into which to store the directory tree in text form." msgstr "" #: ../infinoted/plugins/infinoted-plugin-directory-sync.c:611 msgid "" "Interval, in seconds, after which to save documents into the given directory." msgstr "" #: ../infinoted/plugins/infinoted-plugin-directory-sync.c:634 msgid "" "Periodically saves the content of all documents into a custom directory, " "without any infinote metadata such as which user wrote what text. This " "option can be used to (automatically) process the files on the server by " "standard tools that operate on normal UTF-8 encoded text files" msgstr "" #: ../infinoted/plugins/infinoted-plugin-document-stream.c:669 msgid "Not a text or chat node" msgstr "" #: ../infinoted/plugins/infinoted-plugin-document-stream.c:1503 msgid "Allows streaming of document changes to external programs" msgstr "" #: ../infinoted/plugins/infinoted-plugin-linekeeper.c:317 #, c-format msgid "Could not join LineKeeper user for document: %s\n" msgstr "" #: ../infinoted/plugins/infinoted-plugin-linekeeper.c:549 msgid "The number of empty lines to keep at the end of the document." msgstr "" #: ../infinoted/plugins/infinoted-plugin-linekeeper.c:550 msgid "LINES" msgstr "" #: ../infinoted/plugins/infinoted-plugin-linekeeper.c:562 msgid "" "This plugin makes sure that at the end of every document there is always a " "fixed number of empty lines." msgstr "" #: ../infinoted/plugins/infinoted-plugin-logging.c:224 #, c-format msgid "when executing request \"%s\" from user %s (%s) in document %s" msgstr "" #: ../infinoted/plugins/infinoted-plugin-logging.c:285 #, c-format msgid "Error from connection %s: %s" msgstr "" #: ../infinoted/plugins/infinoted-plugin-logging.c:322 #, c-format msgid "in document %s from connection %s. The request was: %s" msgstr "" #: ../infinoted/plugins/infinoted-plugin-logging.c:336 #, c-format msgid "Session error: %s" msgstr "" #: ../infinoted/plugins/infinoted-plugin-logging.c:449 #: ../infinoted/plugins/infinoted-plugin-logging.c:517 #: ../infinoted/plugins/infinoted-plugin-traffic-logging.c:237 #, c-format msgid "%s connected" msgstr "" #: ../infinoted/plugins/infinoted-plugin-logging.c:566 #, c-format msgid "Unsuccessful connection attempt from %s" msgstr "" #: ../infinoted/plugins/infinoted-plugin-logging.c:574 #, c-format msgid "%s disconnected" msgstr "" #: ../infinoted/plugins/infinoted-plugin-logging.c:711 msgid "Whether to write a log message when a new user connects or disconnects." msgstr "" #: ../infinoted/plugins/infinoted-plugin-logging.c:721 msgid "" "Whether to write a log message when an error with a connection is detected, " "usually leading to disconnection of the user." msgstr "" #: ../infinoted/plugins/infinoted-plugin-logging.c:731 msgid "" "Whether to write a log message when a session cannot process a client " "request, mostly caused by invalid client requests." msgstr "" #: ../infinoted/plugins/infinoted-plugin-logging.c:741 msgid "" "Whether to write an additional line into the log when a message occurs " "during transformation of an adOPTed request. This is mostly used for " "debugging purposes to find problems in the server implementation itself." msgstr "" #: ../infinoted/plugins/infinoted-plugin-logging.c:757 msgid "" "This plugin writes extra information into the infinoted log. By default all " "extra information is logged, but individual events can be turned off with " "the plugin options." msgstr "" #: ../infinoted/plugins/infinoted-plugin-note-chat.c:166 #: ../infinoted/plugins/infinoted-plugin-note-text.c:172 #, c-format msgid "There is a already a plugin which handles sessions of type \"%s\"" msgstr "" #: ../infinoted/plugins/infinoted-plugin-note-chat.c:211 msgid "Adds support to handle chat documents." msgstr "" #: ../infinoted/plugins/infinoted-plugin-note-text.c:217 msgid "Adds support to handle plain text documents." msgstr "" #: ../infinoted/plugins/infinoted-plugin-record.c:71 #, c-format msgid "" "Could not create record file for session \"%s\": Could not generate unused " "record file in directory \"%s\"" msgstr "" #: ../infinoted/plugins/infinoted-plugin-record.c:88 #, c-format msgid "Could not create directory \"%s\": %s" msgstr "" #: ../infinoted/plugins/infinoted-plugin-record.c:104 #, c-format msgid "Error while writing record for session \"%s\" into \"%s\": %s" msgstr "" #: ../infinoted/plugins/infinoted-plugin-record.c:221 msgid "" "Creates a recording of each session that can be replayed later. The records " "are created in the ~/.infinoted-records directory." msgstr "" #: ../infinoted/plugins/infinoted-plugin-traffic-logging.c:136 #, c-format msgid "Connection error: %s" msgstr "" #: ../infinoted/plugins/infinoted-plugin-traffic-logging.c:211 #, c-format msgid "" "Failed to create directory \"%s\": %s\n" "Traffic logging for connection \"%s\" is disabled." msgstr "" #: ../infinoted/plugins/infinoted-plugin-traffic-logging.c:228 #, c-format msgid "" "Failed to open file \"%s\": %s\n" "Traffic logging for connection \"%s\" is disabled." msgstr "" #: ../infinoted/plugins/infinoted-plugin-traffic-logging.c:300 msgid "Log closed" msgstr "" #: ../infinoted/plugins/infinoted-plugin-traffic-logging.c:325 msgid "The directory into which to write the log files." msgstr "" #: ../infinoted/plugins/infinoted-plugin-traffic-logging.c:338 msgid "" "This plugin writes a dump of all network traffic between the server and the " "client into a file. Note that the traffic written to the log files is " "unencrypted. It is meant to be used as a diagnostic tool for debugging, and " "it should never be used in a production environment as it is a severe " "privacy issue." msgstr "" #: ../infinoted/plugins/infinoted-plugin-transformation-protection.c:105 #, c-format msgid "" "In document \"%s\": Attempt to transform request \"%s\" to current state \"%s" "\" (vdiff=%u) by user \"%s\" (id=%u, conn=%s). Maximum allowed is %u; the " "connection has been unsubscribed." msgstr "" #: ../infinoted/plugins/infinoted-plugin-transformation-protection.c:216 msgid "" "The maximum number of individual transformations to allow. If a client makes " "a request that would require more than this number of transformations, the " "request is rejected and the client is unsubscribed from the session." msgstr "" #: ../infinoted/plugins/infinoted-plugin-transformation-protection.c:220 msgid "DIFF" msgstr "" #: ../infinoted/plugins/infinoted-plugin-transformation-protection.c:232 msgid "" "This plugin tries to protect the server from malicious clients that send " "formally valid requests but would take the server a long time to process, " "making in unresponsive to other requests. This is only possible if sessions " "use the \"central\" communication method. At the moment this is the only " "method available, so the plugin can always be used. Currently the plugin " "rejects requests that were made in a state too far behind the current state. " "However, additional criteria might be implemented in future versions." msgstr "" #: ../infinoted/plugins/util/infinoted-plugin-util-navigate-browser.c:137 #, c-format msgid "The path \"%.*s\" does not exist" msgstr "" #. should be const... #: ../infinoted/plugins/util/infinoted-plugin-util-navigate-browser.c:170 #, c-format msgid "Failed to explore path \"%.*s\": " msgstr "" #: ../infinoted/plugins/util/infinoted-plugin-util-navigate-browser.c:213 #, c-format msgid "The path \"%.*s\" does not exist or is not a directory" msgstr "" #: ../infinoted/plugins/util/infinoted-plugin-util-navigate-browser.c:284 #, c-format msgid "The path \"%.*s\" is not an absolute path" msgstr "" #: ../libinfgtk/inf-gtk-account-creation-dialog.c:198 #: ../libinfgtk/inf-gtk-account-creation-dialog.c:206 msgid "Not connected to a server" msgstr "" #: ../libinfgtk/inf-gtk-account-creation-dialog.c:226 msgid "Permissions to create an account are not granted" msgstr "" #: ../libinfgtk/inf-gtk-account-creation-dialog.c:265 msgid "" "A private key is being generated. This process might take a few seconds..." msgstr "" #: ../libinfgtk/inf-gtk-account-creation-dialog.c:275 msgid "" "New account is being requested from the server. Usually, this should not " "take very long." msgstr "" #: ../libinfgtk/inf-gtk-browser-store.c:685 msgid "Disconnected" msgstr "" #: ../libinfgtk/inf-gtk-browser-view.c:2197 msgid "Exploring..." msgstr "" #: ../libinfgtk/inf-gtk-browser-view.c:2236 msgid "Synchronizing..." msgstr "" #: ../libinfgtk/inf-gtk-browser-view.c:2319 msgid "Not connected" msgstr "" #: ../libinfgtk/inf-gtk-browser-view.c:2330 msgid "Connecting..." msgstr "" #: ../libinfgtk/inf-gtk-browser-view.c:2340 msgid "Connected" msgstr "" #: ../libinfgtk/inf-gtk-certificate-dialog.c:109 #, c-format msgid "The connection to host \"%s\" is not considered secure" msgstr "" #: ../libinfgtk/inf-gtk-certificate-dialog.c:130 msgid "The host has presented a new certificate." msgstr "" #: ../libinfgtk/inf-gtk-certificate-dialog.c:139 msgid "" "Its previous certificate has expired or is closed to expiration. Please make " "sure that you trust the new certificate." msgstr "" #: ../libinfgtk/inf-gtk-certificate-dialog.c:146 msgid "The host has presented an unexpected certificate!" msgstr "" #: ../libinfgtk/inf-gtk-certificate-dialog.c:155 msgid "" "This means someone might be eavesdropping on the connection. Please only " "continue if you expected this message, otherwise please contact the server " "administrator." msgstr "" #: ../libinfgtk/inf-gtk-certificate-dialog.c:165 msgid "" "The server certificate cannot be verified automatically. Please make sure " "that you trust this host before proceeding." msgstr "" #: ../libinfgtk/inf-gtk-certificate-dialog.c:176 msgid "The issuer of the certificate is not known." msgstr "" #: ../libinfgtk/inf-gtk-certificate-dialog.c:189 #, c-format msgid "" "The hostname of the server, \"%s\", does not match the hostname the " "certificate is issued to, \"%s\"." msgstr "" #: ../libinfgtk/inf-gtk-certificate-dialog.c:342 msgid "" msgstr "" #: ../libinfgtk/inf-gtk-certificate-manager.c:226 msgid "_Cancel connection" msgstr "" #: ../libinfgtk/inf-gtk-certificate-manager.c:232 msgid "C_ontinue connection" msgstr "" #: ../libinfgtk/inf-gtk-certificate-manager.c:237 #, c-format msgid "" "Do you want to continue the connection to host \"%s\"? If you choose to " "continue, this certificate will be trusted in the future when connecting to " "this host." msgstr "" #: ../libinfgtk/inf-gtk-certificate-view.c:72 msgid "" msgstr "" #: ../libinfgtk/inf-gtk-chat.c:202 #, c-format msgid "%s has joined" msgstr "" #: ../libinfgtk/inf-gtk-chat.c:209 #, c-format msgid "%s has left" msgstr "" #. Then, show a menu item to remove an account. #: ../libinfgtk/inf-gtk-permissions-dialog.c:1879 msgid "_Delete Account" msgstr "" #: ../libinfgtk/inf-gtk-permissions-dialog.c:2312 msgid "No node selected" msgstr "" #: ../libinfgtk/inf-gtk-permissions-dialog.c:2318 #, c-format msgid "Permissions for %s" msgstr "" #: ../libinfgtk/inf-gtk-permissions-dialog.c:2496 msgid "" "Permission is not granted to modify the permission list. It is read-" "only." msgstr "" #: ../libinfgtk/inf-gtk-permissions-dialog.c:2520 msgid "Permission is granted to modify the permission list." msgstr "" #: ../libinfgtk/inf-gtk-permissions-dialog.c:2530 #, c-format msgid "Server Error: %s" msgstr "" #: ../libinfgtk/inf-gtk-permissions-dialog.c:2538 msgid "Querying current permissions for this node from the server..." msgstr "" #: ../libinfgtk/inf-gtk-permissions-dialog.c:2544 msgid "" "Permission is not granted to query the permission list for this node " "from the server. Showing only default permissions and permissions for the " "own account." msgstr "" #: ../libinfgtk/inf-gtk-permissions-dialog.c:2551 msgid "" "Permissions are granted to query the full permission list from the " "server. Showing all permissions." msgstr "" #: ../libinfgtk/resources/ui/infgtkaccountcreationdialog.ui:12 msgid "Create New Account" msgstr "" #: ../libinfgtk/resources/ui/infgtkaccountcreationdialog.ui:75 msgid "Account Name:" msgstr "" #: ../libinfgtk/resources/ui/infgtkaccountcreationdialog.ui:98 msgid "Create _Account" msgstr "" #: ../libinfgtk/resources/ui/infgtkaclsheetview.ui:31 msgid "Permission" msgstr "" #: ../libinfgtk/resources/ui/infgtkaclsheetview.ui:43 msgid "Default" msgstr "" #: ../libinfgtk/resources/ui/infgtkaclsheetview.ui:55 msgid "Yes" msgstr "" #: ../libinfgtk/resources/ui/infgtkaclsheetview.ui:67 msgid "No" msgstr "" #: ../libinfgtk/resources/ui/infgtkcertificatedialog.ui:14 msgid "Connection Not Secure" msgstr "" #: ../libinfgtk/resources/ui/infgtkcertificatedialog.ui:138 msgid "Certificate Chain" msgstr "" #: ../libinfgtk/resources/ui/infgtkcertificatedialog.ui:172 msgid "_View Certificate" msgstr "" #: ../libinfgtk/resources/ui/infgtkcertificateview.ui:11 msgid "Issued To" msgstr "" #: ../libinfgtk/resources/ui/infgtkcertificateview.ui:26 #: ../libinfgtk/resources/ui/infgtkcertificateview.ui:134 msgid "Common Name:" msgstr "" #: ../libinfgtk/resources/ui/infgtkcertificateview.ui:48 #: ../libinfgtk/resources/ui/infgtkcertificateview.ui:156 msgid "Organization:" msgstr "" #: ../libinfgtk/resources/ui/infgtkcertificateview.ui:70 #: ../libinfgtk/resources/ui/infgtkcertificateview.ui:178 msgid "Organizational Unit:" msgstr "" #: ../libinfgtk/resources/ui/infgtkcertificateview.ui:92 msgid "Serial Number:" msgstr "" #: ../libinfgtk/resources/ui/infgtkcertificateview.ui:119 msgid "Issued By" msgstr "" #: ../libinfgtk/resources/ui/infgtkcertificateview.ui:200 msgid "Validity" msgstr "" #: ../libinfgtk/resources/ui/infgtkcertificateview.ui:215 msgid "Issued On:" msgstr "" #: ../libinfgtk/resources/ui/infgtkcertificateview.ui:237 msgid "Expires On:" msgstr "" #: ../libinfgtk/resources/ui/infgtkcertificateview.ui:259 msgid "Fingerprints" msgstr "" #: ../libinfgtk/resources/ui/infgtkcertificateview.ui:274 msgid "SHA-1 Fingerprint:" msgstr "" #: ../libinfgtk/resources/ui/infgtkcertificateview.ui:301 msgid "SHA-256 Fingerprint:" msgstr "" #: ../libinfgtk/resources/ui/infgtkcertificateview.ui:333 msgid "Signature" msgstr "" #: ../libinfgtk/resources/ui/infgtkcertificateview.ui:348 msgid "Signature Algorithm:" msgstr "" #: ../libinfgtk/resources/ui/infgtkchat.ui:93 msgid "Send" msgstr "" #: ../libinfgtk/resources/ui/infgtkpermissionsdialog.ui:121 msgid "Accounts" msgstr "" #: ../libinfinity/adopted/inf-adopted-algorithm.c:1013 #, c-format msgid "Failed to apply request \"%s\" from user \"%s\" at state \"%s\": " msgstr "" #: ../libinfinity/adopted/inf-adopted-algorithm.c:1899 #, c-format msgid "" "The request \"%s\" from user \"%s\" is an UNDO request but there is no " "request to be undone." msgstr "" #: ../libinfinity/adopted/inf-adopted-algorithm.c:1920 #, c-format msgid "" "The request \"%s\" from user \"%s\" is a REDO request but there is no " "request to be redone." msgstr "" #: ../libinfinity/adopted/inf-adopted-session.c:160 #, c-format msgid "Request has index '%u', but index '%u' was expected" msgstr "" #: ../libinfinity/adopted/inf-adopted-session.c:181 msgid "Undo received, but no previous request found" msgstr "" #: ../libinfinity/adopted/inf-adopted-session.c:197 msgid "Redo received, but no previous request found" msgstr "" #: ../libinfinity/adopted/inf-adopted-session.c:238 #, c-format msgid "No such user with user ID '%u'" msgstr "" #: ../libinfinity/adopted/inf-adopted-session.c:481 msgid "The request was rejected via the API" msgstr "" #: ../libinfinity/adopted/inf-adopted-session.c:1173 #: ../libinfinity/common/inf-chat-session.c:468 #: ../libinfinity/common/inf-session.c:782 ../libinftext/inf-text-session.c:949 msgid "User did not join from this connection" msgstr "" #: ../libinfinity/adopted/inf-adopted-session.c:1223 #, c-format msgid "" "Request \"%s\" by user \"%s\" is not consecutive with respect to previously " "received request \"%s\"" msgstr "" #: ../libinfinity/adopted/inf-adopted-session.c:1436 msgid "\"time\" attribute in user message is missing" msgstr "" #: ../libinfinity/adopted/inf-adopted-session.c:1884 msgid "Operation for request missing" msgstr "" #. Error writing record `': #: ../libinfinity/adopted/inf-adopted-session-record.c:95 #, c-format msgid "Error writing record \"%s\": %s" msgstr "" #: ../libinfinity/adopted/inf-adopted-session-replay.c:164 msgid "Unexpected end of recording" msgstr "" #: ../libinfinity/adopted/inf-adopted-session-replay.c:356 msgid "Document is not a session recording" msgstr "" #: ../libinfinity/adopted/inf-adopted-session-replay.c:371 msgid "Session type of the recording does not match" msgstr "" #: ../libinfinity/adopted/inf-adopted-session-replay.c:391 msgid "Initial session state missing in recording" msgstr "" #: ../libinfinity/adopted/inf-adopted-session-replay.c:465 msgid "Session switched to running without having finished playing the initial" msgstr "" #: ../libinfinity/adopted/inf-adopted-session-replay.c:485 msgid "Superfluous XML in initial session section" msgstr "" #: ../libinfinity/adopted/inf-adopted-session-replay.c:498 msgid "Session is still in synchronizing state after having played the initial" msgstr "" #: ../libinfinity/adopted/inf-adopted-session-replay.c:892 msgid "Superfluous XML in requests section" msgstr "" #: ../libinfinity/adopted/inf-adopted-session-replay.c:919 #: ../libinfinity/common/inf-chat-session.c:269 #, c-format msgid "No such user with ID \"%u\"" msgstr "" #: ../libinfinity/adopted/inf-adopted-session-replay.c:992 #, c-format msgid "Unexpected node \"%s\" in requests section" msgstr "" #: ../libinfinity/adopted/inf-adopted-state-vector.c:730 msgid "Expected \":\" after ID" msgstr "" #: ../libinfinity/adopted/inf-adopted-state-vector.c:744 #, c-format msgid "ID '%u' already occured before" msgstr "" #: ../libinfinity/adopted/inf-adopted-state-vector.c:761 #, c-format msgid "Expected ';' or end of string after component of ID '%u'" msgstr "" #: ../libinfinity/client/infc-browser.c:784 msgid "The node to subscribe to has been removed" msgstr "" #: ../libinfinity/client/infc-browser.c:811 #: ../libinfinity/client/infc-browser.c:839 msgid "" "The subdirectory into which the new node should have been created has been " "removed" msgstr "" #: ../libinfinity/client/infc-browser.c:990 msgid "Permissions to explore this node have been revoked" msgstr "" #: ../libinfinity/client/infc-browser.c:1030 #: ../libinfinity/client/infc-browser.c:1059 msgid "Permissions to explore the parent node have been revoked" msgstr "" #: ../libinfinity/client/infc-browser.c:1354 msgid "" "The server did not send an initial welcome message. This means that the " "server is running a lower version of the software which is incompatible to " "the client. Consider downgrading the client, or ask the server " "administrators to upgrade their software." msgstr "" #: ../libinfinity/client/infc-browser.c:1635 #, c-format msgid "" "This session requires communication method `%s' which is not installed for " "network `%s'" msgstr "" #: ../libinfinity/client/infc-browser.c:2448 #, c-format msgid "There is no such node with ID %u" msgstr "" #: ../libinfinity/client/infc-browser.c:2580 #, c-format msgid "" "The request contains a sequence number refering to a request of type '%s', " "but a request of either 'explore-node' or 'add-node' was expected." msgstr "" #: ../libinfinity/client/infc-browser.c:2831 msgid "" "The server uses an older version of the protocol which is no longer " "supported by this client. Consider using an earlier version of it, or ask " "the server administrators to upgrade their software." msgstr "" #: ../libinfinity/client/infc-browser.c:2844 msgid "" "The server uses a newer version of the protocol which is not supported by " "this client. Consider upgrading your client." msgstr "" #: ../libinfinity/client/infc-browser.c:3005 msgid "Node to explore does no longer exist" msgstr "" #: ../libinfinity/client/infc-browser.c:3016 msgid "Node to explore is not a subdirectory" msgstr "" #: ../libinfinity/client/infc-browser.c:3027 msgid "Node to explore is already explored" msgstr "" #: ../libinfinity/client/infc-browser.c:3072 msgid "Not all nodes were received before explore-end was received" msgstr "" #: ../libinfinity/client/infc-browser.c:3134 #: ../libinfinity/client/infc-browser.c:3358 #, c-format msgid "Node with ID \"%u\" exists already" msgstr "" #: ../libinfinity/client/infc-browser.c:3157 msgid "The parent node has not been explored yet" msgstr "" #: ../libinfinity/client/infc-browser.c:3232 msgid "Explored nodes cannot be initially be subscribed to" msgstr "" #: ../libinfinity/client/infc-browser.c:3247 #, c-format msgid "Note type \"%s\" not known" msgstr "" #: ../libinfinity/client/infc-browser.c:3402 msgid "Received sync-in without having requested one" msgstr "" #: ../libinfinity/client/infc-browser.c:3422 #, c-format msgid "Expected note type \"%s\" for sync-in, but received \"%s\"" msgstr "" #: ../libinfinity/client/infc-browser.c:3578 #, c-format msgid "Note type '%s' is not supported" msgstr "" #: ../libinfinity/client/infc-browser.c:3592 msgid "Already subscribed to this session" msgstr "" #: ../libinfinity/client/infc-browser.c:3648 msgid "Already subscribed to the chat session" msgstr "" #: ../libinfinity/client/infc-browser.c:3870 msgid "Not all users have been transmitted before user-list-end was received" msgstr "" #: ../libinfinity/client/infc-browser.c:4149 #, c-format msgid "" "Unknown account ID \"%s\" in server reply of \"%s\". Typically, this means " "the server claimed it notified us about new connections as soon as they are " "available, but it did not do so." msgstr "" #: ../libinfinity/client/infc-browser.c:4411 msgid "No certificate request has been made" msgstr "" #: ../libinfinity/client/infc-browser.c:4438 #: ../libinfinity/client/infc-browser.c:4468 msgid "No certificate provided" msgstr "" #: ../libinfinity/client/infc-browser.c:4486 msgid "Cannot verify the certificate without server certificate" msgstr "" #: ../libinfinity/client/infc-browser.c:4536 #, c-format msgid "Server sent an invalid certificate (%s)" msgstr "" #: ../libinfinity/client/infc-browser.c:4643 #: ../libinfinity/server/infd-directory.c:3306 msgid "The default account cannot be removed" msgstr "" #: ../libinfinity/client/infc-browser.c:4796 #, c-format msgid "" "The request contains a sequence number refering to a request of type '%s', " "but a request of either 'query-acl' or 'set-acl' was expected." msgstr "" #: ../libinfinity/client/infc-browser.c:4969 #, c-format msgid "Error comes from unknown error domain '%s' (code %u)" msgstr "" #: ../libinfinity/client/infc-browser.c:5193 #, c-format msgid "Received unexpected network message \"%s\"" msgstr "" #: ../libinfinity/client/infc-browser.c:5216 #: ../libinfinity/client/infc-session-proxy.c:989 #, c-format msgid "Server reply could not be processed: %s" msgstr "" #: ../libinfinity/client/infc-request-manager.c:126 msgid "Sequence identifier causes overflow" msgstr "" #: ../libinfinity/client/infc-request-manager.c:138 msgid "Sequence components are not separated by '/'" msgstr "" #: ../libinfinity/client/infc-request-manager.c:152 msgid "Sequence number causes overflow" msgstr "" #: ../libinfinity/client/infc-request-manager.c:164 msgid "Trailing characters after sequence number" msgstr "" #: ../libinfinity/client/infc-request-manager.c:735 #, c-format msgid "No such sequence number %u" msgstr "" #: ../libinfinity/client/infc-request-manager.c:748 #, c-format msgid "" "The request contains a sequence number refering to a request of type '%s', " "but a request of type '%s' was expected" msgstr "" #: ../libinfinity/client/infc-request-manager.c:803 msgid "The request does not contain a sequence number, but one is required" msgstr "" #: ../libinfinity/client/infc-session-proxy.c:524 #, c-format msgid "Error comes from unknown error domain \"%s\" (code %u)" msgstr "" #: ../libinfinity/client/infc-session-proxy.c:666 msgid "Request does not contain required attribute \"id\"" msgstr "" #: ../libinfinity/client/infc-session-proxy.c:684 #: ../libinfinity/common/inf-session.c:768 #, c-format msgid "No such user with ID %u" msgstr "" #: ../libinfinity/common/inf-acl.c:763 msgid "ACL field must be either \"yes\" or \"no\"" msgstr "" #: ../libinfinity/common/inf-acl.c:1273 #, c-format msgid "Permissions for account ID \"%s\" defined more than once" msgstr "" #: ../libinfinity/common/inf-async-operation.c:115 msgid "" "InfIo object was deleted without InfAsyncOperation being freed! This is a " "programming error that leaves the program in an inconsistent state. " "Therefore, the program is aborted. Please fix your code." msgstr "" #: ../libinfinity/common/inf-chat-session.c:90 msgid "An invalid message type was sent" msgstr "" #: ../libinfinity/common/inf-chat-session.c:92 msgid "A user with the requested ID does not exist" msgstr "" #: ../libinfinity/common/inf-chat-session.c:94 msgid "An unknown chat session error has occured" msgstr "" #: ../libinfinity/common/inf-chat-session.c:96 #: ../libinfinity/common/inf-error.c:84 ../libinfinity/common/inf-error.c:131 #: ../libinfinity/common/inf-session.c:233 msgid "An error with unknown error code occured" msgstr "" #: ../libinfinity/common/inf-chat-session.c:360 #, c-format msgid "%s --- %s has joined\n" msgstr "" #: ../libinfinity/common/inf-chat-session.c:363 #, c-format msgid "%s --- %s has left\n" msgstr "" #: ../libinfinity/common/inf-chat-session.c:421 #, c-format msgid "%s --- %u users total\n" msgstr "" #: ../libinfinity/common/inf-chat-session.c:1244 #, c-format msgid "%s --- Log closed\n" msgstr "" #: ../libinfinity/common/inf-chat-session.c:1258 #, c-format msgid "%s --- Log opened\n" msgstr "" #: ../libinfinity/common/inf-discovery-avahi.c:542 #, c-format msgid "" "Avahi service browser is in failure state. Services of type '%s' are no " "longer discovered.\n" "\n" "The failure was: %s\n" msgstr "" #: ../libinfinity/common/inf-discovery-avahi.c:629 #, c-format msgid "" "Avahi entry group is in failure state. The service '%s' of type '%s' is no " "longer published.\n" "\n" "The failure was: %s\n" msgstr "" #: ../libinfinity/common/inf-discovery-avahi.c:839 #, c-format msgid "" "Failed to start Avahi client. Service discovery or publishing will not be " "possible.\n" "\n" "The occurred failure was: %s" msgstr "" #: ../libinfinity/common/inf-discovery-avahi.c:882 #, c-format msgid "" "Avahi client is in failure state. Service discovery or publishing is no " "longer possible.\n" "\n" "The occured failure was: %s\n" msgstr "" #. Translators: This is " (via on #. *
)", for example "ck (via eth0 on IPv4)". #: ../libinfinity/common/inf-discovery-avahi.c:1465 #, c-format msgid "%s (via %s on IPv4)" msgstr "" #: ../libinfinity/common/inf-discovery-avahi.c:1466 #, c-format msgid "%s (via %s on IPv6)" msgstr "" #: ../libinfinity/common/inf-error.c:68 msgid "Received error from an unknown domain" msgstr "" #: ../libinfinity/common/inf-error.c:70 msgid "Failed to process server reply" msgstr "" #: ../libinfinity/common/inf-error.c:72 msgid "Server reply contains invalid sequence number" msgstr "" #: ../libinfinity/common/inf-error.c:74 msgid "A required attribute was not set in request" msgstr "" #: ../libinfinity/common/inf-error.c:76 msgid "An attribute did not have valid content" msgstr "" #: ../libinfinity/common/inf-error.c:78 msgid "An attribute contained an invalid number" msgstr "" #: ../libinfinity/common/inf-error.c:80 msgid "Not authorized" msgstr "" #: ../libinfinity/common/inf-error.c:82 msgid "An unknown request error occured" msgstr "" #: ../libinfinity/common/inf-error.c:117 msgid "Name is already in use" msgstr "" #: ../libinfinity/common/inf-error.c:119 msgid "'id' attribute provided in request" msgstr "" #: ../libinfinity/common/inf-error.c:121 msgid "There is no user with the given ID" msgstr "" #: ../libinfinity/common/inf-error.c:123 msgid "'status' attribute is 'unavailable' in join or rejoin request" msgstr "" #: ../libinfinity/common/inf-error.c:125 msgid "User did not join via this connection" msgstr "" #: ../libinfinity/common/inf-error.c:127 msgid "'status' attribute has invalid value" msgstr "" #: ../libinfinity/common/inf-error.c:129 msgid "An unknown user error occured" msgstr "" #: ../libinfinity/common/inf-error.c:164 msgid "Server did not send an initial welcome message" msgstr "" #: ../libinfinity/common/inf-error.c:166 msgid "The server and client use different protocol versions" msgstr "" #: ../libinfinity/common/inf-error.c:168 msgid "A node with this name exists already" msgstr "" #: ../libinfinity/common/inf-error.c:170 msgid "Invalid node name" msgstr "" #: ../libinfinity/common/inf-error.c:172 msgid "Node does not exist" msgstr "" #: ../libinfinity/common/inf-error.c:174 msgid "No previous subscription request present" msgstr "" #: ../libinfinity/common/inf-error.c:176 msgid "The chat is disabled on the server side" msgstr "" #: ../libinfinity/common/inf-error.c:178 msgid "Node is not a subdirectory" msgstr "" #: ../libinfinity/common/inf-error.c:180 msgid "Node is not a note" msgstr "" #: ../libinfinity/common/inf-error.c:182 msgid "The node type is not supported by the server" msgstr "" #: ../libinfinity/common/inf-error.c:184 #: ../libinfinity/server/infd-directory.c:5950 msgid "The root node cannot be removed" msgstr "" #: ../libinfinity/common/inf-error.c:186 msgid "Subdirectory is not explored" msgstr "" #: ../libinfinity/common/inf-error.c:188 msgid "Subdirectory has already been explored" msgstr "" #: ../libinfinity/common/inf-error.c:190 msgid "Note type is not supported" msgstr "" #: ../libinfinity/common/inf-error.c:192 msgid "Connection is already subscribed to this session" msgstr "" #: ../libinfinity/common/inf-error.c:194 #: ../libinfinity/server/infd-directory.c:6214 msgid "The requesting connection is not subscribed to the session" msgstr "" #: ../libinfinity/common/inf-error.c:196 msgid "" "The server started to send explored nodes before telling howmany nodes to " "expect" msgstr "" #: ../libinfinity/common/inf-error.c:199 msgid "Server sent more explored nodes then announced" msgstr "" #: ../libinfinity/common/inf-error.c:201 msgid "Server sent not as much explored nodes as announced" msgstr "" #: ../libinfinity/common/inf-error.c:203 msgid "" "The session does not support the network through which the connection " "attempt is being made." msgstr "" #: ../libinfinity/common/inf-error.c:206 msgid "The session uses an unsupported communication method" msgstr "" #: ../libinfinity/common/inf-error.c:208 msgid "The requested operation is not supported by the server" msgstr "" #: ../libinfinity/common/inf-error.c:210 msgid "Received sync-in message without having requested a sync-in" msgstr "" #: ../libinfinity/common/inf-error.c:212 msgid "Client rejected subscription" msgstr "" #: ../libinfinity/common/inf-error.c:214 msgid "Unexpected XML message" msgstr "" #: ../libinfinity/common/inf-error.c:216 msgid "Server does not have a background storage" msgstr "" #: ../libinfinity/common/inf-error.c:218 msgid "The certificate is invalid or not trusted" msgstr "" #: ../libinfinity/common/inf-error.c:220 msgid "The account list has already been queried before" msgstr "" #: ../libinfinity/common/inf-error.c:222 msgid "The account list has not been queried" msgstr "" #: ../libinfinity/common/inf-error.c:224 msgid "An account with this ID exists already" msgstr "" #: ../libinfinity/common/inf-error.c:226 msgid "There is no such account with the given ID" msgstr "" #: ../libinfinity/common/inf-error.c:228 msgid "The ACL has already been queried" msgstr "" #: ../libinfinity/common/inf-error.c:230 msgid "The ACL has not been queried" msgstr "" #: ../libinfinity/common/inf-error.c:232 msgid "An unknown directory error has occured" msgstr "" #: ../libinfinity/common/inf-error.c:234 ../libinfinity/common/inf-error.c:277 msgid "An error with unknown code has occured" msgstr "" #: ../libinfinity/common/inf-error.c:268 msgid "User did not provide valid credentials." msgstr "" #: ../libinfinity/common/inf-error.c:270 msgid "User is not permitted to connect to this server." msgstr "" #: ../libinfinity/common/inf-error.c:272 msgid "Authentication was temporarily interrupted on the server side." msgstr "" #: ../libinfinity/common/inf-error.c:275 msgid "An error cocured while checking user permissions." msgstr "" #: ../libinfinity/common/inf-error.c:351 msgid "The certificate was revoked" msgstr "" #: ../libinfinity/common/inf-error.c:353 msgid "The certificate was not signed by a trusted CA" msgstr "" #: ../libinfinity/common/inf-error.c:355 msgid "The signer of the certificate is not a CA" msgstr "" #: ../libinfinity/common/inf-error.c:357 msgid "The certificate uses an insecure algorithm" msgstr "" #: ../libinfinity/common/inf-error.c:359 msgid "The certificate is not yet activated" msgstr "" #: ../libinfinity/common/inf-error.c:361 msgid "The certificate has expired" msgstr "" #: ../libinfinity/common/inf-error.c:363 msgid "The certificate is invalid" msgstr "" #: ../libinfinity/common/inf-name-resolver.c:205 msgid "The reply from the DNS server is incomplete" msgstr "" #: ../libinfinity/common/inf-name-resolver.c:742 #, c-format msgid "" "Failure during SRV record lookup: %s\n" "Will go on with normal A/AAAA lookup" msgstr "" #: ../libinfinity/common/inf-protocol.c:85 msgid "Major part of version number causes overflow" msgstr "" #: ../libinfinity/common/inf-protocol.c:97 msgid "Version number parts are not separated by '.'" msgstr "" #: ../libinfinity/common/inf-protocol.c:111 msgid "Minor part of version number causes overflow" msgstr "" #: ../libinfinity/common/inf-protocol.c:123 msgid "Trailing characters after version number" msgstr "" #: ../libinfinity/common/inf-session.c:198 msgid "Unexpectedly got an XML message in presync" msgstr "" #: ../libinfinity/common/inf-session.c:200 msgid "Got unexpected XML node during synchronization" msgstr "" #: ../libinfinity/common/inf-session.c:202 msgid "'id' attribute in user message is missing" msgstr "" #: ../libinfinity/common/inf-session.c:204 msgid "User ID is already in use" msgstr "" #: ../libinfinity/common/inf-session.c:206 msgid "'name' attribute in user message is missing" msgstr "" #: ../libinfinity/common/inf-session.c:208 msgid "User Name is already in use" msgstr "" #: ../libinfinity/common/inf-session.c:210 msgid "The connection was closed unexpectedly" msgstr "" #: ../libinfinity/common/inf-session.c:212 msgid "The sender cancelled the synchronization" msgstr "" #: ../libinfinity/common/inf-session.c:214 msgid "The receiver cancelled the synchronization" msgstr "" #: ../libinfinity/common/inf-session.c:216 msgid "Got begin-of-sync message, but synchronization is already in progress" msgstr "" #: ../libinfinity/common/inf-session.c:219 msgid "begin-of-sync message does not contain the number of messages to expect" msgstr "" #: ../libinfinity/common/inf-session.c:222 msgid "Got end-of-sync message, but synchronization is still in progress" msgstr "" #: ../libinfinity/common/inf-session.c:225 msgid "Expected begin-of-sync message as first message during synchronization" msgstr "" #: ../libinfinity/common/inf-session.c:228 msgid "Expected end-of-sync message as last message during synchronization" msgstr "" #: ../libinfinity/common/inf-session.c:231 msgid "An unknown synchronization error has occured" msgstr "" #. TODO: Add a possibilty for sub classes to register their error domains #. * that can occur in process_xml_sync. Maybe via a translate_error_sync #. * vfunc. #: ../libinfinity/common/inf-session.c:247 msgid "An error with unknown error domain occured" msgstr "" #: ../libinfinity/common/inf-session.c:937 #, c-format msgid "Received unhandled XML message '%s'" msgstr "" #: ../libinfinity/common/inf-session.c:1467 #, c-format msgid "Unexpectedly received XML message \"%s\" in presync" msgstr "" #: ../libinfinity/common/inf-session.c:1576 #, c-format msgid "Received unexpected XML message \"%s\" while synchronizing" msgstr "" #: ../libinfinity/common/inf-tcp-connection.c:1039 #, c-format msgid "Interface `%s' does not exist" msgstr "" #: ../libinfinity/common/inf-tcp-connection.c:1100 #, c-format msgid "Failed to retrieve local address: %s" msgstr "" #: ../libinfinity/common/inf-tcp-connection.c:1118 #, c-format msgid "Failed to retrieve local port: %s" msgstr "" #. TODO: We can probably implement this using GetInterfaceInfo() #: ../libinfinity/common/inf-tcp-connection.c:1134 msgid "The device-name property is not implemented on Win32" msgstr "" #. Failed to get name for device : #: ../libinfinity/common/inf-tcp-connection.c:1147 #, c-format msgid "Failed to get name for device %u: %s" msgstr "" #: ../libinfinity/common/inf-user.c:497 #, c-format msgid "Invalid user status: '%s'" msgstr "" #: ../libinfinity/common/inf-xml-util.c:60 #: ../libinfinity/common/inf-xml-util.c:117 #: ../libinfinity/common/inf-xml-util.c:236 #, c-format msgid "Attribute '%s' does not contain a valid number" msgstr "" #: ../libinfinity/common/inf-xml-util.c:72 #: ../libinfinity/common/inf-xml-util.c:129 #: ../libinfinity/common/inf-xml-util.c:160 #: ../libinfinity/common/inf-xml-util.c:204 #: ../libinfinity/common/inf-xml-util.c:249 #, c-format msgid "Attribute '%s' causes overflow (%s)" msgstr "" #: ../libinfinity/common/inf-xml-util.c:85 #: ../libinfinity/common/inf-xml-util.c:173 #: ../libinfinity/common/inf-xml-util.c:262 #, c-format msgid "Attribute '%s' causes underflow (%s)" msgstr "" #: ../libinfinity/common/inf-xml-util.c:454 #, c-format msgid "Request '%s' does not contain required attribute '%s'" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:400 msgid "The entity has sent XML that cannot be processed" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:402 msgid "" "The entity has sent a namespace prefix that is unsupported, or has sent no " "namespace prefix on an element that requires such a prefix" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:406 msgid "" "The server is closing the active stream for this entity because a new stream " "has been initiated that conflicts with the existing stream" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:410 msgid "" "The entity has not generated any traffic over the stream for some period of " "time" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:413 msgid "" "The value of the 'to' attribute provided by the initiating entity in the " "stream header corresponds to a hostname that is no longer hosted by the " "server" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:417 msgid "" "The value of the 'to' attribute provided by the initiating entity in the " "stream header does not correspond to a hostname that is hosted by the server" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:421 msgid "A stanza sent between two servers lacks a 'to' or 'from'attribute" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:424 msgid "" "The server has experienced a misconfiguration or an otherwise-undefined " "internal error that prevents it from servicing the stream" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:428 msgid "" "The JID or hostname provided in a 'from' address does not match an " "authorized JID or validated domain negotiated between servers via SASL or " "dialback, or between a client and a server via authentication and resource " "binding" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:433 msgid "" "The stream ID or dialback ID is invalid or does not match an ID previously " "provided" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:436 msgid "" "The streams namespace is something other than \"http://etherx.jabber.org/" "streams\" or the dialback namespace name is something other than \"jabber:" "server:dialback\"" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:440 msgid "" "The entity has sent invalid XML over the stream to a server that performs " "validation" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:443 msgid "" "The entity has attempted to send data before the stream has been " "authenticated, or otherwise is not authorized to perform an action related " "to stream negotiation" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:447 msgid "The entity has violated some local service policy" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:449 msgid "" "The server is unable to properly connect to a remote entity that is required " "for authentication or authorization" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:452 msgid "The server lacks the system resources necessary to service the stream" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:455 msgid "The entity has attempted to send restricted XML features" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:457 msgid "" "The server will not provide service to the initiating entity but is " "redirecting traffic to another host" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:460 msgid "The server is being shut down and all active streams are being closed" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:464 msgid "The error condition is not one of those defined by the other conditions" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:467 msgid "" "The initiating entity has encoded the stream in an encoding that is not " "supported by the server" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:470 msgid "" "The initiating entity has sent a first-level child of the stream that is not " "supported by the server." msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:473 msgid "" "The value of the 'version' attribute provided by the initiating entity in " "the stream header specifies a version of XMPP that is not supported by the " "server" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:477 msgid "The initiating entity has sent XML that is not well-formed" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:522 msgid "" "The receiving entity acknowledged an element sent by the initiating " "entity" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:525 msgid "" "The data provided by the initiating entity could not be processed because " "the Base64 encoding is incorrect" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:528 msgid "" "The authzid provided by the initiating entity is invalid, either because it " "is incorrectly formatted or because the initiating entity does not have " "permissions to authorize that ID" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:533 msgid "" "The initiating entity did not provide a mechanism or requested a mechanism " "that is not supported by the receiving entity" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:536 msgid "" "The mechanism requsted by the initiating entity is weaker than server policy " "permits for that initiating entity" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:539 msgid "" "The authentication failed because the initiating entity did not provide " "valid credentials" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:542 msgid "" "The authentication failed because of a temporary error condition within the " "receiving entity" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:545 msgid "An unknown authentication error has occured" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:1314 msgid "The server did not provide a certificate" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:2109 msgid "Stream is not yet secured with TLS" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:2176 msgid "Stream is not yet authorized" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:2304 msgid "The server does not offer a suitable authentication mechanism" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:2349 msgid "The server does not support transport layer security (TLS)" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:2372 msgid "The server requires transport layer security (TLS)" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:2406 msgid "The server does not provide any authentication mechanism" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:2464 msgid "The server cannot perform the TLS handshake" msgstr "" #. XML Warning from : #: ../libinfinity/common/inf-xmpp-connection.c:2946 #, c-format msgid "XML warning from %s: %s\n" msgstr "" #. The server sent something which is not XML #: ../libinfinity/common/inf-xmpp-connection.c:2990 msgid "Remote site is not an XMPP server" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:4606 msgid "The server certificate is not trusted" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:4614 #, c-format msgid "The server certificate is not trusted: %s" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:4626 msgid "The client certificate is not trusted" msgstr "" #: ../libinfinity/common/inf-xmpp-connection.c:4634 #, c-format msgid "The client certificate is not trusted: %s" msgstr "" #: ../libinfinity/server/infd-account-storage.c:333 msgid "The account backend does not support acount listing" msgstr "" #: ../libinfinity/server/infd-account-storage.c:387 msgid "The account backend does not support adding accounts" msgstr "" #: ../libinfinity/server/infd-account-storage.c:427 msgid "The account backend does not support removing accounts" msgstr "" #: ../libinfinity/server/infd-account-storage.c:471 msgid "The account backend does not support logging in with a certificate" msgstr "" #: ../libinfinity/server/infd-account-storage.c:522 msgid "The account backend does not support logging in with a password" msgstr "" #: ../libinfinity/server/infd-account-storage.c:573 msgid "The account backend does not support changing the certificate" msgstr "" #: ../libinfinity/server/infd-account-storage.c:619 msgid "The account backend does not support changing the password" msgstr "" #: ../libinfinity/server/infd-chat-filesystem-format.c:145 #: ../libinfinity/server/infd-filesystem-storage.c:269 #: ../libinftext/inf-text-filesystem-format.c:368 #, c-format msgid "Error parsing XML in file \"%s\": [%d]: %s" msgstr "" #: ../libinfinity/server/infd-chat-filesystem-format.c:162 #: ../libinftext/inf-text-filesystem-format.c:385 #, c-format msgid "Error processing file \"%s\": %s" msgstr "" #: ../libinfinity/server/infd-chat-filesystem-format.c:164 msgid "The document is not a chat session" msgstr "" #: ../libinfinity/server/infd-directory.c:431 #, c-format msgid "" "Failed to save note \"%s\": %s\n" "\n" "Keeping it in memory. Another save attempt will be made when the server is " "shut down." msgstr "" #: ../libinfinity/server/infd-directory.c:955 #, c-format msgid "Failed to login client \"%s\" by certificate: %s" msgstr "" #: ../libinfinity/server/infd-directory.c:1000 #, c-format msgid "" "Failed to write ACL for node \"%s\": %s\n" "The new ACL is applied but will be lost after a server re-start. This is a " "possible security problem. Please fix the problem with the storage!" msgstr "" #: ../libinfinity/server/infd-directory.c:1198 #, c-format msgid "Failed to look up accounts in account storage: %s" msgstr "" #: ../libinfinity/server/infd-directory.c:1690 #, c-format msgid "" "Failed to read the ACL for the root node: %s\n" "In order not to compromise security all permissions have been revoked for " "all users. The infinote server is likely not very usable in this " "configuration, so please check the storage system, fix the problem and re-" "start the server." msgstr "" #: ../libinfinity/server/infd-directory.c:2086 #, c-format msgid "" "Could not write session \"%s\" to storage: %s\n" "\n" "All changes since the document das been saved are lost." msgstr "" #: ../libinfinity/server/infd-directory.c:2901 msgid "Server does not support issuing certificates" msgstr "" #: ../libinfinity/server/infd-directory.c:3014 msgid "The certificate request has no common name set" msgstr "" #: ../libinfinity/server/infd-directory.c:3069 #, c-format msgid "There is already a transient account with name \"%s\"" msgstr "" #: ../libinfinity/server/infd-directory.c:3132 msgid "This server does not support creating accounts" msgstr "" #: ../libinfinity/server/infd-directory.c:3333 #: ../libinfinity/server/infd-directory.c:11247 #: ../libinfinity/server/infd-filesystem-account-storage.c:1264 #: ../libinfinity/server/infd-filesystem-account-storage.c:1446 #: ../libinfinity/server/infd-filesystem-account-storage.c:1560 #, c-format msgid "There is no such account with ID \"%s\"" msgstr "" #: ../libinfinity/server/infd-directory.c:3389 msgid "This server does not support removing accounts" msgstr "" #: ../libinfinity/server/infd-directory.c:3732 #, c-format msgid "" "Session \"%s\" could not be saved: %s\n" "Another attempt will be made when the session is unused for a while or the " "server is shut down." msgstr "" #: ../libinfinity/server/infd-directory.c:4256 #, c-format msgid "Name \"%s\" is an invalid name: contains non-printable characters" msgstr "" #: ../libinfinity/server/infd-directory.c:4274 #, c-format msgid "Name \"%s\" is an invalid name: contains only space characters" msgstr "" #: ../libinfinity/server/infd-directory.c:4287 #, c-format msgid "Name \"%s\" is an invalid name: contains \"/\"" msgstr "" #: ../libinfinity/server/infd-directory.c:4302 #, c-format msgid "A node with name \"%s\" exists already" msgstr "" #: ../libinfinity/server/infd-directory.c:5223 #: ../libinfinity/server/infd-session-proxy.c:419 msgid "Permission denied" msgstr "" #: ../libinfinity/server/infd-directory.c:5370 #, c-format msgid "Failed to look up account: %s. Logging out user..." msgstr "" #: ../libinfinity/server/infd-directory.c:5440 msgid "No subscription request for the server chat" msgstr "" #: ../libinfinity/server/infd-directory.c:5459 #, c-format msgid "No subscription request with ID %u" msgstr "" #: ../libinfinity/server/infd-directory.c:5526 #, c-format msgid "Node with ID \"%u\" is not a subdirectory node" msgstr "" #: ../libinfinity/server/infd-directory.c:5538 #, c-format msgid "Node with ID \"%u\" has unsupported type \"%s\"" msgstr "" #: ../libinfinity/server/infd-directory.c:5549 #, c-format msgid "Node with ID \"%u\" is not a leaf node" msgstr "" #: ../libinfinity/server/infd-directory.c:6189 #: ../libinfinity/server/infd-directory.c:11332 msgid "No background storage available" msgstr "" #: ../libinfinity/server/infd-directory.c:6312 msgid "The chat is disabled" msgstr "" #: ../libinfinity/server/infd-directory.c:6421 msgid "No certificate request provided" msgstr "" #: ../libinfinity/server/infd-directory.c:6952 msgid "The ACL for this node has already been queried" msgstr "" #: ../libinfinity/server/infd-directory.c:7039 msgid "The ACL for this node has not been queried yet" msgstr "" #: ../libinfinity/server/infd-directory.c:7065 msgid "The set-acl request does not have any ACL provided" msgstr "" #: ../libinfinity/server/infd-directory.c:7081 #: ../libinfinity/server/infd-directory.c:10456 msgid "This server does not support the requested permissions" msgstr "" #: ../libinfinity/server/infd-directory.c:7348 msgid "The node to be subscribed to has been removed" msgstr "" #: ../libinfinity/server/infd-directory.c:7469 #: ../libinfinity/server/infd-directory.c:7584 msgid "The parent node of the node to be added has been removed" msgstr "" #: ../libinfinity/server/infd-directory.c:7669 msgid "Client did not acknowledge initial subscription" msgstr "" #: ../libinfinity/server/infd-directory.c:7991 #, c-format msgid "Failed to explore the root directory of the new storage: %s" msgstr "" #: ../libinfinity/server/infd-directory.c:8082 #, c-format msgid "" "Failed to lookup account IDs on account storage change: %s. Demoting clients " "to default account." msgstr "" #: ../libinfinity/server/infd-directory.c:8162 #, c-format msgid "Failed to obtain account list from account storage: %s" msgstr "" #: ../libinfinity/server/infd-directory.c:8294 #: ../libinfinity/server/infd-directory.c:8379 #, c-format msgid "Failed to look up accounts in new account storage: %s" msgstr "" #: ../libinfinity/server/infd-filesystem-account-storage.c:189 msgid "" "If one of \"password-hash\" or \"password-salt\" is provided, the other must " "be provided as well." msgstr "" #: ../libinfinity/server/infd-filesystem-account-storage.c:216 msgid "The length of the password salt is incorrect, it should be 32 bytes" msgstr "" #: ../libinfinity/server/infd-filesystem-account-storage.c:247 #, c-format msgid "The length of the password hash is incorrect, it should be %u bytes" msgstr "" #: ../libinfinity/server/infd-filesystem-account-storage.c:541 #, c-format msgid "Duplicate account ID \"%s\" in file \"%s\"" msgstr "" #: ../libinfinity/server/infd-filesystem-account-storage.c:585 #, c-format msgid "" "Accounts \"%s\" and \"%s\" have the same name. This is not supported by " "InfdFilesystemAccountStorage." msgstr "" #: ../libinfinity/server/infd-filesystem-account-storage.c:606 #, c-format msgid "" "Accounts \"%s\" and \"%s\" have the same certificate with DN=%s. This is not " "supported by InfdFilesystemAccountStorage." msgstr "" #: ../libinfinity/server/infd-filesystem-account-storage.c:904 #, c-format msgid "Failed to read accounts from filesystem: %s" msgstr "" #: ../libinfinity/server/infd-filesystem-account-storage.c:1094 #, c-format msgid "There is already an account with name \"%s\"" msgstr "" #: ../libinfinity/server/infd-filesystem-account-storage.c:1107 msgid "The account name is too long" msgstr "" #: ../libinfinity/server/infd-filesystem-account-storage.c:1124 #, c-format msgid "There is already an account with a certificate with DN=\"%s\"" msgstr "" #: ../libinfinity/server/infd-filesystem-account-storage.c:1145 #, c-format msgid "There is already an account with a certificate with fingerprint=\"%s\"" msgstr "" #: ../libinfinity/server/infd-filesystem-account-storage.c:1197 #, c-format msgid "Could not generate a unique ID for account with name \"%s\"" msgstr "" #: ../libinfinity/server/infd-filesystem-account-storage.c:1464 #, c-format msgid "The certificate with DN=%s is already in use by another account" msgstr "" #: ../libinfinity/server/infd-filesystem-storage.c:78 msgid "The path does not start with \"/\"" msgstr "" #: ../libinfinity/server/infd-filesystem-storage.c:92 msgid "The path contains invalid components" msgstr "" #: ../libinfinity/server/infd-filesystem-storage.c:122 #, c-format msgid "Failed to convert root directory to filename encoding: %s" msgstr "" #: ../libinfinity/server/infd-filesystem-storage.c:141 #, c-format msgid "" "Failed to create root directory: %s\n" "Subsequent storage operations will most likely fail\n" msgstr "" #: ../libinfinity/server/infd-filesystem-storage.c:284 #, c-format msgid "Error processing file \"%s\": Toplevel tag is not \"%s\"" msgstr "" #: ../libinfinity/server/infd-session-proxy.c:299 msgid "Request does not contain required attribute \"name\"" msgstr "" #: ../libinfinity/server/infd-session-proxy.c:317 #, c-format msgid "Name \"%s\" already in use" msgstr "" #: ../libinfinity/server/infd-session-proxy.c:359 msgid "\"status\" attribute is \"unavailable\" in user join request" msgstr "" #: ../libinftext/inf-text-default-delete-operation.c:271 #: ../libinftext/inf-text-remote-delete-operation.c:380 msgid "Attempt to remove text from after the end of the document" msgstr "" #: ../libinftext/inf-text-default-insert-operation.c:223 msgid "Attempt to insert text after the end of the document" msgstr "" #: ../libinftext/inf-text-filesystem-format.c:99 #, c-format msgid "User with ID %u exists already" msgstr "" #: ../libinftext/inf-text-filesystem-format.c:113 #, c-format msgid "User with name \"%s\" exists already" msgstr "" #: ../libinftext/inf-text-filesystem-format.c:193 #, c-format msgid "User with ID \"%u\" does not exist" msgstr "" #: ../libinftext/inf-text-filesystem-format.c:387 msgid "The document is not a text session" msgstr "" #: ../libinftext/inf-text-filesystem-format.c:403 #: ../libinftext/inf-text-filesystem-format.c:413 #, c-format msgid "Error processing file \"%s\": " msgstr "" #: ../libinftext/inf-text-move-operation.c:228 msgid "Attempt to move cursor or selection beyond the end of the document" msgstr "" #: ../libinftext/inf-text-session.c:935 ../libinftext/inf-text-session.c:1081 #, c-format msgid "No such user with ID '%u'" msgstr "" #: ../libinftext/inf-text-session.c:963 #, c-format msgid "Invalid hue value: '%g'" msgstr "" #: ../libinftext/inf-text-session.c:1276 msgid "\"caret\" attribute in user message is missing" msgstr "" libinfinity-0.7.1/po/PaxHeaders.26529/LINGUAS0000644000000000000000000000013012400102201015222 xustar0029 mtime=1409320065.13113192 29 atime=1409320065.13113192 30 ctime=1488261621.320067286 libinfinity-0.7.1/po/LINGUAS0000644000175000017500000000006512400102201015757 0ustar00arminarmin00000000000000# Please keep this list sorted alphabetically. ca de libinfinity-0.7.1/po/PaxHeaders.26529/POTFILES.in0000644000000000000000000000013213034544707016005 xustar0030 mtime=1483917767.602911315 30 atime=1483917767.602911315 30 ctime=1488261621.320067286 libinfinity-0.7.1/po/POTFILES.in0000644000175000017500000000550113034544707016540 0ustar00arminarmin00000000000000infinoted/infinoted-config-reload.c infinoted/infinoted-dh-params.c infinoted/infinoted-main.c infinoted/infinoted-options.c infinoted/infinoted-pam.c infinoted/infinoted-parameter.c infinoted/infinoted-plugin-manager.c infinoted/infinoted-run.c infinoted/infinoted-signal.c infinoted/infinoted-startup.c infinoted/plugins/infinoted-plugin-autosave.c infinoted/plugins/infinoted-plugin-certificate-auth.c infinoted/plugins/infinoted-plugin-dbus.c infinoted/plugins/infinoted-plugin-directory-sync.c infinoted/plugins/infinoted-plugin-document-stream.c infinoted/plugins/infinoted-plugin-linekeeper.c infinoted/plugins/infinoted-plugin-logging.c infinoted/plugins/infinoted-plugin-note-chat.c infinoted/plugins/infinoted-plugin-note-text.c infinoted/plugins/infinoted-plugin-record.c infinoted/plugins/infinoted-plugin-traffic-logging.c infinoted/plugins/infinoted-plugin-transformation-protection.c infinoted/plugins/util/infinoted-plugin-util-navigate-browser.c libinfgtk/inf-gtk-account-creation-dialog.c libinfgtk/inf-gtk-browser-store.c libinfgtk/inf-gtk-browser-view.c libinfgtk/inf-gtk-certificate-dialog.c libinfgtk/inf-gtk-certificate-manager.c libinfgtk/inf-gtk-certificate-view.c libinfgtk/inf-gtk-chat.c libinfgtk/inf-gtk-permissions-dialog.c libinfgtk/inf-gtk-resources.c libinfgtk/resources/ui/infgtkaccountcreationdialog.ui libinfgtk/resources/ui/infgtkaclsheetview.ui libinfgtk/resources/ui/infgtkcertificatedialog.ui libinfgtk/resources/ui/infgtkcertificateview.ui libinfgtk/resources/ui/infgtkchat.ui libinfgtk/resources/ui/infgtkpermissionsdialog.ui libinfinity/adopted/inf-adopted-algorithm.c libinfinity/adopted/inf-adopted-session.c libinfinity/adopted/inf-adopted-session-record.c libinfinity/adopted/inf-adopted-session-replay.c libinfinity/adopted/inf-adopted-state-vector.c libinfinity/client/infc-browser.c libinfinity/client/infc-request-manager.c libinfinity/client/infc-session-proxy.c libinfinity/common/inf-acl.c libinfinity/common/inf-async-operation.c libinfinity/common/inf-chat-session.c libinfinity/common/inf-discovery-avahi.c libinfinity/common/inf-error.c libinfinity/common/inf-name-resolver.c libinfinity/common/inf-protocol.c libinfinity/common/inf-session.c libinfinity/common/inf-tcp-connection.c libinfinity/common/inf-user.c libinfinity/common/inf-xml-util.c libinfinity/common/inf-xmpp-connection.c libinfinity/inf-i18n.h libinfinity/server/infd-account-storage.c libinfinity/server/infd-chat-filesystem-format.c libinfinity/server/infd-directory.c libinfinity/server/infd-filesystem-account-storage.c libinfinity/server/infd-filesystem-storage.c libinfinity/server/infd-session-proxy.c libinftext/inf-text-default-delete-operation.c libinftext/inf-text-default-insert-operation.c libinftext/inf-text-filesystem-format.c libinftext/inf-text-move-operation.c libinftext/inf-text-remote-delete-operation.c libinftext/inf-text-session.c libinfinity-0.7.1/PaxHeaders.26529/missing0000644000000000000000000000013213036062707015203 xustar0030 mtime=1484285383.715895807 30 atime=1484285383.715895807 30 ctime=1488261588.784139538 libinfinity-0.7.1/missing0000755000175000017500000001533013036062707015742 0ustar00arminarmin00000000000000#! /bin/sh # Common wrapper for a few potentially missing GNU programs. scriptversion=2013-10-28.13; # UTC # Copyright (C) 1996-2014 Free Software Foundation, Inc. # Originally written by Fran,cois Pinard , 1996. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. if test $# -eq 0; then echo 1>&2 "Try '$0 --help' for more information" exit 1 fi case $1 in --is-lightweight) # Used by our autoconf macros to check whether the available missing # script is modern enough. exit 0 ;; --run) # Back-compat with the calling convention used by older automake. shift ;; -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due to PROGRAM being missing or too old. Options: -h, --help display this help and exit -v, --version output version information and exit Supported PROGRAM values: aclocal autoconf autoheader autom4te automake makeinfo bison yacc flex lex help2man Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and 'g' are ignored when checking the name. Send bug reports to ." exit $? ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing $scriptversion (GNU Automake)" exit $? ;; -*) echo 1>&2 "$0: unknown '$1' option" echo 1>&2 "Try '$0 --help' for more information" exit 1 ;; esac # Run the given program, remember its exit status. "$@"; st=$? # If it succeeded, we are done. test $st -eq 0 && exit 0 # Also exit now if we it failed (or wasn't found), and '--version' was # passed; such an option is passed most likely to detect whether the # program is present and works. case $2 in --version|--help) exit $st;; esac # Exit code 63 means version mismatch. This often happens when the user # tries to use an ancient version of a tool on a file that requires a # minimum version. if test $st -eq 63; then msg="probably too old" elif test $st -eq 127; then # Program was missing. msg="missing on your system" else # Program was found and executed, but failed. Give up. exit $st fi perl_URL=http://www.perl.org/ flex_URL=http://flex.sourceforge.net/ gnu_software_URL=http://www.gnu.org/software program_details () { case $1 in aclocal|automake) echo "The '$1' program is part of the GNU Automake package:" echo "<$gnu_software_URL/automake>" echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/autoconf>" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; autoconf|autom4te|autoheader) echo "The '$1' program is part of the GNU Autoconf package:" echo "<$gnu_software_URL/autoconf/>" echo "It also requires GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; esac } give_advice () { # Normalize program name to check for. normalized_program=`echo "$1" | sed ' s/^gnu-//; t s/^gnu//; t s/^g//; t'` printf '%s\n' "'$1' is $msg." configure_deps="'configure.ac' or m4 files included by 'configure.ac'" case $normalized_program in autoconf*) echo "You should only need it if you modified 'configure.ac'," echo "or m4 files included by it." program_details 'autoconf' ;; autoheader*) echo "You should only need it if you modified 'acconfig.h' or" echo "$configure_deps." program_details 'autoheader' ;; automake*) echo "You should only need it if you modified 'Makefile.am' or" echo "$configure_deps." program_details 'automake' ;; aclocal*) echo "You should only need it if you modified 'acinclude.m4' or" echo "$configure_deps." program_details 'aclocal' ;; autom4te*) echo "You might have modified some maintainer files that require" echo "the 'autom4te' program to be rebuilt." program_details 'autom4te' ;; bison*|yacc*) echo "You should only need it if you modified a '.y' file." echo "You may want to install the GNU Bison package:" echo "<$gnu_software_URL/bison/>" ;; lex*|flex*) echo "You should only need it if you modified a '.l' file." echo "You may want to install the Fast Lexical Analyzer package:" echo "<$flex_URL>" ;; help2man*) echo "You should only need it if you modified a dependency" \ "of a man page." echo "You may want to install the GNU Help2man package:" echo "<$gnu_software_URL/help2man/>" ;; makeinfo*) echo "You should only need it if you modified a '.texi' file, or" echo "any other file indirectly affecting the aspect of the manual." echo "You might want to install the Texinfo package:" echo "<$gnu_software_URL/texinfo/>" echo "The spurious makeinfo call might also be the consequence of" echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" echo "want to install GNU make:" echo "<$gnu_software_URL/make/>" ;; *) echo "You might have modified some files without having the proper" echo "tools for further handling them. Check the 'README' file, it" echo "often tells you about the needed prerequisites for installing" echo "this package. You may also peek at any GNU archive site, in" echo "case some other package contains this missing '$1' program." ;; esac } give_advice "$1" | sed -e '1s/^/WARNING: /' \ -e '2,$s/^/ /' >&2 # Propagate the correct exit status (expected to be 127 for a program # not found, 63 for a program that failed due to version mismatch). exit $st # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: libinfinity-0.7.1/PaxHeaders.26529/Makefile.in0000644000000000000000000000013213051241007015641 xustar0030 mtime=1487225351.565147975 30 atime=1487225351.565147975 30 ctime=1488261588.756139598 libinfinity-0.7.1/Makefile.in0000644000175000017500000007731213051241007016405 0ustar00arminarmin00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 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__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) 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@ @WITH_INFGTK_TRUE@am__append_1 = libinfgtk @WITH_INFGTK_TRUE@am__append_2 = libinfgtk-$(LIBINFINITY_API_VERSION).pc @WITH_INFTEXTGTK_TRUE@am__append_3 = libinftextgtk @WITH_INFTEXTGTK_TRUE@am__append_4 = libinftextgtk-$(LIBINFINITY_API_VERSION).pc @WITH_INFINOTED_TRUE@am__append_5 = infinoted @WITH_INFINOTED_TRUE@am__append_6 = libinfinoted-plugin-manager-$(LIBINFINITY_API_VERSION).pc subdir = . ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/gtk-doc.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ $(am__configure_deps) $(am__DIST_COMMON) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(install_sh) -d CONFIG_HEADER = config.h $(top_builddir)/libinfinity/inf-config.h CONFIG_CLEAN_FILES = libinfinity-0.7.pc libinftext-0.7.pc \ libinfgtk-0.7.pc libinftextgtk-0.7.pc \ libinfinoted-plugin-manager-0.7.pc CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(pkgconfigdir)" DATA = $(pkgconfig_DATA) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ cscope distdir dist dist-all distcheck am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \ $(LISP)config.h.in # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags CSCOPE = cscope DIST_SUBDIRS = libinfinity libinftext libinfgtk libinftextgtk \ infinoted pixmaps test docs po am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in \ $(srcdir)/libinfgtk.pc.in $(srcdir)/libinfinity.pc.in \ $(srcdir)/libinfinoted-plugin-manager.pc.in \ $(srcdir)/libinftext.pc.in $(srcdir)/libinftextgtk.pc.in \ AUTHORS COPYING ChangeLog INSTALL NEWS TODO ar-lib compile \ config.guess config.sub depcomp install-sh ltmain.sh missing DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) am__remove_distdir = \ if test -d "$(distdir)"; then \ find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ && rm -rf "$(distdir)" \ || { sleep 5 && rm -rf "$(distdir)"; }; \ else :; fi am__post_remove_distdir = $(am__remove_distdir) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" DIST_ARCHIVES = $(distdir).tar.gz $(distdir).tar.bz2 GZIP_ENV = --best DIST_TARGETS = dist-bzip2 dist-gzip distuninstallcheck_listfiles = find . -type f -print am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' distcleancheck_listfiles = find . -type f -print ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ 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@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIRNAME = @DATADIRNAME@ 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@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ GTKDOC_CHECK = @GTKDOC_CHECK@ GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ GTKDOC_MKPDF = @GTKDOC_MKPDF@ GTKDOC_REBASE = @GTKDOC_REBASE@ HTML_DIR = @HTML_DIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INSTOBJEXT = @INSTOBJEXT@ INTLLIBS = @INTLLIBS@ INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBINFINITY_API_VERSION = @LIBINFINITY_API_VERSION@ LIBINFINITY_LIBTOOL_VERSION = @LIBINFINITY_LIBTOOL_VERSION@ LIBINFINITY_VERSION = @LIBINFINITY_VERSION@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGFMT_OPTS = @MSGFMT_OPTS@ 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@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ 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@ avahi_CFLAGS = @avahi_CFLAGS@ avahi_LIBS = @avahi_LIBS@ 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@ gio_CFLAGS = @gio_CFLAGS@ gio_LIBS = @gio_LIBS@ gtk_requirement = @gtk_requirement@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infgtk_CFLAGS = @infgtk_CFLAGS@ infgtk_LIBS = @infgtk_LIBS@ infinity_CFLAGS = @infinity_CFLAGS@ infinity_LIBS = @infinity_LIBS@ infinoted_CFLAGS = @infinoted_CFLAGS@ infinoted_LIBS = @infinoted_LIBS@ infodir = @infodir@ inftext_CFLAGS = @inftext_CFLAGS@ inftext_LIBS = @inftext_LIBS@ inftextgtk_CFLAGS = @inftextgtk_CFLAGS@ inftextgtk_LIBS = @inftextgtk_LIBS@ install_sh = @install_sh@ libdaemon_CFLAGS = @libdaemon_CFLAGS@ libdaemon_LIBS = @libdaemon_LIBS@ 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@ runstatedir = @runstatedir@ 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@ SUBDIRS = libinfinity libinftext $(am__append_1) $(am__append_3) \ $(am__append_5) pixmaps test docs po pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libinfinity-$(LIBINFINITY_API_VERSION).pc \ libinftext-$(LIBINFINITY_API_VERSION).pc $(am__append_2) \ $(am__append_4) $(am__append_6) EXTRA_DIST = README.md DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc MAINTAINERCLEANFILES = \ ChangeLog all: config.h $(MAKE) $(AM_MAKEFLAGS) all-recursive .SUFFIXES: am--refresh: Makefile @: $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ echo ' $(SHELL) ./config.status'; \ $(SHELL) ./config.status;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) $(am__cd) $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) $(am__aclocal_m4_deps): config.h: stamp-h1 @test -f $@ || rm -f stamp-h1 @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1 stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status @rm -f stamp-h1 cd $(top_builddir) && $(SHELL) ./config.status config.h $(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) rm -f stamp-h1 touch $@ distclean-hdr: -rm -f config.h stamp-h1 libinfinity-0.7.pc: $(top_builddir)/config.status $(srcdir)/libinfinity.pc.in cd $(top_builddir) && $(SHELL) ./config.status $@ libinftext-0.7.pc: $(top_builddir)/config.status $(srcdir)/libinftext.pc.in cd $(top_builddir) && $(SHELL) ./config.status $@ libinfgtk-0.7.pc: $(top_builddir)/config.status $(srcdir)/libinfgtk.pc.in cd $(top_builddir) && $(SHELL) ./config.status $@ libinftextgtk-0.7.pc: $(top_builddir)/config.status $(srcdir)/libinftextgtk.pc.in cd $(top_builddir) && $(SHELL) ./config.status $@ libinfinoted-plugin-manager-0.7.pc: $(top_builddir)/config.status $(srcdir)/libinfinoted-plugin-manager.pc.in cd $(top_builddir) && $(SHELL) ./config.status $@ mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs distclean-libtool: -rm -f libtool config.lt install-pkgconfigDATA: $(pkgconfig_DATA) @$(NORMAL_INSTALL) @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgconfigdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \ done uninstall-pkgconfigDATA: @$(NORMAL_UNINSTALL) @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgconfigdir)'; $(am__uninstall_files_from_dir) # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ 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-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ 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" cscope: cscope.files test ! -s cscope.files \ || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) clean-cscope: -rm -f cscope.files cscope.files: clean-cscope cscopelist cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -rm -f cscope.out cscope.in.out cscope.po.out cscope.files distdir: $(DISTFILES) @case `sed 15q $(srcdir)/NEWS` in \ *"$(VERSION)"*) : ;; \ *) \ echo "NEWS not updated; not releasing" 1>&2; \ exit 1;; \ esac $(am__remove_distdir) test -d "$(distdir)" || mkdir "$(distdir)" @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 @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done -test -n "$(am__skip_mode_fix)" \ || find "$(distdir)" -type d ! -perm -755 \ -exec chmod u+rwx,go+rx {} \; -o \ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r "$(distdir)" dist-gzip: distdir tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz $(am__post_remove_distdir) dist-bzip2: distdir tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 $(am__post_remove_distdir) dist-lzip: distdir tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz $(am__post_remove_distdir) dist-xz: distdir tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz $(am__post_remove_distdir) dist-tarZ: distdir @echo WARNING: "Support for distribution archives compressed with" \ "legacy program 'compress' is deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__post_remove_distdir) dist-shar: distdir @echo WARNING: "Support for shar distribution archives is" \ "deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz $(am__post_remove_distdir) dist-zip: distdir -rm -f $(distdir).zip zip -rq $(distdir).zip $(distdir) $(am__post_remove_distdir) dist dist-all: $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' $(am__post_remove_distdir) # This target untars the dist file and tries a VPATH configuration. Then # it guarantees that the distribution is self-contained by making another # tarfile. distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.lz*) \ lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ *.tar.xz*) \ xz -dc $(distdir).tar.xz | $(am__untar) ;;\ *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ esac chmod -R a-w $(distdir) chmod u+w $(distdir) mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst chmod a-w $(distdir) test -d $(distdir)/_build || exit 0; \ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && am__cwd=`pwd` \ && $(am__cd) $(distdir)/_build/sub \ && ../../configure \ $(AM_DISTCHECK_CONFIGURE_FLAGS) \ $(DISTCHECK_CONFIGURE_FLAGS) \ --srcdir=../.. --prefix="$$dc_install_base" \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) check \ && $(MAKE) $(AM_MAKEFLAGS) install \ && $(MAKE) $(AM_MAKEFLAGS) installcheck \ && $(MAKE) $(AM_MAKEFLAGS) uninstall \ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ distuninstallcheck \ && chmod -R a-w "$$dc_install_base" \ && ({ \ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ } || { rm -rf "$$dc_destdir"; exit 1; }) \ && rm -rf "$$dc_destdir" \ && $(MAKE) $(AM_MAKEFLAGS) dist \ && rm -rf $(DIST_ARCHIVES) \ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ && cd "$$am__cwd" \ || exit 1 $(am__post_remove_distdir) @(echo "$(distdir) archives ready for distribution: "; \ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' distuninstallcheck: @test -n '$(distuninstallcheck_dir)' || { \ echo 'ERROR: trying to run $@ with an empty' \ '$$(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ $(am__cd) '$(distuninstallcheck_dir)' || { \ echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left after uninstall:" ; \ if test -n "$(DESTDIR)"; then \ echo " (check DESTDIR support)"; \ fi ; \ $(distuninstallcheck_listfiles) ; \ exit 1; } >&2 distcleancheck: distclean @if test '$(srcdir)' = . ; then \ echo "ERROR: distcleancheck can only run from a VPATH build" ; \ exit 1 ; \ fi @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left in build directory after distclean:" ; \ $(distcleancheck_listfiles) ; \ exit 1; } >&2 check-am: all-am check: check-recursive all-am: Makefile $(DATA) config.h installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(pkgconfigdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive 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: 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 "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-recursive clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -f Makefile distclean-am: clean-am distclean-generic distclean-hdr \ distclean-libtool distclean-local distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-pkgconfigDATA install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-pkgconfigDATA .MAKE: $(am__recursive_targets) all install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am \ am--refresh check check-am clean clean-cscope clean-generic \ clean-libtool cscope cscopelist-am ctags ctags-am dist \ dist-all dist-bzip2 dist-gzip dist-lzip dist-shar dist-tarZ \ dist-xz dist-zip distcheck distclean distclean-generic \ distclean-hdr distclean-libtool distclean-local distclean-tags \ distcleancheck distdir distuninstallcheck 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-pkgconfigDATA install-ps install-ps-am install-strip \ installcheck installcheck-am installdirs installdirs-am \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags tags-am uninstall uninstall-am uninstall-pkgconfigDATA .PRECIOUS: Makefile distclean-local: if test "$(srcdir)" = "."; then :; else \ rm -f ChangeLog; \ fi ChangeLog: $(AM_V_GEN) if test -d "$(srcdir)/.git"; then \ (GIT_DIR=$(top_srcdir)/.git ./missing --run git log \ 4021c6e493112f901fb5bfb5daf4d3546272ac69..HEAD --stat=78) \ | fmt --split-only --width=78 > $@.tmp \ && cat $@.tmp ChangeLog.manual > $@ && $(RM) $@.tmp \ || ($(RM) $@.tmp; \ echo Failed to generate ChangeLog, your ChangeLog may be outdated >&2; \ (test -f $@ || echo git-log is required to generate this file >> $@)); \ else \ test -f $@ || \ (echo A git checkout and git-log is required to generate ChangeLog >&2 && \ echo A git checkout and git-log is required to generate this file >> $@); \ fi .PHONY: ChangeLog # 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: libinfinity-0.7.1/PaxHeaders.26529/test-driver0000644000000000000000000000013213036062711015775 xustar0030 mtime=1484285385.059896908 30 atime=1484285385.059896908 30 ctime=1488261589.712137508 libinfinity-0.7.1/test-driver0000755000175000017500000001104013036062711016526 0ustar00arminarmin00000000000000#! /bin/sh # test-driver - basic testsuite driver script. scriptversion=2013-07-13.22; # UTC # Copyright (C) 2011-2014 Free Software Foundation, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # This file is maintained in Automake, please report # bugs to or send patches to # . # Make unconditional expansion of undefined variables an error. This # helps a lot in preventing typo-related bugs. set -u usage_error () { echo "$0: $*" >&2 print_usage >&2 exit 2 } print_usage () { cat <$log_file 2>&1 estatus=$? if test $enable_hard_errors = no && test $estatus -eq 99; then tweaked_estatus=1 else tweaked_estatus=$estatus fi case $tweaked_estatus:$expect_failure in 0:yes) col=$red res=XPASS recheck=yes gcopy=yes;; 0:*) col=$grn res=PASS recheck=no gcopy=no;; 77:*) col=$blu res=SKIP recheck=no gcopy=yes;; 99:*) col=$mgn res=ERROR recheck=yes gcopy=yes;; *:yes) col=$lgn res=XFAIL recheck=no gcopy=yes;; *:*) col=$red res=FAIL recheck=yes gcopy=yes;; esac # Report the test outcome and exit status in the logs, so that one can # know whether the test passed or failed simply by looking at the '.log' # file, without the need of also peaking into the corresponding '.trs' # file (automake bug#11814). echo "$res $test_name (exit status: $estatus)" >>$log_file # Report outcome to console. echo "${col}${res}${std}: $test_name" # Register the test result, and other relevant metadata. echo ":test-result: $res" > $trs_file echo ":global-test-result: $res" >> $trs_file echo ":recheck: $recheck" >> $trs_file echo ":copy-in-global-log: $gcopy" >> $trs_file # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: libinfinity-0.7.1/PaxHeaders.26529/Makefile.am0000644000000000000000000000013213034342512015634 xustar0030 mtime=1483851082.013718339 30 atime=1483851082.013718339 30 ctime=1488261588.736139642 libinfinity-0.7.1/Makefile.am0000644000175000017500000000261413034342512016371 0ustar00arminarmin00000000000000SUBDIRS = libinfinity libinftext pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = \ libinfinity-$(LIBINFINITY_API_VERSION).pc \ libinftext-$(LIBINFINITY_API_VERSION).pc if WITH_INFGTK SUBDIRS += libinfgtk pkgconfig_DATA += libinfgtk-$(LIBINFINITY_API_VERSION).pc endif if WITH_INFTEXTGTK SUBDIRS += libinftextgtk pkgconfig_DATA += libinftextgtk-$(LIBINFINITY_API_VERSION).pc endif if WITH_INFINOTED SUBDIRS += infinoted pkgconfig_DATA += libinfinoted-plugin-manager-$(LIBINFINITY_API_VERSION).pc endif SUBDIRS += pixmaps test docs po EXTRA_DIST = README.md DISTCHECK_CONFIGURE_FLAGS=--enable-gtk-doc MAINTAINERCLEANFILES = \ ChangeLog distclean-local: if test "$(srcdir)" = "."; then :; else \ rm -f ChangeLog; \ fi ChangeLog: $(AM_V_GEN) if test -d "$(srcdir)/.git"; then \ (GIT_DIR=$(top_srcdir)/.git ./missing --run git log \ 4021c6e493112f901fb5bfb5daf4d3546272ac69..HEAD --stat=78) \ | fmt --split-only --width=78 > $@.tmp \ && cat $@.tmp ChangeLog.manual > $@ && $(RM) $@.tmp \ || ($(RM) $@.tmp; \ echo Failed to generate ChangeLog, your ChangeLog may be outdated >&2; \ (test -f $@ || echo git-log is required to generate this file >> $@)); \ else \ test -f $@ || \ (echo A git checkout and git-log is required to generate ChangeLog >&2 && \ echo A git checkout and git-log is required to generate this file >> $@); \ fi .PHONY: ChangeLog libinfinity-0.7.1/PaxHeaders.26529/README.md0000644000000000000000000000013213034342512015057 xustar0030 mtime=1483851082.013718339 30 atime=1483851082.013718339 30 ctime=1488261588.788139528 libinfinity-0.7.1/README.md0000644000175000017500000000344413034342512015616 0ustar00arminarmin00000000000000# libinfinity [![Build Status](https://travis-ci.org/gobby/libinfinity.svg?branch=master)](https://travis-ci.org/gobby/libinfinity) libinfinity is library to build collaborative text editors. Changes to the text buffers are synced to all other clients over a central server. Even though a central server is involved, the local user sees his changes applied instantly and the merging is done on the individual clients. ## Components infinote consists of the following parts: - **libinfinity:** Library implementing the core infinote part - **infinoted:** Simple stand-alone infinote server application - **libinfgtk:** Provides glib main loop integration and GTK+ widgets related to libinfinity - **libinftext:** Infinote plugin implementing real-time collaborative text editing - **libinftextgtk:** Implements the InfTextBuffer interface with a GtkTextBuffer as backend - **libinfinoted-plugin-manager:** Provides an interface to infinoted for plugins. ## Requirements libinfinity requires: - glib-2.0 >= 2.38 - gobject-2.0 >= 2.38 - libxml-2.0 - gnutls >= 2.12.0 - gsasl >= 0.2.21 - avahi (optional) infinoted: - libinfinity - libdaemon (optional) libinfgtk: - libinfinity - gtk+-3.0 >= 3.10 libinftext: - libinfinity libinftextgtk: - libinftext - gtk+-3.0 >= 3.10 ## Development This library is developed by Armin Burgmeier . Artwork is done by Benjamin Herr . To get in contact with the developers, either use the mailing list obby-users@list.0x539.de (to which you can subscribe by sending mail to obby-users-subscribe@list.0x539.de) or drop by in our IRC channel #infinote on irc.freenode.org. Feel free to clone this GitHub repository and propose pull requests. Issues can be reported to the [GitHub issue tracker](https://github.com/gobby/libinfinity/issues). libinfinity-0.7.1/PaxHeaders.26529/TODO0000644000000000000000000000013213034342512014270 xustar0030 mtime=1483851082.013718339 30 atime=1483851082.013718339 30 ctime=1488261588.772139564 libinfinity-0.7.1/TODO0000644000175000017500000001475713034342512015040 0ustar00arminarmin00000000000000This is a more or less incomplete list of more or less independant tasks that would be nice to have done for the first stable release. Performance (Some ideas to improve performance, profile to verify!): * callgrind suggests g_object_new requires much time, especially for objects that are often instantianted, such as InfAdoptedRequest, InfTextDefaultInsertOperation and InfTextDefaultDeleteOperation. Maybe we can improve this by not initializing the member variables by properties, but by setting them after the g_object_new() call. Can we make InfAdoptedRequest a boxed type? * Move state vector helper functions in algorithm to InfAdoptedStateVector, with a better O(n) implementation. * Cache request.vector[request.user] in every request, this seems to be used pretty often. * There is already a function for this, inf_adopted_request_get_index() * It needs to be consistently used where this information is required * And then the cache actually be introduced * Optionally compile with - G_DISABLE_CAST_CHECKS - G_DISABLE_ASSERT - G_DISABLE_CHECKS defined. Protocol Break: The following features would be nice to have, but they require breaking the protocol. Maybe it could be introduced such that new clients can still talk to old servers. * Change the transformation function such that all text that starts with a newline character is transformed to the right when two insert operations are at the same location. This would allow people to create a new line at the end of the line where someone else is currently typing while not interrupting their workflow. It would also making the linekeeper plugin safe from such conflicts. If we do this, we also need to add some unit tests in test/session which check that it is implemented correctly. * Add a rename functionality Others: * Split InfXmppConnection (XMPP) - InfXmppConnection: XMPP core implementation - InfJabberConnection: Connection to jabber server, managing roster, presence, etc. Derives from InfXmppConnection, not used on server side - InfRawXmppConnection: InfXmlConnection implementation by sending raw messages to XMPP server (Derive from InfXmppConnection, make XMPP server create these connections (unsure: rather add a vfunc and subclass InfXmppServer?)) - InfJabberUserConnection: Implements InfXmlConnection by sending stuff to a particular Jabber user (owns InfJabberConnection) - InfJabberDiscovery (owns InfJabberConnection) * Make InfTextChunk reference-counted, or implement copy-on-write semantics. It is currently copied way too often. (InfText) * Implement inf_text_chunk_insert_substring, and make use in InfTextDeleteOperation (InfText) * Add a set_caret paramater to insert_text and erase_text of InfTextBuffer and derive a InfTextRequest with a "set-caret" flag. * InfTextEncoding boxed type * Create a pseudo XML connection implementation, re-enable INF_IS_XML_CONNECTION check in inf_net_object_received * Add accessor API in InfGtkBrowserModel, so InfGtkBrowserView does not need to call gtk_tree_model_get all the time (which unnecssarily dups/refs) * Add append() and clear() virtual methods to InfTextBuffer. These may not have to be implemented since a default implementation can be used if no special one is provided, but it could help to speed up special operations. Make use in infd_note_plugin_text. * Allow split-operations of insert and delete operations to be made in one go, to atomically modify the document at many places at once * This can be used between begin-user-action and end-user-action, to keep the operation atomic on the infinote side * maybe need to evaluate whether a split operation which has insert as one child and delete as other child is handled correctly * definitely add more unit tests for this * Make InfLocalPublisher take a InfdXmlServer instead of a port number. Maybe even rename to InfPublisher, with InfDiscoveryAvahi assuming an InfdXmppServer. Or, consider simply removing the interface, and require people to use InfDiscoveryAvahi directly (check how well that works with InfdServerPool). * Make a InfcChat object that handles the chat session from InfcBrowser. InfcBrowser should relay messages to it, and if not handled by InfcChat, handle it by itself. InfcChat should be a public property of InfcBrowser, but handle all the chat stuff itself. Maybe implement InfCommunicationObject and still have the stuff relayed? Check again how the InfcBrowser->InfcSessionProxy->InfSession flow goes and do the same. * The same kind of thing should be implemented on the server side. * Remove infc_browser_get_status() function * Change the storage interface to be asynchronous * take the chance and require gio * port the network code to gnio? * Also create InfcRequests for remotely triggered actions that do not come with a local request. Such requests would have the "seq" property set to some invalid value. Basically all operations made should have a request for them, the parameter should never be NULL. * InfcBrowser and InfdDirectory have grown very large. This code should be refactored a bit, and allow plugins to dynamically add handling of network messages. Stuff like create-acl-account could then perhaps be delegated to the certificate-auth plugin... in that particular case maybe better a hook into the create_acl_account impl, but custom network messages might still be nice for git integration. * InfDirectoryTree: Implements the basic tree structure, with node management functions. * Inf(c)RemoteBrowser: Owns a InfDirectoryTree, implements the InfBrowser interface with a server connection. * Inf(d)StorageBrowser: Owns a InfDirectoryTree, implements the InfBrowser interface with a storage backend (--enable async storage backend here!). * Inf(d)Server: References a InfBrowser, and implements the networking on top of it. This approach would even allow implementing a "delegating" server which does not serve the content itself but actually asks another server, by using a InfRemoteBrowser as a backend. * Threading: Better support for multi-core CPUs, ideally by running each InfCommunicationGroup in a separate thread. Would need many adaptions in other code to be thread-safe. * OCSP: Server asks for OCSP status periodically, and delivers ocsp status if client asks for it. Client always asks for OCSP status, and fails the connection if no OCSP response is retrieved and OCSP MUST STAPLE is set in server's cert. libinfinity-0.7.1/PaxHeaders.26529/infinoted0000644000000000000000000000013213055210725015505 xustar0030 mtime=1488261589.480138016 30 atime=1488261589.404138182 30 ctime=1488261589.480138016 libinfinity-0.7.1/infinoted/0000755000175000017500000000000013055210725016314 5ustar00arminarmin00000000000000libinfinity-0.7.1/infinoted/PaxHeaders.26529/infinoted-startup.c0000644000000000000000000000013213034342512021402 xustar0030 mtime=1483851082.017718362 30 atime=1483851082.017718362 30 ctime=1488261589.476138024 libinfinity-0.7.1/infinoted/infinoted-startup.c0000644000175000017500000003370413034342512022143 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include #include #include #include static void infinoted_startup_free_certificate_array(gnutls_x509_crt_t* certificates, guint n_certificates) { guint i; for(i = 0; i < n_certificates; ++i) gnutls_x509_crt_deinit(certificates[i]); g_free(certificates); } static gnutls_x509_privkey_t infinoted_startup_load_key(InfinotedLog* log, gboolean create_key, const gchar* key_file, GError** error) { gnutls_x509_privkey_t key; if(create_key == TRUE) { if(infinoted_util_create_dirname(key_file, error) == FALSE) return NULL; /* TODO: Open the key file beforehand */ infinoted_log_info(log, _("Generating 4096 bit RSA private key...")); key = inf_cert_util_create_private_key(GNUTLS_PK_RSA, 4096, error); if(key == NULL) return NULL; if(inf_cert_util_write_private_key(key, key_file, error) == FALSE) { gnutls_x509_privkey_deinit(key); return NULL; } } else { key = inf_cert_util_read_private_key(key_file, error); } return key; } static gnutls_x509_crt_t* infinoted_startup_load_certificate(InfinotedLog* log, gboolean create_self_signed_certificate, gnutls_x509_privkey_t key, const gchar* certificate_file, const gchar* certificate_chain_file, guint* n_certificates, GError** error) { InfCertUtilDescription desc; gnutls_x509_crt_t* result; gnutls_x509_crt_t cert; GPtrArray* certs; GPtrArray* chain_certs; gboolean res; if(create_self_signed_certificate == TRUE) { if(infinoted_util_create_dirname(certificate_file, error) == FALSE) return NULL; infinoted_log_info(log, _("Generating self-signed certificate...")); desc.validity = 365 * 24 * 3600; desc.dn_common_name = g_get_host_name(); desc.san_dnsname = g_get_host_name(); cert = inf_cert_util_create_self_signed_certificate(key, &desc, error); if(cert == NULL) return NULL; res = inf_cert_util_write_certificate(&cert, 1, certificate_file, error); if(res == FALSE) { gnutls_x509_crt_deinit(cert); return NULL; } else { result = g_malloc(sizeof(gnutls_x509_crt_t)); *result = cert; *n_certificates = 1; } } else { certs = inf_cert_util_read_certificate(certificate_file, NULL, error); if(certs == NULL) return NULL; if(certificate_chain_file != NULL) { chain_certs = inf_cert_util_read_certificate(certificate_chain_file, certs, error); if(chain_certs == NULL) { result = (gnutls_x509_crt_t*)g_ptr_array_free(certs, FALSE); infinoted_startup_free_certificate_array(result, *n_certificates); return NULL; } } *n_certificates = certs->len; result = (gnutls_x509_crt_t*)g_ptr_array_free(certs, FALSE); } return result; } static gboolean infinoted_startup_load_credentials(InfinotedStartup* startup, GError** error) { gnutls_x509_crt_t* certs; guint n_certs; gnutls_certificate_credentials_t creds; int res; if(startup->options->security_policy != INF_XMPP_CONNECTION_SECURITY_ONLY_UNSECURED) { startup->private_key = infinoted_startup_load_key( startup->log, startup->options->create_key, startup->options->key_file, error ); if(startup->private_key == NULL) return FALSE; certs = infinoted_startup_load_certificate( startup->log, startup->options->create_certificate, startup->private_key, startup->options->certificate_file, startup->options->certificate_chain_file, &n_certs, error ); if(certs == NULL) return FALSE; /* Takes ownership of certificates: */ startup->certificates = inf_certificate_chain_new(certs, n_certs); startup->credentials = inf_certificate_credentials_new(); creds = inf_certificate_credentials_get(startup->credentials); res = gnutls_certificate_set_x509_key( creds, inf_certificate_chain_get_raw(startup->certificates), inf_certificate_chain_get_n_certificates(startup->certificates), startup->private_key ); if(res != 0) { inf_gnutls_set_error(error, res); return FALSE; } } return TRUE; } static gboolean infinoted_startup_load_options(InfinotedStartup* startup, int* argc, char*** argv, GError** error) { const gchar* const* system_config_dirs; guint n_system_config_dirs; const gchar* user_config_dir; const gchar* const* dir; guint i; gchar** config_files; system_config_dirs = g_get_system_config_dirs(); user_config_dir = g_get_user_config_dir(); n_system_config_dirs = 0; if(system_config_dirs != NULL) { for(dir = system_config_dirs; *dir != NULL; ++ dir) ++ n_system_config_dirs; } config_files = g_malloc( (n_system_config_dirs + 2) * sizeof(gchar*)); config_files[n_system_config_dirs + 1] = NULL; config_files[0] = g_build_filename(user_config_dir, "infinoted.conf", NULL); for(i = 0; i < n_system_config_dirs; ++ i) { config_files[i + 1] = g_build_filename(system_config_dirs[i], "infinoted.conf", NULL); } startup->options = infinoted_options_new( (gchar const* const*) config_files, argc, argv, error); for(i = 0; i < n_system_config_dirs + 1; ++ i) g_free(config_files[i]); g_free(config_files); if(startup->options == NULL) return FALSE; return TRUE; } static void infinoted_startup_sasl_callback_set_error(InfXmppConnection* connection, InfAuthenticationDetailError code, const GError* error) { GError* own_error; own_error = NULL; if(!error) { own_error = g_error_new_literal( inf_authentication_detail_error_quark(), code, inf_authentication_detail_strerror(code) ); inf_xmpp_connection_set_sasl_error(connection, own_error); g_error_free(own_error); } else { inf_xmpp_connection_set_sasl_error(connection, error); } } static void infinoted_startup_sasl_callback(InfSaslContextSession* session, Gsasl_property prop, gpointer session_data, gpointer user_data) { InfinotedStartup* startup; const char* username; const char* password; InfXmppConnection* xmpp; gchar cmp; gsize password_len; gsize i; #ifdef LIBINFINITY_HAVE_PAM const gchar* pam_service; GError* error; #endif gchar* remote_id; xmpp = INF_XMPP_CONNECTION(session_data); g_object_get(xmpp, "remote-id", &remote_id, NULL); switch(prop) { case GSASL_VALIDATE_SIMPLE: startup = (InfinotedStartup*)user_data; username = inf_sasl_context_session_get_property(session, GSASL_AUTHID); password = inf_sasl_context_session_get_property(session, GSASL_PASSWORD); #ifdef LIBINFINITY_HAVE_PAM pam_service = startup->options->pam_service; if(pam_service != NULL) { error = NULL; if(!infinoted_pam_authenticate(pam_service, username, password)) { infinoted_log_warning( startup->log, _("User %s failed to log in from %s: PAM authentication failed"), username, remote_id ); infinoted_startup_sasl_callback_set_error( xmpp, INF_AUTHENTICATION_DETAIL_ERROR_AUTHENTICATION_FAILED, NULL ); inf_sasl_context_session_continue( session, GSASL_AUTHENTICATION_ERROR ); } else if(!infinoted_pam_user_is_allowed(startup, username, &error)) { infinoted_log_warning( startup->log, _("User %s failed to log in from %s: PAM user not allowed"), username, remote_id ); infinoted_startup_sasl_callback_set_error( xmpp, INF_AUTHENTICATION_DETAIL_ERROR_USER_NOT_AUTHORIZED, error ); inf_sasl_context_session_continue( session, GSASL_AUTHENTICATION_ERROR ); } else { infinoted_log_info( startup->log, _("User %s logged in from %s via PAM"), username, remote_id ); inf_sasl_context_session_continue(session, GSASL_OK); } } else #endif /* LIBINFINITY_HAVE_PAM */ { g_assert(startup->options->password != NULL); /* length-independent string compare */ cmp = 0; password_len = strlen(password); for(i = 0; i < startup->options->password_len; ++i) { if(i < password_len) cmp |= (startup->options->password[i] ^ password[i]); else cmp |= (startup->options->password[i] ^ 0x00); } if(startup->options->password_len != password_len) cmp |= 0xFF; if(cmp == 0) { infinoted_log_info( startup->log, _("User %s logged in from %s via password"), username, remote_id ); inf_sasl_context_session_continue(session, GSASL_OK); } else { infinoted_log_warning( startup->log, _("User %s failed to log in from %s: wrong password"), username, remote_id ); infinoted_startup_sasl_callback_set_error( xmpp, INF_AUTHENTICATION_DETAIL_ERROR_AUTHENTICATION_FAILED, NULL ); inf_sasl_context_session_continue( session, GSASL_AUTHENTICATION_ERROR ); } } break; default: inf_sasl_context_session_continue(session, GSASL_AUTHENTICATION_ERROR); break; } g_free(remote_id); } static gboolean infinoted_startup_load(InfinotedStartup* startup, int* argc, char*** argv, GError** error) { gboolean requires_password; if(infinoted_startup_load_options(startup, argc, argv, error) == FALSE) return FALSE; startup->log = infinoted_log_new(); if(!infinoted_log_open(startup->log, startup->options->log_path, error)) return FALSE; if(infinoted_startup_load_credentials(startup, error) == FALSE) return FALSE; requires_password = startup->options->password != NULL; #ifdef LIBINFINITY_HAVE_PAM requires_password = requires_password || startup->options->pam_service != NULL; #endif /* LIBINFINITY_HAVE_PAM */ if(requires_password) { startup->sasl_context = inf_sasl_context_new(error); if(!startup->sasl_context) return FALSE; inf_sasl_context_set_callback( startup->sasl_context, infinoted_startup_sasl_callback, startup, NULL ); } return TRUE; } /** * infinoted_startup_new: * @error: Location to store error information, if any. * * Creates parameters for starting an infinote daemon. This involves option * parsing, reading config files, reading or creating data for TLS * (private key and certificate). * * Returns: A new #InfinotedStartup. Free with infinoted_startup_free(). */ InfinotedStartup* infinoted_startup_new(int* argc, char*** argv, GError** error) { InfinotedStartup* startup; if(!inf_init(error)) return NULL; startup = g_slice_new(InfinotedStartup); startup->options = NULL; startup->log = NULL; startup->private_key = NULL; startup->certificates = NULL; startup->credentials = NULL; startup->sasl_context = NULL; if(infinoted_startup_load(startup, argc, argv, error) == FALSE) { infinoted_startup_free(startup); return NULL; } startup->keepalive.mask = INF_KEEPALIVE_ENABLED | INF_KEEPALIVE_TIME | INF_KEEPALIVE_INTERVAL; startup->keepalive.enabled = TRUE; startup->keepalive.time = 60; startup->keepalive.interval = 5; return startup; } /** * infinoted_startup_free: * @startup: A #InfinotedStartup. * * Frees all ressources allocated by @startup. */ void infinoted_startup_free(InfinotedStartup* startup) { guint i; if(startup->credentials != NULL) inf_certificate_credentials_unref(startup->credentials); if(startup->certificates != NULL) inf_certificate_chain_unref(startup->certificates); if(startup->private_key != NULL) gnutls_x509_privkey_deinit(startup->private_key); if(startup->log != NULL) g_object_unref(startup->log); if(startup->options != NULL) infinoted_options_free(startup->options); if(startup->sasl_context != NULL) inf_sasl_context_unref(startup->sasl_context); g_slice_free(InfinotedStartup, startup); inf_deinit(); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/infinoted/PaxHeaders.26529/infinoted-dh-params.c0000644000000000000000000000013213034342512021554 xustar0030 mtime=1483851082.013718339 30 atime=1483851082.013718339 30 ctime=1488261589.472138033 libinfinity-0.7.1/infinoted/infinoted-dh-params.c0000644000175000017500000000636713034342512022322 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include #include #include #include #include /** * infinoted_dh_params_ensure: * @log: A #InfinotedLog, or %NULL. * @credentials: A #InfCertificateCredentials. * @dh_params: A pointer to a gnutils_dh_params_t structure. * @error: Location to store error information, if any. * * Ensures that DH parameters are set in the certificate credentials. If * *@dh_params is non-%NULL, then this simply sets *@dh_params in * @credentials. Otherwise it tries to read the server's cached DH params * from disk. If successful, it sets them in @credentials and stores them in * *@dh_params. If not, then it generates new DH params, writes them to the * disk cache and sets them into *@dh_params. If generation fails, the * function returns %FALSE and @error is set. * * @log is used to write a log message about the parameters being generated * if they are not cached, so the user knows what's going on during this * lengthy operation. * * Returns: %TRUE on success or %FALSE on error. */ gboolean infinoted_dh_params_ensure(InfinotedLog* log, InfCertificateCredentials* credentials, gnutls_dh_params_t* dh_params, GError** error) { gnutls_certificate_credentials_t creds; gchar* filename; struct stat st; creds = inf_certificate_credentials_get(credentials); if(*dh_params != NULL) { gnutls_certificate_set_dh_params(creds, *dh_params); return TRUE; } filename = g_build_filename(g_get_home_dir(), ".infinoted", "dh.pem", NULL); if(g_stat(filename, &st) == 0) { /* DH params expire every week */ /*if(st.st_mtime + 60 * 60 * 24 * 7 > time(NULL))*/ *dh_params = inf_cert_util_read_dh_params(filename, NULL); } if(*dh_params == NULL) { infinoted_util_create_dirname(filename, NULL); if(log != NULL) { infinoted_log_info( log, _("Generating 2048 bit Diffie-Hellman parameters...")); } *dh_params = inf_cert_util_create_dh_params(error); if(*dh_params == NULL) { g_free(filename); return FALSE; } inf_cert_util_write_dh_params(*dh_params, filename, NULL); } g_free(filename); gnutls_certificate_set_dh_params(creds, *dh_params); return TRUE; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/infinoted/PaxHeaders.26529/infinoted-config-reload.c0000644000000000000000000000013213051240623022410 xustar0030 mtime=1487225235.440756142 30 atime=1487225235.440756142 30 ctime=1488261589.468138042 libinfinity-0.7.1/infinoted/infinoted-config-reload.c0000644000175000017500000003244713051240623023154 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include static const guint8 INFINOTED_CONFIG_RELOAD_IPV6_ANY_ADDR[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static void infinoted_config_reload_update_connection_sasl_context(InfXmlConnection* xml, gpointer userdata) { if(!INF_IS_XMPP_CONNECTION(xml)) return; inf_xmpp_connection_reset_sasl_authentication( INF_XMPP_CONNECTION(xml), (InfSaslContext*) userdata, userdata ? "PLAIN" : NULL ); } /** * infinoted_config_reload: * @run: A #InfinotedRun. * @error: Location to store error information, if any. * * Reloads the server's config file(s) at runtime. If there is a problem * loading them the server is untouched, the function returns %FALSE and * @error is set. * * Returns: %TRUE on success or %FALSE if an error occured. */ gboolean infinoted_config_reload(InfinotedRun* run, GError** error) { InfinotedStartup* startup; gnutls_dh_params_t dh_params; InfdTcpServer* tcp6; InfdTcpServer* tcp4; guint port; InfIpAddress* addr4; InfIpAddress* addr6; GError* local_error; InfdStorage* storage; InfdFilesystemStorage* filesystem_storage; InfdFilesystemAccountStorage* filesystem_account_storage; gchar* root_directory; gboolean result; #ifdef G_OS_WIN32 gchar* module_path; #endif gchar* plugin_path; InfinotedPluginManager* plugin_manager; /* Note that this opens a new log handle to the log file. */ startup = infinoted_startup_new(NULL, NULL, error); if(!startup) return FALSE; /* Acquire DH params if necessary (if security policy changed from * no-tls to one of allow-tls or require-tls). */ dh_params = run->dh_params; if(startup->credentials) { result = infinoted_dh_params_ensure( startup->log, startup->credentials, &dh_params, error ); if(!result) { infinoted_startup_free(startup); return FALSE; } } if((startup->options->listen_address != NULL && run->startup->options->listen_address == NULL) || (startup->options->listen_address == NULL && run->startup->options->listen_address != NULL) || (startup->options->listen_address != NULL && run->startup->options->listen_address != NULL && inf_ip_address_collate(startup->options->listen_address, run->startup->options->listen_address) != 0)) { g_set_error_literal( error, g_quark_from_static_string("INFINOTED_CONFIG_RELOAD_ERROR"), 0, _("Changing the listen address at runtime is not supported") ); infinoted_startup_free(startup); return FALSE; } /* Find out the port we are currently running on */ tcp4 = tcp6 = NULL; if(run->xmpp6) g_object_get(G_OBJECT(run->xmpp6), "tcp-server", &tcp6, NULL); if(run->xmpp4) g_object_get(G_OBJECT(run->xmpp4), "tcp-server", &tcp4, NULL); g_assert(tcp4 != NULL || tcp6 != NULL); if(tcp6) g_object_get(G_OBJECT(tcp6), "local-port", &port, NULL); else g_object_get(G_OBJECT(tcp4), "local-port", &port, NULL); if(tcp4) g_object_unref(tcp4); if(tcp6) g_object_unref(tcp6); tcp4 = tcp6 = NULL; /* If the port changes, then create new servers */ if(startup->options->port != port) { /* TODO: This is the same logic as in infinoted_run_new()... should * probably go into an extra function. */ if(startup->options->listen_address == NULL) { addr4 = NULL; addr6 = inf_ip_address_new_raw6(INFINOTED_CONFIG_RELOAD_IPV6_ANY_ADDR); } else { addr4 = startup->options->listen_address; addr6 = startup->options->listen_address; } tcp6 = g_object_new( INFD_TYPE_TCP_SERVER, "io", run->io, "local-address", addr6, "local-port", startup->options->port, NULL ); if(startup->options->listen_address == NULL) inf_ip_address_free(addr6); if(!infd_tcp_server_bind(tcp6, NULL)) { g_object_unref(tcp6); tcp6 = NULL; } tcp4 = g_object_new( INFD_TYPE_TCP_SERVER, "io", run->io, "local-address", addr4, "local-port", startup->options->port, NULL ); local_error = NULL; if(!infd_tcp_server_bind(tcp4, &local_error)) { g_object_unref(tcp4); tcp4 = NULL; if(tcp6 != NULL) { g_error_free(local_error); } else { g_propagate_error(error, local_error); infinoted_startup_free(startup); return FALSE; } } } /* Beyond this point, tcp4 or tcp6 are non-null if the port was changed and * the new server sockets could be bound successfully. */ g_object_get(G_OBJECT(run->directory), "storage", &storage, NULL); g_assert(INFD_IS_FILESYSTEM_STORAGE(storage)); filesystem_storage = INFD_FILESYSTEM_STORAGE(storage); g_object_get( G_OBJECT(filesystem_storage), "root-directory", &root_directory, NULL ); g_object_unref(storage); filesystem_storage = NULL; filesystem_account_storage = NULL; if(strcmp(root_directory, startup->options->root_directory) != 0) { /* Root directory changes. I don't think this is actually useful, but * all code is there, so let's support it. */ filesystem_storage = infd_filesystem_storage_new(startup->options->root_directory); filesystem_account_storage = infd_filesystem_account_storage_new(); result = infd_filesystem_account_storage_set_filesystem( filesystem_account_storage, filesystem_storage, error ); if(result == FALSE) { g_object_unref(filesystem_account_storage); g_object_unref(filesystem_storage); g_object_unref(plugin_manager); infinoted_startup_free(startup); return FALSE; } } /* This should be the last thing that may fail which we do, because we * allow connection on the new port after this. */ if(tcp4 != NULL || tcp6 != NULL) { local_error = NULL; if(tcp6 != NULL) { local_error = NULL; if(!infd_tcp_server_open(tcp6, &local_error)) { g_object_unref(tcp6); tcp6 = NULL; } } if(tcp4) { if(!infd_tcp_server_open(tcp4, (local_error != NULL) ? NULL : &local_error)) { g_object_unref(tcp4); tcp4 = NULL; } } if(tcp4 == NULL && tcp6 == NULL) { g_propagate_error(error, local_error); g_object_unref(plugin_manager); if(filesystem_storage) g_object_unref(filesystem_storage); if(filesystem_account_storage) g_object_unref(filesystem_account_storage); infinoted_startup_free(startup); return FALSE; } /* One of the server startups might have failed - that's not a problem if * we could start the other one. */ if(local_error) g_error_free(local_error); } /* OK, so beyond this point there is nothing that can fail anymore. */ if(tcp4 != NULL || tcp6 != NULL) { /* We have new servers, close old ones */ if(run->xmpp6 != NULL) { infd_server_pool_remove_server(run->pool, INFD_XML_SERVER(run->xmpp6)); infd_xml_server_close(INFD_XML_SERVER(run->xmpp6)); g_object_unref(run->xmpp6); run->xmpp6 = NULL; } if(run->xmpp4 != NULL) { infd_server_pool_remove_server(run->pool, INFD_XML_SERVER(run->xmpp4)); infd_xml_server_close(INFD_XML_SERVER(run->xmpp4)); g_object_unref(run->xmpp4); run->xmpp4 = NULL; } if(tcp6 != NULL) { run->xmpp6 = infd_xmpp_server_new( tcp6, startup->options->security_policy, startup->credentials, NULL, NULL ); g_object_unref(tcp6); infd_server_pool_add_server(run->pool, INFD_XML_SERVER(run->xmpp6)); #ifdef LIBINFINITY_HAVE_AVAHI infd_server_pool_add_local_publisher( run->pool, run->xmpp6, INF_LOCAL_PUBLISHER(run->avahi) ); #endif } if(tcp4 != NULL) { run->xmpp4 = infd_xmpp_server_new( tcp4, startup->options->security_policy, startup->credentials, NULL, NULL ); g_object_unref(tcp4); infd_server_pool_add_server(run->pool, INFD_XML_SERVER(run->xmpp4)); #ifdef LIBINFINITY_HAVE_AVAHI infd_server_pool_add_local_publisher( run->pool, run->xmpp4, INF_LOCAL_PUBLISHER(run->avahi) ); #endif } } else { /* No new servers, so just set new certificate settings * for existing ones. */ if(run->xmpp6 != NULL) { /* Make sure to set credentials before security-policy */ g_object_set( G_OBJECT(run->xmpp6), "credentials", startup->credentials, "security-policy", startup->options->security_policy, NULL ); } if(run->xmpp4 != NULL) { g_object_set( G_OBJECT(run->xmpp4), "credentials", startup->credentials, "security-policy", startup->options->security_policy, NULL ); } } /* Now, re-initialize plugins. This is a bit tricky, because it can fail, * and because we need to unload the previous plugins first. * * TODO: It would be better if we only add or remove plugins that did not * exist before, and for the rest we call a _reload_params() function. That * function should be allowed to fail, and if it fails, the plugin is * unloaded. */ /* TODO: Make sure this unloads all plugins... at the moment it wouldn't * happen if some plugin ref-ed the plugin manager. */ g_assert(run->plugin_manager != NULL); g_object_unref(run->plugin_manager); /* TODO: Storage and account storage should not be updated if they have * been altered by a plugin... maybe the storage itself should be turned * into a plugin. */ if(filesystem_storage != NULL) { g_object_set( G_OBJECT(run->directory), "storage", filesystem_storage, "account-storage", filesystem_account_storage, NULL ); g_object_unref(filesystem_storage); g_object_unref(filesystem_account_storage); } #ifdef G_OS_WIN32 module_path = g_win32_get_package_installation_directory_of_module(NULL); plugin_path = g_build_filename(module_path, "lib", PLUGIN_PATH, NULL); g_free(module_path); #else plugin_path = g_build_filename(PLUGIN_LIBPATH, PLUGIN_PATH, NULL); #endif plugin_manager = infinoted_plugin_manager_new( run->directory, startup->log, startup->credentials ); local_error = NULL; result = infinoted_plugin_manager_load( plugin_manager, plugin_path, (const gchar* const*)startup->options->plugins, startup->options->config_key_file, &local_error ); g_free(plugin_path); infinoted_options_drop_config_file(startup->options); if(result == FALSE) { infinoted_log_error( startup->log, _("Failed to re-load plugins: %s"), local_error->message ); infinoted_log_error( startup->log, _("Plugins are disabled. Please fix the problem and reload " "configuration again.") ); g_error_free(local_error); } run->plugin_manager = plugin_manager; #ifdef LIBINFINITY_HAVE_LIBDAEMON /* Remember whether we have been daemonized; this is not a config file * option, so not properly set in our newly created startup. */ startup->options->daemonize = run->startup->options->daemonize; #endif if(run->xmpp4 != NULL) { g_object_set( G_OBJECT(run->xmpp4), "sasl-context", startup->sasl_context, "sasl-mechanisms", startup->sasl_context ? "PLAIN" : NULL, NULL ); } if(run->xmpp6 != NULL) { g_object_set( G_OBJECT(run->xmpp6), "sasl-context", startup->sasl_context, "sasl-mechanisms", startup->sasl_context ? "PLAIN" : NULL, NULL ); } /* Give each connection the new sasl context. This is necessary even if the * connection already had a sasl context since that holds on to the old * startup object. This aborts authentications in progress and otherwise * has no effect, really. */ infd_directory_foreach_connection( run->directory, infinoted_config_reload_update_connection_sasl_context, startup->sasl_context ); infinoted_startup_free(run->startup); run->startup = startup; return TRUE; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/infinoted/PaxHeaders.26529/infinoted-signal.c0000644000000000000000000000013213034342512021155 xustar0030 mtime=1483851082.013718339 30 atime=1483851082.013718339 30 ctime=1488261589.476138024 libinfinity-0.7.1/infinoted/infinoted-signal.c0000644000175000017500000001532013034342512021710 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include #include #include #include #ifdef LIBINFINITY_HAVE_LIBDAEMON #include #endif #ifdef G_OS_WIN32 # include # include #endif #ifdef LIBINFINITY_HAVE_LIBDAEMON static void infinoted_signal_sig_func(InfNativeSocket* fd, InfIoEvent event, gpointer user_data) { InfinotedSignal* sig; int occured; GError* error; sig = (InfinotedSignal*)user_data; if(event & INF_IO_ERROR) { inf_io_remove_watch(INF_IO(sig->run->io), sig->watch); daemon_signal_done(); sig->run = NULL; sig->signal_fd = 0; sig->watch = NULL; infinoted_log_error( sig->run->startup->log, _("Error on signal handler connection; signal " "handlers have been removed from now on") ); } else if(event & INF_IO_INCOMING) { occured = daemon_signal_next(); if(occured == SIGINT || occured == SIGTERM || occured == SIGQUIT) { printf("\n"); inf_standalone_io_loop_quit(sig->run->io); } else if(occured == SIGHUP) { error = NULL; if(!infinoted_config_reload(sig->run, &error)) { infinoted_log_error( sig->run->startup->log, _("Configuration reload failed: %s"), error->message ); g_error_free(error); } else { infinoted_log_info( sig->run->startup->log, _("Configuration reloaded") ); } } } } #else static InfinotedRun* _infinoted_signal_server = NULL; static void infinoted_signal_terminate(void) { InfinotedRun* run; /* We do a hard exit here, not calling inf_standalone_io_loop_quit(), * because the signal handler could be called from anywhere in the code. */ if(_infinoted_signal_server != NULL) { run = _infinoted_signal_server; _infinoted_signal_server = NULL; infinoted_run_free(run); exit(0); } } static void infinoted_signal_sigint_handler(int sig) { printf("\n"); infinoted_signal_terminate(); } static void infinoted_signal_sigterm_handler(int sig) { printf("\n"); infinoted_signal_terminate(); } #ifndef G_OS_WIN32 static void infinoted_signal_sigquit_handler(int sig) { printf("\n"); infinoted_signal_terminate(); } static void infinoted_signal_sighup_handler(int sig) { InfinotedRun* run; if(_infinoted_signal_server != NULL) run = _infinoted_signal_server; /* We don't reload the config file here since the signal handler could be * called from anywhere in the code. */ infinoted_log_error( run->startup->log, _("For config reloading to work libinfinity needs " "to be compiled with libdaemon support") ); /* Make sure the signal handler is not reset */ signal(SIGHUP, infinoted_signal_sighup_handler); } #endif /* !G_OS_WIN32 */ #endif /* !LIBINFINITY_HAVE_LIBDAEMON */ #ifdef G_OS_WIN32 BOOL WINAPI infinoted_signal_console_handler(DWORD fdwCtrlType) { InfinotedRun* run; run = _infinoted_signal_server; _infinoted_signal_server = NULL; /* TODO: Don't terminate for CTRL_LOGOFF_EVENT? */ /* Shutdown the server properly. Unlike with UNIX signal handlers we should * be good to do this, since this function seems to be called in an extra * thread. */ if(run != NULL) infinoted_run_stop(run); /* Doesn't matter, we exit() anyway (in the main thread) */ return TRUE; } #endif /** * infinoted_signal_register: * @run: A #InfinotedRun. * * Registers signal handlers for SIGINT and SIGTERM that terminate the given * infinote server. When you don't need the signal handlers anymore, you * must unregister them again using infinoted_signal_unregister(). * * Returns: A #InfinotedSignal to unregister the signal handlers again later. */ InfinotedSignal* infinoted_signal_register(InfinotedRun* run) { InfinotedSignal* sig; sig = g_slice_new(InfinotedSignal); #ifdef LIBINFINITY_HAVE_LIBDAEMON sig->run = run; /* TODO: Should we report when this fails? Should ideally happen before * actually forking then - are signal connections kept in fork()'s child? */ if(daemon_signal_init(SIGINT, SIGTERM, SIGQUIT, SIGHUP, 0) == 0) { sig->signal_fd = daemon_signal_fd(); sig->watch = inf_io_add_watch( INF_IO(run->io), &sig->signal_fd, INF_IO_INCOMING | INF_IO_ERROR, infinoted_signal_sig_func, sig, NULL ); } #else sig->previous_sigint_handler = signal(SIGINT, &infinoted_signal_sigint_handler); sig->previous_sigterm_handler = signal(SIGTERM, &infinoted_signal_sigterm_handler); sig->previous_sigquit_handler = #ifndef G_OS_WIN32 signal(SIGQUIT, &infinoted_signal_sigquit_handler); sig->previous_sighup_handler = signal(SIGHUP, &infinoted_signal_sighup_handler); #endif /* !G_OS_WIN32 */ _infinoted_signal_server = run; #endif /* !LIBINFINITY_HAVE_LIBDAEMON */ #ifdef G_OS_WIN32 SetConsoleCtrlHandler(infinoted_signal_console_handler, TRUE); #endif return sig; } /** * infinoted_signal_unregister: * @sig: A #InfinotedSignal. * * Unregisters signal handlers registered with infinoted_signal_register(). */ void infinoted_signal_unregister(InfinotedSignal* sig) { #ifdef G_OS_WIN32 SetConsoleCtrlHandler(infinoted_signal_console_handler, FALSE); #endif #ifdef LIBINFINITY_HAVE_LIBDAEMON if(sig->run) { inf_io_remove_watch(INF_IO(sig->run->io), sig->watch); sig->watch = NULL; daemon_signal_done(); } #else signal(SIGINT, sig->previous_sigint_handler); signal(SIGTERM, sig->previous_sigterm_handler); #ifndef G_OS_WIN32 signal(SIGQUIT, sig->previous_sigquit_handler); signal(SIGHUP, sig->previous_sighup_handler); #endif /* !G_OS_WIN32 */ _infinoted_signal_server = NULL; #endif /* !LIBINFINITY_HAVE_LIBDAEMON */ g_slice_free(InfinotedSignal, sig); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/infinoted/PaxHeaders.26529/plugins0000644000000000000000000000013213055210725017166 xustar0030 mtime=1488261589.540137884 30 atime=1488261589.480138016 30 ctime=1488261589.540137884 libinfinity-0.7.1/infinoted/plugins/0000755000175000017500000000000013055210725017775 5ustar00arminarmin00000000000000libinfinity-0.7.1/infinoted/plugins/PaxHeaders.26529/infinoted-plugin-directory-sync.c0000644000000000000000000000013213034342512025633 xustar0030 mtime=1483851082.017718362 30 atime=1483851082.017718362 30 ctime=1488261589.528137911 libinfinity-0.7.1/infinoted/plugins/infinoted-plugin-directory-sync.c0000644000175000017500000004026513034342512026374 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include #include typedef struct _InfinotedPluginDirectorySync InfinotedPluginDirectorySync; struct _InfinotedPluginDirectorySync { InfinotedPluginManager* manager; gchar* directory; guint interval; gchar* hook; }; typedef struct _InfinotedPluginDirectorySyncSessionInfo InfinotedPluginDirectorySyncSessionInfo; struct _InfinotedPluginDirectorySyncSessionInfo { InfinotedPluginDirectorySync* plugin; InfBrowserIter iter; InfSessionProxy* proxy; InfIoTimeout* timeout; }; static const gchar* infinoted_plugin_directory_sync_get_filename_encoding(void) { const gchar* encoding; encoding = g_getenv("G_FILENAME_ENCODING"); if(encoding != NULL && *encoding != '\0') return encoding; return "UTF-8"; } static gchar* infinoted_plugin_directory_sync_get_filename( InfinotedPluginDirectorySync* plugin, const InfBrowserIter* iter, GError** error) { gchar* iter_path; #ifdef G_OS_WIN32 gchar* pos; #endif gchar* converted; gchar* full_path; iter_path = inf_browser_get_path( INF_BROWSER(infinoted_plugin_manager_get_directory(plugin->manager)), iter ); #ifdef G_OS_WIN32 for(pos = iter_path; *pos != '\0'; ++pos) if(*pos == '/') *pos = '\\'; #endif converted = g_filename_from_utf8(iter_path, -1, NULL, NULL, error); g_free(iter_path); if(converted == NULL) { g_prefix_error( error, _("Failed to convert path \"%s\" from UTF-8 to %s: "), iter_path, infinoted_plugin_directory_sync_get_filename_encoding() ); return NULL; } full_path = g_build_filename(plugin->directory, converted + 1, NULL); g_free(converted); return full_path; } static gchar* infinoted_plugin_directory_sync_filename_to_utf8(const gchar* filename) { gchar* utf8; utf8 = g_filename_to_utf8(filename, -1, NULL, NULL, NULL); /* This cannot fail really, since the passed filename was created with * g_utf8_to_filename, so we have a correctly encoded string. */ g_assert(utf8 != NULL); return utf8; } static void infinoted_plugin_directory_sync_timeout_cb(gpointer user_data); static void infinoted_plugin_directory_sync_start( InfinotedPluginDirectorySyncSessionInfo* info) { InfIo* io; io = infd_directory_get_io( infinoted_plugin_manager_get_directory(info->plugin->manager) ); g_assert(info->timeout == NULL); info->timeout = inf_io_add_timeout( io, info->plugin->interval * 1000, infinoted_plugin_directory_sync_timeout_cb, info, NULL ); } static void infinoted_plugin_directory_sync_stop( InfinotedPluginDirectorySyncSessionInfo* info) { InfIo* io; io = infd_directory_get_io( infinoted_plugin_manager_get_directory(info->plugin->manager) ); g_assert(info->timeout != NULL); inf_io_remove_timeout(io, info->timeout); info->timeout = NULL; } static gboolean infinoted_plugin_directory_sync_remove( InfinotedPluginDirectorySync* plugin, const InfBrowserIter* iter, GError** error) { gchar* filename; gboolean result; gchar* utf8; GError* local_error; filename = infinoted_plugin_directory_sync_get_filename( plugin, iter, error ); if(filename == NULL) return FALSE; local_error = NULL; result = inf_file_util_delete(filename, &local_error); if(result == FALSE) { /* Accept when the directory did not exist in the first place */ if(local_error->domain == G_FILE_ERROR && local_error->code == G_FILE_ERROR_NOENT) { g_error_free(local_error); local_error = NULL; result = TRUE; } else { utf8 = infinoted_plugin_directory_sync_filename_to_utf8(filename); g_free(filename); g_propagate_prefixed_error( error, local_error, _("Failed to remove directory \"%s\": "), utf8 ); g_free(utf8); return FALSE; } } g_free(filename); return result; } static gboolean infinoted_plugin_directory_sync_save( InfinotedPluginDirectorySyncSessionInfo* info, GError** error) { gchar* filename; gchar* utf8; InfSession* session; InfTextBuffer* buffer; InfTextChunk* chunk; gchar* content; gsize bytes; gchar* path; gchar* argv[4]; if(info->timeout != NULL) { inf_io_remove_timeout( infd_directory_get_io( infinoted_plugin_manager_get_directory(info->plugin->manager) ), info->timeout ); info->timeout = NULL; } filename = infinoted_plugin_directory_sync_get_filename( info->plugin, &info->iter, error ); if(filename == NULL) return FALSE; if(infinoted_util_create_dirname(filename, error) == FALSE) { utf8 = infinoted_plugin_directory_sync_filename_to_utf8(filename); g_free(filename); g_prefix_error( error, _("Failed to create directory for path \"%s\": "), utf8 ); g_free(utf8); return FALSE; } g_object_get(G_OBJECT(info->proxy), "session", &session, NULL); buffer = INF_TEXT_BUFFER(inf_session_get_buffer(session)); /* TODO: Use the iterator API here, which should be less expensive */ chunk = inf_text_buffer_get_slice( buffer, 0, inf_text_buffer_get_length(buffer) ); content = inf_text_chunk_get_text(chunk, &bytes); inf_text_chunk_free(chunk); if(!g_file_set_contents(filename, content, bytes, error)) { utf8 = infinoted_plugin_directory_sync_filename_to_utf8(filename); g_free(filename); g_prefix_error( error, _("Failed to write session for path \"%s\": "), utf8 ); g_free(content); g_object_unref(session); g_free(utf8); return FALSE; } g_free(content); g_object_unref(session); if(info->plugin->hook != NULL) { path = inf_browser_get_path( INF_BROWSER( infinoted_plugin_manager_get_directory(info->plugin->manager) ), &info->iter ); argv[0] = info->plugin->hook; argv[1] = path; argv[2] = filename; argv[3] = NULL; if(!g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, error)) { g_prefix_error( error, _("Failed to execute hook \"%s\": "), info->plugin->hook ); g_free(path); g_free(filename); return FALSE; } g_free(path); } g_free(filename); return TRUE; } static void infinoted_plugin_directory_sync_save_with_error( InfinotedPluginDirectorySyncSessionInfo* info, gboolean retry) { GError* error; error = NULL; if(!infinoted_plugin_directory_sync_save(info, &error)) { if(retry) { /* TODO: Provide a simple error to write a secondary log message... we * could also make use of such an API in the logging plugin. */ infinoted_log_error( infinoted_plugin_manager_get_log(info->plugin->manager), _("%s\n\tWill retry in %u seconds"), error->message, info->plugin->interval ); infinoted_plugin_directory_sync_start(info); } else { infinoted_log_error( infinoted_plugin_manager_get_log(info->plugin->manager), _("%s"), error->message ); } g_error_free(error); } } static void infinoted_plugin_directory_sync_timeout_cb(gpointer user_data) { InfinotedPluginDirectorySyncSessionInfo* info; info = (InfinotedPluginDirectorySyncSessionInfo*)user_data; info->timeout = NULL; infinoted_plugin_directory_sync_save_with_error(info, TRUE); } static void infinoted_plugin_directory_sync_buffer_text_inserted_cb(InfTextBuffer* buffer, guint pos, InfTextChunk* chunk, InfUser* user, gpointer user_data) { InfinotedPluginDirectorySyncSessionInfo* info; info = (InfinotedPluginDirectorySyncSessionInfo*)user_data; if(info->timeout == NULL) infinoted_plugin_directory_sync_start(info); } static void infinoted_plugin_directory_sync_buffer_text_erased_cb(InfTextBuffer* buffer, guint pos, InfTextChunk* chunk, InfUser* user, gpointer user_data) { InfinotedPluginDirectorySyncSessionInfo* info; info = (InfinotedPluginDirectorySyncSessionInfo*)user_data; if(info->timeout == NULL) infinoted_plugin_directory_sync_start(info); } static void infinoted_plugin_directory_sync_node_removed_cb(InfBrowser* browser, const InfBrowserIter* iter, InfRequest* request, gpointer user_data) { InfinotedPluginDirectorySync* plugin; GError* error; plugin = (InfinotedPluginDirectorySync*)user_data; error = NULL; if(!infinoted_plugin_directory_sync_remove(plugin, iter, &error)) { infinoted_log_error( infinoted_plugin_manager_get_log(plugin->manager), "%s", error->message ); g_error_free(error); } } static void infinoted_plugin_directory_sync_info_initialize(gpointer plugin_info) { InfinotedPluginDirectorySync* plugin; plugin = (InfinotedPluginDirectorySync*)plugin_info; plugin->manager = NULL; plugin->directory = NULL; plugin->interval = 0; plugin->hook = NULL; } static gboolean infinoted_plugin_directory_sync_initialize(InfinotedPluginManager* manager, gpointer plugin_info, GError** error) { InfinotedPluginDirectorySync* plugin; plugin = (InfinotedPluginDirectorySync*)plugin_info; plugin->manager = manager; if(inf_file_util_create_directory(plugin->directory, 0777, error) == FALSE) return FALSE; g_signal_connect( G_OBJECT(infinoted_plugin_manager_get_directory(manager)), "node-removed", G_CALLBACK(infinoted_plugin_directory_sync_node_removed_cb), plugin ); return TRUE; } static void infinoted_plugin_directory_sync_deinitialize(gpointer plugin_info) { InfinotedPluginDirectorySync* plugin; plugin = (InfinotedPluginDirectorySync*)plugin_info; g_signal_handlers_disconnect_by_func( G_OBJECT(infinoted_plugin_manager_get_directory(plugin->manager)), G_CALLBACK(infinoted_plugin_directory_sync_node_removed_cb), plugin ); g_free(plugin->directory); g_free(plugin->hook); } static void infinoted_plugin_directory_sync_session_added(const InfBrowserIter* iter, InfSessionProxy* proxy, gpointer plugin_info, gpointer session_info) { InfinotedPluginDirectorySyncSessionInfo* info; InfSession* session; InfBuffer* buffer; #ifdef G_OS_WIN32 gchar* path; gchar* pos; #endif gboolean name_okay; info = (InfinotedPluginDirectorySyncSessionInfo*)session_info; info->plugin = (InfinotedPluginDirectorySync*)plugin_info; info->iter = *iter; info->proxy = proxy; info->timeout = NULL; g_object_ref(proxy); name_okay = TRUE; /* Check that there are no '\' characters somewhere on the path, this would * not be allowed on Windows. */ #ifdef G_OS_WIN32 path = inf_browser_get_path( INF_BROWSER( infinoted_plugin_manager_get_directory(info->plugin->manager) ), iter ); for(pos = path; *pos != '\0'; ++pos) { if(*pos == '\\') { infinoted_log_error( infinoted_plugin_manager_get_log(info->plugin->manager), _("Node \"%s\" contains invalid characters"), path ); name_okay = FALSE; break; } } g_free(path); #endif if(name_okay == TRUE) { g_object_get(G_OBJECT(proxy), "session", &session, NULL); buffer = inf_session_get_buffer(session); g_signal_connect( G_OBJECT(buffer), "text-inserted", G_CALLBACK(infinoted_plugin_directory_sync_buffer_text_inserted_cb), info ); g_signal_connect( G_OBJECT(buffer), "text-erased", G_CALLBACK(infinoted_plugin_directory_sync_buffer_text_erased_cb), info ); infinoted_plugin_directory_sync_save_with_error(info, TRUE); g_object_unref(session); } } static void infinoted_plugin_directory_sync_session_removed(const InfBrowserIter* iter, InfSessionProxy* proxy, gpointer plugin_info, gpointer session_info) { InfinotedPluginDirectorySyncSessionInfo* info; InfSession* session; InfBuffer* buffer; info = (InfinotedPluginDirectorySyncSessionInfo*)session_info; /* If a directory sync was scheduled for this session, then do it now */ if(info->timeout != NULL) infinoted_plugin_directory_sync_save_with_error(info, FALSE); g_object_get(G_OBJECT(info->proxy), "session", &session, NULL); buffer = inf_session_get_buffer(session); inf_signal_handlers_disconnect_by_func( G_OBJECT(buffer), G_CALLBACK(infinoted_plugin_directory_sync_buffer_text_inserted_cb), info ); inf_signal_handlers_disconnect_by_func( G_OBJECT(buffer), G_CALLBACK(infinoted_plugin_directory_sync_buffer_text_erased_cb), info ); g_object_unref(session); g_object_unref(info->proxy); } static const InfinotedParameterInfo INFINOTED_PLUGIN_DIRECTORY_SYNC_OPTIONS[] = { { "directory", INFINOTED_PARAMETER_STRING, INFINOTED_PARAMETER_REQUIRED, offsetof(InfinotedPluginDirectorySync, directory), infinoted_parameter_convert_filename, 0, N_("The directory into which to store the directory tree in text form."), N_("DIRECTORY") }, { "interval", INFINOTED_PARAMETER_INT, INFINOTED_PARAMETER_REQUIRED, offsetof(InfinotedPluginDirectorySync, interval), infinoted_parameter_convert_positive, 0, N_("Interval, in seconds, after which to save documents into the given " "directory."), N_("SECONDS") }, { "hook", INFINOTED_PARAMETER_STRING, 0, offsetof(InfinotedPluginDirectorySync, hook), infinoted_parameter_convert_filename, 0, N_("Command to run after having saved a document."), N_("PROGRAM") }, { NULL, 0, 0, 0, NULL } }; const InfinotedPlugin INFINOTED_PLUGIN = { "directory-sync", N_("Periodically saves the content of all documents into a custom " "directory, without any infinote metadata such as which user wrote what " "text. This option can be used to (automatically) process the files on " "the server by standard tools that operate on normal UTF-8 encoded text " "files"), INFINOTED_PLUGIN_DIRECTORY_SYNC_OPTIONS, sizeof(InfinotedPluginDirectorySync), 0, sizeof(InfinotedPluginDirectorySyncSessionInfo), "InfTextSession", infinoted_plugin_directory_sync_info_initialize, infinoted_plugin_directory_sync_initialize, infinoted_plugin_directory_sync_deinitialize, NULL, NULL, infinoted_plugin_directory_sync_session_added, infinoted_plugin_directory_sync_session_removed }; /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/infinoted/plugins/PaxHeaders.26529/infinoted-plugin-note-text.c0000644000000000000000000000013213034342512024604 xustar0030 mtime=1483851082.017718362 30 atime=1483851082.017718362 30 ctime=1488261589.536137894 libinfinity-0.7.1/infinoted/plugins/infinoted-plugin-note-text.c0000644000175000017500000001422613034342512025343 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include #include #include #include #include typedef struct _InfinotedPluginNoteText InfinotedPluginNoteText; struct _InfinotedPluginNoteText { InfinotedPluginManager* manager; const InfdNotePlugin* plugin; }; /* Note plugin implementation */ static InfSession* infinoted_plugin_note_text_session_new(InfIo* io, InfCommunicationManager* manager, InfSessionStatus status, InfCommunicationGroup* sync_group, InfXmlConnection* sync_connection, const gchar* path, gpointer user_data) { InfTextSession* session; InfTextBuffer* buffer; buffer = INF_TEXT_BUFFER(inf_text_default_buffer_new("UTF-8")); session = inf_text_session_new( manager, buffer, io, status, sync_group, sync_connection ); g_object_unref(buffer); return INF_SESSION(session); } static InfSession* infinoted_plugin_note_text_session_read(InfdStorage* storage, InfIo* io, InfCommunicationManager* manager, const gchar* path, gpointer user_data, GError** error) { InfUserTable* user_table; InfTextBuffer* buffer; gboolean result; InfTextSession* session; g_assert(INFD_IS_FILESYSTEM_STORAGE(storage)); user_table = inf_user_table_new(); buffer = INF_TEXT_BUFFER(inf_text_default_buffer_new("UTF-8")); result = inf_text_filesystem_format_read( INFD_FILESYSTEM_STORAGE(storage), path, user_table, buffer, error ); if(result == FALSE) { g_object_unref(user_table); g_object_unref(buffer); return NULL; } session = inf_text_session_new_with_user_table( manager, buffer, io, user_table, INF_SESSION_RUNNING, NULL, NULL ); g_object_unref(user_table); g_object_unref(buffer); return INF_SESSION(session); } static gboolean infinoted_plugin_note_text_session_write(InfdStorage* storage, InfSession* session, const gchar* path, gpointer user_data, GError** error) { return inf_text_filesystem_format_write( INFD_FILESYSTEM_STORAGE(storage), path, inf_session_get_user_table(session), INF_TEXT_BUFFER(inf_session_get_buffer(session)), error ); } const InfdNotePlugin INFINOTED_PLUGIN_NOTE_TEXT_PLUGIN = { NULL, "InfdFilesystemStorage", "InfText", infinoted_plugin_note_text_session_new, infinoted_plugin_note_text_session_read, infinoted_plugin_note_text_session_write }; /* Infinoted plugin glue */ static void infinoted_plugin_note_text_info_initialize(gpointer plugin_info) { InfinotedPluginNoteText* plugin; plugin = (InfinotedPluginNoteText*)plugin_info; plugin->manager = NULL; plugin->plugin = NULL; } static gboolean infinoted_plugin_note_text_initialize(InfinotedPluginManager* manager, gpointer plugin_info, GError** error) { InfinotedPluginNoteText* plugin; gboolean result; plugin = (InfinotedPluginNoteText*)plugin_info; plugin->manager = manager; result = infd_directory_add_plugin( infinoted_plugin_manager_get_directory(manager), &INFINOTED_PLUGIN_NOTE_TEXT_PLUGIN ); if(result != TRUE) { g_set_error( error, g_quark_from_static_string("INFINOTED_PLUGIN_NOTE_TEXT_ERROR"), 0, _("There is a already a plugin which handles sessions of type \"%s\""), INFINOTED_PLUGIN_NOTE_TEXT_PLUGIN.note_type ); return FALSE; } plugin->plugin = &INFINOTED_PLUGIN_NOTE_TEXT_PLUGIN; return TRUE; } static void infinoted_plugin_note_text_deinitialize(gpointer plugin_info) { InfinotedPluginNoteText* plugin; plugin = (InfinotedPluginNoteText*)plugin_info; /* Note that this kills all sessions with that particular type. This is * typically not wanted when reloading a plugin in which case a plugin is * deinitialized and then re-initialized. */ /* TODO: To fix this, we should add a plugin API to reload its parameters * without unloading and reloading the whole plugin. */ if(plugin->plugin != NULL) { infd_directory_remove_plugin( infinoted_plugin_manager_get_directory(plugin->manager), plugin->plugin ); plugin->plugin = NULL; } } static const InfinotedParameterInfo INFINOTED_PLUGIN_NOTE_TEXT_OPTIONS[] = { { NULL, 0, 0, 0, NULL } }; const InfinotedPlugin INFINOTED_PLUGIN = { "note-text", N_("Adds support to handle plain text documents."), INFINOTED_PLUGIN_NOTE_TEXT_OPTIONS, sizeof(InfinotedPluginNoteText), 0, 0, NULL, infinoted_plugin_note_text_info_initialize, infinoted_plugin_note_text_initialize, infinoted_plugin_note_text_deinitialize, NULL, NULL, NULL, NULL }; /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/infinoted/plugins/PaxHeaders.26529/infinoted-plugin-note-chat.c0000644000000000000000000000013213034342512024537 xustar0030 mtime=1483851082.017718362 30 atime=1483851082.017718362 30 ctime=1488261589.536137894 libinfinity-0.7.1/infinoted/plugins/infinoted-plugin-note-chat.c0000644000175000017500000001422013034342512025270 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include #include #include #include #include typedef struct _InfinotedPluginNoteChat InfinotedPluginNoteChat; struct _InfinotedPluginNoteChat { InfinotedPluginManager* manager; const InfdNotePlugin* plugin; }; typedef enum InfinotedPluginNoteChatError { INFINOTED_PLUGIN_NOTE_CHAT_ERROR_NOT_A_CHAT_SESSION, INFINOTED_PLUGIN_NOTE_CHAT_ERROR_TYPE_ALREADY_HANDLED } InfinotedPluginNoteChatError; /* Note plugin implementation */ static InfSession* infinoted_plugin_note_chat_session_new(InfIo* io, InfCommunicationManager* manager, InfSessionStatus status, InfCommunicationGroup* sync_group, InfXmlConnection* sync_connection, const gchar* path, gpointer user_data) { InfChatBuffer* buffer; InfChatSession* session; buffer = inf_chat_buffer_new(256); session = inf_chat_session_new( manager, buffer, status, INF_COMMUNICATION_GROUP(sync_group), sync_connection ); g_object_unref(buffer); return INF_SESSION(session); } static InfSession* infinoted_plugin_note_chat_session_read(InfdStorage* storage, InfIo* io, InfCommunicationManager* manager, const gchar* path, gpointer user_data, GError** error) { InfChatBuffer* buffer; gboolean result; InfChatSession* session; g_assert(INFD_IS_FILESYSTEM_STORAGE(storage)); buffer = inf_chat_buffer_new(256); result = infd_chat_filesystem_format_read( INFD_FILESYSTEM_STORAGE(storage), path, buffer, error ); if(result == FALSE) { g_object_unref(buffer); return NULL; } session = inf_chat_session_new( manager, buffer, INF_SESSION_RUNNING, NULL, NULL ); g_object_unref(buffer); return INF_SESSION(session); } static gboolean infinoted_plugin_note_chat_session_write(InfdStorage* storage, InfSession* session, const gchar* path, gpointer user_data, GError** error) { return infd_chat_filesystem_format_write( INFD_FILESYSTEM_STORAGE(storage), path, INF_CHAT_BUFFER(inf_session_get_buffer(session)), error ); } const InfdNotePlugin INFINOTED_PLUGIN_NOTE_CHAT_PLUGIN = { NULL, "InfdFilesystemStorage", "InfChat", infinoted_plugin_note_chat_session_new, infinoted_plugin_note_chat_session_read, infinoted_plugin_note_chat_session_write }; /* Infinoted plugin glue */ static void infinoted_plugin_note_chat_info_initialize(gpointer plugin_info) { InfinotedPluginNoteChat* plugin; plugin = (InfinotedPluginNoteChat*)plugin_info; plugin->manager = NULL; plugin->plugin = NULL; } static gboolean infinoted_plugin_note_chat_initialize(InfinotedPluginManager* manager, gpointer plugin_info, GError** error) { InfinotedPluginNoteChat* plugin; gboolean result; plugin = (InfinotedPluginNoteChat*)plugin_info; plugin->manager = manager; result = infd_directory_add_plugin( infinoted_plugin_manager_get_directory(manager), &INFINOTED_PLUGIN_NOTE_CHAT_PLUGIN ); if(result != TRUE) { g_set_error( error, g_quark_from_static_string("INFINOTED_PLUGIN_NOTE_CHAT_ERROR"), INFINOTED_PLUGIN_NOTE_CHAT_ERROR_TYPE_ALREADY_HANDLED, _("There is a already a plugin which handles sessions of type \"%s\""), INFINOTED_PLUGIN_NOTE_CHAT_PLUGIN.note_type ); return FALSE; } plugin->plugin = &INFINOTED_PLUGIN_NOTE_CHAT_PLUGIN; return TRUE; } static void infinoted_plugin_note_chat_deinitialize(gpointer plugin_info) { InfinotedPluginNoteChat* plugin; plugin = (InfinotedPluginNoteChat*)plugin_info; /* Note that this kills all sessions with that particular type. This is * typically not wanted when reloading a plugin in which case a plugin is * deinitialized and then re-initialized. */ /* TODO: To fix this, we should add a plugin API to reload its parameters * without unloading and reloading the whole plugin. */ if(plugin->plugin != NULL) { infd_directory_remove_plugin( infinoted_plugin_manager_get_directory(plugin->manager), plugin->plugin ); plugin->plugin = NULL; } } static const InfinotedParameterInfo INFINOTED_PLUGIN_NOTE_CHAT_OPTIONS[] = { { NULL, 0, 0, 0, NULL } }; const InfinotedPlugin INFINOTED_PLUGIN = { "note-chat", N_("Adds support to handle chat documents."), INFINOTED_PLUGIN_NOTE_CHAT_OPTIONS, sizeof(InfinotedPluginNoteChat), 0, 0, NULL, infinoted_plugin_note_chat_info_initialize, infinoted_plugin_note_chat_initialize, infinoted_plugin_note_chat_deinitialize, NULL, NULL, NULL, NULL }; /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/infinoted/plugins/PaxHeaders.26529/infinoted-plugin-logging.c0000644000000000000000000000013213034342512024303 xustar0030 mtime=1483851082.017718362 30 atime=1483851082.017718362 30 ctime=1488261589.536137894 libinfinity-0.7.1/infinoted/plugins/infinoted-plugin-logging.c0000644000175000017500000005122313034342512025040 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include #include typedef struct _InfinotedPluginLogging InfinotedPluginLogging; struct _InfinotedPluginLogging { InfinotedPluginManager* manager; gboolean log_connections; gboolean log_connection_errors; gboolean log_session_errors; gboolean log_session_request_extra; /* TODO: Make this a hash table, and use the thread ID as a key */ gchar* extra_message; InfSessionProxy* current_session; }; typedef struct _InfinotedPluginLoggingSessionInfo InfinotedPluginLoggingSessionInfo; struct _InfinotedPluginLoggingSessionInfo { InfinotedPluginLogging* plugin; InfSessionProxy* proxy; InfBrowserIter iter; }; static gchar* infinoted_plugin_logging_connection_string(InfXmlConnection* connection) { gchar* remote_id; InfCertificateChain* remote_certificate; gchar* name; gchar* result; g_object_get( G_OBJECT(connection), "remote-id", &remote_id, "remote-certificate", &remote_certificate, NULL ); name = NULL; if(remote_certificate != NULL) { name = inf_cert_util_get_dn_by_oid( inf_certificate_chain_get_own_certificate(remote_certificate), GNUTLS_OID_X520_COMMON_NAME, 0 ); inf_certificate_chain_unref(remote_certificate); } if(name != NULL) result = g_strdup_printf("%s (%s)", remote_id, name); else result = g_strdup_printf("%s (no client certificate)", remote_id); g_free(remote_id); g_free(name); return result; } static gchar* infinoted_plugin_logging_get_document_name( InfinotedPluginLoggingSessionInfo* info) { InfSession* session; InfAdoptedSessionRecord* record; gchar* record_basename; gchar* record_filename; gchar* path; gchar* document_name; g_object_get(G_OBJECT(info->proxy), "session", &session, NULL); record = INF_ADOPTED_SESSION_RECORD( g_object_get_data( G_OBJECT(session), "infinoted-record" ) ); g_object_unref(session); record_basename = NULL; if(record != NULL) { g_object_get(G_OBJECT(record), "filename", &record_filename, NULL); record_basename = g_path_get_basename(record_filename); g_free(record_filename); } path = inf_browser_get_path( INF_BROWSER( infinoted_plugin_manager_get_directory(info->plugin->manager) ), &info->iter ); if(record_basename == NULL) { document_name = path; } else { document_name = g_strdup_printf("%s (%s)", path, record_basename); g_free(record_basename); g_free(path); } return document_name; } static void infinoted_plugin_logging_log_message_cb(InfinotedLog* log, guint priority, guint depth, const gchar* text, gpointer user_data) { InfinotedPluginLogging* plugin; InfinotedPluginLoggingSessionInfo* info; InfAdoptedSession* session; InfAdoptedRequest* request; gchar* request_str; InfUser* user; const gchar* user_name; InfXmlConnection* user_connection; gchar* user_connection_str; gchar* document_name; plugin = (InfinotedPluginLogging*)user_data; if(depth == 0) { if(plugin->extra_message != NULL) infinoted_log_log(log, priority, "%s", plugin->extra_message); if(plugin->current_session) { info = infinoted_plugin_manager_get_session_info( plugin->manager, plugin, plugin->current_session ); g_assert(info != NULL); g_object_get( G_OBJECT(plugin->current_session), "session", &session, NULL ); request = inf_adopted_algorithm_get_execute_request( inf_adopted_session_get_algorithm(session) ); g_assert(request != NULL); request_str = inf_adopted_state_vector_to_string( inf_adopted_request_get_vector(request) ); user = inf_user_table_lookup_user_by_id( inf_session_get_user_table(INF_SESSION(session)), inf_adopted_request_get_user_id(request) ); g_assert(user != NULL); user_name = inf_user_get_name(user); user_connection = inf_user_get_connection(user); if(user_connection != NULL) { user_connection_str = infinoted_plugin_logging_connection_string(user_connection); } else { user_connection_str = g_strdup("local"); } document_name = infinoted_plugin_logging_get_document_name(info); infinoted_log_log( log, priority, _("when executing request \"%s\" from user %s (%s) in document %s"), request_str, user_name, user_connection_str, document_name ); g_free(document_name); g_free(user_connection_str); g_free(request_str); g_object_unref(session); } } } static void infinoted_plugin_logging_begin_execute_request_cb(InfAdoptedAlgorithm* algo, InfAdoptedUser* user, InfAdoptedRequest* request, gpointer user_data) { InfinotedPluginLoggingSessionInfo* info; info = (InfinotedPluginLoggingSessionInfo*)user_data; /* Don't need to ref this */ g_assert(info->plugin->current_session == NULL); info->plugin->current_session = info->proxy; } static void infinoted_plugin_logging_end_execute_request_cb(InfAdoptedAlgorithm* algo, InfAdoptedUser* user, InfAdoptedRequest* request, InfAdoptedRequest* translated, const GError* error, gpointer user_data) { InfinotedPluginLoggingSessionInfo* info; info = (InfinotedPluginLoggingSessionInfo*)user_data; /* TODO: If error is set then log it here, so that the actual request that * caused the error is written in the log file. */ g_assert(info->plugin->current_session != NULL); info->plugin->current_session = NULL; } static void infinoted_plugin_logging_connection_error_cb(InfXmlConnection* connection, const GError* error, gpointer user_data) { InfinotedPluginLogging* plugin; gchar* connection_str; plugin = (InfinotedPluginLogging*)user_data; connection_str = infinoted_plugin_logging_connection_string(connection); infinoted_log_error( infinoted_plugin_manager_get_log(plugin->manager), _("Error from connection %s: %s"), connection_str, error->message ); g_free(connection_str); } static void infinoted_pluggin_logging_session_error_cb(InfSession* session, InfXmlConnection* connection, xmlNodePtr xml, const GError* error, gpointer user_data) { InfinotedPluginLoggingSessionInfo* info; InfAdoptedSessionRecord* record; gchar* connection_str; gchar* document_name; xmlBufferPtr buffer; xmlSaveCtxtPtr ctx; gchar* error_msg; gchar* extra_msg; info = (InfinotedPluginLoggingSessionInfo*)user_data; connection_str = infinoted_plugin_logging_connection_string(connection); document_name = infinoted_plugin_logging_get_document_name(info); buffer = xmlBufferCreate(); ctx = xmlSaveToBuffer(buffer, "UTF-8", 0); xmlSaveTree(ctx, xml); xmlSaveClose(ctx); g_assert(info->plugin->extra_message == NULL); info->plugin->extra_message = g_strdup_printf( _("in document %s from connection %s. The request was: %s"), document_name, connection_str, (const gchar*)xmlBufferContent(buffer) ); g_free(connection_str); g_free(document_name); xmlBufferFree(buffer); /* The extra message is being written inside the handler of the * InfinotedLog::log-message signal. */ infinoted_log_error( infinoted_plugin_manager_get_log(info->plugin->manager), _("Session error: %s"), error->message ); g_free(info->plugin->extra_message); info->plugin->extra_message = NULL; } static void infinoted_plugin_logging_notify_status_cb(InfSession* session, GParamSpec* pspec, gpointer user_data) { InfinotedPluginLoggingSessionInfo* info; InfAdoptedAlgorithm* algorithm; info = (InfinotedPluginLoggingSessionInfo*)user_data; g_assert(INF_ADOPTED_IS_SESSION(session)); if(inf_session_get_status(session) == INF_SESSION_RUNNING) { algorithm = inf_adopted_session_get_algorithm(INF_ADOPTED_SESSION(session)); g_signal_connect( G_OBJECT(algorithm), "begin-execute-request", G_CALLBACK(infinoted_plugin_logging_begin_execute_request_cb), info ); g_signal_connect_after( G_OBJECT(algorithm), "end-execute-request", G_CALLBACK(infinoted_plugin_logging_end_execute_request_cb), info ); } } static void infinoted_plugin_logging_info_initialize(gpointer plugin_info) { InfinotedPluginLogging* plugin; plugin = (InfinotedPluginLogging*)plugin_info; /* default values: log everything */ plugin->log_connections = TRUE; plugin->log_connection_errors = TRUE; plugin->log_session_errors = TRUE; plugin->log_session_request_extra = TRUE; } static gboolean infinoted_plugin_logging_initialize(InfinotedPluginManager* manager, gpointer plugin_info, GError** error) { InfinotedPluginLogging* plugin; plugin = (InfinotedPluginLogging*)plugin_info; plugin->manager = manager; g_signal_connect( G_OBJECT(infinoted_plugin_manager_get_log(manager)), "log-message", G_CALLBACK(infinoted_plugin_logging_log_message_cb), plugin ); plugin->extra_message = NULL; plugin->current_session = NULL; return TRUE; } static void infinoted_plugin_logging_deinitialize(gpointer plugin_info) { InfinotedPluginLogging* plugin; plugin = (InfinotedPluginLogging*)plugin_info; inf_signal_handlers_disconnect_by_func( G_OBJECT(infinoted_plugin_manager_get_log(plugin->manager)), G_CALLBACK(infinoted_plugin_logging_log_message_cb), plugin ); } static void infinoted_plugin_logging_connection_notify_status_cb(GObject* object, GParamSpec* pspec, gpointer user_data) { InfinotedPluginLogging* plugin; gchar* connection_str; InfXmlConnectionStatus status; plugin = (InfinotedPluginLogging*)user_data; g_object_get(G_OBJECT(object), "status", &status, NULL); switch(status) { case INF_XML_CONNECTION_OPENING: /* Nothing happened */ break; case INF_XML_CONNECTION_OPEN: connection_str = infinoted_plugin_logging_connection_string(INF_XML_CONNECTION(object)); infinoted_log_info( infinoted_plugin_manager_get_log(plugin->manager), _("%s connected"), connection_str ); g_free(connection_str); inf_signal_handlers_disconnect_by_func( G_OBJECT(object), G_CALLBACK(infinoted_plugin_logging_connection_notify_status_cb), plugin ); break; case INF_XML_CONNECTION_CLOSING: case INF_XML_CONNECTION_CLOSED: /* This is handled in infinoted_plugin_logging_connection_removed() */ break; default: g_assert_not_reached(); break; } } static void infinoted_plugin_logging_connection_added(InfXmlConnection* connection, gpointer plugin_info, gpointer connection_info) { InfinotedPluginLogging* plugin; gchar* connection_str; InfXmlConnectionStatus status; plugin = (InfinotedPluginLogging*)plugin_info; if(plugin->log_connection_errors) { g_signal_connect( G_OBJECT(connection), "error", G_CALLBACK(infinoted_plugin_logging_connection_error_cb), plugin ); } if(plugin->log_connections) { g_object_get(G_OBJECT(connection), "status", &status, NULL); switch(status) { case INF_XML_CONNECTION_OPENING: g_signal_connect( G_OBJECT(connection), "notify::status", G_CALLBACK(infinoted_plugin_logging_connection_notify_status_cb), plugin ); break; case INF_XML_CONNECTION_OPEN: /* If the connection is in CONNECTING status, then wait for * CONNECTED, to be able to read the certificate. If CONNECTION_REMOVED * happens before CONNECTED, then skip the certificate, but print the * connection attempt nevertheless. */ connection_str = infinoted_plugin_logging_connection_string(connection); infinoted_log_info( infinoted_plugin_manager_get_log(plugin->manager), _("%s connected"), connection_str ); g_free(connection_str); break; default: g_assert_not_reached(); break; } } } static void infinoted_plugin_logging_connection_removed(InfXmlConnection* connection, gpointer plugin_info, gpointer connection_info) { InfinotedPluginLogging* plugin; gchar* connection_str; guint n_connected; plugin = (InfinotedPluginLogging*)plugin_info; if(plugin->log_connection_errors) { inf_signal_handlers_disconnect_by_func( G_OBJECT(connection), G_CALLBACK(infinoted_plugin_logging_connection_error_cb), plugin ); } if(plugin->log_connections) { n_connected = inf_signal_handlers_disconnect_by_func( G_OBJECT(connection), G_CALLBACK(infinoted_plugin_logging_connection_notify_status_cb), plugin ); connection_str = infinoted_plugin_logging_connection_string(connection); if(n_connected > 0) { /* The connection went down before being fully functional */ infinoted_log_info( infinoted_plugin_manager_get_log(plugin->manager), _("Unsuccessful connection attempt from %s"), connection_str ); } else { infinoted_log_info( infinoted_plugin_manager_get_log(plugin->manager), _("%s disconnected"), connection_str ); } g_free(connection_str); } } static void infinoted_plugin_logging_session_added(const InfBrowserIter* iter, InfSessionProxy* proxy, gpointer plugin_info, gpointer session_info) { InfinotedPluginLoggingSessionInfo* info; InfSession* session; InfAdoptedAlgorithm* algorithm; info = (InfinotedPluginLoggingSessionInfo*)session_info; info->plugin = (InfinotedPluginLogging*)plugin_info; info->proxy = proxy; info->iter = *iter; g_object_ref(proxy); g_object_get(G_OBJECT(proxy), "session", &session, NULL); if(info->plugin->log_session_errors) { g_signal_connect( G_OBJECT(session), "error", G_CALLBACK(infinoted_pluggin_logging_session_error_cb), info ); } if(INF_ADOPTED_IS_SESSION(session) && info->plugin->log_session_request_extra) { if(inf_session_get_status(session) == INF_SESSION_RUNNING) { algorithm = inf_adopted_session_get_algorithm(INF_ADOPTED_SESSION(session)); g_signal_connect( G_OBJECT(algorithm), "begin-execute-request", G_CALLBACK(infinoted_plugin_logging_begin_execute_request_cb), info ); g_signal_connect_after( G_OBJECT(algorithm), "end-execute-request", G_CALLBACK(infinoted_plugin_logging_end_execute_request_cb), info ); } else { g_signal_connect( G_OBJECT(session), "notify::status", G_CALLBACK(infinoted_plugin_logging_notify_status_cb), info ); } } g_object_unref(session); } static void infinoted_plugin_logging_session_removed(const InfBrowserIter* iter, InfSessionProxy* proxy, gpointer plugin_info, gpointer session_info) { InfinotedPluginLoggingSessionInfo* info; InfSession* session; InfAdoptedAlgorithm* algorithm; info = (InfinotedPluginLoggingSessionInfo*)session_info; g_assert(info->proxy == proxy); g_object_get(G_OBJECT(proxy), "session", &session, NULL); if(info->plugin->log_session_errors) { inf_signal_handlers_disconnect_by_func( G_OBJECT(session), G_CALLBACK(infinoted_pluggin_logging_session_error_cb), info ); } if(INF_ADOPTED_IS_SESSION(session) && info->plugin->log_session_request_extra) { inf_signal_handlers_disconnect_by_func( G_OBJECT(session), G_CALLBACK(infinoted_plugin_logging_notify_status_cb), info ); if(inf_session_get_status(session) == INF_SESSION_RUNNING) { algorithm = inf_adopted_session_get_algorithm(INF_ADOPTED_SESSION(session)); inf_signal_handlers_disconnect_by_func( G_OBJECT(algorithm), G_CALLBACK(infinoted_plugin_logging_begin_execute_request_cb), info ); inf_signal_handlers_disconnect_by_func( G_OBJECT(algorithm), G_CALLBACK(infinoted_plugin_logging_end_execute_request_cb), info ); } } g_object_unref(info->proxy); g_object_unref(session); } static const InfinotedParameterInfo INFINOTED_PLUGIN_LOGGING_OPTIONS[] = { { "log-connections", INFINOTED_PARAMETER_BOOLEAN, 0, offsetof(InfinotedPluginLogging, log_connections), infinoted_parameter_convert_boolean, 0, N_("Whether to write a log message when a new user connects " "or disconnects."), NULL }, { "log-connection-errors", INFINOTED_PARAMETER_BOOLEAN, 0, offsetof(InfinotedPluginLogging, log_connection_errors), infinoted_parameter_convert_boolean, 0, N_("Whether to write a log message when an error with a connection is " "detected, usually leading to disconnection of the user."), NULL }, { "log-session-errors", INFINOTED_PARAMETER_BOOLEAN, 0, offsetof(InfinotedPluginLogging, log_session_errors), infinoted_parameter_convert_boolean, 0, N_("Whether to write a log message when a session cannot process a " "client request, mostly caused by invalid client requests."), NULL }, { "log-session-request-extra", INFINOTED_PARAMETER_BOOLEAN, 0, offsetof(InfinotedPluginLogging, log_session_request_extra), infinoted_parameter_convert_boolean, 0, N_("Whether to write an additional line into the log when a message " "occurs during transformation of an adOPTed request. This is mostly " "used for debugging purposes to find problems in the server " "implementation itself."), NULL }, { NULL, 0, 0, 0, NULL } }; const InfinotedPlugin INFINOTED_PLUGIN = { "logging", N_("This plugin writes extra information into the infinoted log. By " "default all extra information is logged, but individual events " "can be turned off with the plugin options."), INFINOTED_PLUGIN_LOGGING_OPTIONS, sizeof(InfinotedPluginLogging), 0, sizeof(InfinotedPluginLoggingSessionInfo), NULL, infinoted_plugin_logging_info_initialize, infinoted_plugin_logging_initialize, infinoted_plugin_logging_deinitialize, infinoted_plugin_logging_connection_added, infinoted_plugin_logging_connection_removed, infinoted_plugin_logging_session_added, infinoted_plugin_logging_session_removed }; /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/infinoted/plugins/PaxHeaders.26529/infinoted-plugin-traffic-logging.c0000644000000000000000000000013213034342512025717 xustar0030 mtime=1483851082.017718362 30 atime=1483851082.017718362 30 ctime=1488261589.540137884 libinfinity-0.7.1/infinoted/plugins/infinoted-plugin-traffic-logging.c0000644000175000017500000002261613034342512026460 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include typedef struct _InfinotedPluginTrafficLogging InfinotedPluginTrafficLogging; struct _InfinotedPluginTrafficLogging { InfinotedPluginManager* manager; gchar* path; }; typedef struct _InfinotedPluginTrafficLoggingConnectionInfo InfinotedPluginTrafficLoggingConnectionInfo; struct _InfinotedPluginTrafficLoggingConnectionInfo { InfinotedPluginTrafficLogging* plugin; InfXmlConnection* connection; gchar* filename; FILE* file; }; static void infinoted_plugin_traffic_logging_write( InfinotedPluginTrafficLoggingConnectionInfo* info, const gchar* fmt, ...) { GTimeVal cur_timeval; time_t cur_time; struct tm* cur_tm; char time_msg[128]; va_list arglist; g_assert(info->file != NULL); g_get_current_time(&cur_timeval); cur_time = cur_timeval.tv_sec; cur_tm = localtime(&cur_time); strftime(time_msg, 128, "[%c ", cur_tm); fputs(time_msg, info->file); fprintf(info->file, ".%06ld] ", cur_timeval.tv_usec); va_start(arglist, fmt); vfprintf(info->file, fmt, arglist); va_end(arglist); fputc('\n', info->file); fflush(info->file); } static void infinoted_plugin_traffic_logging_received_cb(InfXmlConnection* conn, xmlNodePtr xml, gpointer user_data) { InfinotedPluginTrafficLoggingConnectionInfo* info; xmlBufferPtr buffer; xmlSaveCtxtPtr ctx; info = (InfinotedPluginTrafficLoggingConnectionInfo*)user_data; buffer = xmlBufferCreate(); ctx = xmlSaveToBuffer(buffer, "UTF-8", 0); xmlSaveTree(ctx, xml); xmlSaveClose(ctx); infinoted_plugin_traffic_logging_write( info, "<<< %s", (const gchar*)xmlBufferContent(buffer) ); xmlBufferFree(buffer); } static void infinoted_plugin_traffic_logging_sent_cb(InfXmlConnection* conn, xmlNodePtr xml, gpointer user_data) { InfinotedPluginTrafficLoggingConnectionInfo* info; xmlBufferPtr buffer; xmlSaveCtxtPtr ctx; info = (InfinotedPluginTrafficLoggingConnectionInfo*)user_data; buffer = xmlBufferCreate(); ctx = xmlSaveToBuffer(buffer, "UTF-8", 0); xmlSaveTree(ctx, xml); xmlSaveClose(ctx); infinoted_plugin_traffic_logging_write( info, ">>> %s", (const gchar*)xmlBufferContent(buffer) ); xmlBufferFree(buffer); } static void infinoted_plugin_traffic_logging_error_cb(InfXmlConnection* conn, const GError* error, gpointer user_data) { InfinotedPluginTrafficLoggingConnectionInfo* info; gchar* text; info = (InfinotedPluginTrafficLoggingConnectionInfo*)user_data; text = g_strdup_printf(_("Connection error: %s"), error->message); infinoted_plugin_traffic_logging_write(info, "!!! %s", text); g_free(text); } static void infinoted_plugin_traffic_logging_info_initialize(gpointer plugin_info) { InfinotedPluginTrafficLogging* plugin; plugin = (InfinotedPluginTrafficLogging*)plugin_info; plugin->manager = NULL; plugin->path = NULL; } static gboolean infinoted_plugin_traffic_logging_initialize(InfinotedPluginManager* manager, gpointer plugin_info, GError** error) { InfinotedPluginTrafficLogging* plugin; plugin = (InfinotedPluginTrafficLogging*)plugin_info; plugin->manager = manager; return TRUE; } static void infinoted_plugin_traffic_logging_deinitialize(gpointer plugin_info) { InfinotedPluginTrafficLogging* plugin; plugin = (InfinotedPluginTrafficLogging*)plugin_info; g_free(plugin->path); } static void infinoted_plugin_traffic_logging_connection_added( InfXmlConnection* connection, gpointer plugin_info, gpointer connection_info) { InfinotedPluginTrafficLogging* plugin; InfinotedPluginTrafficLoggingConnectionInfo* info; gchar* remote_id; gchar* basename; gchar* c; gchar* text; GError* error; plugin = (InfinotedPluginTrafficLogging*)plugin_info; info = (InfinotedPluginTrafficLoggingConnectionInfo*)connection_info; info->plugin = plugin; info->connection = connection; info->filename = NULL; info->file = NULL; g_object_get(G_OBJECT(connection), "remote-id", &remote_id, NULL); basename = g_strdup(remote_id); for(c = basename; *c != '\0'; ++c) if(*c == '[' || *c == ']') *c = '_'; info->filename = g_build_filename(plugin->path, basename, NULL); g_free(basename); error = NULL; if(infinoted_util_create_dirname(info->filename, &error) == FALSE) { basename = g_path_get_dirname(info->filename); infinoted_log_warning( infinoted_plugin_manager_get_log(plugin->manager), _("Failed to create directory \"%s\": %s\nTraffic logging " "for connection \"%s\" is disabled."), basename, error->message, remote_id ); g_error_free(error); g_free(basename); } else { info->file = fopen(info->filename, "a"); if(info->file == NULL) { infinoted_log_warning( infinoted_plugin_manager_get_log(plugin->manager), _("Failed to open file \"%s\": %s\nTraffic logging " "for connection \"%s\" is disabled."), info->filename, strerror(errno), remote_id ); } else { text = g_strdup_printf(_("%s connected"), remote_id); infinoted_plugin_traffic_logging_write(info, "!!! %s", text); g_free(text); g_signal_connect( G_OBJECT(connection), "received", G_CALLBACK(infinoted_plugin_traffic_logging_received_cb), info ); g_signal_connect( G_OBJECT(connection), "sent", G_CALLBACK(infinoted_plugin_traffic_logging_sent_cb), info ); g_signal_connect( G_OBJECT(connection), "error", G_CALLBACK(infinoted_plugin_traffic_logging_error_cb), info ); } } g_free(remote_id); } static void infinoted_plugin_traffic_logging_connection_removed( InfXmlConnection* connection, gpointer plugin_info, gpointer connection_info) { InfinotedPluginTrafficLogging* plugin; InfinotedPluginTrafficLoggingConnectionInfo* info; gchar* remote_id; plugin = (InfinotedPluginTrafficLogging*)plugin_info; info = (InfinotedPluginTrafficLoggingConnectionInfo*)connection_info; if(info->file != NULL) { inf_signal_handlers_disconnect_by_func( G_OBJECT(connection), G_CALLBACK(infinoted_plugin_traffic_logging_received_cb), info ); inf_signal_handlers_disconnect_by_func( G_OBJECT(connection), G_CALLBACK(infinoted_plugin_traffic_logging_sent_cb), info ); inf_signal_handlers_disconnect_by_func( G_OBJECT(connection), G_CALLBACK(infinoted_plugin_traffic_logging_error_cb), info ); infinoted_plugin_traffic_logging_write(info, "!!! %s", _("Log closed")); if(fclose(info->file) == -1) { infinoted_log_warning( infinoted_plugin_manager_get_log(plugin->manager), "Failed to close file \"%s\": %s", info->filename, strerror(errno) ); } } g_free(info->filename); } static const InfinotedParameterInfo INFINOTED_PLUGIN_TRAFFIC_LOGGING_OPTIONS[] = { { "path", INFINOTED_PARAMETER_STRING, INFINOTED_PARAMETER_REQUIRED, offsetof(InfinotedPluginTrafficLogging, path), infinoted_parameter_convert_filename, 0, N_("The directory into which to write the log files."), N_("DIRECTORY") }, { NULL, 0, 0, 0, NULL } }; const InfinotedPlugin INFINOTED_PLUGIN = { "traffic-logging", N_("This plugin writes a dump of all network traffic between the server " "and the client into a file. Note that the traffic written to the log " "files is unencrypted. It is meant to be used as a diagnostic tool for " "debugging, and it should never be used in a production environment as " "it is a severe privacy issue."), INFINOTED_PLUGIN_TRAFFIC_LOGGING_OPTIONS, sizeof(InfinotedPluginTrafficLogging), sizeof(InfinotedPluginTrafficLoggingConnectionInfo), 0, NULL, infinoted_plugin_traffic_logging_info_initialize, infinoted_plugin_traffic_logging_initialize, infinoted_plugin_traffic_logging_deinitialize, infinoted_plugin_traffic_logging_connection_added, infinoted_plugin_traffic_logging_connection_removed, NULL, NULL }; /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/infinoted/plugins/PaxHeaders.26529/infinoted-plugin-linekeeper.c0000644000000000000000000000013213034342512025000 xustar0030 mtime=1483851082.017718362 30 atime=1483851082.017718362 30 ctime=1488261589.532137902 libinfinity-0.7.1/infinoted/plugins/infinoted-plugin-linekeeper.c0000644000175000017500000003640613034342512025543 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include typedef struct _InfinotedPluginLinekeeper InfinotedPluginLinekeeper; struct _InfinotedPluginLinekeeper { InfinotedPluginManager* manager; guint n_lines; }; typedef struct _InfinotedPluginLinekeeperSessionInfo InfinotedPluginLinekeeperSessionInfo; struct _InfinotedPluginLinekeeperSessionInfo { InfinotedPluginLinekeeper* plugin; InfSessionProxy* proxy; InfRequest* request; InfUser* user; InfTextBuffer* buffer; InfIoDispatch* dispatch; }; typedef struct _InfinotedPluginLinekeeperHasAvailableUsersData InfinotedPluginLinekeeperHasAvailableUsersData; struct _InfinotedPluginLinekeeperHasAvailableUsersData { InfUser* own_user; gboolean has_available_user; }; static gboolean infinoted_plugin_linekeeper_initialize(InfinotedPluginManager* manager, gpointer plugin_info, GError** error) { InfinotedPluginLinekeeper* plugin; plugin = (InfinotedPluginLinekeeper*)plugin_info; plugin->manager = manager; return TRUE; } static void infinoted_plugin_linekeeper_deinitialize(gpointer plugin_info) { InfinotedPluginLinekeeper* plugin; plugin = (InfinotedPluginLinekeeper*)plugin_info; } static guint infinoted_plugin_linekeeper_count_lines(InfTextBuffer* buffer) { /* Count the number of lines at the end of the document. This assumes the * buffer content is in UTF-8, which is currently hardcoded in infinoted. */ InfTextBufferIter* iter; guint n_lines; gboolean has_iter; guint length; gsize bytes; gchar* text; gchar* pos; gchar* new_pos; gunichar c; g_assert(strcmp(inf_text_buffer_get_encoding(buffer), "UTF-8") == 0); n_lines = 0; iter = inf_text_buffer_create_end_iter(buffer); if(iter == NULL) return 0; do { length = inf_text_buffer_iter_get_length(buffer, iter); bytes = inf_text_buffer_iter_get_bytes(buffer, iter); text = inf_text_buffer_iter_get_text(buffer, iter); pos = text + bytes; while(length > 0) { new_pos = g_utf8_prev_char(pos); g_assert(bytes >= (pos - new_pos)); c = g_utf8_get_char(new_pos); if(c == '\n' || g_unichar_type(c) == G_UNICODE_LINE_SEPARATOR) ++n_lines; else break; --length; bytes -= (pos - new_pos); pos = new_pos; } g_free(text); } while(length == 0 && inf_text_buffer_iter_prev(buffer, iter)); inf_text_buffer_destroy_iter(buffer, iter); return n_lines; } static void infinoted_plugin_linekeeper_run(InfinotedPluginLinekeeperSessionInfo* info) { guint cur_lines; guint n; gchar* text; cur_lines = infinoted_plugin_linekeeper_count_lines(info->buffer); if(cur_lines > info->plugin->n_lines) { n = cur_lines - info->plugin->n_lines; inf_text_buffer_erase_text( info->buffer, inf_text_buffer_get_length(info->buffer) - n, n, info->user ); } else if(cur_lines < info->plugin->n_lines) { n = info->plugin->n_lines - cur_lines; text = g_malloc(n * sizeof(gchar)); memset(text, '\n', n); inf_text_buffer_insert_text( info->buffer, inf_text_buffer_get_length(info->buffer), text, n, n, info->user ); } } static void infinoted_plugin_linekeeper_run_dispatch_func(gpointer user_data) { InfinotedPluginLinekeeperSessionInfo* info; info = (InfinotedPluginLinekeeperSessionInfo*)user_data; info->dispatch = NULL; infinoted_plugin_linekeeper_run(info); } static void infinoted_plugin_linekeeper_text_inserted_cb(InfTextBuffer* buffer, guint pos, InfTextChunk* chunk, InfUser* user, gpointer user_data) { InfinotedPluginLinekeeperSessionInfo* info; InfdDirectory* directory; info = (InfinotedPluginLinekeeperSessionInfo*)user_data; if(info->dispatch == NULL) { directory = infinoted_plugin_manager_get_directory(info->plugin->manager); info->dispatch = inf_io_add_dispatch( infd_directory_get_io(directory), infinoted_plugin_linekeeper_run_dispatch_func, info, NULL ); } } static void infinoted_plugin_linekeeper_text_erased_cb(InfTextBuffer* buffer, guint pos, InfTextChunk* chunk, InfUser* user, gpointer user_data) { InfinotedPluginLinekeeperSessionInfo* info; InfdDirectory* directory; info = (InfinotedPluginLinekeeperSessionInfo*)user_data; if(info->dispatch == NULL) { directory = infinoted_plugin_manager_get_directory(info->plugin->manager); info->dispatch = inf_io_add_dispatch( infd_directory_get_io(directory), infinoted_plugin_linekeeper_run_dispatch_func, info, NULL ); } } static void infinoted_plugin_linekeeper_remove_user( InfinotedPluginLinekeeperSessionInfo* info) { InfSession* session; InfUser* user; g_assert(info->user != NULL); g_assert(info->request == NULL); user = info->user; info->user = NULL; g_object_get(G_OBJECT(info->proxy), "session", &session, NULL); inf_session_set_user_status(session, user, INF_USER_UNAVAILABLE); g_object_unref(user); inf_signal_handlers_disconnect_by_func( G_OBJECT(info->buffer), G_CALLBACK(infinoted_plugin_linekeeper_text_inserted_cb), info ); inf_signal_handlers_disconnect_by_func( G_OBJECT(info->buffer), G_CALLBACK(infinoted_plugin_linekeeper_text_erased_cb), info ); g_object_unref(session); } static void infinoted_plugin_linekeeper_has_available_users_foreach_func(InfUser* user, gpointer udata) { InfinotedPluginLinekeeperHasAvailableUsersData* data; data = (InfinotedPluginLinekeeperHasAvailableUsersData*)udata; /* Return TRUE if there are non-local users connected */ if(user != data->own_user && inf_user_get_status(user) != INF_USER_UNAVAILABLE && (inf_user_get_flags(user) & INF_USER_LOCAL) == 0) { data->has_available_user = TRUE; } } static gboolean infinoted_plugin_linekeeper_has_available_users( InfinotedPluginLinekeeperSessionInfo* info) { InfinotedPluginLinekeeperHasAvailableUsersData data; InfSession* session; InfUserTable* user_table; g_object_get(G_OBJECT(info->proxy), "session", &session, NULL); user_table = inf_session_get_user_table(session); data.has_available_user = FALSE; data.own_user = info->user; inf_user_table_foreach_user( user_table, infinoted_plugin_linekeeper_has_available_users_foreach_func, &data ); g_object_unref(session); return data.has_available_user; } static void infinoted_plugin_linekeeper_user_join_cb(InfRequest* request, const InfRequestResult* result, const GError* error, gpointer user_data) { InfinotedPluginLinekeeperSessionInfo* info; InfUser* user; info = (InfinotedPluginLinekeeperSessionInfo*)user_data; info->request = NULL; if(error != NULL) { infinoted_log_warning( infinoted_plugin_manager_get_log(info->plugin->manager), _("Could not join LineKeeper user for document: %s\n"), error->message ); } else { inf_request_result_get_join_user(result, NULL, &user); info->user = user; g_object_ref(info->user); /* Initial run */ infinoted_plugin_linekeeper_run(info); g_signal_connect( G_OBJECT(info->buffer), "text-inserted", G_CALLBACK(infinoted_plugin_linekeeper_text_inserted_cb), info ); g_signal_connect( G_OBJECT(info->buffer), "text-erased", G_CALLBACK(infinoted_plugin_linekeeper_text_erased_cb), info ); /* It can happen that while the request is being processed, the situation * changes again. */ if(infinoted_plugin_linekeeper_has_available_users(info) == FALSE) { infinoted_plugin_linekeeper_remove_user(info); } } } static void infinoted_plugin_linekeeper_add_available_user_cb(InfUserTable* user_table, InfUser* user, gpointer user_data); static void infinoted_plugin_linekeeper_join_user( InfinotedPluginLinekeeperSessionInfo* info) { InfSession* session; InfUserTable* user_table; g_assert(info->user == NULL); g_assert(info->request == NULL); g_object_get(G_OBJECT(info->proxy), "session", &session, NULL); user_table = inf_session_get_user_table(session); /* Prevent double user join attempt by blocking the callback for * joining our local user. */ g_signal_handlers_block_by_func( user_table, G_CALLBACK(infinoted_plugin_linekeeper_add_available_user_cb), info ); info->request = inf_text_session_join_user( info->proxy, "LineKeeper", INF_USER_ACTIVE, 0.0, inf_text_buffer_get_length(info->buffer), 0, infinoted_plugin_linekeeper_user_join_cb, info ); g_signal_handlers_unblock_by_func( user_table, G_CALLBACK(infinoted_plugin_linekeeper_add_available_user_cb), info ); g_object_unref(session); } static void infinoted_plugin_linekeeper_add_available_user_cb(InfUserTable* user_table, InfUser* user, gpointer user_data) { InfinotedPluginLinekeeperSessionInfo* info; info = (InfinotedPluginLinekeeperSessionInfo*)user_data; if(info->user == NULL && info->request == NULL && infinoted_plugin_linekeeper_has_available_users(info)) { infinoted_plugin_linekeeper_join_user(info); } } static void infinoted_plugin_linekeeper_remove_available_user_cb(InfUserTable* user_table, InfUser* user, gpointer user_data) { InfinotedPluginLinekeeperSessionInfo* info; info = (InfinotedPluginLinekeeperSessionInfo*)user_data; if(info->user != NULL && !infinoted_plugin_linekeeper_has_available_users(info)) { infinoted_plugin_linekeeper_remove_user(info); } } static void infinoted_plugin_linekeeper_session_added(const InfBrowserIter* iter, InfSessionProxy* proxy, gpointer plugin_info, gpointer session_info) { InfinotedPluginLinekeeperSessionInfo* info; InfSession* session; InfUserTable* user_table; info = (InfinotedPluginLinekeeperSessionInfo*)session_info; info->plugin = (InfinotedPluginLinekeeper*)plugin_info; info->proxy = proxy; info->request = NULL; info->user = NULL; info->dispatch = NULL; g_object_ref(proxy); g_object_get(G_OBJECT(proxy), "session", &session, NULL); g_assert(inf_session_get_status(session) == INF_SESSION_RUNNING); info->buffer = INF_TEXT_BUFFER(inf_session_get_buffer(session)); g_object_ref(info->buffer); user_table = inf_session_get_user_table(session); g_signal_connect( G_OBJECT(user_table), "add-available-user", G_CALLBACK(infinoted_plugin_linekeeper_add_available_user_cb), info ); g_signal_connect( G_OBJECT(user_table), "remove-available-user", G_CALLBACK(infinoted_plugin_linekeeper_remove_available_user_cb), info ); /* Only join a user when there are other nonlocal users available, so that * we don't keep the session from going idle. */ if(infinoted_plugin_linekeeper_has_available_users(info) == TRUE) infinoted_plugin_linekeeper_join_user(info); g_object_unref(session); } static void infinoted_plugin_linekeeper_session_removed(const InfBrowserIter* iter, InfSessionProxy* proxy, gpointer plugin_info, gpointer session_info) { InfinotedPluginLinekeeperSessionInfo* info; InfdDirectory* directory; InfSession* session; InfUserTable* user_table; info = (InfinotedPluginLinekeeperSessionInfo*)session_info; g_object_get(G_OBJECT(info->proxy), "session", &session, NULL); user_table = inf_session_get_user_table(session); g_signal_handlers_disconnect_by_func( G_OBJECT(user_table), G_CALLBACK(infinoted_plugin_linekeeper_add_available_user_cb), info ); g_signal_handlers_disconnect_by_func( G_OBJECT(user_table), G_CALLBACK(infinoted_plugin_linekeeper_remove_available_user_cb), info ); if(info->dispatch != NULL) { directory = infinoted_plugin_manager_get_directory(info->plugin->manager); inf_io_remove_dispatch(infd_directory_get_io(directory), info->dispatch); info->dispatch = NULL; } if(info->user != NULL) { infinoted_plugin_linekeeper_remove_user(info); } if(info->buffer != NULL) { g_object_unref(info->buffer); info->buffer = NULL; } if(info->request != NULL) { inf_signal_handlers_disconnect_by_func( info->request, G_CALLBACK(infinoted_plugin_linekeeper_user_join_cb), info ); info->request = NULL; } g_assert(info->proxy != NULL); g_object_unref(info->proxy); g_object_unref(session); } static const InfinotedParameterInfo INFINOTED_PLUGIN_LINEKEEPER_OPTIONS[] = { { "n-lines", INFINOTED_PARAMETER_INT, INFINOTED_PARAMETER_REQUIRED, offsetof(InfinotedPluginLinekeeper, n_lines), infinoted_parameter_convert_nonnegative, 0, N_("The number of empty lines to keep at the end of the document."), N_("LINES") }, { NULL, 0, 0, 0, NULL } }; const InfinotedPlugin INFINOTED_PLUGIN = { "linekeeper", N_("This plugin makes sure that at the end of every document there is " "always a fixed number of empty lines."), INFINOTED_PLUGIN_LINEKEEPER_OPTIONS, sizeof(InfinotedPluginLinekeeper), 0, sizeof(InfinotedPluginLinekeeperSessionInfo), "InfTextSession", NULL, infinoted_plugin_linekeeper_initialize, infinoted_plugin_linekeeper_deinitialize, NULL, NULL, infinoted_plugin_linekeeper_session_added, infinoted_plugin_linekeeper_session_removed }; /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/infinoted/plugins/PaxHeaders.26529/Makefile.in0000644000000000000000000000013213051241007021301 xustar0030 mtime=1487225351.933149146 30 atime=1487225351.933149146 30 ctime=1488261589.520137928 libinfinity-0.7.1/infinoted/plugins/Makefile.in0000644000175000017500000012330213051241007022034 0ustar00arminarmin00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 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__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) 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@ @LIBINFINITY_HAVE_GIO_TRUE@@WIN32_FALSE@am__append_1 = \ @LIBINFINITY_HAVE_GIO_TRUE@@WIN32_FALSE@ libinfinoted-plugin-dbus.la subdir = infinoted/plugins ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/gtk-doc.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/libinfinity/inf-config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(plugindir)" LTLIBRARIES = $(plugin_LTLIBRARIES) am__DEPENDENCIES_1 = libinfinoted_plugin_autosave_la_DEPENDENCIES = ${top_builddir}/infinoted/libinfinoted-plugin-manager-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) am_libinfinoted_plugin_autosave_la_OBJECTS = \ infinoted-plugin-autosave.lo libinfinoted_plugin_autosave_la_OBJECTS = \ $(am_libinfinoted_plugin_autosave_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libinfinoted_plugin_certificate_auth_la_DEPENDENCIES = ${top_builddir}/infinoted/libinfinoted-plugin-manager-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_libinfinoted_plugin_certificate_auth_la_OBJECTS = \ infinoted-plugin-certificate-auth.lo libinfinoted_plugin_certificate_auth_la_OBJECTS = \ $(am_libinfinoted_plugin_certificate_auth_la_OBJECTS) @LIBINFINITY_HAVE_GIO_TRUE@@WIN32_FALSE@libinfinoted_plugin_dbus_la_DEPENDENCIES = ${top_builddir}/infinoted/libinfinoted-plugin-manager-$(LIBINFINITY_API_VERSION).la \ @LIBINFINITY_HAVE_GIO_TRUE@@WIN32_FALSE@ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ @LIBINFINITY_HAVE_GIO_TRUE@@WIN32_FALSE@ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ @LIBINFINITY_HAVE_GIO_TRUE@@WIN32_FALSE@ $(am__DEPENDENCIES_1) \ @LIBINFINITY_HAVE_GIO_TRUE@@WIN32_FALSE@ $(am__DEPENDENCIES_1) \ @LIBINFINITY_HAVE_GIO_TRUE@@WIN32_FALSE@ $(am__DEPENDENCIES_1) \ @LIBINFINITY_HAVE_GIO_TRUE@@WIN32_FALSE@ $(am__DEPENDENCIES_1) am__libinfinoted_plugin_dbus_la_SOURCES_DIST = \ util/infinoted-plugin-util-navigate-browser.h \ util/infinoted-plugin-util-navigate-browser.c \ infinoted-plugin-dbus.c am__dirstamp = $(am__leading_dot)dirstamp @LIBINFINITY_HAVE_GIO_TRUE@@WIN32_FALSE@am_libinfinoted_plugin_dbus_la_OBJECTS = util/infinoted-plugin-util-navigate-browser.lo \ @LIBINFINITY_HAVE_GIO_TRUE@@WIN32_FALSE@ infinoted-plugin-dbus.lo libinfinoted_plugin_dbus_la_OBJECTS = \ $(am_libinfinoted_plugin_dbus_la_OBJECTS) @LIBINFINITY_HAVE_GIO_TRUE@@WIN32_FALSE@am_libinfinoted_plugin_dbus_la_rpath = \ @LIBINFINITY_HAVE_GIO_TRUE@@WIN32_FALSE@ -rpath $(plugindir) libinfinoted_plugin_directory_sync_la_DEPENDENCIES = ${top_builddir}/infinoted/libinfinoted-plugin-manager-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) am_libinfinoted_plugin_directory_sync_la_OBJECTS = \ infinoted-plugin-directory-sync.lo libinfinoted_plugin_directory_sync_la_OBJECTS = \ $(am_libinfinoted_plugin_directory_sync_la_OBJECTS) @WIN32_FALSE@libinfinoted_plugin_document_stream_la_DEPENDENCIES = ${top_builddir}/infinoted/libinfinoted-plugin-manager-$(LIBINFINITY_API_VERSION).la \ @WIN32_FALSE@ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ @WIN32_FALSE@ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ @WIN32_FALSE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ @WIN32_FALSE@ $(am__DEPENDENCIES_1) am__libinfinoted_plugin_document_stream_la_SOURCES_DIST = \ util/infinoted-plugin-util-navigate-browser.h \ util/infinoted-plugin-util-navigate-browser.c \ infinoted-plugin-document-stream.c @WIN32_FALSE@am_libinfinoted_plugin_document_stream_la_OBJECTS = \ @WIN32_FALSE@ util/infinoted-plugin-util-navigate-browser.lo \ @WIN32_FALSE@ infinoted-plugin-document-stream.lo libinfinoted_plugin_document_stream_la_OBJECTS = \ $(am_libinfinoted_plugin_document_stream_la_OBJECTS) @WIN32_FALSE@am_libinfinoted_plugin_document_stream_la_rpath = -rpath \ @WIN32_FALSE@ $(plugindir) libinfinoted_plugin_linekeeper_la_DEPENDENCIES = ${top_builddir}/infinoted/libinfinoted-plugin-manager-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) am_libinfinoted_plugin_linekeeper_la_OBJECTS = \ infinoted-plugin-linekeeper.lo libinfinoted_plugin_linekeeper_la_OBJECTS = \ $(am_libinfinoted_plugin_linekeeper_la_OBJECTS) libinfinoted_plugin_logging_la_DEPENDENCIES = ${top_builddir}/infinoted/libinfinoted-plugin-manager-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) am_libinfinoted_plugin_logging_la_OBJECTS = \ infinoted-plugin-logging.lo libinfinoted_plugin_logging_la_OBJECTS = \ $(am_libinfinoted_plugin_logging_la_OBJECTS) libinfinoted_plugin_note_chat_la_DEPENDENCIES = ${top_builddir}/infinoted/libinfinoted-plugin-manager-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_libinfinoted_plugin_note_chat_la_OBJECTS = \ infinoted-plugin-note-chat.lo libinfinoted_plugin_note_chat_la_OBJECTS = \ $(am_libinfinoted_plugin_note_chat_la_OBJECTS) libinfinoted_plugin_note_text_la_DEPENDENCIES = ${top_builddir}/infinoted/libinfinoted-plugin-manager-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) am_libinfinoted_plugin_note_text_la_OBJECTS = \ infinoted-plugin-note-text.lo libinfinoted_plugin_note_text_la_OBJECTS = \ $(am_libinfinoted_plugin_note_text_la_OBJECTS) libinfinoted_plugin_record_la_DEPENDENCIES = ${top_builddir}/infinoted/libinfinoted-plugin-manager-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) am_libinfinoted_plugin_record_la_OBJECTS = infinoted-plugin-record.lo libinfinoted_plugin_record_la_OBJECTS = \ $(am_libinfinoted_plugin_record_la_OBJECTS) libinfinoted_plugin_traffic_logging_la_DEPENDENCIES = ${top_builddir}/infinoted/libinfinoted-plugin-manager-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) am_libinfinoted_plugin_traffic_logging_la_OBJECTS = \ infinoted-plugin-traffic-logging.lo libinfinoted_plugin_traffic_logging_la_OBJECTS = \ $(am_libinfinoted_plugin_traffic_logging_la_OBJECTS) libinfinoted_plugin_transformation_protection_la_DEPENDENCIES = ${top_builddir}/infinoted/libinfinoted-plugin-manager-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) am_libinfinoted_plugin_transformation_protection_la_OBJECTS = \ infinoted-plugin-transformation-protection.lo libinfinoted_plugin_transformation_protection_la_OBJECTS = $(am_libinfinoted_plugin_transformation_protection_la_OBJECTS) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) -I$(top_builddir)/libinfinity 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_CC_1 = 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_CCLD_1 = SOURCES = $(libinfinoted_plugin_autosave_la_SOURCES) \ $(libinfinoted_plugin_certificate_auth_la_SOURCES) \ $(libinfinoted_plugin_dbus_la_SOURCES) \ $(libinfinoted_plugin_directory_sync_la_SOURCES) \ $(libinfinoted_plugin_document_stream_la_SOURCES) \ $(libinfinoted_plugin_linekeeper_la_SOURCES) \ $(libinfinoted_plugin_logging_la_SOURCES) \ $(libinfinoted_plugin_note_chat_la_SOURCES) \ $(libinfinoted_plugin_note_text_la_SOURCES) \ $(libinfinoted_plugin_record_la_SOURCES) \ $(libinfinoted_plugin_traffic_logging_la_SOURCES) \ $(libinfinoted_plugin_transformation_protection_la_SOURCES) DIST_SOURCES = $(libinfinoted_plugin_autosave_la_SOURCES) \ $(libinfinoted_plugin_certificate_auth_la_SOURCES) \ $(am__libinfinoted_plugin_dbus_la_SOURCES_DIST) \ $(libinfinoted_plugin_directory_sync_la_SOURCES) \ $(am__libinfinoted_plugin_document_stream_la_SOURCES_DIST) \ $(libinfinoted_plugin_linekeeper_la_SOURCES) \ $(libinfinoted_plugin_logging_la_SOURCES) \ $(libinfinoted_plugin_note_chat_la_SOURCES) \ $(libinfinoted_plugin_note_text_la_SOURCES) \ $(libinfinoted_plugin_record_la_SOURCES) \ $(libinfinoted_plugin_traffic_logging_la_SOURCES) \ $(libinfinoted_plugin_transformation_protection_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ 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@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIRNAME = @DATADIRNAME@ 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@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ GTKDOC_CHECK = @GTKDOC_CHECK@ GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ GTKDOC_MKPDF = @GTKDOC_MKPDF@ GTKDOC_REBASE = @GTKDOC_REBASE@ HTML_DIR = @HTML_DIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INSTOBJEXT = @INSTOBJEXT@ INTLLIBS = @INTLLIBS@ INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBINFINITY_API_VERSION = @LIBINFINITY_API_VERSION@ LIBINFINITY_LIBTOOL_VERSION = @LIBINFINITY_LIBTOOL_VERSION@ LIBINFINITY_VERSION = @LIBINFINITY_VERSION@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGFMT_OPTS = @MSGFMT_OPTS@ 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@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ 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@ avahi_CFLAGS = @avahi_CFLAGS@ avahi_LIBS = @avahi_LIBS@ 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@ gio_CFLAGS = @gio_CFLAGS@ gio_LIBS = @gio_LIBS@ gtk_requirement = @gtk_requirement@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infgtk_CFLAGS = @infgtk_CFLAGS@ infgtk_LIBS = @infgtk_LIBS@ infinity_CFLAGS = @infinity_CFLAGS@ infinity_LIBS = @infinity_LIBS@ infinoted_CFLAGS = @infinoted_CFLAGS@ infinoted_LIBS = @infinoted_LIBS@ infodir = @infodir@ inftext_CFLAGS = @inftext_CFLAGS@ inftext_LIBS = @inftext_LIBS@ inftextgtk_CFLAGS = @inftextgtk_CFLAGS@ inftextgtk_LIBS = @inftextgtk_LIBS@ install_sh = @install_sh@ libdaemon_CFLAGS = @libdaemon_CFLAGS@ libdaemon_LIBS = @libdaemon_LIBS@ 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@ runstatedir = @runstatedir@ 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@ @WIN32_FALSE@nonwin_plugins = libinfinoted-plugin-document-stream.la \ @WIN32_FALSE@ $(am__append_1) plugin_LTLIBRARIES = \ libinfinoted-plugin-autosave.la \ libinfinoted-plugin-certificate-auth.la \ libinfinoted-plugin-directory-sync.la \ libinfinoted-plugin-linekeeper.la \ libinfinoted-plugin-logging.la \ libinfinoted-plugin-note-chat.la \ libinfinoted-plugin-note-text.la \ libinfinoted-plugin-record.la \ libinfinoted-plugin-traffic-logging.la \ libinfinoted-plugin-transformation-protection.la \ $(nonwin_plugins) plugindir = ${libdir}/infinoted-$(LIBINFINITY_API_VERSION)/plugins AM_CPPFLAGS = \ -I$(top_srcdir) \ $(infinoted_CFLAGS) \ $(inftext_CFLAGS) \ $(infinity_CFLAGS) \ $(gio_CFLAGS) AM_LDFLAGS = \ -avoid-version -module -no-undefined libinfinoted_plugin_autosave_la_LIBADD = \ ${top_builddir}/infinoted/libinfinoted-plugin-manager-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(infinoted_LIBS) \ $(inftext_LIBS) \ $(infinity_LIBS) libinfinoted_plugin_certificate_auth_la_LIBADD = \ ${top_builddir}/infinoted/libinfinoted-plugin-manager-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(infinoted_LIBS) \ $(infinity_LIBS) libinfinoted_plugin_directory_sync_la_LIBADD = \ ${top_builddir}/infinoted/libinfinoted-plugin-manager-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(infinoted_LIBS) \ $(inftext_LIBS) \ $(infinity_LIBS) libinfinoted_plugin_linekeeper_la_LIBADD = \ ${top_builddir}/infinoted/libinfinoted-plugin-manager-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(infinoted_LIBS) \ $(inftext_LIBS) \ $(infinity_LIBS) libinfinoted_plugin_logging_la_LIBADD = \ ${top_builddir}/infinoted/libinfinoted-plugin-manager-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(infinoted_LIBS) \ $(inftext_LIBS) \ $(infinity_LIBS) libinfinoted_plugin_note_chat_la_LIBADD = \ ${top_builddir}/infinoted/libinfinoted-plugin-manager-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(infinoted_LIBS) \ $(infinity_LIBS) libinfinoted_plugin_note_text_la_LIBADD = \ ${top_builddir}/infinoted/libinfinoted-plugin-manager-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(infinoted_LIBS) \ $(inftext_LIBS) \ $(infinity_LIBS) libinfinoted_plugin_record_la_LIBADD = \ ${top_builddir}/infinoted/libinfinoted-plugin-manager-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(infinoted_LIBS) \ $(inftext_LIBS) \ $(infinity_LIBS) libinfinoted_plugin_traffic_logging_la_LIBADD = \ ${top_builddir}/infinoted/libinfinoted-plugin-manager-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(infinoted_LIBS) \ $(inftext_LIBS) \ $(infinity_LIBS) libinfinoted_plugin_transformation_protection_la_LIBADD = \ ${top_builddir}/infinoted/libinfinoted-plugin-manager-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(infinoted_LIBS) \ $(inftext_LIBS) \ $(infinity_LIBS) @WIN32_FALSE@libinfinoted_plugin_document_stream_la_LIBADD = \ @WIN32_FALSE@ ${top_builddir}/infinoted/libinfinoted-plugin-manager-$(LIBINFINITY_API_VERSION).la \ @WIN32_FALSE@ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ @WIN32_FALSE@ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ @WIN32_FALSE@ $(infinoted_LIBS) \ @WIN32_FALSE@ $(inftext_LIBS) \ @WIN32_FALSE@ $(infinity_LIBS) @LIBINFINITY_HAVE_GIO_TRUE@@WIN32_FALSE@libinfinoted_plugin_dbus_la_LIBADD = \ @LIBINFINITY_HAVE_GIO_TRUE@@WIN32_FALSE@ ${top_builddir}/infinoted/libinfinoted-plugin-manager-$(LIBINFINITY_API_VERSION).la \ @LIBINFINITY_HAVE_GIO_TRUE@@WIN32_FALSE@ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ @LIBINFINITY_HAVE_GIO_TRUE@@WIN32_FALSE@ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ @LIBINFINITY_HAVE_GIO_TRUE@@WIN32_FALSE@ $(infinoted_LIBS) \ @LIBINFINITY_HAVE_GIO_TRUE@@WIN32_FALSE@ $(inftext_LIBS) \ @LIBINFINITY_HAVE_GIO_TRUE@@WIN32_FALSE@ $(infinity_LIBS) \ @LIBINFINITY_HAVE_GIO_TRUE@@WIN32_FALSE@ $(gio_LIBS) libinfinoted_plugin_autosave_la_SOURCES = \ infinoted-plugin-autosave.c libinfinoted_plugin_certificate_auth_la_SOURCES = \ infinoted-plugin-certificate-auth.c libinfinoted_plugin_directory_sync_la_SOURCES = \ infinoted-plugin-directory-sync.c libinfinoted_plugin_linekeeper_la_SOURCES = \ infinoted-plugin-linekeeper.c libinfinoted_plugin_logging_la_SOURCES = \ infinoted-plugin-logging.c libinfinoted_plugin_note_chat_la_SOURCES = \ infinoted-plugin-note-chat.c libinfinoted_plugin_note_text_la_SOURCES = \ infinoted-plugin-note-text.c libinfinoted_plugin_record_la_SOURCES = \ infinoted-plugin-record.c libinfinoted_plugin_traffic_logging_la_SOURCES = \ infinoted-plugin-traffic-logging.c libinfinoted_plugin_transformation_protection_la_SOURCES = \ infinoted-plugin-transformation-protection.c @WIN32_FALSE@libinfinoted_plugin_document_stream_la_SOURCES = \ @WIN32_FALSE@ util/infinoted-plugin-util-navigate-browser.h \ @WIN32_FALSE@ util/infinoted-plugin-util-navigate-browser.c \ @WIN32_FALSE@ infinoted-plugin-document-stream.c @LIBINFINITY_HAVE_GIO_TRUE@@WIN32_FALSE@libinfinoted_plugin_dbus_la_SOURCES = \ @LIBINFINITY_HAVE_GIO_TRUE@@WIN32_FALSE@ util/infinoted-plugin-util-navigate-browser.h \ @LIBINFINITY_HAVE_GIO_TRUE@@WIN32_FALSE@ util/infinoted-plugin-util-navigate-browser.c \ @LIBINFINITY_HAVE_GIO_TRUE@@WIN32_FALSE@ infinoted-plugin-dbus.c all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(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) --foreign infinoted/plugins/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign infinoted/plugins/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: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(plugindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(plugindir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \ } uninstall-pluginLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \ done clean-pluginLTLIBRARIES: -test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES) @list='$(plugin_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libinfinoted-plugin-autosave.la: $(libinfinoted_plugin_autosave_la_OBJECTS) $(libinfinoted_plugin_autosave_la_DEPENDENCIES) $(EXTRA_libinfinoted_plugin_autosave_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) -rpath $(plugindir) $(libinfinoted_plugin_autosave_la_OBJECTS) $(libinfinoted_plugin_autosave_la_LIBADD) $(LIBS) libinfinoted-plugin-certificate-auth.la: $(libinfinoted_plugin_certificate_auth_la_OBJECTS) $(libinfinoted_plugin_certificate_auth_la_DEPENDENCIES) $(EXTRA_libinfinoted_plugin_certificate_auth_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) -rpath $(plugindir) $(libinfinoted_plugin_certificate_auth_la_OBJECTS) $(libinfinoted_plugin_certificate_auth_la_LIBADD) $(LIBS) util/$(am__dirstamp): @$(MKDIR_P) util @: > util/$(am__dirstamp) util/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) util/$(DEPDIR) @: > util/$(DEPDIR)/$(am__dirstamp) util/infinoted-plugin-util-navigate-browser.lo: util/$(am__dirstamp) \ util/$(DEPDIR)/$(am__dirstamp) libinfinoted-plugin-dbus.la: $(libinfinoted_plugin_dbus_la_OBJECTS) $(libinfinoted_plugin_dbus_la_DEPENDENCIES) $(EXTRA_libinfinoted_plugin_dbus_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(am_libinfinoted_plugin_dbus_la_rpath) $(libinfinoted_plugin_dbus_la_OBJECTS) $(libinfinoted_plugin_dbus_la_LIBADD) $(LIBS) libinfinoted-plugin-directory-sync.la: $(libinfinoted_plugin_directory_sync_la_OBJECTS) $(libinfinoted_plugin_directory_sync_la_DEPENDENCIES) $(EXTRA_libinfinoted_plugin_directory_sync_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) -rpath $(plugindir) $(libinfinoted_plugin_directory_sync_la_OBJECTS) $(libinfinoted_plugin_directory_sync_la_LIBADD) $(LIBS) libinfinoted-plugin-document-stream.la: $(libinfinoted_plugin_document_stream_la_OBJECTS) $(libinfinoted_plugin_document_stream_la_DEPENDENCIES) $(EXTRA_libinfinoted_plugin_document_stream_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) $(am_libinfinoted_plugin_document_stream_la_rpath) $(libinfinoted_plugin_document_stream_la_OBJECTS) $(libinfinoted_plugin_document_stream_la_LIBADD) $(LIBS) libinfinoted-plugin-linekeeper.la: $(libinfinoted_plugin_linekeeper_la_OBJECTS) $(libinfinoted_plugin_linekeeper_la_DEPENDENCIES) $(EXTRA_libinfinoted_plugin_linekeeper_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) -rpath $(plugindir) $(libinfinoted_plugin_linekeeper_la_OBJECTS) $(libinfinoted_plugin_linekeeper_la_LIBADD) $(LIBS) libinfinoted-plugin-logging.la: $(libinfinoted_plugin_logging_la_OBJECTS) $(libinfinoted_plugin_logging_la_DEPENDENCIES) $(EXTRA_libinfinoted_plugin_logging_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) -rpath $(plugindir) $(libinfinoted_plugin_logging_la_OBJECTS) $(libinfinoted_plugin_logging_la_LIBADD) $(LIBS) libinfinoted-plugin-note-chat.la: $(libinfinoted_plugin_note_chat_la_OBJECTS) $(libinfinoted_plugin_note_chat_la_DEPENDENCIES) $(EXTRA_libinfinoted_plugin_note_chat_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) -rpath $(plugindir) $(libinfinoted_plugin_note_chat_la_OBJECTS) $(libinfinoted_plugin_note_chat_la_LIBADD) $(LIBS) libinfinoted-plugin-note-text.la: $(libinfinoted_plugin_note_text_la_OBJECTS) $(libinfinoted_plugin_note_text_la_DEPENDENCIES) $(EXTRA_libinfinoted_plugin_note_text_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) -rpath $(plugindir) $(libinfinoted_plugin_note_text_la_OBJECTS) $(libinfinoted_plugin_note_text_la_LIBADD) $(LIBS) libinfinoted-plugin-record.la: $(libinfinoted_plugin_record_la_OBJECTS) $(libinfinoted_plugin_record_la_DEPENDENCIES) $(EXTRA_libinfinoted_plugin_record_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) -rpath $(plugindir) $(libinfinoted_plugin_record_la_OBJECTS) $(libinfinoted_plugin_record_la_LIBADD) $(LIBS) libinfinoted-plugin-traffic-logging.la: $(libinfinoted_plugin_traffic_logging_la_OBJECTS) $(libinfinoted_plugin_traffic_logging_la_DEPENDENCIES) $(EXTRA_libinfinoted_plugin_traffic_logging_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) -rpath $(plugindir) $(libinfinoted_plugin_traffic_logging_la_OBJECTS) $(libinfinoted_plugin_traffic_logging_la_LIBADD) $(LIBS) libinfinoted-plugin-transformation-protection.la: $(libinfinoted_plugin_transformation_protection_la_OBJECTS) $(libinfinoted_plugin_transformation_protection_la_DEPENDENCIES) $(EXTRA_libinfinoted_plugin_transformation_protection_la_DEPENDENCIES) $(AM_V_CCLD)$(LINK) -rpath $(plugindir) $(libinfinoted_plugin_transformation_protection_la_OBJECTS) $(libinfinoted_plugin_transformation_protection_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) -rm -f util/*.$(OBJEXT) -rm -f util/*.lo distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/infinoted-plugin-autosave.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/infinoted-plugin-certificate-auth.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/infinoted-plugin-dbus.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/infinoted-plugin-directory-sync.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/infinoted-plugin-document-stream.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/infinoted-plugin-linekeeper.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/infinoted-plugin-logging.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/infinoted-plugin-note-chat.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/infinoted-plugin-note-text.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/infinoted-plugin-record.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/infinoted-plugin-traffic-logging.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/infinoted-plugin-transformation-protection.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@util/$(DEPDIR)/infinoted-plugin-util-navigate-browser.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.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 -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.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 -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.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 $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs -rm -rf util/.libs util/_libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ 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-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ 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" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files 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: check-am all-am: Makefile $(LTLIBRARIES) installdirs: for dir in "$(DESTDIR)$(plugindir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: 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: 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) -rm -f util/$(DEPDIR)/$(am__dirstamp) -rm -f util/$(am__dirstamp) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-pluginLTLIBRARIES \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) util/$(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-pluginLTLIBRARIES install-dvi: install-dvi-am install-dvi-am: install-exec-am: 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) util/$(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-pluginLTLIBRARIES .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool clean-pluginLTLIBRARIES cscopelist-am ctags \ ctags-am 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-pluginLTLIBRARIES 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 tags-am uninstall uninstall-am \ uninstall-pluginLTLIBRARIES .PRECIOUS: Makefile # 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: libinfinity-0.7.1/infinoted/plugins/PaxHeaders.26529/infinoted-plugin-document-stream.c0000644000000000000000000000013213034342512025764 xustar0030 mtime=1483851082.017718362 30 atime=1483851082.017718362 30 ctime=1488261589.532137902 libinfinity-0.7.1/infinoted/plugins/infinoted-plugin-document-stream.c0000644000175000017500000011167313034342512026527 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include "util/infinoted-plugin-util-navigate-browser.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "config.h" typedef enum _InfinotedPluginDocumentStreamStatus { INFINOTED_PLUGIN_DOCUMENT_STREAM_NORMAL, INFINOTED_PLUGIN_DOCUMENT_STREAM_RECEIVING, INFINOTED_PLUGIN_DOCUMENT_STREAM_CLOSED } InfinotedPluginDocumentStreamStatus; typedef struct _InfinotedPluginDocumentStream InfinotedPluginDocumentStream; struct _InfinotedPluginDocumentStream { InfinotedPluginManager* manager; InfNativeSocket socket; InfIoWatch* watch; GSList* streams; }; typedef struct _InfinotedPluginDocumentStreamQueue InfinotedPluginDocumentStreamQueue; struct _InfinotedPluginDocumentStreamQueue { gchar* data; gsize pos; gsize len; gsize alloc; }; typedef struct _InfinotedPluginDocumentStreamStream InfinotedPluginDocumentStreamStream; struct _InfinotedPluginDocumentStreamStream { InfinotedPluginDocumentStream* plugin; InfNativeSocket socket; InfIoWatch* watch; InfinotedPluginDocumentStreamStatus status; InfinotedPluginDocumentStreamQueue send_queue; InfinotedPluginDocumentStreamQueue recv_queue; gchar* username; /* set if either subscribe_request or proxy are set */ InfBrowserIter iter; InfinotedPluginUtilNavigateData* navigate_handle; InfRequest* subscribe_request; InfRequest* user_request; InfSessionProxy* proxy; InfUser* user; InfBuffer* buffer; }; static void infinoted_plugin_document_stream_queue_initialize( InfinotedPluginDocumentStreamQueue* queue) { queue->data = NULL; queue->pos = 0; queue->len = 0; queue->alloc = 0; } static void infinoted_plugin_document_stream_queue_finalize( InfinotedPluginDocumentStreamQueue* queue) { g_free(queue->data); } static void infinoted_plugin_document_stream_queue_reserve( InfinotedPluginDocumentStreamQueue* queue, gsize len) { if(queue->pos + queue->len + len > queue->alloc) { /* Need to make new space in the queue */ if(queue->pos != 0) { /* First, try by moving contents to front */ g_assert(queue->len > 0); g_memmove( queue->data, queue->data + queue->pos, queue->len ); queue->pos = 0; } if(queue->len + len > queue->alloc) { queue->alloc = queue->len + len; queue->data = g_realloc(queue->data, queue->alloc); } } } static void infinoted_plugin_document_stream_queue_append( InfinotedPluginDocumentStreamQueue* queue, const gchar* data, gsize len) { infinoted_plugin_document_stream_queue_reserve(queue, len); g_assert(queue->len + len <= queue->alloc); memcpy(queue->data + queue->pos + queue->len, data, len); queue->len += len; } static void infinoted_plugin_document_stream_queue_consume( InfinotedPluginDocumentStreamQueue* queue, gsize len) { g_assert(len <= queue->len); queue->pos += len; queue->len -= len; if(queue->len == 0) queue->pos = 0; } static void infinoted_plugin_document_stream_make_system_error(int code, GError** error) { g_set_error_literal( error, g_quark_from_static_string( "INFINOTED_PLUGIN_DOCUMENT_STREAM_SYSTEM_ERROR" ), code, strerror(code) ); } static void infinoted_plugin_document_stream_subscribe_func(InfRequest* request, const InfRequestResult* res, const GError* error, gpointer user_data); static void infinoted_plugin_document_stream_user_join_func(InfRequest* request, const InfRequestResult* res, const GError* error, gpointer user_data); static void infinoted_plugin_document_stream_close_stream( InfinotedPluginDocumentStreamStream* stream); static gboolean infinoted_plugin_document_stream_send( InfinotedPluginDocumentStreamStream* stream, const void* data, gsize len); static void infinoted_plugin_document_stream_send_error( InfinotedPluginDocumentStreamStream* stream, const gchar* message) { guint32 errcom; guint16 errlen; errcom = 0; errlen = strlen(message); if(!infinoted_plugin_document_stream_send(stream, &errcom, 4)) return; if(!infinoted_plugin_document_stream_send(stream, &errlen, 2)) return; if(!infinoted_plugin_document_stream_send(stream, message, errlen)) return; } static void infinoted_plugin_document_stream_text_inserted_cb(InfTextBuffer* buffer, guint pos, InfTextChunk* chunk, InfUser* user, gpointer user_data) { InfinotedPluginDocumentStreamStream* stream; guint32 comm; guint32 pos32; gsize bytes; guint32 bytes32; gpointer text; gboolean alive; stream = (InfinotedPluginDocumentStreamStream*)user_data; text = inf_text_chunk_get_text(chunk, &bytes); comm = 3; /* INSERT */ pos32 = (guint32)pos; bytes32 = (guint32)bytes; alive = infinoted_plugin_document_stream_send(stream, &comm, 4); if(alive) alive = infinoted_plugin_document_stream_send(stream, &pos32, 4); if(alive) alive = infinoted_plugin_document_stream_send(stream, &bytes32, 4); if(alive) alive = infinoted_plugin_document_stream_send(stream, text, bytes); g_free(text); } static void infinoted_plugin_document_stream_text_erased_cb(InfTextBuffer* buffer, guint pos, InfTextChunk* chunk, InfUser* user, gpointer user_data) { InfinotedPluginDocumentStreamStream* stream; guint32 comm; guint32 pos32; guint32 len32; gboolean alive; stream = (InfinotedPluginDocumentStreamStream*)user_data; comm = 4; /* ERASE */ pos32 = (guint32)pos; len32 = inf_text_chunk_get_length(chunk); alive = infinoted_plugin_document_stream_send(stream, &comm, 4); if(alive) alive = infinoted_plugin_document_stream_send(stream, &pos32, 4); if(alive) alive = infinoted_plugin_document_stream_send(stream, &len32, 4); } static void infinoted_plugin_document_stream_chat_send_message( InfinotedPluginDocumentStreamStream* stream, const InfChatBufferMessage* ms) { guint32 comm; guint64 timestamp; guint16 type; guint16 namelen; guint16 textlen; gboolean alive; comm = 6; /* CHAT */ timestamp = (guint64)ms->time; type = (guint16)ms->type; namelen = strlen(inf_user_get_name(ms->user)); textlen = ms->length; alive = infinoted_plugin_document_stream_send(stream, &comm, 4); if(alive) alive = infinoted_plugin_document_stream_send(stream, ×tamp, 8); if(alive) alive = infinoted_plugin_document_stream_send(stream, &type, 2); if(alive) alive = infinoted_plugin_document_stream_send(stream, &namelen, 2); if(alive) alive = infinoted_plugin_document_stream_send(stream, inf_user_get_name(ms->user), namelen); if(alive) alive = infinoted_plugin_document_stream_send(stream, &textlen, 2); if(alive && textlen > 0) alive = infinoted_plugin_document_stream_send(stream, ms->text, textlen); } static void infinoted_plugin_document_stream_chat_add_message_cb(InfChatBuffer* buffer, InfChatBufferMessage* ms, gpointer user_data) { InfinotedPluginDocumentStreamStream* stream; stream = (InfinotedPluginDocumentStreamStream*)user_data; infinoted_plugin_document_stream_chat_send_message(stream, ms); } static void infinoted_plugin_document_stream_chat_add_message( InfinotedPluginDocumentStreamStream* stream, const gchar* message, gsize len) { g_assert(stream->user != NULL); inf_signal_handlers_block_by_func( G_OBJECT(stream->buffer), G_CALLBACK(infinoted_plugin_document_stream_chat_add_message_cb), stream ); inf_chat_buffer_add_message( INF_CHAT_BUFFER(stream->buffer), stream->user, message, len, time(NULL), 0 ); inf_signal_handlers_unblock_by_func( G_OBJECT(stream->buffer), G_CALLBACK(infinoted_plugin_document_stream_chat_add_message_cb), stream ); } static void infinoted_plugin_document_stream_sync_chat( InfinotedPluginDocumentStreamStream* stream) { InfChatBuffer* buffer; guint n_messages; guint i; const InfChatBufferMessage* message; g_assert(INF_IS_CHAT_BUFFER(stream->buffer)); buffer = INF_CHAT_BUFFER(stream->buffer); n_messages = inf_chat_buffer_get_n_messages(buffer); for(i = 0; i < n_messages; ++i) { message = inf_chat_buffer_get_message(buffer, i); infinoted_plugin_document_stream_chat_send_message(stream, message); } } static void infinoted_plugin_document_stream_sync_text( InfinotedPluginDocumentStreamStream* stream) { InfTextBuffer* buffer; InfTextBufferIter* iter; gpointer text; guint32 comm; guint32 len; gboolean alive; buffer = INF_TEXT_BUFFER(stream->buffer); iter = inf_text_buffer_create_begin_iter(buffer); alive = TRUE; if(iter != NULL) { do { comm = 1; /* SYNC */ len = inf_text_buffer_iter_get_bytes(buffer, iter); alive = infinoted_plugin_document_stream_send(stream, &comm, 4); if(!alive) break; alive = infinoted_plugin_document_stream_send(stream, &len, 4); if(!alive) break; text = inf_text_buffer_iter_get_text(buffer, iter); alive = infinoted_plugin_document_stream_send(stream, text, len); g_free(text); if(!alive) break; } while(inf_text_buffer_iter_next(buffer, iter)); inf_text_buffer_destroy_iter(buffer, iter); } if(alive) { comm = 2; /* SYNC DONE */ alive = infinoted_plugin_document_stream_send(stream, &comm, 4); } } static void infinoted_plugin_document_stream_start( InfinotedPluginDocumentStreamStream* stream) { InfSession* session; InfBuffer* buffer; g_object_get(G_OBJECT(stream->proxy), "session", &session, NULL); buffer = inf_session_get_buffer(session); stream->buffer = buffer; g_object_ref(buffer); if(INF_TEXT_IS_SESSION(session)) { infinoted_plugin_document_stream_sync_text(stream); g_signal_connect( G_OBJECT(buffer), "text-inserted", G_CALLBACK(infinoted_plugin_document_stream_text_inserted_cb), stream ); g_signal_connect( G_OBJECT(buffer), "text-erased", G_CALLBACK(infinoted_plugin_document_stream_text_erased_cb), stream ); } else if(INF_IS_CHAT_SESSION(session)) { infinoted_plugin_document_stream_sync_chat(stream); g_signal_connect_after( G_OBJECT(buffer), "add-message", G_CALLBACK(infinoted_plugin_document_stream_chat_add_message_cb), stream ); } g_object_unref(session); } static void infinoted_plugin_document_stream_stop( InfinotedPluginDocumentStreamStream* stream, gboolean send_stop) { guint32 comm; InfSession* session; if(send_stop) { comm = 5; /* STOP */ if(!infinoted_plugin_document_stream_send(stream, &comm, 4)) return; } if(stream->user != NULL) { g_assert(stream->proxy != NULL); g_object_get(G_OBJECT(stream->proxy), "session", &session, NULL); inf_session_set_user_status(session, stream->user, INF_USER_UNAVAILABLE); g_object_unref(session); g_object_unref(stream->user); stream->user = NULL; } if(stream->proxy != NULL) { g_object_unref(stream->proxy); stream->proxy = NULL; } if(stream->buffer != NULL) { if(INF_TEXT_IS_BUFFER(stream->buffer)) { inf_signal_handlers_disconnect_by_func( G_OBJECT(stream->buffer), G_CALLBACK(infinoted_plugin_document_stream_text_inserted_cb), stream ); inf_signal_handlers_disconnect_by_func( G_OBJECT(stream->buffer), G_CALLBACK(infinoted_plugin_document_stream_text_erased_cb), stream ); } else if(INF_IS_CHAT_BUFFER(stream->buffer)) { inf_signal_handlers_disconnect_by_func( G_OBJECT(stream->buffer), G_CALLBACK(infinoted_plugin_document_stream_chat_add_message_cb), stream ); } g_object_unref(stream->buffer); stream->buffer = NULL; } if(stream->subscribe_request != NULL) { inf_signal_handlers_disconnect_by_func( G_OBJECT(stream->subscribe_request), G_CALLBACK(infinoted_plugin_document_stream_subscribe_func), stream ); stream->subscribe_request = NULL; } if(stream->user_request != NULL) { inf_signal_handlers_disconnect_by_func( G_OBJECT(stream->user_request), G_CALLBACK(infinoted_plugin_document_stream_user_join_func), stream ); stream->user_request = NULL; } } static void infinoted_plugin_document_stream_user_join_func(InfRequest* request, const InfRequestResult* res, const GError* error, gpointer user_data) { InfinotedPluginDocumentStreamStream* stream; InfUser* user; stream = (InfinotedPluginDocumentStreamStream*)user_data; stream->user_request = NULL; if(error != NULL) { infinoted_plugin_document_stream_send_error(stream, error->message); } else { inf_request_result_get_join_user(res, NULL, &user); g_assert(stream->user == NULL); stream->user = user; g_object_ref(stream->user); infinoted_plugin_document_stream_start(stream); } } static void infinoted_plugin_document_stream_subscribe_done( InfinotedPluginDocumentStreamStream* stream, InfSessionProxy* proxy) { InfSession* session; GParameter params[2] = { { "name", { 0 } }, { "status", { 0 } } }; g_assert(stream->proxy == NULL); stream->proxy = proxy; g_object_ref(proxy); g_object_get(G_OBJECT(proxy), "session", &session, NULL); /* User join via document stream only works for chat sessions * at the moment. */ if(stream->username == NULL || *stream->username == '\0' || INF_TEXT_IS_SESSION(session)) { infinoted_plugin_document_stream_start(stream); } else if(INF_IS_CHAT_SESSION(session)) { g_value_init(¶ms[0].value, G_TYPE_STRING); g_value_set_static_string(¶ms[0].value, stream->username); g_value_init(¶ms[1].value, INF_TYPE_USER_STATUS); g_value_set_enum(¶ms[1].value, INF_USER_ACTIVE); /* Join a user */ stream->user_request = inf_session_proxy_join_user( INF_SESSION_PROXY(proxy), 2, params, infinoted_plugin_document_stream_user_join_func, stream ); } else { g_assert_not_reached(); } g_object_unref(session); } static void infinoted_plugin_document_stream_subscribe_func(InfRequest* request, const InfRequestResult* res, const GError* error, gpointer user_data) { InfinotedPluginDocumentStreamStream* stream; InfSessionProxy* proxy; stream = (InfinotedPluginDocumentStreamStream*)user_data; stream->subscribe_request = NULL; if(error != NULL) { infinoted_plugin_document_stream_send_error(stream, error->message); } else { inf_request_result_get_subscribe_session(res, NULL, NULL, &proxy); infinoted_plugin_document_stream_subscribe_done(stream, proxy); } } static void infinoted_plugin_document_stream_navigate_func(InfBrowser* browser, const InfBrowserIter* iter, const GError* error, gpointer user_data) { InfinotedPluginDocumentStreamStream* stream; InfSessionProxy* proxy; InfRequest* request; stream = (InfinotedPluginDocumentStreamStream*)user_data; stream->navigate_handle = NULL; if(error != NULL) { infinoted_plugin_document_stream_send_error(stream, error->message); } else { if(inf_browser_is_subdirectory(browser, iter) || (strcmp(inf_browser_get_node_type(browser, iter), "InfText") != 0 && strcmp(inf_browser_get_node_type(browser, iter), "InfChat") != 0)) { infinoted_plugin_document_stream_send_error( stream, _("Not a text or chat node") ); } else { stream->iter = *iter; proxy = inf_browser_get_session(browser, iter); if(proxy != NULL) { infinoted_plugin_document_stream_subscribe_done(stream, proxy); } else { request = inf_browser_get_pending_request( browser, iter, "subscribe-session" ); if(request != NULL) { g_signal_connect( G_OBJECT(browser), "finished", G_CALLBACK(infinoted_plugin_document_stream_subscribe_func), stream ); } else { request = inf_browser_subscribe( browser, iter, infinoted_plugin_document_stream_subscribe_func, stream ); } stream->subscribe_request = request; } } } } static gboolean infinoted_plugin_document_stream_process_send_chat_message( InfinotedPluginDocumentStreamStream* stream, const gchar** data, gsize* len) { guint16 text_len; const gchar* text; if(*len < 2) return FALSE; text_len = *(guint16*)(*data); *data += 2; *len -= 2; if(*len < text_len) return FALSE; text = *data; *data += text_len; *len -= text_len; if(!INF_IS_CHAT_BUFFER(stream->buffer)) { infinoted_plugin_document_stream_send_error( stream, "Not a chat session" ); } else { infinoted_plugin_document_stream_chat_add_message(stream, text, text_len); } return TRUE; } static gboolean infinoted_plugin_document_stream_process_get_document( InfinotedPluginDocumentStreamStream* stream, const gchar** data, gsize* len) { guint16 user_len; const gchar* user_name; guint16 doc_len; const gchar* doc_name; /* get size of user name string */ if(*len < 2) return FALSE; user_len = *(guint16*)(*data); *data += 2; *len -= 2; /* get user name string */ if(*len < user_len) return FALSE; user_name = *data; *data += user_len; *len -= user_len; /* get size of document string */ if(*len < 2) return FALSE; doc_len = *(guint16*)(*data); *data += 2; *len -= 2; /* get document string */ if(*len < doc_len) return FALSE; doc_name = *data; *data += doc_len; *len -= doc_len; /* quit connection if we already have a buffer */ if(stream->buffer != NULL) { infinoted_plugin_document_stream_send_error( stream, "Stream is already open" ); } else { stream->username = g_strndup(user_name, user_len); stream->navigate_handle = infinoted_plugin_util_navigate_to( INF_BROWSER( infinoted_plugin_manager_get_directory(stream->plugin->manager) ), doc_name, doc_len, FALSE, infinoted_plugin_document_stream_navigate_func, stream ); } return TRUE; } static gboolean infinoted_plugin_document_stream_process( InfinotedPluginDocumentStreamStream* stream, const gchar** data, gsize* len) { guint32 command; /* Get message */ if(*len < 4) return FALSE; command = *(guint32*)(*data); *data += 4; *len -= 4; switch(command) { case 0: /* get document */ return infinoted_plugin_document_stream_process_get_document( stream, data, len ); case 1: /* send chat message */ return infinoted_plugin_document_stream_process_send_chat_message( stream, data, len ); default: /* unrecognized command; don't know how to proceed, so disconnect */ infinoted_plugin_document_stream_close_stream(stream); return FALSE; } } static void infinoted_plugin_document_stream_received( InfinotedPluginDocumentStreamStream* stream, gsize new_pos, gsize new_len) { gsize prev_queue_len; const gchar* data; gsize len; g_assert(stream->status == INFINOTED_PLUGIN_DOCUMENT_STREAM_RECEIVING); prev_queue_len = 0; while(stream->status == INFINOTED_PLUGIN_DOCUMENT_STREAM_RECEIVING && stream->recv_queue.len > 0 && (prev_queue_len == 0 || stream->recv_queue.len < prev_queue_len)) { prev_queue_len = stream->recv_queue.len; data = stream->recv_queue.data; len = stream->recv_queue.len; if(infinoted_plugin_document_stream_process(stream, &data, &len)) { if(stream->status == INFINOTED_PLUGIN_DOCUMENT_STREAM_RECEIVING) { infinoted_plugin_document_stream_queue_consume( &stream->recv_queue, stream->recv_queue.len - len ); } } } } static gsize infinoted_plugin_document_stream_send_direct( InfinotedPluginDocumentStreamStream* stream, const gchar* data, gsize len, GError** error) { int errcode; ssize_t bytes; gsize sent; sent = 0; g_assert(stream->status != INFINOTED_PLUGIN_DOCUMENT_STREAM_CLOSED); do { bytes = send( stream->socket, data, len, #ifdef HAVE_MSG_NOSIGNAL MSG_NOSIGNAL #else 0 #endif ); errcode = errno; if(bytes > 0) { g_assert(bytes <= len); sent += bytes; data += bytes; len -= bytes; } } while(len > 0 && (bytes > 0 || (bytes < 0 && errcode == EINTR))); if(bytes == 0) return 0; if(bytes < 0 && errno != EAGAIN) { infinoted_plugin_document_stream_make_system_error(errno, error); return 0; } return sent; } static gboolean infinoted_plugin_document_stream_send( InfinotedPluginDocumentStreamStream* stream, const void* data, gsize len) { GError* error; gsize sent; if(stream->send_queue.len > 0) { infinoted_plugin_document_stream_queue_append( &stream->send_queue, data, len ); return TRUE; } else { error = NULL; sent = infinoted_plugin_document_stream_send_direct( stream, data, len, &error ); if(error != NULL) { infinoted_log_warning( infinoted_plugin_manager_get_log(stream->plugin->manager), "Document stream error: %s", error->message ); g_error_free(error); return FALSE; } else { if(sent < len) { infinoted_plugin_document_stream_queue_append( &stream->send_queue, (const gchar*)data + sent, len - sent ); inf_io_update_watch( infinoted_plugin_manager_get_io(stream->plugin->manager), stream->watch, INF_IO_INCOMING | INF_IO_OUTGOING ); } return TRUE; } } } static gboolean infinoted_plugin_document_stream_io_in( InfinotedPluginDocumentStreamStream* stream, GError** error) { int errcode; ssize_t bytes; gsize queue_offset; g_assert(stream->status == INFINOTED_PLUGIN_DOCUMENT_STREAM_NORMAL); stream->status = INFINOTED_PLUGIN_DOCUMENT_STREAM_RECEIVING; do { infinoted_plugin_document_stream_queue_reserve(&stream->recv_queue, 4096); queue_offset = stream->recv_queue.pos + stream->recv_queue.len; bytes = recv( stream->socket, stream->recv_queue.data + queue_offset, stream->recv_queue.alloc - queue_offset, #ifdef HAVE_MSG_NOSIGNAL MSG_NOSIGNAL #else 0 #endif ); errcode = errno; if(bytes > 0) { queue_offset = stream->recv_queue.len; stream->recv_queue.len += bytes; infinoted_plugin_document_stream_received( stream, queue_offset, stream->recv_queue.len - queue_offset ); } } while( (bytes < 0 && errcode == EINTR) || (bytes > 0 && stream->status == INFINOTED_PLUGIN_DOCUMENT_STREAM_RECEIVING)); switch(stream->status) { case INFINOTED_PLUGIN_DOCUMENT_STREAM_NORMAL: g_assert_not_reached(); return FALSE; case INFINOTED_PLUGIN_DOCUMENT_STREAM_RECEIVING: stream->status = INFINOTED_PLUGIN_DOCUMENT_STREAM_NORMAL; if(bytes < 0 && errcode != EAGAIN) { infinoted_plugin_document_stream_make_system_error(errno, error); infinoted_plugin_document_stream_close_stream(stream); return FALSE; } if(bytes == 0) infinoted_plugin_document_stream_close_stream(stream); return TRUE; case INFINOTED_PLUGIN_DOCUMENT_STREAM_CLOSED: /* The stream was closed during the received callback. */ g_slice_free(InfinotedPluginDocumentStreamStream, stream); return TRUE; default: g_assert_not_reached(); return FALSE; } } static gboolean infinoted_plugin_document_stream_io_out( InfinotedPluginDocumentStreamStream* stream, GError** error) { GError* local_error; gsize sent; g_assert(stream->status == INFINOTED_PLUGIN_DOCUMENT_STREAM_NORMAL); g_assert(stream->send_queue.len > 0); local_error = NULL; sent = infinoted_plugin_document_stream_send_direct( stream, stream->send_queue.data + stream->send_queue.pos, stream->send_queue.len, &local_error ); if(local_error != NULL) { g_propagate_error(error, local_error); infinoted_plugin_document_stream_close_stream(stream); return FALSE; } else if(sent == 0) { infinoted_plugin_document_stream_close_stream(stream); return TRUE; } else { infinoted_plugin_document_stream_queue_consume(&stream->send_queue, sent); if(stream->send_queue.len == 0) { inf_io_update_watch( infinoted_plugin_manager_get_io(stream->plugin->manager), stream->watch, INF_IO_INCOMING ); } return TRUE; } } static void infinoted_plugin_document_stream_io_func(InfNativeSocket* socket, InfIoEvent event, gpointer user_data) { InfinotedPluginDocumentStreamStream* stream; InfinotedPluginManager* manager; int val; int errval; socklen_t len; GError* error; stream = (InfinotedPluginDocumentStreamStream*)user_data; manager = stream->plugin->manager; if(event & INF_IO_ERROR) { len = sizeof(errval); val = getsockopt(*socket, SOL_SOCKET, SO_ERROR, &errval, &len); if(val == -1) { infinoted_log_warning( infinoted_plugin_manager_get_log(manager), "Failed to obtain error from socket: %s", strerror(errno) ); } else { if(errval == 0) { /* Connection closed */ infinoted_plugin_document_stream_close_stream(stream); } else { infinoted_log_warning( infinoted_plugin_manager_get_log(manager), "Document stream error: %s", strerror(errval) ); } } } else if(event & INF_IO_INCOMING) { error = NULL; if(!infinoted_plugin_document_stream_io_in(stream, &error)) { infinoted_log_warning( infinoted_plugin_manager_get_log(manager), "Document stream error: %s", error->message ); g_error_free(error); } } else if(event & INF_IO_OUTGOING) { error = NULL; if(!infinoted_plugin_document_stream_io_out(stream, &error)) { infinoted_log_warning( infinoted_plugin_manager_get_log(manager), "Document stream error: %s", error->message ); g_error_free(error); } } } static void infinoted_plugin_document_stream_add_stream( InfinotedPluginDocumentStream* plugin, InfNativeSocket new_socket) { InfinotedPluginDocumentStreamStream* stream; stream = g_slice_new(InfinotedPluginDocumentStreamStream); stream->plugin = plugin; stream->socket = new_socket; stream->watch = inf_io_add_watch( infinoted_plugin_manager_get_io(plugin->manager), &stream->socket, INF_IO_INCOMING, infinoted_plugin_document_stream_io_func, stream, NULL ); stream->username = NULL; stream->status = INFINOTED_PLUGIN_DOCUMENT_STREAM_NORMAL; infinoted_plugin_document_stream_queue_initialize(&stream->send_queue); infinoted_plugin_document_stream_queue_initialize(&stream->recv_queue); stream->navigate_handle = NULL; stream->subscribe_request = NULL; stream->user_request = NULL; stream->proxy = NULL; stream->user = NULL; stream->buffer = NULL; plugin->streams = g_slist_prepend(plugin->streams, stream); } static void infinoted_plugin_document_stream_close_stream( InfinotedPluginDocumentStreamStream* stream) { stream->plugin->streams = g_slist_remove(stream->plugin->streams, stream); if(stream->proxy != NULL || stream->subscribe_request != NULL) infinoted_plugin_document_stream_stop(stream, FALSE); if(stream->navigate_handle != NULL) { infinoted_plugin_util_navigate_cancel(stream->navigate_handle); stream->navigate_handle = NULL; } infinoted_plugin_document_stream_queue_finalize(&stream->send_queue); infinoted_plugin_document_stream_queue_finalize(&stream->recv_queue); inf_io_remove_watch( infinoted_plugin_manager_get_io(stream->plugin->manager), stream->watch ); g_free(stream->username); stream->username = NULL; close(stream->socket); stream->socket = -1; if(stream->status == INFINOTED_PLUGIN_DOCUMENT_STREAM_NORMAL) g_slice_free(InfinotedPluginDocumentStreamStream, stream); else if(stream->status == INFINOTED_PLUGIN_DOCUMENT_STREAM_RECEIVING) stream->status = INFINOTED_PLUGIN_DOCUMENT_STREAM_CLOSED; } static gboolean infinoted_plugin_document_stream_set_nonblock(InfNativeSocket socket, GError** error) { int result; result = fcntl(socket, F_GETFL); if(result == -1) { infinoted_plugin_document_stream_make_system_error(errno, error); return FALSE; } if(fcntl(socket, F_SETFL, result | O_NONBLOCK) == -1) { infinoted_plugin_document_stream_make_system_error(errno, error); return FALSE; } return TRUE; } static InfNativeSocket infinoted_plugin_document_stream_accept_socket(InfNativeSocket socket, GError** error) { InfNativeSocket new_socket; new_socket = accept(socket, NULL, NULL); if(new_socket == -1) { infinoted_plugin_document_stream_make_system_error(errno, error); return -1; } if(!infinoted_plugin_document_stream_set_nonblock(new_socket, error)) { close(new_socket); return -1; } return new_socket; } static void infinoted_plugin_manager_socket_accept_func(InfNativeSocket* socket, InfIoEvent event, gpointer user_data) { InfinotedPluginDocumentStream* plugin; int val; int errval; socklen_t len; InfNativeSocket new_socket; GError* error; plugin = (InfinotedPluginDocumentStream*)user_data; if(event & INF_IO_ERROR) { len = sizeof(errval); val = getsockopt(*socket, SOL_SOCKET, SO_ERROR, &errval, &len); if(val == -1) { infinoted_log_warning( infinoted_plugin_manager_get_log(plugin->manager), "Failed to obtain error from socket: %s", strerror(errno) ); } else { infinoted_log_warning( infinoted_plugin_manager_get_log(plugin->manager), "Document streaming server error: %s", strerror(errval) ); } } else if(event & INF_IO_INCOMING) { error = NULL; new_socket = infinoted_plugin_document_stream_accept_socket( *socket, &error ); if(error != NULL) { infinoted_log_warning( infinoted_plugin_manager_get_log(plugin->manager), "Failed to accept new stream: %s", error->message ); g_error_free(error); } else { infinoted_plugin_document_stream_add_stream(plugin, new_socket); } } } static void infinoted_plugin_document_stream_node_removed_cb(InfBrowser* browser, InfBrowserIter* iter, InfRequest* request, gpointer user_data) { InfinotedPluginDocumentStream* plugin; InfinotedPluginDocumentStreamStream* stream; GSList* item; plugin = (InfinotedPluginDocumentStream*)user_data; for(item = plugin->streams; item != NULL; item = item->next) { stream = (InfinotedPluginDocumentStreamStream*)item->data; if(stream->subscribe_request != NULL || stream->proxy != NULL) { if(inf_browser_is_ancestor(browser, iter, &stream->iter)) { infinoted_plugin_document_stream_stop(stream, TRUE); } } } } static void infinoted_plugin_document_stream_info_initialize(gpointer plugin_info) { InfinotedPluginDocumentStream* plugin; plugin = (InfinotedPluginDocumentStream*)plugin_info; plugin->manager = NULL; plugin->socket = -1; plugin->watch = NULL; plugin->streams = NULL; } static gboolean infinoted_plugin_document_stream_initialize(InfinotedPluginManager* manager, gpointer plugin_info, GError** error) { static const char ADDRESS_NAME[] = "org.infinote.infinoted"; struct sockaddr_un addr; InfinotedPluginDocumentStream* plugin; plugin = (InfinotedPluginDocumentStream*)plugin_info; plugin->manager = manager; plugin->socket = socket(AF_UNIX, SOCK_STREAM, 0); if(plugin->socket == -1) { infinoted_plugin_document_stream_make_system_error(errno, error); return FALSE; } /* TODO: Make the address configurable -- note that abstract paths * are a Linux extension. */ addr.sun_family = AF_UNIX; addr.sun_path[0] = '\0'; memcpy(&addr.sun_path[1], ADDRESS_NAME, sizeof(ADDRESS_NAME) - 1); memset( &addr.sun_path[1] + sizeof(ADDRESS_NAME) - 1, '\0', sizeof(addr.sun_path) - 1 - (sizeof(ADDRESS_NAME) - 1) ); if(!infinoted_plugin_document_stream_set_nonblock(plugin->socket, error)) return FALSE; if(bind(plugin->socket, (struct sockaddr*)&addr, sizeof(addr)) == -1) { infinoted_plugin_document_stream_make_system_error(errno, error); return FALSE; } if(listen(plugin->socket, 5) == -1) { infinoted_plugin_document_stream_make_system_error(errno, error); return FALSE; } plugin->watch = inf_io_add_watch( infinoted_plugin_manager_get_io(plugin->manager), &plugin->socket, INF_IO_INCOMING, infinoted_plugin_manager_socket_accept_func, plugin, NULL ); g_signal_connect( G_OBJECT(infinoted_plugin_manager_get_directory(plugin->manager)), "node-removed", G_CALLBACK(infinoted_plugin_document_stream_node_removed_cb), plugin ); return TRUE; } static void infinoted_plugin_document_stream_deinitialize(gpointer plugin_info) { InfinotedPluginDocumentStream* plugin; plugin = (InfinotedPluginDocumentStream*)plugin_info; while(plugin->streams != NULL) { infinoted_plugin_document_stream_close_stream( (InfinotedPluginDocumentStreamStream*)plugin->streams->data ); } inf_signal_handlers_disconnect_by_func( G_OBJECT(infinoted_plugin_manager_get_directory(plugin->manager)), G_CALLBACK(infinoted_plugin_document_stream_node_removed_cb), plugin ); if(plugin->watch != NULL) { inf_io_remove_watch( infinoted_plugin_manager_get_io(plugin->manager), plugin->watch ); } if(plugin->socket != -1) { close(plugin->socket); } } static const InfinotedParameterInfo INFINOTED_PLUGIN_DOCUMENT_STREAM_OPTIONS[] = { { NULL, 0, 0, 0, NULL } }; const InfinotedPlugin INFINOTED_PLUGIN = { "document-stream", N_("Allows streaming of document changes to external programs"), INFINOTED_PLUGIN_DOCUMENT_STREAM_OPTIONS, sizeof(InfinotedPluginDocumentStream), 0, 0, NULL, infinoted_plugin_document_stream_info_initialize, infinoted_plugin_document_stream_initialize, infinoted_plugin_document_stream_deinitialize, NULL, NULL, NULL, NULL }; /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/infinoted/plugins/PaxHeaders.26529/Makefile.am0000644000000000000000000000013213034342512021274 xustar0030 mtime=1483851082.017718362 30 atime=1483851082.017718362 30 ctime=1488261589.516137937 libinfinity-0.7.1/infinoted/plugins/Makefile.am0000644000175000017500000001350713034342512022034 0ustar00arminarmin00000000000000if !WIN32 nonwin_plugins = \ libinfinoted-plugin-document-stream.la if LIBINFINITY_HAVE_GIO nonwin_plugins += \ libinfinoted-plugin-dbus.la endif endif plugin_LTLIBRARIES = \ libinfinoted-plugin-autosave.la \ libinfinoted-plugin-certificate-auth.la \ libinfinoted-plugin-directory-sync.la \ libinfinoted-plugin-linekeeper.la \ libinfinoted-plugin-logging.la \ libinfinoted-plugin-note-chat.la \ libinfinoted-plugin-note-text.la \ libinfinoted-plugin-record.la \ libinfinoted-plugin-traffic-logging.la \ libinfinoted-plugin-transformation-protection.la \ $(nonwin_plugins) plugindir = ${libdir}/infinoted-$(LIBINFINITY_API_VERSION)/plugins AM_CPPFLAGS = \ -I$(top_srcdir) \ $(infinoted_CFLAGS) \ $(inftext_CFLAGS) \ $(infinity_CFLAGS) \ $(gio_CFLAGS) AM_LDFLAGS = \ -avoid-version -module -no-undefined libinfinoted_plugin_autosave_la_LIBADD = \ ${top_builddir}/infinoted/libinfinoted-plugin-manager-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(infinoted_LIBS) \ $(inftext_LIBS) \ $(infinity_LIBS) libinfinoted_plugin_certificate_auth_la_LIBADD = \ ${top_builddir}/infinoted/libinfinoted-plugin-manager-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(infinoted_LIBS) \ $(infinity_LIBS) libinfinoted_plugin_directory_sync_la_LIBADD = \ ${top_builddir}/infinoted/libinfinoted-plugin-manager-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(infinoted_LIBS) \ $(inftext_LIBS) \ $(infinity_LIBS) libinfinoted_plugin_linekeeper_la_LIBADD = \ ${top_builddir}/infinoted/libinfinoted-plugin-manager-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(infinoted_LIBS) \ $(inftext_LIBS) \ $(infinity_LIBS) libinfinoted_plugin_logging_la_LIBADD = \ ${top_builddir}/infinoted/libinfinoted-plugin-manager-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(infinoted_LIBS) \ $(inftext_LIBS) \ $(infinity_LIBS) libinfinoted_plugin_note_chat_la_LIBADD = \ ${top_builddir}/infinoted/libinfinoted-plugin-manager-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(infinoted_LIBS) \ $(infinity_LIBS) libinfinoted_plugin_note_text_la_LIBADD = \ ${top_builddir}/infinoted/libinfinoted-plugin-manager-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(infinoted_LIBS) \ $(inftext_LIBS) \ $(infinity_LIBS) libinfinoted_plugin_record_la_LIBADD = \ ${top_builddir}/infinoted/libinfinoted-plugin-manager-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(infinoted_LIBS) \ $(inftext_LIBS) \ $(infinity_LIBS) libinfinoted_plugin_traffic_logging_la_LIBADD = \ ${top_builddir}/infinoted/libinfinoted-plugin-manager-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(infinoted_LIBS) \ $(inftext_LIBS) \ $(infinity_LIBS) libinfinoted_plugin_transformation_protection_la_LIBADD = \ ${top_builddir}/infinoted/libinfinoted-plugin-manager-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(infinoted_LIBS) \ $(inftext_LIBS) \ $(infinity_LIBS) if !WIN32 libinfinoted_plugin_document_stream_la_LIBADD = \ ${top_builddir}/infinoted/libinfinoted-plugin-manager-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(infinoted_LIBS) \ $(inftext_LIBS) \ $(infinity_LIBS) if LIBINFINITY_HAVE_GIO libinfinoted_plugin_dbus_la_LIBADD = \ ${top_builddir}/infinoted/libinfinoted-plugin-manager-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(infinoted_LIBS) \ $(inftext_LIBS) \ $(infinity_LIBS) \ $(gio_LIBS) endif endif libinfinoted_plugin_autosave_la_SOURCES = \ infinoted-plugin-autosave.c libinfinoted_plugin_certificate_auth_la_SOURCES = \ infinoted-plugin-certificate-auth.c libinfinoted_plugin_directory_sync_la_SOURCES = \ infinoted-plugin-directory-sync.c libinfinoted_plugin_linekeeper_la_SOURCES = \ infinoted-plugin-linekeeper.c libinfinoted_plugin_logging_la_SOURCES = \ infinoted-plugin-logging.c libinfinoted_plugin_note_chat_la_SOURCES = \ infinoted-plugin-note-chat.c libinfinoted_plugin_note_text_la_SOURCES = \ infinoted-plugin-note-text.c libinfinoted_plugin_record_la_SOURCES = \ infinoted-plugin-record.c libinfinoted_plugin_traffic_logging_la_SOURCES = \ infinoted-plugin-traffic-logging.c libinfinoted_plugin_transformation_protection_la_SOURCES = \ infinoted-plugin-transformation-protection.c if !WIN32 libinfinoted_plugin_document_stream_la_SOURCES = \ util/infinoted-plugin-util-navigate-browser.h \ util/infinoted-plugin-util-navigate-browser.c \ infinoted-plugin-document-stream.c if LIBINFINITY_HAVE_GIO libinfinoted_plugin_dbus_la_SOURCES = \ util/infinoted-plugin-util-navigate-browser.h \ util/infinoted-plugin-util-navigate-browser.c \ infinoted-plugin-dbus.c endif endif libinfinity-0.7.1/infinoted/plugins/PaxHeaders.26529/infinoted-plugin-dbus.c0000644000000000000000000000013213034342512023612 xustar0030 mtime=1483851082.017718362 30 atime=1483851082.017718362 30 ctime=1488261589.528137911 libinfinity-0.7.1/infinoted/plugins/infinoted-plugin-dbus.c0000644000175000017500000007722213034342512024356 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include "util/infinoted-plugin-util-navigate-browser.h" #include #include #include #include #include static const gchar infinoted_plugin_dbus_introspection[] = "" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " ""; typedef struct _InfinotedPluginDbus InfinotedPluginDbus; struct _InfinotedPluginDbus { GBusType bus_type; gchar* bus_name; InfinotedPluginManager* manager; GMutex mutex; GThread* thread; GMainContext* context; GMainLoop* loop; guint id; GSList* invocations; /* invocations currently being processed */ }; typedef struct _InfinotedPluginDbusInvocation InfinotedPluginDbusInvocation; struct _InfinotedPluginDbusInvocation { InfinotedPluginDbus* plugin; int ref_count; gchar* method_name; GVariant* parameters; GDBusMethodInvocation* invocation; InfinotedPluginUtilNavigateData* navigate; InfRequest* request; InfRequestFunc request_func; }; static void infinoted_plugin_dbus_invocation_unref(gpointer data) { InfinotedPluginDbusInvocation* invocation; invocation = (InfinotedPluginDbusInvocation*)data; if(g_atomic_int_dec_and_test(&invocation->ref_count) == TRUE) { if(invocation->navigate != NULL) infinoted_plugin_util_navigate_cancel(invocation->navigate); if(invocation->request != NULL) { g_signal_handlers_disconnect_by_func( G_OBJECT(invocation->request), G_CALLBACK(invocation->request_func), invocation ); } g_free(invocation->method_name); g_variant_unref(invocation->parameters); g_object_unref(invocation->invocation); g_slice_free(InfinotedPluginDbusInvocation, invocation); } } static void infinoted_plugin_dbus_invocation_free(InfinotedPluginDbus* plugin, InfinotedPluginDbusInvocation* inv) { plugin->invocations = g_slist_remove(plugin->invocations, inv); infinoted_plugin_dbus_invocation_unref(inv); } static GVariant* infinoted_plugin_dbus_perms_to_variant(const InfAclMask* mask, const InfAclMask* perms) { GVariantBuilder builder; GEnumClass* enum_class; guint i; enum_class = G_ENUM_CLASS(g_type_class_ref(INF_TYPE_ACL_SETTING)); g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sb}")); for(i = 0; i < enum_class->n_values; ++i) { if(inf_acl_mask_has(mask, enum_class->values[i].value)) { g_variant_builder_add( &builder, "{sb}", enum_class->values[i].value_nick, inf_acl_mask_has(perms, enum_class->values[i].value) ); } } g_type_class_unref(enum_class); return g_variant_builder_end(&builder); } static gboolean infinoted_plugin_dbus_mask_from_variant(InfAclMask* mask, GVariant* variant, GError** error) { GEnumClass* enum_class; GEnumValue* val; GVariantIter iter; const gchar* perm; inf_acl_mask_clear(mask); enum_class = G_ENUM_CLASS(g_type_class_ref(INF_TYPE_ACL_SETTING)); g_variant_iter_init(&iter, variant); while(g_variant_iter_next(&iter, "&s", &perm)) { val = g_enum_get_value_by_nick(enum_class, perm); if(val == NULL) { g_set_error( error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "No such permission: \"%s\"", perm ); g_type_class_unref(enum_class); return FALSE; } inf_acl_mask_or1(mask, val->value); } g_type_class_unref(enum_class); return TRUE; } static gboolean infinoted_plugin_dbus_perms_from_variant(InfAclMask* mask, InfAclMask* perms, GVariant* variant, GError** error) { GEnumClass* enum_class; GEnumValue* val; GVariantIter iter; const gchar* perm; gboolean set; inf_acl_mask_clear(mask); inf_acl_mask_clear(perms); enum_class = G_ENUM_CLASS(g_type_class_ref(INF_TYPE_ACL_SETTING)); g_variant_iter_init(&iter, variant); while(g_variant_iter_next(&iter, "{&sb}", &perm, &set)) { val = g_enum_get_value_by_nick(enum_class, perm); if(val == NULL) { g_set_error( error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "No such permission: \"%s\"", perm ); g_type_class_unref(enum_class); return FALSE; } inf_acl_mask_or1(mask, val->value); if(set == TRUE) inf_acl_mask_or1(perms, val->value); } g_type_class_unref(enum_class); return TRUE; } static GVariant* infinoted_builder_dbus_sheet_set_to_variant(const InfAclSheetSet* sheet_set) { GVariantBuilder builder; const InfAclSheet* sheet; guint i; g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sa{sb}}")); if(sheet_set != NULL) { for(i = 0; i < sheet_set->n_sheets; ++i) { sheet = &sheet_set->sheets[i]; g_variant_builder_add( &builder, "{s@a{sb}}", inf_acl_account_id_to_string(sheet->account), infinoted_plugin_dbus_perms_to_variant(&sheet->mask, &sheet->perms) ); } } return g_variant_builder_end(&builder); } static InfAclSheetSet* infinoted_plugin_dbus_sheet_set_from_variant(GVariant* variant, GError** error) { InfAclSheetSet* sheet_set; GVariantIter iter; const gchar* account; GVariant* sub_variant; InfAclSheet* sheet; gboolean success; sheet_set = inf_acl_sheet_set_new(); g_variant_iter_init(&iter, variant); while(g_variant_iter_loop(&iter, "{&s@a{sb}}", &account, &sub_variant)) { sheet = inf_acl_sheet_set_add_sheet( sheet_set, inf_acl_account_id_from_string(account) ); success = infinoted_plugin_dbus_perms_from_variant( &sheet->mask, &sheet->perms, sub_variant, error ); if(success != TRUE) { inf_acl_sheet_set_free(sheet_set); g_variant_unref(sub_variant); return NULL; } } return sheet_set; } static void infinoted_plugin_dbus_explore_node(InfinotedPluginDbus* plugin, InfinotedPluginDbusInvocation* invocation, InfBrowser* browser, const InfBrowserIter* iter) { InfBrowserIter child_iter; GVariantBuilder builder; child_iter = *iter; g_variant_builder_init(&builder, G_VARIANT_TYPE("a(ss)")); if(inf_browser_get_child(browser, &child_iter)) { do { if(inf_browser_is_subdirectory(browser, &child_iter)) { g_variant_builder_add( &builder, "(ss)", inf_browser_get_node_name(browser, &child_iter), "InfSubdirectory" ); } else { g_variant_builder_add( &builder, "(ss)", inf_browser_get_node_name(browser, &child_iter), inf_browser_get_node_type(browser, &child_iter) ); } } while(inf_browser_get_next(browser, &child_iter)); } g_dbus_method_invocation_return_value( invocation->invocation, g_variant_new("(@a(ss))", g_variant_builder_end(&builder)) ); infinoted_plugin_dbus_invocation_free(invocation->plugin, invocation); } static void infinoted_plugin_dbus_add_node_finished_cb(InfRequest* request, const InfRequestResult* result, const GError* error, gpointer user_data) { InfinotedPluginDbusInvocation* invocation; invocation = (InfinotedPluginDbusInvocation*)user_data; invocation->request = NULL; if(error != NULL) { g_dbus_method_invocation_return_error_literal( invocation->invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, error->message ); } else { g_dbus_method_invocation_return_value( invocation->invocation, g_variant_new_tuple(NULL, 0) ); } infinoted_plugin_dbus_invocation_free(invocation->plugin, invocation); } static void infinoted_plugin_dbus_add_node(InfinotedPluginDbus* plugin, InfinotedPluginDbusInvocation* invocation, InfBrowser* browser, const InfBrowserIter* iter) { const gchar* name; const gchar* type; GVariant* sheet_set_variant; InfAclSheetSet* sheet_set; GError* error; InfRequest* request; g_variant_get_child(invocation->parameters, 1, "&s", &name); g_variant_get_child(invocation->parameters, 2, "&s", &type); g_variant_get_child( invocation->parameters, 3, "@a{sa{sb}}", &sheet_set_variant ); error = NULL; sheet_set = infinoted_plugin_dbus_sheet_set_from_variant( sheet_set_variant, &error ); g_variant_unref(sheet_set_variant); if(error != NULL) { g_dbus_method_invocation_return_gerror(invocation->invocation, error); g_error_free(error); infinoted_plugin_dbus_invocation_free(plugin, invocation); } else { if(strcmp(type, "InfSubdirectory") == 0) { request = inf_browser_add_subdirectory( browser, iter, name, sheet_set, infinoted_plugin_dbus_add_node_finished_cb, invocation ); } else { request = inf_browser_add_note( browser, iter, name, type, sheet_set, NULL, FALSE, infinoted_plugin_dbus_add_node_finished_cb, invocation ); } if(request != NULL) { invocation->request = request; invocation->request_func = infinoted_plugin_dbus_add_node_finished_cb; } } } static void infinoted_plugin_dbus_remove_node_finished_cb(InfRequest* request, const InfRequestResult* result, const GError* error, gpointer user_data) { InfinotedPluginDbusInvocation* invocation; invocation = (InfinotedPluginDbusInvocation*)user_data; invocation->request = NULL; if(error != NULL) { g_dbus_method_invocation_return_error_literal( invocation->invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, error->message ); } else { g_dbus_method_invocation_return_value( invocation->invocation, g_variant_new_tuple(NULL, 0) ); } infinoted_plugin_dbus_invocation_free(invocation->plugin, invocation); } static void infinoted_plugin_dbus_remove_node(InfinotedPluginDbus* plugin, InfinotedPluginDbusInvocation* invocation, InfBrowser* browser, const InfBrowserIter* iter) { InfRequest* request; request = inf_browser_remove_node( browser, iter, infinoted_plugin_dbus_remove_node_finished_cb, invocation ); if(request != NULL) { invocation->request = request; invocation->request_func = infinoted_plugin_dbus_remove_node_finished_cb; } } static void infinoted_plugin_dbus_query_acl(InfinotedPluginDbus* plugin, InfinotedPluginDbusInvocation* invocation, InfBrowser* browser, const InfBrowserIter* iter) { const InfAclSheetSet* sheet_set; const InfAclSheet* sheet; const gchar* account; InfAclAccountId id; GVariantBuilder builder; /* TODO: Actually query the ACL if not available */ sheet_set = inf_browser_get_acl(browser, iter); g_variant_get_child(invocation->parameters, 1, "&s", &account); if(*account == '\0') { g_dbus_method_invocation_return_value( invocation->invocation, g_variant_new( "(@a{sa{sb}})", infinoted_builder_dbus_sheet_set_to_variant(sheet_set) ) ); } else { id = inf_acl_account_id_from_string(account); if(sheet_set != NULL) sheet = inf_acl_sheet_set_find_const_sheet(sheet_set, id); else sheet = NULL; g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sa{sb}}")); if(sheet != NULL) { g_variant_builder_add( &builder, "{s@a{sb}}", account, infinoted_plugin_dbus_perms_to_variant(&sheet->mask, &sheet->perms) ); } g_dbus_method_invocation_return_value( invocation->invocation, g_variant_new("(@a{sa{sb}})", g_variant_builder_end(&builder)) ); } infinoted_plugin_dbus_invocation_free(plugin, invocation); } static void infinoted_plugin_dbus_set_acl_finished_cb(InfRequest* request, const InfRequestResult* result, const GError* error, gpointer user_data) { InfinotedPluginDbusInvocation* invocation; invocation = (InfinotedPluginDbusInvocation*)user_data; invocation->request = NULL; if(error != NULL) { g_dbus_method_invocation_return_error_literal( invocation->invocation, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, error->message ); } else { g_dbus_method_invocation_return_value( invocation->invocation, g_variant_new_tuple(NULL, 0) ); } infinoted_plugin_dbus_invocation_free(invocation->plugin, invocation); } static void infinoted_plugin_dbus_set_acl(InfinotedPluginDbus* plugin, InfinotedPluginDbusInvocation* invocation, InfBrowser* browser, const InfBrowserIter* iter) { GVariant* sheet_set_variant; InfAclSheetSet* sheet_set; GError* error; InfRequest* request; g_variant_get_child( invocation->parameters, 1, "@a{sa{sb}}", &sheet_set_variant ); error = NULL; sheet_set = infinoted_plugin_dbus_sheet_set_from_variant( sheet_set_variant, &error ); g_variant_unref(sheet_set_variant); if(error != NULL) { g_dbus_method_invocation_return_gerror(invocation->invocation, error); g_error_free(error); infinoted_plugin_dbus_invocation_free(plugin, invocation); } else { request = inf_browser_set_acl( browser, iter, sheet_set, infinoted_plugin_dbus_set_acl_finished_cb, invocation ); inf_acl_sheet_set_free(sheet_set); if(request != NULL) { invocation->request = request; invocation->request_func = infinoted_plugin_dbus_set_acl_finished_cb; } } } static void infinoted_plugin_dbus_check_acl(InfinotedPluginDbus* plugin, InfinotedPluginDbusInvocation* invocation, InfBrowser* browser, const InfBrowserIter* iter) { const gchar* account; GVariant* mask_variant; InfAclMask mask; InfAclMask out; GError* error; g_variant_get_child(invocation->parameters, 1, "&s", &account); g_variant_get_child(invocation->parameters, 2, "@as", &mask_variant); error = NULL; infinoted_plugin_dbus_mask_from_variant(&mask, mask_variant, &error); g_variant_unref(mask_variant); if(error != NULL) { g_dbus_method_invocation_return_gerror(invocation->invocation, error); g_error_free(error); } else { inf_browser_check_acl( browser, iter, inf_acl_account_id_from_string(account), &mask, &out ); g_dbus_method_invocation_return_value( invocation->invocation, g_variant_new( "(@a{sb})", infinoted_plugin_dbus_perms_to_variant(&mask, &out) ) ); } infinoted_plugin_dbus_invocation_free(plugin, invocation); } static void infinoted_plugin_dbus_navigate_done(InfBrowser* browser, const InfBrowserIter* iter, const GError* error, gpointer user_data) { InfinotedPluginDbusInvocation* invocation; invocation = (InfinotedPluginDbusInvocation*)user_data; if(error != NULL) { g_dbus_method_invocation_return_error_literal( invocation->invocation, G_DBUS_ERROR, G_DBUS_ERROR_FILE_NOT_FOUND, error->message ); infinoted_plugin_dbus_invocation_free(invocation->plugin, invocation); } else if(strcmp(invocation->method_name, "explore_node") == 0) { infinoted_plugin_dbus_explore_node( invocation->plugin, invocation, browser, iter ); } else if(strcmp(invocation->method_name, "add_node") == 0) { infinoted_plugin_dbus_add_node( invocation->plugin, invocation, browser, iter ); } else if(strcmp(invocation->method_name, "remove_node") == 0) { infinoted_plugin_dbus_remove_node( invocation->plugin, invocation, browser, iter ); } else if(strcmp(invocation->method_name, "query_acl") == 0) { infinoted_plugin_dbus_query_acl( invocation->plugin, invocation, browser, iter ); } else if(strcmp(invocation->method_name, "set_acl") == 0) { infinoted_plugin_dbus_set_acl( invocation->plugin, invocation, browser, iter ); } else if(strcmp(invocation->method_name, "check_acl") == 0) { infinoted_plugin_dbus_check_acl( invocation->plugin, invocation, browser, iter ); } else { g_assert_not_reached(); } } static void infinoted_plugin_dbus_main_invocation(gpointer user_data) { /* Main thread invocation handler */ InfinotedPluginDbusInvocation* invocation; const gchar* path; gsize len; InfinotedPluginUtilNavigateData* navigate; invocation = (InfinotedPluginDbusInvocation*)user_data; invocation->plugin->invocations = g_slist_prepend(invocation->plugin->invocations, invocation); g_atomic_int_inc(&invocation->ref_count); /* These commands take a path as the first parameter and do not * require that path to be explored. */ if(strcmp(invocation->method_name, "remove_node") == 0 || strcmp(invocation->method_name, "query_acl") == 0 || strcmp(invocation->method_name, "set_acl") == 0 || strcmp(invocation->method_name, "check_acl") == 0) { path = g_variant_get_string( g_variant_get_child_value(invocation->parameters, 0), &len ); navigate = infinoted_plugin_util_navigate_to( INF_BROWSER(infinoted_plugin_manager_get_directory(invocation->plugin->manager)), path, len, FALSE, infinoted_plugin_dbus_navigate_done, invocation ); if(navigate != NULL) invocation->navigate = navigate; } /* These commands take a path as the first parameter and DO require that * path to be explored. */ else if(strcmp(invocation->method_name, "explore_node") == 0 || strcmp(invocation->method_name, "add_node") == 0) { path = g_variant_get_string( g_variant_get_child_value(invocation->parameters, 0), &len ); navigate = infinoted_plugin_util_navigate_to( INF_BROWSER(infinoted_plugin_manager_get_directory(invocation->plugin->manager)), path, len, TRUE, infinoted_plugin_dbus_navigate_done, invocation ); if(navigate != NULL) invocation->navigate = navigate; } else { g_dbus_method_invocation_return_error_literal( invocation->invocation, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD, "Not implemented" ); infinoted_plugin_dbus_invocation_free(invocation->plugin, invocation); } } static void infinoted_plugin_dbus_method_call_func(GDBusConnection* connection, const gchar* sender, const gchar* object_path, const gchar* interface_name, const gchar* method_name, GVariant* parameters, GDBusMethodInvocation* invocation, gpointer user_data) { /* Dispatch to the main thread */ InfinotedPluginDbus* plugin; InfinotedPluginDbusInvocation* thread_invocation; InfIo* io; plugin = (InfinotedPluginDbus*)user_data; thread_invocation = g_slice_new(InfinotedPluginDbusInvocation); thread_invocation->plugin = plugin; thread_invocation->ref_count = 1; thread_invocation->method_name = g_strdup(method_name); thread_invocation->parameters = g_variant_ref(parameters); thread_invocation->invocation = g_object_ref(invocation); thread_invocation->navigate = NULL; thread_invocation->request = NULL; thread_invocation->request_func = NULL; io = infinoted_plugin_manager_get_io(plugin->manager); inf_io_add_dispatch( io, infinoted_plugin_dbus_main_invocation, thread_invocation, infinoted_plugin_dbus_invocation_unref ); } static void infinoted_plugin_dbus_bus_acquired_func(GDBusConnection* connection, const gchar* name, gpointer user_data) { GDBusNodeInfo* node_info; GDBusInterfaceInfo* interface_info; GDBusInterfaceVTable vtable; GError* error; node_info = g_dbus_node_info_new_for_xml( infinoted_plugin_dbus_introspection, NULL ); g_assert(node_info != NULL); interface_info = g_dbus_node_info_lookup_interface( node_info, "org.infinote.server" ); g_assert(interface_info != NULL); vtable.method_call = infinoted_plugin_dbus_method_call_func; vtable.get_property = NULL; vtable.set_property = NULL; error = NULL; g_dbus_connection_register_object( connection, "/org/infinote/infinoted", interface_info, &vtable, user_data, NULL, &error ); if(error != NULL) { g_warning("Failed to register D-Bus object: %s\n", error->message); g_error_free(error); error = NULL; } g_dbus_node_info_unref(node_info); } static void infinoted_plugin_dbus_name_acquired_func(GDBusConnection* connection, const gchar* name, gpointer user_data) { /* nothing to do */ } static void infinoted_plugin_dbus_name_lost_func(GDBusConnection* connection, const gchar* name, gpointer user_data) { InfinotedPluginDbus* plugin; plugin = (InfinotedPluginDbus*)user_data; infinoted_log_warning( infinoted_plugin_manager_get_log(plugin->manager), "The name \"%s\" could not be acquired on the bus: " "d-bus functionality is not available", name ); } static gpointer infinoted_plugin_dbus_thread_func(gpointer plugin_info) { InfinotedPluginDbus* plugin; plugin = (InfinotedPluginDbus*)plugin_info; g_mutex_lock(&plugin->mutex); if(plugin->thread == NULL) { g_mutex_unlock(&plugin->mutex); return NULL; } plugin->context = g_main_context_new(); g_main_context_push_thread_default(plugin->context); plugin->loop = g_main_loop_new(plugin->context, FALSE); g_mutex_unlock(&plugin->mutex); plugin->id = g_bus_own_name( plugin->bus_type, plugin->bus_name, G_BUS_NAME_OWNER_FLAGS_NONE, infinoted_plugin_dbus_bus_acquired_func, infinoted_plugin_dbus_name_acquired_func, infinoted_plugin_dbus_name_lost_func, plugin, NULL ); g_main_loop_run(plugin->loop); g_bus_unown_name(plugin->id); plugin->id = 0; /* TODO: This is an enormous hack. Apparently, g_bus_own_name starts some * thread internally, and that thread is not stopped by g_bus_unown_name. * When the plugin is then unloaded, it leads to a crash because the thread * is still doing some cleanup work. I don't see a possibility for us here * to wait for that thread to finish, so we simply wait 100ms. * * Waiting with quitting the main loop until either bus_acquired or * name_lost are called does not help. * * A solution might be to not use the g_bus_own_name and g_bus_unown_name * APIs, but some more low-level APIs. */ g_usleep(100000); g_mutex_lock(&plugin->mutex); g_main_loop_unref(plugin->loop); plugin->loop = NULL; g_main_context_unref(plugin->context); plugin->context = NULL; g_mutex_unlock(&plugin->mutex); return NULL; } static gboolean infinoted_plugin_dbus_deinitialize_thread_func(gpointer user_data) { InfinotedPluginDbus* plugin; plugin = (InfinotedPluginDbus*)user_data; /* If none of the callbacks has been called yet, then wait for them to be * called. */ g_main_loop_quit(plugin->loop); return FALSE; } static void infinoted_plugin_dbus_info_initialize(gpointer plugin_info) { InfinotedPluginDbus* plugin; plugin = (InfinotedPluginDbus*)plugin_info; plugin->bus_type = G_BUS_TYPE_SESSION; /* good default? */ plugin->bus_name = g_strdup("org.infinote.infinoted"); plugin->manager = NULL; plugin->thread = NULL; plugin->context = NULL; plugin->loop = NULL; plugin->id = 0; plugin->invocations = NULL; } static gboolean infinoted_plugin_dbus_initialize(InfinotedPluginManager* manager, gpointer plugin_info, GError** error) { InfinotedPluginDbus* plugin; gchar* gio_path; GModule* gio_module; plugin = (InfinotedPluginDbus*)plugin_info; /* Load the GIO dynamic library and make it resident. The reason for this * is that the infinoted executable does not link against gio, but this * module does. Therefore, when the module gets unloaded, libgio would be * unloaded as well. However, gio registers several types into global * gobject buffers such as the signal or property tables. After unloading, * those registrations would still be around, and some static strings would * even point to memory that is no longer available. This can lead to * seemingly random crashes when accessing some signals or properties of * intact objects/types, because gobject will scan its internal data * structures that also contain the invalidated strings. To avoid this * mess, we simply make sure that libgio stays around even after we are * unloaded. */ gio_path = g_module_build_path(NULL, "gio-2.0"); gio_module = g_module_open(gio_path, 0); g_free(gio_path); if(gio_module == NULL) { /* The error might be consumed after we have been dlclose()'d, so * use g_quark_from_string instead of g_quark_from_static_string. */ g_set_error( error, g_quark_from_string("INFINOTED_PLUGIN_DBUS_ERROR"), 0, "%s", g_module_error() ); return FALSE; } else { g_module_make_resident(gio_module); if(g_module_close(gio_module) != TRUE) { g_warning("Failed to close gio module: %s", g_module_error()); } } plugin->manager = manager; g_mutex_init(&plugin->mutex); g_mutex_lock(&plugin->mutex); /* We run the DBus activity in its own thread, so that we can iterate * a glib main loop there. */ plugin->thread = g_thread_try_new( "InfinotedPluginDbus", infinoted_plugin_dbus_thread_func, plugin_info, error ); g_mutex_unlock(&plugin->mutex); if(plugin->thread == NULL) { g_mutex_clear(&plugin->mutex); return FALSE; } return TRUE; } static void infinoted_plugin_dbus_deinitialize(gpointer plugin_info) { InfinotedPluginDbus* plugin; GMainContext* ctx; GSource* source; GThread* thread; plugin = (InfinotedPluginDbus*)plugin_info; if(plugin->thread != NULL) { g_mutex_lock(&plugin->mutex); thread = plugin->thread; plugin->thread = NULL; /* Tell the thread to quit */ if(plugin->loop != NULL) { ctx = g_main_loop_get_context(plugin->loop); source = g_idle_source_new(); g_source_set_callback( source, infinoted_plugin_dbus_deinitialize_thread_func, plugin, NULL ); g_source_attach(source, ctx); } g_mutex_unlock(&plugin->mutex); g_thread_join(thread); thread = NULL; g_mutex_clear(&plugin->mutex); } while(plugin->invocations != NULL) { infinoted_plugin_dbus_invocation_unref(plugin->invocations->data); plugin->invocations = g_slist_delete_link(plugin->invocations, plugin->invocations); } g_free(plugin->bus_name); } static gboolean infinoted_plugin_dbus_parameter_convert_bus_type(gpointer out, gpointer in, GError** error) { gchar** in_str; GBusType* out_val; in_str = (gchar**)in; out_val = (GBusType*)out; if(strcmp(*in_str, "system") == 0) { *out_val = G_BUS_TYPE_SYSTEM; } else if(strcmp(*in_str, "session") == 0) { *out_val = G_BUS_TYPE_SESSION; } else { g_set_error( error, infinoted_parameter_error_quark(), INFINOTED_PARAMETER_ERROR_INVALID_FLAG, _("\"%s\" is not a valid bus type. Allowed values are " "\"system\" or \"session\""), *in_str ); return FALSE; } return TRUE; } static const InfinotedParameterInfo INFINOTED_PLUGIN_DBUS_OPTIONS[] = { { "type", INFINOTED_PARAMETER_STRING, 0, offsetof(InfinotedPluginDbus, bus_type), infinoted_plugin_dbus_parameter_convert_bus_type, 0, N_("The bus type to use, either \"session\" or \"system\". " "[default=session]"), N_("TYPE") }, { "name", INFINOTED_PARAMETER_STRING, 0, offsetof(InfinotedPluginDbus, bus_name), infinoted_parameter_convert_string, 0, N_("The name to own on the bus. [default=org.infinote.infinoted]"), N_("NAME") }, { NULL, 0, 0, 0, NULL } }; const InfinotedPlugin INFINOTED_PLUGIN = { "dbus", N_("Exports infinoted functionality on D-Bus"), INFINOTED_PLUGIN_DBUS_OPTIONS, sizeof(InfinotedPluginDbus), 0, 0, NULL, infinoted_plugin_dbus_info_initialize, infinoted_plugin_dbus_initialize, infinoted_plugin_dbus_deinitialize, NULL, NULL, NULL, NULL }; /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/infinoted/plugins/PaxHeaders.26529/infinoted-plugin-certificate-auth.c0000644000000000000000000000013113034342512026075 xustar0030 mtime=1483851082.017718362 30 atime=1483851082.017718362 29 ctime=1488261589.52413792 libinfinity-0.7.1/infinoted/plugins/infinoted-plugin-certificate-auth.c0000644000175000017500000004625413034342512026643 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include #include #include #include #include #include typedef enum _InfinotedPluginCertificateAuthError { INFINOTED_PLUGIN_CERTIFICATE_AUTH_ERROR_NO_CREDENTIALS, INFINOTED_PLUGIN_CERTIFICATE_AUTH_ERROR_NO_CAS, INFINOTED_PLUGIN_CERTIFICATE_AUTH_ERROR_NO_CA_FOR_KEY, INFINOTED_PLUGIN_CERTIFICATE_AUTH_ERROR_NO_CA_KEY } InfinotedPluginCertificateAuthError; typedef struct _InfinotedPluginCertificateAuth InfinotedPluginCertificateAuth; struct _InfinotedPluginCertificateAuth { InfinotedPluginManager* manager; gchar* ca_list_file; gchar* ca_key_file; gboolean accept_unauthenticated_clients; gchar* super_user; gnutls_x509_crt_t* cas; guint n_cas; gnutls_x509_privkey_t ca_key; guint ca_key_index; gint verify_flags; InfAclAccountId super_id; InfRequest* set_acl_request; }; static GQuark infinoted_plugin_certificate_auth_error_quark() { return g_quark_from_static_string( "INFINOTED_PLUGIN_CERTIFICATE_AUTH_ERROR" ); } static void infinoted_plugin_certificate_auth_set_acl_cb(InfRequest* request, const InfRequestResult* result, const GError* error, gpointer user_data) { InfinotedPluginCertificateAuth* plugin; plugin = (InfinotedPluginCertificateAuth*)user_data; if(error != NULL) { infinoted_log_warning( infinoted_plugin_manager_get_log(plugin->manager), _("Failed to set permissions for super user: %s"), error->message ); } } static void infinoted_plugin_certificate_auth_remove_acl_account_cb( InfRequest* request, const InfRequestResult* result, const GError* error, gpointer user_data) { InfinotedPluginCertificateAuth* plugin; plugin = (InfinotedPluginCertificateAuth*)user_data; if(error != NULL) { infinoted_log_warning( infinoted_plugin_manager_get_log(plugin->manager), _("Failed to remove super user on server shutdown. This should not be " "a problem since the account is not made persistent, however might " "point to an inconsistency in the server setup. The error message " "was: %s"), error->message ); } } static void infinoted_plugin_certificate_auth_certificate_func(InfXmppConnection* xmpp, gnutls_session_t session, InfCertificateChain* chain, gpointer user_data) { InfinotedPluginCertificateAuth* plugin; int res; int verify_result; GError* error; plugin = (InfinotedPluginCertificateAuth*)user_data; if(chain != NULL) { res = gnutls_x509_crt_list_verify( inf_certificate_chain_get_raw(chain), inf_certificate_chain_get_n_certificates(chain), plugin->cas, plugin->n_cas, NULL, 0, plugin->verify_flags, &verify_result ); error = NULL; if(res != GNUTLS_E_SUCCESS) inf_gnutls_set_error(&error, res); else if( (verify_result & GNUTLS_CERT_INVALID) != 0) inf_gnutls_certificate_verification_set_error(&error, verify_result); if(error != NULL) { inf_xmpp_connection_certificate_verify_cancel(xmpp, error); g_error_free(error); } else { inf_xmpp_connection_certificate_verify_continue(xmpp); } } else { /* If we do not accept unauthenticated clients, then GnuTLS should have * blocked the connection already, since we set the certificate request * to GNUTLS_CERT_REQUIRE in that case. */ g_assert(plugin->accept_unauthenticated_clients == TRUE); inf_xmpp_connection_certificate_verify_continue(xmpp); } } static void infinoted_plugin_certificate_auth_info_initialize(gpointer plugin_info) { InfinotedPluginCertificateAuth* plugin; plugin = (InfinotedPluginCertificateAuth*)plugin_info; plugin->manager = NULL; plugin->ca_list_file = NULL; plugin->ca_key_file = NULL; plugin->accept_unauthenticated_clients = FALSE; plugin->super_user = NULL; plugin->cas = NULL; plugin->n_cas = 0; plugin->ca_key = NULL; plugin->ca_key_index = G_MAXUINT; /* Note that we don't require client certificates to be signed by a CA, * by default. We only require them to be signed by one of the certificates * in our list, but we don't care whether that's a CA or not. A common use * case is to sign client certificates with our own server certificate. */ plugin->verify_flags = GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT | GNUTLS_VERIFY_DISABLE_CA_SIGN; plugin->super_id = 0; plugin->set_acl_request = NULL; } static gboolean infinoted_plugin_certificate_auth_initialize(InfinotedPluginManager* manager, gpointer plugin_info, GError** error) { InfinotedPluginCertificateAuth* plugin; InfCertificateCredentials* creds; GPtrArray* read_certs; int res; guint i; gnutls_x509_crt_t* sign_certs; InfCertificateChain* sign_chain; gnutls_x509_privkey_t super_key; InfCertUtilDescription desc; gnutls_x509_crt_t super_cert; InfAclAccountId super_id; gnutls_x509_crt_t chain[2]; gboolean written; InfdDirectory* directory; InfBrowserIter iter; InfAclSheetSet sheet_set; InfAclSheet sheet; InfRequest* request; plugin = (InfinotedPluginCertificateAuth*)plugin_info; plugin->manager = manager; creds = infinoted_plugin_manager_get_credentials(manager); if(creds == NULL) { g_set_error_literal( error, infinoted_plugin_certificate_auth_error_quark(), INFINOTED_PLUGIN_CERTIFICATE_AUTH_ERROR_NO_CREDENTIALS, _("The certificate-auth plugin can only be used when TLS is enabled " "and a server certificate has been set.") ); return FALSE; } read_certs = inf_cert_util_read_certificate(plugin->ca_list_file, NULL, error); if(read_certs == NULL) return FALSE; if(read_certs->len == 0) { g_set_error( error, infinoted_plugin_certificate_auth_error_quark(), INFINOTED_PLUGIN_CERTIFICATE_AUTH_ERROR_NO_CAS, _("File \"%s\" does not contain any CA certificates"), plugin->ca_list_file ); g_ptr_array_free(read_certs, TRUE); return FALSE; } plugin->n_cas = read_certs->len; plugin->cas = (gnutls_x509_crt_t*)g_ptr_array_free(read_certs, FALSE); res = gnutls_certificate_set_x509_trust( inf_certificate_credentials_get(creds), plugin->cas, plugin->n_cas ); if(res < 0) { inf_gnutls_set_error(error, res); return FALSE; } if(plugin->ca_key_file != NULL) { plugin->ca_key = inf_cert_util_read_private_key(plugin->ca_key_file, error); if(plugin->ca_key == NULL) return FALSE; /* Walk through certificates and find the certificate that the key * belongs to. */ for(i = 0; i < plugin->n_cas; ++i) if(inf_cert_util_check_certificate_key(plugin->cas[i], plugin->ca_key)) break; if(i == plugin->n_cas) { gnutls_x509_privkey_deinit(plugin->ca_key); plugin->ca_key = NULL; g_set_error_literal( error, infinoted_plugin_certificate_auth_error_quark(), INFINOTED_PLUGIN_CERTIFICATE_AUTH_ERROR_NO_CA_FOR_KEY, _("The given CA key does not match with any of the CA certificates") ); return FALSE; } plugin->ca_key_index = i; /* Set the signing certificate of the directory, so that it can handle * account creation requests. Note that this takes ownership of the * certificate, so we take special care in the cleanup code in * infinoted_plugin_certificate_auth_deinitialize(). */ sign_certs = g_malloc(sizeof(gnutls_x509_crt_t)); sign_certs[0] = plugin->cas[plugin->ca_key_index]; sign_chain = inf_certificate_chain_new(sign_certs, 1); infd_directory_set_certificate( infinoted_plugin_manager_get_directory(plugin->manager), plugin->ca_key, sign_chain ); inf_certificate_chain_unref(sign_chain); } if(plugin->super_user != NULL) { if(plugin->ca_key == NULL) { g_set_error_literal( error, infinoted_plugin_certificate_auth_error_quark(), INFINOTED_PLUGIN_CERTIFICATE_AUTH_ERROR_NO_CA_KEY, _("Cannot generate a superuser certificate without CA key") ); return FALSE; } /* Create a private key and certificate for the super user. */ infinoted_log_info( infinoted_plugin_manager_get_log(plugin->manager), _("Creating 4096-bit RSA private key for the super user account...") ); super_key = inf_cert_util_create_private_key(GNUTLS_PK_RSA, 4096, error); if(super_key == NULL) return FALSE; desc.validity = 12 * 3600; /* 12 hours */ desc.dn_common_name = "Super User"; desc.san_dnsname = NULL; super_cert = inf_cert_util_create_signed_certificate( super_key, &desc, plugin->cas[plugin->ca_key_index], plugin->ca_key, error ); if(super_cert == NULL) { gnutls_x509_privkey_deinit(super_key); return FALSE; } super_id = infd_directory_create_acl_account( infinoted_plugin_manager_get_directory(plugin->manager), _("Super User"), TRUE, /* transient */ &super_cert, 1, error ); if(super_id == 0) { gnutls_x509_crt_deinit(super_cert); gnutls_x509_privkey_deinit(super_key); return FALSE; } plugin->super_id = super_id; chain[0] = super_cert; chain[1] = plugin->cas[plugin->ca_key_index]; written = inf_cert_util_write_certificate_with_key( super_key, chain, 2, plugin->super_user, error ); gnutls_x509_crt_deinit(super_cert); gnutls_x509_privkey_deinit(super_key); if(written == FALSE) return FALSE; inf_browser_get_root( INF_BROWSER(infinoted_plugin_manager_get_directory(plugin->manager)), &iter ); directory = infinoted_plugin_manager_get_directory(plugin->manager); sheet.account = super_id; sheet.mask = INF_ACL_MASK_ALL; infd_directory_get_support_mask(directory, &sheet.perms); sheet_set.n_sheets = 1; sheet_set.own_sheets = NULL; sheet_set.sheets = &sheet; request = inf_browser_set_acl( INF_BROWSER(directory), &iter, &sheet_set, infinoted_plugin_certificate_auth_set_acl_cb, plugin ); if(request != NULL) { plugin->set_acl_request = request; g_object_ref(plugin->set_acl_request); } } return TRUE; } static void infinoted_plugin_certificate_auth_deinitialize(gpointer plugin_info) { InfinotedPluginCertificateAuth* plugin; InfRequest* remove_acl_account_request; InfCertificateCredentials* creds; guint i; plugin = (InfinotedPluginCertificateAuth*)plugin_info; /* Remove super user account. Note that this is not strictly necessary, * since the acocunt is transient and therefore is not written to disk, * so will not be re-created at the next server start. However, to be sure, * we explicitly remove the account at this point. */ if(plugin->super_id != 0) { remove_acl_account_request = inf_browser_remove_acl_account( INF_BROWSER(infinoted_plugin_manager_get_directory(plugin->manager)), plugin->super_id, infinoted_plugin_certificate_auth_remove_acl_account_cb, plugin ); /* This should be instantaneous: if we are not called back within the call * to inf_browser_remove_acl_account(), then we don't care about the * result, since we are being deinitialized. */ if(remove_acl_account_request != NULL) { inf_signal_handlers_disconnect_by_func( plugin->set_acl_request, G_CALLBACK(infinoted_plugin_certificate_auth_remove_acl_account_cb), plugin ); } } if(plugin->set_acl_request != NULL) { inf_signal_handlers_disconnect_by_func( plugin->set_acl_request, G_CALLBACK(infinoted_plugin_certificate_auth_set_acl_cb), plugin ); g_object_unref(plugin->set_acl_request); } creds = infinoted_plugin_manager_get_credentials(plugin->manager); if(creds != NULL) gnutls_certificate_free_cas(inf_certificate_credentials_get(creds)); infd_directory_set_certificate( infinoted_plugin_manager_get_directory(plugin->manager), NULL, NULL ); /* If we have a ca_key set, the certificate that belongs to the key had * its ownership transferred to the directory, so make sure not to free * it twice here. */ for(i = 0; i < plugin->n_cas; ++i) if(plugin->ca_key == NULL || i != plugin->ca_key_index) gnutls_x509_crt_deinit(plugin->cas[i]); g_free(plugin->cas); if(plugin->ca_key != NULL) gnutls_x509_privkey_deinit(plugin->ca_key); g_free(plugin->ca_list_file); g_free(plugin->ca_key_file); g_free(plugin->super_user); } static void infinoted_plugin_certificate_auth_connection_added(InfXmlConnection* conn, gpointer plugin_info, gpointer connection_info) { InfinotedPluginCertificateAuth* plugin; InfXmppConnection* xmpp; gnutls_certificate_request_t cert_req; plugin = (InfinotedPluginCertificateAuth*)plugin_info; if(INF_IS_XMPP_CONNECTION(conn)) { xmpp = INF_XMPP_CONNECTION(conn); if(plugin->accept_unauthenticated_clients == TRUE) cert_req = GNUTLS_CERT_REQUEST; else cert_req = GNUTLS_CERT_REQUIRE; inf_xmpp_connection_set_certificate_callback( xmpp, cert_req, infinoted_plugin_certificate_auth_certificate_func, plugin, NULL ); } } static void infinoted_plugin_certificate_auth_connection_removed(InfXmlConnection* conn, gpointer plugin_info, gpointer session_info) { InfinotedPluginCertificateAuth* plugin; InfXmppConnection* xmpp; plugin = (InfinotedPluginCertificateAuth*)plugin_info; if(INF_IS_XMPP_CONNECTION(conn)) { xmpp = INF_XMPP_CONNECTION(conn); inf_xmpp_connection_set_certificate_callback( xmpp, GNUTLS_CERT_IGNORE, NULL, NULL, NULL ); } } static const GFlagsValue INFINOTED_PLUGIN_CERTIFICATE_AUTH_VERIFY_FLAGS[] = { { GNUTLS_VERIFY_DISABLE_CA_SIGN, "GNUTLS_VERIFY_DISABLE_CA_SIGN", "disable-ca-sign" }, { GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT, "GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT", "allow-v1-ca-certificate" }, { GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD2, "GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD2", "allow-md2" }, { GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD2, "GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD2", "allow-md5" }, { GNUTLS_VERIFY_DISABLE_TIME_CHECKS, "GNUTLS_VERIFY_DISABLE_TIME_CHECKS", "disable-time-checks" }, { 0, NULL, NULL } }; static gboolean infinoted_plugin_certificate_auth_convert_verify_flags(gpointer in, gpointer out, GError** error) { return infinoted_parameter_convert_flags( in, out, INFINOTED_PLUGIN_CERTIFICATE_AUTH_VERIFY_FLAGS, error ); } static const InfinotedParameterInfo INFINOTED_PLUGIN_CERTIFICATE_AUTH_OPTIONS[] = { { "ca-list", INFINOTED_PARAMETER_STRING, INFINOTED_PARAMETER_REQUIRED, offsetof(InfinotedPluginCertificateAuth, ca_list_file), infinoted_parameter_convert_filename, 0, N_("The trusted CA or list of trusted CAs. Only clients presenting a " "certificate signed by one of these CAs are accepted."), N_("CA-LIST") }, { "ca-key", INFINOTED_PARAMETER_STRING, 0, offsetof(InfinotedPluginCertificateAuth, ca_key_file), infinoted_parameter_convert_filename, 0, N_("If given, this is the private key for one of the CA certificates in " "the list given by the \"ca-list\" parameter. In this case, the server " "itself acts as a CA and can issue certificates to clients. This can " "be used to allow clients to create their own accounts."), N_("CA-KEY") }, { "accept-unauthenticated-clients", INFINOTED_PARAMETER_BOOLEAN, 0, offsetof(InfinotedPluginCertificateAuth, accept_unauthenticated_clients), infinoted_parameter_convert_boolean, 0, N_("If this value is set to false, then clients that cannot authenticate " "themselves with a valid certificate are rejected and the connection " "is closed. If it is set to true, the connection will be accepted, " "but the client will only have unauthenticated access to the server. " "[Default: false]"), NULL }, { "super-user", INFINOTED_PARAMETER_STRING, 0, offsetof(InfinotedPluginCertificateAuth, super_user), infinoted_parameter_convert_string, 0, N_("Filename to which to write a short-lived super-user private key and " "certificate. The user is deleted when the infinoted server goes down " "or the plugin is re-loaded. This option can only be given when " "the \"ca-key\" parameter is set."), N_("FILENAME") }, { "verification-flags", INFINOTED_PARAMETER_STRING_LIST, 0, offsetof(InfinotedPluginCertificateAuth, verify_flags), infinoted_plugin_certificate_auth_convert_verify_flags, 0, N_("Flags to be used when verifying a client certificate. Each of these " "flags weakens the security, and so should be set only when " "absolutely necessary, and it should be done with care. " "[Default: disable-ca-sign]"), N_("flag1;flag2;[...]") }, { NULL, 0, 0, 0, NULL } }; const InfinotedPlugin INFINOTED_PLUGIN = { "certificate-auth", N_("Allows clients to authenticate themselves with client-side " "certificates. If authentication is successful, the certificate ID " "is used to log the user into its account."), INFINOTED_PLUGIN_CERTIFICATE_AUTH_OPTIONS, sizeof(InfinotedPluginCertificateAuth), 0, 0, NULL, infinoted_plugin_certificate_auth_info_initialize, infinoted_plugin_certificate_auth_initialize, infinoted_plugin_certificate_auth_deinitialize, infinoted_plugin_certificate_auth_connection_added, infinoted_plugin_certificate_auth_connection_removed, NULL, NULL }; /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/infinoted/plugins/PaxHeaders.26529/infinoted-plugin-record.c0000644000000000000000000000013213034342512024133 xustar0030 mtime=1483851082.017718362 30 atime=1483851082.017718362 30 ctime=1488261589.540137884 libinfinity-0.7.1/infinoted/plugins/infinoted-plugin-record.c0000644000175000017500000001460013034342512024666 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include #include #include #include #include #include typedef struct _InfinotedPluginRecord InfinotedPluginRecord; struct _InfinotedPluginRecord { InfinotedPluginManager* manager; }; typedef struct _InfinotedPluginRecordSessionInfo InfinotedPluginRecordSessionInfo; struct _InfinotedPluginRecordSessionInfo { InfinotedPluginRecord* plugin; InfAdoptedSessionRecord* record; }; static InfAdoptedSessionRecord* infinoted_plugin_record_start(InfinotedPluginRecord* plugin, InfAdoptedSession* session, const gchar* title) { gchar* dirname; gchar* basename; gchar* filename; guint i; gsize pos; InfAdoptedSessionRecord* record; GError* error; basename = g_build_filename(g_get_home_dir(), ".infinoted-records", title, NULL); pos = strlen(basename) + 8; filename = g_strdup_printf("%s.record-00000.xml", basename); g_free(basename); i = 0; while(g_file_test(filename, G_FILE_TEST_EXISTS) && ++i < 100000) g_snprintf(filename + pos, 10, "%05u.xml", i); record = NULL; if(i >= 100000) { dirname = g_path_get_dirname(filename); infinoted_log_warning( infinoted_plugin_manager_get_log(plugin->manager), _("Could not create record file for session \"%s\": Could not generate " "unused record file in directory \"%s\""), title, dirname ); g_free(dirname); } else { error = NULL; if(!infinoted_util_create_dirname(filename, &error)) { dirname = g_path_get_dirname(filename); infinoted_log_warning( infinoted_plugin_manager_get_log(plugin->manager), _("Could not create directory \"%s\": %s"), filename, error->message ); g_error_free(error); g_free(dirname); } else { record = inf_adopted_session_record_new(session); inf_adopted_session_record_start_recording(record, filename, &error); if(error != NULL) { infinoted_log_warning( infinoted_plugin_manager_get_log(plugin->manager), _("Error while writing record for session \"%s\" into \"%s\": %s"), title, filename, error->message ); g_error_free(error); g_object_unref(record); record = NULL; } } } g_free(filename); return record; } static void infinoted_plugin_record_info_initialize(gpointer plugin_info) { InfinotedPluginRecord* plugin; plugin = (InfinotedPluginRecord*)plugin_info; plugin->manager = NULL; } static gboolean infinoted_plugin_record_initialize(InfinotedPluginManager* manager, gpointer plugin_info, GError** error) { InfinotedPluginRecord* plugin; plugin = (InfinotedPluginRecord*)plugin_info; plugin->manager = manager; return TRUE; } static void infinoted_plugin_record_deinitialize(gpointer plugin_info) { InfinotedPluginRecord* plugin; plugin = (InfinotedPluginRecord*)plugin_info; } static void infinoted_plugin_record_session_added(const InfBrowserIter* iter, InfSessionProxy* proxy, gpointer plugin_info, gpointer session_info) { InfinotedPluginRecord* plugin; InfinotedPluginRecordSessionInfo* info; InfSession* session; gchar* title; gchar* pos; InfAdoptedSessionRecord* record; plugin = (InfinotedPluginRecord*)plugin_info; info = (InfinotedPluginRecordSessionInfo*)session_info; g_object_get(G_OBJECT(proxy), "session", &session, NULL); g_assert(INF_ADOPTED_IS_SESSION(session)); title = inf_browser_get_path( INF_BROWSER(infinoted_plugin_manager_get_directory(plugin->manager)), iter ); for(pos = title + 1; *pos != '\0'; ++pos) if(*pos == '/') *pos = '_'; info->plugin = plugin; info->record = infinoted_plugin_record_start( plugin, INF_ADOPTED_SESSION(session), title + 1 ); g_object_set_data(G_OBJECT(session), "infinoted-record", info->record); g_object_unref(session); g_free(title); } static void infinoted_plugin_record_session_removed(const InfBrowserIter* iter, InfSessionProxy* proxy, gpointer plugin_info, gpointer session_info) { InfinotedPluginRecordSessionInfo* info; InfSession* session; info = (InfinotedPluginRecordSessionInfo*)session_info; g_object_get(G_OBJECT(proxy), "session", &session, NULL); g_object_set_data(G_OBJECT(session), "infinoted-record", NULL); g_object_unref(info->record); g_object_unref(session); } static const InfinotedParameterInfo INFINOTED_PLUGIN_RECORD_OPTIONS[] = { { NULL, 0, 0, 0, NULL } }; const InfinotedPlugin INFINOTED_PLUGIN = { "record", N_("Creates a recording of each session that can be replayed later. The " "records are created in the ~/.infinoted-records directory."), INFINOTED_PLUGIN_RECORD_OPTIONS, sizeof(InfinotedPluginRecord), 0, sizeof(InfinotedPluginRecordSessionInfo), "InfAdoptedSession", infinoted_plugin_record_info_initialize, infinoted_plugin_record_initialize, infinoted_plugin_record_deinitialize, NULL, NULL, infinoted_plugin_record_session_added, infinoted_plugin_record_session_removed }; /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/infinoted/plugins/PaxHeaders.26529/util0000644000000000000000000000013013055210725020141 xustar0029 mtime=1488261589.52413792 30 atime=1488261589.516137937 29 ctime=1488261589.52413792 libinfinity-0.7.1/infinoted/plugins/util/0000755000175000017500000000000013055210725020752 5ustar00arminarmin00000000000000libinfinity-0.7.1/infinoted/plugins/util/PaxHeaders.26529/infinoted-plugin-util-navigate-browser.h0000644000000000000000000000013113034342512030070 xustar0030 mtime=1483851082.017718362 30 atime=1483851082.017718362 29 ctime=1488261589.52413792 libinfinity-0.7.1/infinoted/plugins/util/infinoted-plugin-util-navigate-browser.h0000644000175000017500000000430313034342512030623 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INFINOTED_PLUGIN_UTIL_NAVIGATE_BROWSER_H__ #define __INFINOTED_PLUGIN_UTIL_NAVIGATE_BROWSER_H__ #include #include G_BEGIN_DECLS typedef struct _InfinotedPluginUtilNavigateData InfinotedPluginUtilNavigateData; typedef enum _InfinotedPluginUtilNavigateError { INFINOTED_PLUGIN_UTIL_NAVIGATE_ERROR_PATH_NOT_ABSOLUTE, INFINOTED_PLUGIN_UTIL_NAVIGATE_ERROR_NOT_EXIST } InfinotedPluginUtilNavigateError; typedef void(*InfinotedPluginUtilNavigateCallback)(InfBrowser* browser, const InfBrowserIter* iter, const GError* error, gpointer user_data); GQuark infinoted_plugin_util_navigate_error_quark(void); InfinotedPluginUtilNavigateData* infinoted_plugin_util_navigate_to(InfBrowser* browser, const gchar* path, gsize len, gboolean explore_last, InfinotedPluginUtilNavigateCallback cb, gpointer user_data); void infinoted_plugin_util_navigate_cancel(InfinotedPluginUtilNavigateData* data); G_END_DECLS #endif /* __INFINOTED_PLUGIN_UTIL_UNIX_NAVIGATE_BROWSER_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/infinoted/plugins/util/PaxHeaders.26529/infinoted-plugin-util-navigate-browser.c0000644000000000000000000000013113034342512030063 xustar0030 mtime=1483851082.017718362 30 atime=1483851082.017718362 29 ctime=1488261589.52413792 libinfinity-0.7.1/infinoted/plugins/util/infinoted-plugin-util-navigate-browser.c0000644000175000017500000002134513034342512030623 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include #include #include #include struct _InfinotedPluginUtilNavigateData { gboolean initial; gchar* path; gsize len; gsize offset; gboolean explore_last; InfinotedPluginUtilNavigateCallback cb; gpointer user_data; InfRequest* request; }; static void infinoted_plugin_util_navigate_explore_cb(InfRequest* request, const InfRequestResult* result, const GError* error, gpointer user_data); static void infinoted_plugin_util_navigate_one(InfBrowser* browser, const InfBrowserIter* iter, InfinotedPluginUtilNavigateData* data); static void infinoted_plugin_util_navigate_data_done(InfinotedPluginUtilNavigateData* dat, InfBrowser* browser, const InfBrowserIter* iter, const GError* error) { if(dat->request != NULL) { inf_signal_handlers_disconnect_by_func( G_OBJECT(dat->request), G_CALLBACK(infinoted_plugin_util_navigate_explore_cb), dat ); dat->request = NULL; } if(dat->cb != NULL) { dat->cb(browser, iter, error, dat->user_data); dat->cb = NULL; } g_free(dat->path); dat->path = NULL; if(!dat->initial) g_slice_free(InfinotedPluginUtilNavigateData, dat); } static void infinoted_plugin_util_navigate_explored(InfBrowser* browser, const InfBrowserIter* iter, InfinotedPluginUtilNavigateData* data) { InfBrowserIter child_iter; const gchar* name; GError* error; g_assert(inf_browser_is_subdirectory(browser, iter)); g_assert(inf_browser_get_explored(browser, iter)); /* In case we explored the last element */ if(data->offset == data->len) { infinoted_plugin_util_navigate_data_done(data, browser, iter, NULL); return; } /* Find the name of the next element */ gsize sep; for(sep = data->offset; sep < data->len; ++sep) if(data->path[sep] == '/') break; /* Find the node */ child_iter = *iter; if(inf_browser_get_child(browser, &child_iter)) { do { name = inf_browser_get_node_name(browser, &child_iter); if(strncmp(&data->path[data->offset], name, sep - data->offset) == 0 && name[sep - data->offset] == '\0') { /* Found the child node, now proceed with next iteration */ if(sep < data->len) { g_assert(data->path[sep] == '/'); data->offset = sep + 1; } else { data->offset = sep; } infinoted_plugin_util_navigate_one(browser, &child_iter, data); return; } } while(inf_browser_get_next(browser, &child_iter)); } error = NULL; g_set_error( &error, infinoted_plugin_util_navigate_error_quark(), INFINOTED_PLUGIN_UTIL_NAVIGATE_ERROR_NOT_EXIST, _("The path \"%.*s\" does not exist"), (int)sep, data->path ); infinoted_plugin_util_navigate_data_done(data, NULL, NULL, error); g_error_free(error); } static void infinoted_plugin_util_navigate_explore_cb(InfRequest* request, const InfRequestResult* result, const GError* error, gpointer user_data) { InfinotedPluginUtilNavigateData* data; InfBrowser* browser; const InfBrowserIter* iter; GError* prefixed; data = (InfinotedPluginUtilNavigateData*)user_data; g_assert(data->request == NULL || data->request == request); data->request = NULL; if(error != NULL) { /* Failed to explore */ prefixed = NULL; g_propagate_prefixed_error( &prefixed, (GError*)error, /* should be const... */ _("Failed to explore path \"%.*s\": "), (int)data->offset, data->path ); infinoted_plugin_util_navigate_data_done(data, NULL, NULL, prefixed); g_error_free(prefixed); } else { inf_request_result_get_explore_node(result, &browser, &iter); infinoted_plugin_util_navigate_explored(browser, iter, data); } } static void infinoted_plugin_util_navigate_one(InfBrowser* browser, const InfBrowserIter* iter, InfinotedPluginUtilNavigateData* data) { GError* error; InfRequest* request; g_assert(data->request == NULL); g_assert(data->offset <= data->len); if(data->offset == data->len && data->explore_last == FALSE) { infinoted_plugin_util_navigate_data_done(data, browser, iter, NULL); } else { /* We have to proceed further, but can only do this if the current node * is a directory. This case happens when /foo/bar is requested, but * /foo is a leaf node. */ if(!inf_browser_is_subdirectory(browser, iter)) { error = NULL; g_set_error( &error, infinoted_plugin_util_navigate_error_quark(), INFINOTED_PLUGIN_UTIL_NAVIGATE_ERROR_NOT_EXIST, _("The path \"%.*s\" does not exist or is not a directory"), (int)data->len, data->path ); infinoted_plugin_util_navigate_data_done(data, browser, iter, error); } else { if(inf_browser_get_explored(browser, iter)) { infinoted_plugin_util_navigate_explored(browser, iter, data); } else { request = inf_browser_get_pending_request(browser, iter, "explore-node"); if(request == NULL) { request = inf_browser_explore( browser, iter, infinoted_plugin_util_navigate_explore_cb, data ); if(request != NULL) data->request = request; } else { data->request = request; g_signal_connect( G_OBJECT(data->request), "finished", G_CALLBACK(infinoted_plugin_util_navigate_explore_cb), data ); } } } } } GQuark infinoted_plugin_util_navigate_error_quark(void) { return g_quark_from_static_string("INFINOTED_PLUGIN_UTIL_NAVIGATE_ERROR"); } InfinotedPluginUtilNavigateData* infinoted_plugin_util_navigate_to(InfBrowser* browser, const gchar* path, gsize len, gboolean explore_last, InfinotedPluginUtilNavigateCallback cb, gpointer user_data) { GError* error; InfBrowserIter iter; InfinotedPluginUtilNavigateData* data; if(len == 0 || path[0] != '/') { error = NULL; g_set_error( &error, infinoted_plugin_util_navigate_error_quark(), INFINOTED_PLUGIN_UTIL_NAVIGATE_ERROR_PATH_NOT_ABSOLUTE, _("The path \"%.*s\" is not an absolute path"), (int)len, path ); cb(browser, NULL, error, user_data); g_error_free(error); return NULL; } data = g_slice_new(InfinotedPluginUtilNavigateData); data->initial = TRUE; data->path = g_memdup(path, len); data->len = len; data->offset = 1; data->explore_last = explore_last; data->cb = cb; data->user_data = user_data; data->request = NULL; inf_browser_get_root(browser, &iter); infinoted_plugin_util_navigate_one(browser, &iter, data); data->initial = FALSE; if(data->path == NULL) { infinoted_plugin_util_navigate_data_done(data, NULL, NULL, NULL); data = NULL; } return data; } void infinoted_plugin_util_navigate_cancel(InfinotedPluginUtilNavigateData* data) { data->cb = NULL; infinoted_plugin_util_navigate_data_done(data, NULL, NULL, NULL); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/infinoted/plugins/PaxHeaders.26529/infinoted-plugin-transformation-protection.c0000644000000000000000000000013213034342512030107 xustar0030 mtime=1483851082.017718362 30 atime=1483851082.017718362 30 ctime=1488261589.540137884 libinfinity-0.7.1/infinoted/plugins/infinoted-plugin-transformation-protection.c0000644000175000017500000001715713034342512030654 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include #include #include #include #include #include typedef struct _InfinotedPluginTransformationProtection InfinotedPluginTransformationProtection; struct _InfinotedPluginTransformationProtection { InfinotedPluginManager* manager; guint max_vdiff; }; typedef struct _InfinotedPluginTransformationProtectionSessionInfo InfinotedPluginTransformationProtectionSessionInfo; struct _InfinotedPluginTransformationProtectionSessionInfo { InfinotedPluginTransformationProtection* plugin; InfSessionProxy* proxy; InfBrowserIter iter; }; static gboolean infinoted_plugin_transformation_protection_check_request_cb(InfAdoptedSession* session, InfAdoptedRequest* request, InfAdoptedUser* user, gpointer user_data) { InfinotedPluginTransformationProtectionSessionInfo* info; guint vdiff; InfXmlConnection* connection; gchar* request_str; gchar* current_str; gchar* remote_id; gchar* path; info = (InfinotedPluginTransformationProtectionSessionInfo*)user_data; vdiff = inf_adopted_state_vector_vdiff( inf_adopted_request_get_vector(request), inf_adopted_algorithm_get_current( inf_adopted_session_get_algorithm(session) ) ); if(vdiff > info->plugin->max_vdiff) { connection = inf_user_get_connection(INF_USER(user)); /* Local requests do not need to be transformed, so always have a * zero vdiff. */ g_assert(connection != NULL); /* Kill the connection */ infd_session_proxy_unsubscribe( INFD_SESSION_PROXY(info->proxy), connection ); /* Write a log message */ path = inf_browser_get_path( INF_BROWSER( infinoted_plugin_manager_get_directory(info->plugin->manager) ), &info->iter ); request_str = inf_adopted_state_vector_to_string( inf_adopted_request_get_vector(request) ); current_str = inf_adopted_state_vector_to_string( inf_adopted_algorithm_get_current( inf_adopted_session_get_algorithm(session) ) ); g_object_get(G_OBJECT(connection), "remote-id", &remote_id, NULL); infinoted_log_warning( infinoted_plugin_manager_get_log(info->plugin->manager), _("In document \"%s\": Attempt to transform request \"%s\" to current state \"%s\" " "(vdiff=%u) by user \"%s\" (id=%u, conn=%s). Maximum allowed is %u; the " "connection has been unsubscribed."), path, request_str, current_str, vdiff, inf_user_get_name(INF_USER(user)), inf_user_get_id(INF_USER(user)), remote_id, info->plugin->max_vdiff ); g_free(path); g_free(request_str); g_free(current_str); g_free(remote_id); /* Prevent the request from being transformed */ return TRUE; } return FALSE; } static gboolean infinoted_plugin_transformation_protection_initialize( InfinotedPluginManager* manager, gpointer plugin_info, GError** error) { InfinotedPluginTransformationProtection* plugin; plugin = (InfinotedPluginTransformationProtection*)plugin_info; plugin->manager = manager; return TRUE; } static void infinoted_plugin_transformation_protection_deinitialize(gpointer plugin_info) { InfinotedPluginTransformationProtection* plugin; plugin = (InfinotedPluginTransformationProtection*)plugin_info; } static void infinoted_plugin_transformation_protection_session_added( const InfBrowserIter* iter, InfSessionProxy* proxy, gpointer plugin_info, gpointer session_info) { InfinotedPluginTransformationProtectionSessionInfo* info; InfSession* session; info = (InfinotedPluginTransformationProtectionSessionInfo*)session_info; info->plugin = (InfinotedPluginTransformationProtection*)plugin_info; info->proxy = proxy; info->iter = *iter; g_object_ref(proxy); g_object_get(G_OBJECT(proxy), "session", &session, NULL); g_assert(INF_ADOPTED_IS_SESSION(session)); /* TODO: Check that the subscription group of session uses the central method */ g_signal_connect( G_OBJECT(session), "check-request", G_CALLBACK(infinoted_plugin_transformation_protection_check_request_cb), info ); g_object_unref(session); } static void infinoted_plugin_transformation_protection_session_removed( const InfBrowserIter* iter, InfSessionProxy* proxy, gpointer plugin_info, gpointer session_info) { InfinotedPluginTransformationProtectionSessionInfo* info; InfSession* session; info = (InfinotedPluginTransformationProtectionSessionInfo*)session_info; g_object_get(G_OBJECT(proxy), "session", &session, NULL); inf_signal_handlers_disconnect_by_func( G_OBJECT(session), G_CALLBACK(infinoted_plugin_transformation_protection_check_request_cb), info ); g_object_unref(info->proxy); g_object_unref(session); } static const InfinotedParameterInfo INFINOTED_PLUGIN_TRANSFORMATION_PROTECTION_OPTIONS[] = { { "max-vdiff", INFINOTED_PARAMETER_INT, INFINOTED_PARAMETER_REQUIRED, offsetof(InfinotedPluginTransformationProtection, max_vdiff), infinoted_parameter_convert_nonnegative, 0, N_("The maximum number of individual transformations to allow. If a " "client makes a request that would require more than this number of " "transformations, the request is rejected and the client is " "unsubscribed from the session."), N_("DIFF") }, { NULL, 0, 0, 0, NULL } }; const InfinotedPlugin INFINOTED_PLUGIN = { "transformation-protection", N_("This plugin tries to protect the server from malicious clients that " "send formally valid requests but would take the server a long time " "to process, making in unresponsive to other requests. This is only " "possible if sessions use the \"central\" communication method. At the " "moment this is the only method available, so the plugin can always be " "used. Currently the plugin rejects requests that were made in a state " "too far behind the current state. However, additional criteria might " "be implemented in future versions."), INFINOTED_PLUGIN_TRANSFORMATION_PROTECTION_OPTIONS, sizeof(InfinotedPluginTransformationProtection), 0, sizeof(InfinotedPluginTransformationProtectionSessionInfo), "InfAdoptedSession", NULL, infinoted_plugin_transformation_protection_initialize, infinoted_plugin_transformation_protection_deinitialize, NULL, NULL, infinoted_plugin_transformation_protection_session_added, infinoted_plugin_transformation_protection_session_removed }; /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/infinoted/plugins/PaxHeaders.26529/infinoted-plugin-autosave.c0000644000000000000000000000013213034342512024504 xustar0030 mtime=1483851082.017718362 30 atime=1483851082.017718362 30 ctime=1488261589.520137928 libinfinity-0.7.1/infinoted/plugins/infinoted-plugin-autosave.c0000644000175000017500000002316513034342512025245 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include typedef struct _InfinotedPluginAutosave InfinotedPluginAutosave; struct _InfinotedPluginAutosave { InfinotedPluginManager* manager; guint interval; gchar* hook; }; typedef struct _InfinotedPluginAutosaveSessionInfo InfinotedPluginAutosaveSessionInfo; struct _InfinotedPluginAutosaveSessionInfo { InfinotedPluginAutosave* plugin; InfBrowserIter iter; InfSessionProxy* proxy; InfIoTimeout* timeout; }; static void infinoted_plugin_autosave_timeout_cb(gpointer user_data); static void infinoted_plugin_autosave_start(InfinotedPluginAutosaveSessionInfo* info) { InfIo* io; io = infd_directory_get_io( infinoted_plugin_manager_get_directory(info->plugin->manager) ); g_assert(info->timeout == NULL); info->timeout = inf_io_add_timeout( io, info->plugin->interval * 1000, infinoted_plugin_autosave_timeout_cb, info, NULL ); } static void infinoted_plugin_autosave_stop(InfinotedPluginAutosaveSessionInfo* info) { InfIo* io; io = infd_directory_get_io( infinoted_plugin_manager_get_directory(info->plugin->manager) ); g_assert(info->timeout != NULL); inf_io_remove_timeout(io, info->timeout); info->timeout = NULL; } static void infinoted_plugin_autosave_buffer_notify_modified_cb(GObject* object, GParamSpec* pspec, gpointer user_data) { InfinotedPluginAutosaveSessionInfo* info; InfSession* session; InfBuffer* buffer; info = (InfinotedPluginAutosaveSessionInfo*)user_data; g_object_get(G_OBJECT(info->proxy), "session", &session, NULL); buffer = inf_session_get_buffer(session); if(inf_buffer_get_modified(buffer) == TRUE) { if(info->timeout == NULL) infinoted_plugin_autosave_start(info); } else { if(info->timeout != NULL) infinoted_plugin_autosave_stop(info); } g_object_unref(session); } static void infinoted_plugin_autosave_save(InfinotedPluginAutosaveSessionInfo* info) { InfdDirectory* directory; InfBrowserIter* iter; GError* error; gchar* path; InfSession* session; InfBuffer* buffer; gchar* root_directory; gchar* argv[4]; directory = infinoted_plugin_manager_get_directory(info->plugin->manager); iter = &info->iter; error = NULL; if(info->timeout != NULL) { inf_io_remove_timeout(infd_directory_get_io(directory), info->timeout); info->timeout = NULL; } g_object_get(G_OBJECT(info->proxy), "session", &session, NULL); buffer = inf_session_get_buffer(session); inf_signal_handlers_block_by_func( G_OBJECT(buffer), G_CALLBACK(infinoted_plugin_autosave_buffer_notify_modified_cb), info ); if(infd_directory_iter_save_session(directory, iter, &error) == FALSE) { path = inf_browser_get_path(INF_BROWSER(directory), iter); infinoted_log_warning( infinoted_plugin_manager_get_log(info->plugin->manager), _("Failed to auto-save session \"%s\": %s\n\n" "Will retry in %u seconds."), path, error->message, info->plugin->interval ); g_free(path); g_error_free(error); error = NULL; infinoted_plugin_autosave_start(info); } else { /* TODO: Remove this as soon as directory itself unsets modified flag * on session_write */ inf_buffer_set_modified(INF_BUFFER(buffer), FALSE); if(info->plugin->hook != NULL) { path = inf_browser_get_path(INF_BROWSER(directory), iter); g_object_get( G_OBJECT(infd_directory_get_storage(directory)), "root-directory", &root_directory, NULL ); argv[0] = info->plugin->hook; argv[1] = root_directory; argv[2] = path; argv[3] = NULL; if(!g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, &error)) { infinoted_log_warning( infinoted_plugin_manager_get_log(info->plugin->manager), _("Could not execute autosave hook: \"%s\""), error->message ); g_error_free(error); error = NULL; } g_free(path); g_free(root_directory); } } inf_signal_handlers_unblock_by_func( G_OBJECT(buffer), G_CALLBACK(infinoted_plugin_autosave_buffer_notify_modified_cb), info ); g_object_unref(session); } static void infinoted_plugin_autosave_timeout_cb(gpointer user_data) { InfinotedPluginAutosaveSessionInfo* info; info = (InfinotedPluginAutosaveSessionInfo*)user_data; info->timeout = NULL; infinoted_plugin_autosave_save(info); } static void infinoted_plugin_autosave_info_initialize(gpointer plugin_info) { InfinotedPluginAutosave* plugin; plugin = (InfinotedPluginAutosave*)plugin_info; plugin->manager = NULL; plugin->interval = 0; plugin->hook = NULL; } static gboolean infinoted_plugin_autosave_initialize(InfinotedPluginManager* manager, gpointer plugin_info, GError** error) { InfinotedPluginAutosave* plugin; plugin = (InfinotedPluginAutosave*)plugin_info; plugin->manager = manager; return TRUE; } static void infinoted_plugin_autosave_deinitialize(gpointer plugin_info) { InfinotedPluginAutosave* plugin; plugin = (InfinotedPluginAutosave*)plugin_info; g_free(plugin->hook); } static void infinoted_plugin_autosave_session_added(const InfBrowserIter* iter, InfSessionProxy* proxy, gpointer plugin_info, gpointer session_info) { InfinotedPluginAutosaveSessionInfo* info; InfSession* session; InfBuffer* buffer; info = (InfinotedPluginAutosaveSessionInfo*)session_info; info->plugin = (InfinotedPluginAutosave*)plugin_info; info->iter = *iter; info->proxy = proxy; info->timeout = NULL; g_object_ref(proxy); g_object_get(G_OBJECT(proxy), "session", &session, NULL); buffer = inf_session_get_buffer(session); g_signal_connect( G_OBJECT(buffer), "notify::modified", G_CALLBACK(infinoted_plugin_autosave_buffer_notify_modified_cb), info ); if(inf_buffer_get_modified(buffer) == TRUE) infinoted_plugin_autosave_start(info); g_object_unref(session); } static void infinoted_plugin_autosave_session_removed(const InfBrowserIter* iter, InfSessionProxy* proxy, gpointer plugin_info, gpointer session_info) { InfinotedPluginAutosaveSessionInfo* info; InfSession* session; InfBuffer* buffer; info = (InfinotedPluginAutosaveSessionInfo*)session_info; /* Cancel autosave timeout even if session is modified. If the directory * removed the session, then it has already saved it anyway. */ if(info->timeout != NULL) infinoted_plugin_autosave_stop(info); g_object_get(G_OBJECT(info->proxy), "session", &session, NULL); buffer = inf_session_get_buffer(session); inf_signal_handlers_disconnect_by_func( G_OBJECT(buffer), G_CALLBACK(infinoted_plugin_autosave_buffer_notify_modified_cb), info ); g_object_unref(session); g_object_unref(info->proxy); } static const InfinotedParameterInfo INFINOTED_PLUGIN_AUTOSAVE_OPTIONS[] = { { "interval", INFINOTED_PARAMETER_INT, INFINOTED_PARAMETER_REQUIRED, offsetof(InfinotedPluginAutosave, interval), infinoted_parameter_convert_positive, 0, N_("Interval, in seconds, after which to save documents into the root " "directory. Documents are also stored to disk when there has been " "no user logged into them for 60 seconds."), N_("SECONDS") }, { "hook", INFINOTED_PARAMETER_STRING, 0, offsetof(InfinotedPluginAutosave, hook), infinoted_parameter_convert_filename, 0, N_("Command to run after having saved a document."), N_("PROGRAM") }, { NULL, 0, 0, 0, NULL } }; const InfinotedPlugin INFINOTED_PLUGIN = { "autosave", N_("Periodically saves the content of all documents to disk. If this " "plugin is not enabled, infinoted only moves a document to permanent " "storage 60 seconds after the last user left the document."), INFINOTED_PLUGIN_AUTOSAVE_OPTIONS, sizeof(InfinotedPluginAutosave), 0, sizeof(InfinotedPluginAutosaveSessionInfo), NULL, infinoted_plugin_autosave_info_initialize, infinoted_plugin_autosave_initialize, infinoted_plugin_autosave_deinitialize, NULL, NULL, infinoted_plugin_autosave_session_added, infinoted_plugin_autosave_session_removed }; /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/infinoted/PaxHeaders.26529/Makefile.in0000644000000000000000000000013113051241007017617 xustar0030 mtime=1487225351.869148942 30 atime=1487225351.869148942 29 ctime=1488261589.46013806 libinfinity-0.7.1/infinoted/Makefile.in0000644000175000017500000017740713051241007020372 0ustar00arminarmin00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 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__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) 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@ bin_PROGRAMS = infinoted-0.7$(EXEEXT) subdir = infinoted ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/gtk-doc.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am \ $(libinfinoted_plugin_manager_0_7_la_HEADERS) \ $(noinst_HEADERS) $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/libinfinity/inf-config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \ "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(girdir)" \ "$(DESTDIR)$(pidfiledir)" "$(DESTDIR)$(typelibdir)" \ "$(DESTDIR)$(libinfinoted_plugin_manager_0_7_ladir)" LTLIBRARIES = $(lib_LTLIBRARIES) am__DEPENDENCIES_1 = libinfinoted_plugin_manager_0_7_la_DEPENDENCIES = ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) am_libinfinoted_plugin_manager_0_7_la_OBJECTS = \ libinfinoted_plugin_manager_0_7_la-infinoted-log.lo \ libinfinoted_plugin_manager_0_7_la-infinoted-parameter.lo \ libinfinoted_plugin_manager_0_7_la-infinoted-plugin-manager.lo \ libinfinoted_plugin_manager_0_7_la-infinoted-util.lo libinfinoted_plugin_manager_0_7_la_OBJECTS = \ $(am_libinfinoted_plugin_manager_0_7_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libinfinoted_plugin_manager_0_7_la_LINK = $(LIBTOOL) $(AM_V_lt) \ --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(libinfinoted_plugin_manager_0_7_la_LDFLAGS) $(LDFLAGS) -o $@ PROGRAMS = $(bin_PROGRAMS) am_infinoted_0_7_OBJECTS = \ infinoted_0_7-infinoted-config-reload.$(OBJEXT) \ infinoted_0_7-infinoted-dh-params.$(OBJEXT) \ infinoted_0_7-infinoted-main.$(OBJEXT) \ infinoted_0_7-infinoted-options.$(OBJEXT) \ infinoted_0_7-infinoted-pam.$(OBJEXT) \ infinoted_0_7-infinoted-run.$(OBJEXT) \ infinoted_0_7-infinoted-signal.$(OBJEXT) \ infinoted_0_7-infinoted-startup.$(OBJEXT) infinoted_0_7_OBJECTS = $(am_infinoted_0_7_OBJECTS) infinoted_0_7_DEPENDENCIES = \ libinfinoted-plugin-manager-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) -I$(top_builddir)/libinfinity 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_CC_1 = 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_CCLD_1 = SOURCES = $(libinfinoted_plugin_manager_0_7_la_SOURCES) \ $(infinoted_0_7_SOURCES) DIST_SOURCES = $(libinfinoted_plugin_manager_0_7_la_SOURCES) \ $(infinoted_0_7_SOURCES) RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac man1dir = $(mandir)/man1 NROFF = nroff MANS = $(dist_man1_MANS) DATA = $(gir_DATA) $(pidfile_DATA) $(typelib_DATA) HEADERS = $(libinfinoted_plugin_manager_0_7_la_HEADERS) \ $(noinst_HEADERS) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) am__DIST_COMMON = $(dist_man1_MANS) $(srcdir)/Makefile.in \ $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ 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@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIRNAME = @DATADIRNAME@ 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@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ GTKDOC_CHECK = @GTKDOC_CHECK@ GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ GTKDOC_MKPDF = @GTKDOC_MKPDF@ GTKDOC_REBASE = @GTKDOC_REBASE@ HTML_DIR = @HTML_DIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INSTOBJEXT = @INSTOBJEXT@ INTLLIBS = @INTLLIBS@ INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBINFINITY_API_VERSION = @LIBINFINITY_API_VERSION@ LIBINFINITY_LIBTOOL_VERSION = @LIBINFINITY_LIBTOOL_VERSION@ LIBINFINITY_VERSION = @LIBINFINITY_VERSION@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGFMT_OPTS = @MSGFMT_OPTS@ 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@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ 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@ avahi_CFLAGS = @avahi_CFLAGS@ avahi_LIBS = @avahi_LIBS@ 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@ gio_CFLAGS = @gio_CFLAGS@ gio_LIBS = @gio_LIBS@ gtk_requirement = @gtk_requirement@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infgtk_CFLAGS = @infgtk_CFLAGS@ infgtk_LIBS = @infgtk_LIBS@ infinity_CFLAGS = @infinity_CFLAGS@ infinity_LIBS = @infinity_LIBS@ infinoted_CFLAGS = @infinoted_CFLAGS@ infinoted_LIBS = @infinoted_LIBS@ infodir = @infodir@ inftext_CFLAGS = @inftext_CFLAGS@ inftext_LIBS = @inftext_LIBS@ inftextgtk_CFLAGS = @inftextgtk_CFLAGS@ inftextgtk_LIBS = @inftextgtk_LIBS@ install_sh = @install_sh@ libdaemon_CFLAGS = @libdaemon_CFLAGS@ libdaemon_LIBS = @libdaemon_LIBS@ 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@ runstatedir = @runstatedir@ 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@ SUBDIRS = . plugins dist_man1_MANS = infinoted-0.7.man plugin_path = infinoted-$(LIBINFINITY_API_VERSION)/plugins # Compile the plugin manager as a shared library: # TODO: Find a way to have the version number set automatically. lib_LTLIBRARIES = libinfinoted-plugin-manager-0.7.la libinfinoted_plugin_manager_0_7_la_CPPFLAGS = \ -I$(top_srcdir) \ $(infinoted_CFLAGS) \ $(infinity_CFLAGS) \ -DPLUGIN_LIBPATH=\"${libdir}\" \ -DPLUGIN_PATH=\"${plugin_path}\" \ -DLOCALSTATEDIR=\"${localstatedir}\" \ -DLIBINFINITY_API_VERSION=\"$(LIBINFINITY_API_VERSION)\" libinfinoted_plugin_manager_0_7_la_LDFLAGS = \ -no-undefined \ -version-info $(LIBINFINITY_LIBTOOL_VERSION) libinfinoted_plugin_manager_0_7_la_LIBADD = \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(infinoted_LIBS) \ $(infinity_LIBS) \ $(libdaemon_LIBS) libinfinoted_plugin_manager_0_7_la_SOURCES = \ infinoted-log.c \ infinoted-parameter.c \ infinoted-plugin-manager.c \ infinoted-util.c libinfinoted_plugin_manager_0_7_la_HEADERS = \ infinoted-log.h \ infinoted-parameter.h \ infinoted-plugin-manager.h \ infinoted-util.h libinfinoted_plugin_manager_0_7_ladir = \ $(includedir)/libinfinoted-plugin-manager-$(LIBINFINITY_API_VERSION)/infinoted # Compile the rest of infinoted as an executable binary infinoted_0_7_CPPFLAGS = \ -I${top_srcdir} \ $(infinoted_CFLAGS) \ $(infinity_CFLAGS) \ -DPLUGIN_LIBPATH=\"${libdir}\" \ -DPLUGIN_PATH=\"${plugin_path}\" \ -DLOCALSTATEDIR=\"${localstatedir}\" \ -DLIBINFINITY_API_VERSION=\"$(LIBINFINITY_API_VERSION)\" infinoted_0_7_LDADD = \ libinfinoted-plugin-manager-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(infinoted_LIBS) \ $(infinity_LIBS) \ $(libdaemon_LIBS) infinoted_0_7_SOURCES = \ infinoted-config-reload.c \ infinoted-dh-params.c \ infinoted-main.c \ infinoted-options.c \ infinoted-pam.c \ infinoted-run.c \ infinoted-signal.c \ infinoted-startup.c noinst_HEADERS = \ infinoted-config-reload.h \ infinoted-dh-params.h \ infinoted-options.h \ infinoted-pam.h \ infinoted-run.h \ infinoted-signal.h \ infinoted-startup.h # Create pid file directory pidfiledir = ${localstatedir}/run/infinoted-$(LIBINFINITY_API_VERSION) pidfile_DATA = @HAVE_INTROSPECTION_TRUE@INTROSPECTION_GIRS = Infinoted-0.7.gir @HAVE_INTROSPECTION_TRUE@INTROSPECTION_SCANNER_ENV = CC="${CC}" @HAVE_INTROSPECTION_TRUE@INTROSPECTION_COMPILER_ARGS = \ @HAVE_INTROSPECTION_TRUE@ --includedir=${top_srcdir}/libinfinity \ @HAVE_INTROSPECTION_TRUE@ --includedir=${top_builddir}/libinfinity \ @HAVE_INTROSPECTION_TRUE@ --includedir=${top_builddir}/libinftext @HAVE_INTROSPECTION_TRUE@Infinoted_0_7_gir_SCANNERFLAGS = \ @HAVE_INTROSPECTION_TRUE@ -I${top_srcdir} \ @HAVE_INTROSPECTION_TRUE@ --add-include-path=$(top_srcdir)/libinfinity \ @HAVE_INTROSPECTION_TRUE@ --add-include-path=$(top_builddir)/libinfinity \ @HAVE_INTROSPECTION_TRUE@ -n Infinoted \ @HAVE_INTROSPECTION_TRUE@ --identifier-prefix=Infinoted \ @HAVE_INTROSPECTION_TRUE@ --warn-all @HAVE_INTROSPECTION_TRUE@Infinoted_0_7_gir_NAMESPACE = Infinoted @HAVE_INTROSPECTION_TRUE@Infinoted_0_7_gir_VERSION = 0.7 @HAVE_INTROSPECTION_TRUE@Infinoted_0_7_gir_CFLAGS = $(infinoted_CFLAGS) $(infinity_CFLAGS) @HAVE_INTROSPECTION_TRUE@Infinoted_0_7_gir_LIBS = libinfinoted-plugin-manager-0.7.la @HAVE_INTROSPECTION_TRUE@Infinoted_0_7_gir_FILES = \ @HAVE_INTROSPECTION_TRUE@ $(libinfinoted_plugin_manager_0_7_la_SOURCES) \ @HAVE_INTROSPECTION_TRUE@ $(libinfinoted_plugin_manager_0_7_la_HEADERS) @HAVE_INTROSPECTION_TRUE@Infinoted_0_7_gir_INCLUDES = Infinity-0.7 Infinityd-0.7 @HAVE_INTROSPECTION_TRUE@Infinoted_0_7_gir_PACKAGES = gobject-2.0 @HAVE_INTROSPECTION_TRUE@Infinoted_0_7_gir_EXPORT_PACKAGES = libinfinoted-plugin-manager-0.7 @HAVE_INTROSPECTION_TRUE@girdir = $(datadir)/gir-1.0 @HAVE_INTROSPECTION_TRUE@gir_DATA = Infinoted-0.7.gir @HAVE_INTROSPECTION_TRUE@typelibdir = $(libdir)/girepository-1.0 @HAVE_INTROSPECTION_TRUE@typelib_DATA = Infinoted-0.7.typelib @HAVE_INTROSPECTION_TRUE@CLEANFILES = \ @HAVE_INTROSPECTION_TRUE@ $(gir_DATA) \ @HAVE_INTROSPECTION_TRUE@ $(typelib_DATA) all: all-recursive .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(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) --foreign infinoted/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign infinoted/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: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libinfinoted-plugin-manager-0.7.la: $(libinfinoted_plugin_manager_0_7_la_OBJECTS) $(libinfinoted_plugin_manager_0_7_la_DEPENDENCIES) $(EXTRA_libinfinoted_plugin_manager_0_7_la_DEPENDENCIES) $(AM_V_CCLD)$(libinfinoted_plugin_manager_0_7_la_LINK) -rpath $(libdir) $(libinfinoted_plugin_manager_0_7_la_OBJECTS) $(libinfinoted_plugin_manager_0_7_la_LIBADD) $(LIBS) install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || 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)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || 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)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_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 infinoted-0.7$(EXEEXT): $(infinoted_0_7_OBJECTS) $(infinoted_0_7_DEPENDENCIES) $(EXTRA_infinoted_0_7_DEPENDENCIES) @rm -f infinoted-0.7$(EXEEXT) $(AM_V_CCLD)$(LINK) $(infinoted_0_7_OBJECTS) $(infinoted_0_7_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/infinoted_0_7-infinoted-config-reload.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/infinoted_0_7-infinoted-dh-params.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/infinoted_0_7-infinoted-main.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/infinoted_0_7-infinoted-options.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/infinoted_0_7-infinoted-pam.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/infinoted_0_7-infinoted-run.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/infinoted_0_7-infinoted-signal.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/infinoted_0_7-infinoted-startup.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libinfinoted_plugin_manager_0_7_la-infinoted-log.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libinfinoted_plugin_manager_0_7_la-infinoted-parameter.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libinfinoted_plugin_manager_0_7_la-infinoted-plugin-manager.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libinfinoted_plugin_manager_0_7_la-infinoted-util.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.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 -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.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 -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.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 $@ $< libinfinoted_plugin_manager_0_7_la-infinoted-log.lo: infinoted-log.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinoted_plugin_manager_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libinfinoted_plugin_manager_0_7_la-infinoted-log.lo -MD -MP -MF $(DEPDIR)/libinfinoted_plugin_manager_0_7_la-infinoted-log.Tpo -c -o libinfinoted_plugin_manager_0_7_la-infinoted-log.lo `test -f 'infinoted-log.c' || echo '$(srcdir)/'`infinoted-log.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libinfinoted_plugin_manager_0_7_la-infinoted-log.Tpo $(DEPDIR)/libinfinoted_plugin_manager_0_7_la-infinoted-log.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='infinoted-log.c' object='libinfinoted_plugin_manager_0_7_la-infinoted-log.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) $(libinfinoted_plugin_manager_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libinfinoted_plugin_manager_0_7_la-infinoted-log.lo `test -f 'infinoted-log.c' || echo '$(srcdir)/'`infinoted-log.c libinfinoted_plugin_manager_0_7_la-infinoted-parameter.lo: infinoted-parameter.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinoted_plugin_manager_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libinfinoted_plugin_manager_0_7_la-infinoted-parameter.lo -MD -MP -MF $(DEPDIR)/libinfinoted_plugin_manager_0_7_la-infinoted-parameter.Tpo -c -o libinfinoted_plugin_manager_0_7_la-infinoted-parameter.lo `test -f 'infinoted-parameter.c' || echo '$(srcdir)/'`infinoted-parameter.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libinfinoted_plugin_manager_0_7_la-infinoted-parameter.Tpo $(DEPDIR)/libinfinoted_plugin_manager_0_7_la-infinoted-parameter.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='infinoted-parameter.c' object='libinfinoted_plugin_manager_0_7_la-infinoted-parameter.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) $(libinfinoted_plugin_manager_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libinfinoted_plugin_manager_0_7_la-infinoted-parameter.lo `test -f 'infinoted-parameter.c' || echo '$(srcdir)/'`infinoted-parameter.c libinfinoted_plugin_manager_0_7_la-infinoted-plugin-manager.lo: infinoted-plugin-manager.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinoted_plugin_manager_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libinfinoted_plugin_manager_0_7_la-infinoted-plugin-manager.lo -MD -MP -MF $(DEPDIR)/libinfinoted_plugin_manager_0_7_la-infinoted-plugin-manager.Tpo -c -o libinfinoted_plugin_manager_0_7_la-infinoted-plugin-manager.lo `test -f 'infinoted-plugin-manager.c' || echo '$(srcdir)/'`infinoted-plugin-manager.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libinfinoted_plugin_manager_0_7_la-infinoted-plugin-manager.Tpo $(DEPDIR)/libinfinoted_plugin_manager_0_7_la-infinoted-plugin-manager.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='infinoted-plugin-manager.c' object='libinfinoted_plugin_manager_0_7_la-infinoted-plugin-manager.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) $(libinfinoted_plugin_manager_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libinfinoted_plugin_manager_0_7_la-infinoted-plugin-manager.lo `test -f 'infinoted-plugin-manager.c' || echo '$(srcdir)/'`infinoted-plugin-manager.c libinfinoted_plugin_manager_0_7_la-infinoted-util.lo: infinoted-util.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinoted_plugin_manager_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libinfinoted_plugin_manager_0_7_la-infinoted-util.lo -MD -MP -MF $(DEPDIR)/libinfinoted_plugin_manager_0_7_la-infinoted-util.Tpo -c -o libinfinoted_plugin_manager_0_7_la-infinoted-util.lo `test -f 'infinoted-util.c' || echo '$(srcdir)/'`infinoted-util.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libinfinoted_plugin_manager_0_7_la-infinoted-util.Tpo $(DEPDIR)/libinfinoted_plugin_manager_0_7_la-infinoted-util.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='infinoted-util.c' object='libinfinoted_plugin_manager_0_7_la-infinoted-util.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) $(libinfinoted_plugin_manager_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libinfinoted_plugin_manager_0_7_la-infinoted-util.lo `test -f 'infinoted-util.c' || echo '$(srcdir)/'`infinoted-util.c infinoted_0_7-infinoted-config-reload.o: infinoted-config-reload.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(infinoted_0_7_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT infinoted_0_7-infinoted-config-reload.o -MD -MP -MF $(DEPDIR)/infinoted_0_7-infinoted-config-reload.Tpo -c -o infinoted_0_7-infinoted-config-reload.o `test -f 'infinoted-config-reload.c' || echo '$(srcdir)/'`infinoted-config-reload.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/infinoted_0_7-infinoted-config-reload.Tpo $(DEPDIR)/infinoted_0_7-infinoted-config-reload.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='infinoted-config-reload.c' object='infinoted_0_7-infinoted-config-reload.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) $(infinoted_0_7_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o infinoted_0_7-infinoted-config-reload.o `test -f 'infinoted-config-reload.c' || echo '$(srcdir)/'`infinoted-config-reload.c infinoted_0_7-infinoted-config-reload.obj: infinoted-config-reload.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(infinoted_0_7_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT infinoted_0_7-infinoted-config-reload.obj -MD -MP -MF $(DEPDIR)/infinoted_0_7-infinoted-config-reload.Tpo -c -o infinoted_0_7-infinoted-config-reload.obj `if test -f 'infinoted-config-reload.c'; then $(CYGPATH_W) 'infinoted-config-reload.c'; else $(CYGPATH_W) '$(srcdir)/infinoted-config-reload.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/infinoted_0_7-infinoted-config-reload.Tpo $(DEPDIR)/infinoted_0_7-infinoted-config-reload.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='infinoted-config-reload.c' object='infinoted_0_7-infinoted-config-reload.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) $(infinoted_0_7_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o infinoted_0_7-infinoted-config-reload.obj `if test -f 'infinoted-config-reload.c'; then $(CYGPATH_W) 'infinoted-config-reload.c'; else $(CYGPATH_W) '$(srcdir)/infinoted-config-reload.c'; fi` infinoted_0_7-infinoted-dh-params.o: infinoted-dh-params.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(infinoted_0_7_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT infinoted_0_7-infinoted-dh-params.o -MD -MP -MF $(DEPDIR)/infinoted_0_7-infinoted-dh-params.Tpo -c -o infinoted_0_7-infinoted-dh-params.o `test -f 'infinoted-dh-params.c' || echo '$(srcdir)/'`infinoted-dh-params.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/infinoted_0_7-infinoted-dh-params.Tpo $(DEPDIR)/infinoted_0_7-infinoted-dh-params.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='infinoted-dh-params.c' object='infinoted_0_7-infinoted-dh-params.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) $(infinoted_0_7_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o infinoted_0_7-infinoted-dh-params.o `test -f 'infinoted-dh-params.c' || echo '$(srcdir)/'`infinoted-dh-params.c infinoted_0_7-infinoted-dh-params.obj: infinoted-dh-params.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(infinoted_0_7_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT infinoted_0_7-infinoted-dh-params.obj -MD -MP -MF $(DEPDIR)/infinoted_0_7-infinoted-dh-params.Tpo -c -o infinoted_0_7-infinoted-dh-params.obj `if test -f 'infinoted-dh-params.c'; then $(CYGPATH_W) 'infinoted-dh-params.c'; else $(CYGPATH_W) '$(srcdir)/infinoted-dh-params.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/infinoted_0_7-infinoted-dh-params.Tpo $(DEPDIR)/infinoted_0_7-infinoted-dh-params.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='infinoted-dh-params.c' object='infinoted_0_7-infinoted-dh-params.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) $(infinoted_0_7_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o infinoted_0_7-infinoted-dh-params.obj `if test -f 'infinoted-dh-params.c'; then $(CYGPATH_W) 'infinoted-dh-params.c'; else $(CYGPATH_W) '$(srcdir)/infinoted-dh-params.c'; fi` infinoted_0_7-infinoted-main.o: infinoted-main.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(infinoted_0_7_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT infinoted_0_7-infinoted-main.o -MD -MP -MF $(DEPDIR)/infinoted_0_7-infinoted-main.Tpo -c -o infinoted_0_7-infinoted-main.o `test -f 'infinoted-main.c' || echo '$(srcdir)/'`infinoted-main.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/infinoted_0_7-infinoted-main.Tpo $(DEPDIR)/infinoted_0_7-infinoted-main.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='infinoted-main.c' object='infinoted_0_7-infinoted-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) $(infinoted_0_7_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o infinoted_0_7-infinoted-main.o `test -f 'infinoted-main.c' || echo '$(srcdir)/'`infinoted-main.c infinoted_0_7-infinoted-main.obj: infinoted-main.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(infinoted_0_7_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT infinoted_0_7-infinoted-main.obj -MD -MP -MF $(DEPDIR)/infinoted_0_7-infinoted-main.Tpo -c -o infinoted_0_7-infinoted-main.obj `if test -f 'infinoted-main.c'; then $(CYGPATH_W) 'infinoted-main.c'; else $(CYGPATH_W) '$(srcdir)/infinoted-main.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/infinoted_0_7-infinoted-main.Tpo $(DEPDIR)/infinoted_0_7-infinoted-main.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='infinoted-main.c' object='infinoted_0_7-infinoted-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) $(infinoted_0_7_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o infinoted_0_7-infinoted-main.obj `if test -f 'infinoted-main.c'; then $(CYGPATH_W) 'infinoted-main.c'; else $(CYGPATH_W) '$(srcdir)/infinoted-main.c'; fi` infinoted_0_7-infinoted-options.o: infinoted-options.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(infinoted_0_7_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT infinoted_0_7-infinoted-options.o -MD -MP -MF $(DEPDIR)/infinoted_0_7-infinoted-options.Tpo -c -o infinoted_0_7-infinoted-options.o `test -f 'infinoted-options.c' || echo '$(srcdir)/'`infinoted-options.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/infinoted_0_7-infinoted-options.Tpo $(DEPDIR)/infinoted_0_7-infinoted-options.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='infinoted-options.c' object='infinoted_0_7-infinoted-options.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) $(infinoted_0_7_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o infinoted_0_7-infinoted-options.o `test -f 'infinoted-options.c' || echo '$(srcdir)/'`infinoted-options.c infinoted_0_7-infinoted-options.obj: infinoted-options.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(infinoted_0_7_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT infinoted_0_7-infinoted-options.obj -MD -MP -MF $(DEPDIR)/infinoted_0_7-infinoted-options.Tpo -c -o infinoted_0_7-infinoted-options.obj `if test -f 'infinoted-options.c'; then $(CYGPATH_W) 'infinoted-options.c'; else $(CYGPATH_W) '$(srcdir)/infinoted-options.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/infinoted_0_7-infinoted-options.Tpo $(DEPDIR)/infinoted_0_7-infinoted-options.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='infinoted-options.c' object='infinoted_0_7-infinoted-options.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) $(infinoted_0_7_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o infinoted_0_7-infinoted-options.obj `if test -f 'infinoted-options.c'; then $(CYGPATH_W) 'infinoted-options.c'; else $(CYGPATH_W) '$(srcdir)/infinoted-options.c'; fi` infinoted_0_7-infinoted-pam.o: infinoted-pam.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(infinoted_0_7_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT infinoted_0_7-infinoted-pam.o -MD -MP -MF $(DEPDIR)/infinoted_0_7-infinoted-pam.Tpo -c -o infinoted_0_7-infinoted-pam.o `test -f 'infinoted-pam.c' || echo '$(srcdir)/'`infinoted-pam.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/infinoted_0_7-infinoted-pam.Tpo $(DEPDIR)/infinoted_0_7-infinoted-pam.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='infinoted-pam.c' object='infinoted_0_7-infinoted-pam.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) $(infinoted_0_7_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o infinoted_0_7-infinoted-pam.o `test -f 'infinoted-pam.c' || echo '$(srcdir)/'`infinoted-pam.c infinoted_0_7-infinoted-pam.obj: infinoted-pam.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(infinoted_0_7_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT infinoted_0_7-infinoted-pam.obj -MD -MP -MF $(DEPDIR)/infinoted_0_7-infinoted-pam.Tpo -c -o infinoted_0_7-infinoted-pam.obj `if test -f 'infinoted-pam.c'; then $(CYGPATH_W) 'infinoted-pam.c'; else $(CYGPATH_W) '$(srcdir)/infinoted-pam.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/infinoted_0_7-infinoted-pam.Tpo $(DEPDIR)/infinoted_0_7-infinoted-pam.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='infinoted-pam.c' object='infinoted_0_7-infinoted-pam.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) $(infinoted_0_7_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o infinoted_0_7-infinoted-pam.obj `if test -f 'infinoted-pam.c'; then $(CYGPATH_W) 'infinoted-pam.c'; else $(CYGPATH_W) '$(srcdir)/infinoted-pam.c'; fi` infinoted_0_7-infinoted-run.o: infinoted-run.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(infinoted_0_7_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT infinoted_0_7-infinoted-run.o -MD -MP -MF $(DEPDIR)/infinoted_0_7-infinoted-run.Tpo -c -o infinoted_0_7-infinoted-run.o `test -f 'infinoted-run.c' || echo '$(srcdir)/'`infinoted-run.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/infinoted_0_7-infinoted-run.Tpo $(DEPDIR)/infinoted_0_7-infinoted-run.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='infinoted-run.c' object='infinoted_0_7-infinoted-run.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) $(infinoted_0_7_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o infinoted_0_7-infinoted-run.o `test -f 'infinoted-run.c' || echo '$(srcdir)/'`infinoted-run.c infinoted_0_7-infinoted-run.obj: infinoted-run.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(infinoted_0_7_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT infinoted_0_7-infinoted-run.obj -MD -MP -MF $(DEPDIR)/infinoted_0_7-infinoted-run.Tpo -c -o infinoted_0_7-infinoted-run.obj `if test -f 'infinoted-run.c'; then $(CYGPATH_W) 'infinoted-run.c'; else $(CYGPATH_W) '$(srcdir)/infinoted-run.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/infinoted_0_7-infinoted-run.Tpo $(DEPDIR)/infinoted_0_7-infinoted-run.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='infinoted-run.c' object='infinoted_0_7-infinoted-run.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) $(infinoted_0_7_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o infinoted_0_7-infinoted-run.obj `if test -f 'infinoted-run.c'; then $(CYGPATH_W) 'infinoted-run.c'; else $(CYGPATH_W) '$(srcdir)/infinoted-run.c'; fi` infinoted_0_7-infinoted-signal.o: infinoted-signal.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(infinoted_0_7_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT infinoted_0_7-infinoted-signal.o -MD -MP -MF $(DEPDIR)/infinoted_0_7-infinoted-signal.Tpo -c -o infinoted_0_7-infinoted-signal.o `test -f 'infinoted-signal.c' || echo '$(srcdir)/'`infinoted-signal.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/infinoted_0_7-infinoted-signal.Tpo $(DEPDIR)/infinoted_0_7-infinoted-signal.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='infinoted-signal.c' object='infinoted_0_7-infinoted-signal.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) $(infinoted_0_7_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o infinoted_0_7-infinoted-signal.o `test -f 'infinoted-signal.c' || echo '$(srcdir)/'`infinoted-signal.c infinoted_0_7-infinoted-signal.obj: infinoted-signal.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(infinoted_0_7_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT infinoted_0_7-infinoted-signal.obj -MD -MP -MF $(DEPDIR)/infinoted_0_7-infinoted-signal.Tpo -c -o infinoted_0_7-infinoted-signal.obj `if test -f 'infinoted-signal.c'; then $(CYGPATH_W) 'infinoted-signal.c'; else $(CYGPATH_W) '$(srcdir)/infinoted-signal.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/infinoted_0_7-infinoted-signal.Tpo $(DEPDIR)/infinoted_0_7-infinoted-signal.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='infinoted-signal.c' object='infinoted_0_7-infinoted-signal.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) $(infinoted_0_7_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o infinoted_0_7-infinoted-signal.obj `if test -f 'infinoted-signal.c'; then $(CYGPATH_W) 'infinoted-signal.c'; else $(CYGPATH_W) '$(srcdir)/infinoted-signal.c'; fi` infinoted_0_7-infinoted-startup.o: infinoted-startup.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(infinoted_0_7_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT infinoted_0_7-infinoted-startup.o -MD -MP -MF $(DEPDIR)/infinoted_0_7-infinoted-startup.Tpo -c -o infinoted_0_7-infinoted-startup.o `test -f 'infinoted-startup.c' || echo '$(srcdir)/'`infinoted-startup.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/infinoted_0_7-infinoted-startup.Tpo $(DEPDIR)/infinoted_0_7-infinoted-startup.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='infinoted-startup.c' object='infinoted_0_7-infinoted-startup.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) $(infinoted_0_7_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o infinoted_0_7-infinoted-startup.o `test -f 'infinoted-startup.c' || echo '$(srcdir)/'`infinoted-startup.c infinoted_0_7-infinoted-startup.obj: infinoted-startup.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(infinoted_0_7_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT infinoted_0_7-infinoted-startup.obj -MD -MP -MF $(DEPDIR)/infinoted_0_7-infinoted-startup.Tpo -c -o infinoted_0_7-infinoted-startup.obj `if test -f 'infinoted-startup.c'; then $(CYGPATH_W) 'infinoted-startup.c'; else $(CYGPATH_W) '$(srcdir)/infinoted-startup.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/infinoted_0_7-infinoted-startup.Tpo $(DEPDIR)/infinoted_0_7-infinoted-startup.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='infinoted-startup.c' object='infinoted_0_7-infinoted-startup.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) $(infinoted_0_7_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o infinoted_0_7-infinoted-startup.obj `if test -f 'infinoted-startup.c'; then $(CYGPATH_W) 'infinoted-startup.c'; else $(CYGPATH_W) '$(srcdir)/infinoted-startup.c'; fi` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-man1: $(dist_man1_MANS) @$(NORMAL_INSTALL) @list1='$(dist_man1_MANS)'; \ list2=''; \ test -n "$(man1dir)" \ && test -n "`echo $$list1$$list2`" \ || exit 0; \ echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \ { for i in $$list1; do echo "$$i"; done; \ if test -n "$$list2"; then \ for i in $$list2; do echo "$$i"; done \ | sed -n '/\.1[a-z]*$$/p'; \ fi; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \ done; } uninstall-man1: @$(NORMAL_UNINSTALL) @list='$(dist_man1_MANS)'; test -n "$(man1dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir) install-girDATA: $(gir_DATA) @$(NORMAL_INSTALL) @list='$(gir_DATA)'; test -n "$(girdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(girdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(girdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(girdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(girdir)" || exit $$?; \ done uninstall-girDATA: @$(NORMAL_UNINSTALL) @list='$(gir_DATA)'; test -n "$(girdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(girdir)'; $(am__uninstall_files_from_dir) install-pidfileDATA: $(pidfile_DATA) @$(NORMAL_INSTALL) @list='$(pidfile_DATA)'; test -n "$(pidfiledir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pidfiledir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pidfiledir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pidfiledir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pidfiledir)" || exit $$?; \ done uninstall-pidfileDATA: @$(NORMAL_UNINSTALL) @list='$(pidfile_DATA)'; test -n "$(pidfiledir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pidfiledir)'; $(am__uninstall_files_from_dir) install-typelibDATA: $(typelib_DATA) @$(NORMAL_INSTALL) @list='$(typelib_DATA)'; test -n "$(typelibdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(typelibdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(typelibdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(typelibdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(typelibdir)" || exit $$?; \ done uninstall-typelibDATA: @$(NORMAL_UNINSTALL) @list='$(typelib_DATA)'; test -n "$(typelibdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(typelibdir)'; $(am__uninstall_files_from_dir) install-libinfinoted_plugin_manager_0_7_laHEADERS: $(libinfinoted_plugin_manager_0_7_la_HEADERS) @$(NORMAL_INSTALL) @list='$(libinfinoted_plugin_manager_0_7_la_HEADERS)'; test -n "$(libinfinoted_plugin_manager_0_7_ladir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libinfinoted_plugin_manager_0_7_ladir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libinfinoted_plugin_manager_0_7_ladir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libinfinoted_plugin_manager_0_7_ladir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(libinfinoted_plugin_manager_0_7_ladir)" || exit $$?; \ done uninstall-libinfinoted_plugin_manager_0_7_laHEADERS: @$(NORMAL_UNINSTALL) @list='$(libinfinoted_plugin_manager_0_7_la_HEADERS)'; test -n "$(libinfinoted_plugin_manager_0_7_ladir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(libinfinoted_plugin_manager_0_7_ladir)'; $(am__uninstall_files_from_dir) # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ 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-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ 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" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files 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 @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(MANS) $(DATA) $(HEADERS) install-binPROGRAMS: install-libLTLIBRARIES installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(girdir)" "$(DESTDIR)$(pidfiledir)" "$(DESTDIR)$(typelibdir)" "$(DESTDIR)$(libinfinoted_plugin_manager_0_7_ladir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive 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." clean: clean-recursive clean-am: clean-binPROGRAMS clean-generic clean-libLTLIBRARIES \ clean-libtool mostlyclean-am distclean: distclean-recursive -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-girDATA \ install-libinfinoted_plugin_manager_0_7_laHEADERS install-man \ install-pidfileDATA install-typelibDATA install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-binPROGRAMS install-libLTLIBRARIES install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-man1 install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-girDATA \ uninstall-libLTLIBRARIES \ uninstall-libinfinoted_plugin_manager_0_7_laHEADERS \ uninstall-man uninstall-pidfileDATA uninstall-typelibDATA uninstall-man: uninstall-man1 .MAKE: $(am__recursive_targets) install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-am clean clean-binPROGRAMS clean-generic \ clean-libLTLIBRARIES clean-libtool cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-binPROGRAMS \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-girDATA install-html \ install-html-am install-info install-info-am \ install-libLTLIBRARIES \ install-libinfinoted_plugin_manager_0_7_laHEADERS install-man \ install-man1 install-pdf install-pdf-am install-pidfileDATA \ install-ps install-ps-am install-strip install-typelibDATA \ installcheck installcheck-am installdirs installdirs-am \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \ uninstall-binPROGRAMS uninstall-girDATA \ uninstall-libLTLIBRARIES \ uninstall-libinfinoted_plugin_manager_0_7_laHEADERS \ uninstall-man uninstall-man1 uninstall-pidfileDATA \ uninstall-typelibDATA .PRECIOUS: Makefile @HAVE_INTROSPECTION_TRUE@-include $(INTROSPECTION_MAKEFILE) @HAVE_INTROSPECTION_TRUE@Infinoted-0.7.gir: libinfinoted-plugin-manager-0.7.la # 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: libinfinity-0.7.1/infinoted/PaxHeaders.26529/infinoted-config-reload.h0000644000000000000000000000013213034342512022416 xustar0030 mtime=1483851082.013718339 30 atime=1483851082.013718339 30 ctime=1488261589.452138077 libinfinity-0.7.1/infinoted/infinoted-config-reload.h0000644000175000017500000000225013034342512023147 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INFINOTED_CONFIG_RELOAD_H__ #define __INFINOTED_CONFIG_RELOAD_H__ #include #include G_BEGIN_DECLS gboolean infinoted_config_reload(InfinotedRun* run, GError** error); G_END_DECLS #endif /* __INFINOTED_CONFIG_RELOAD_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/infinoted/PaxHeaders.26529/infinoted-parameter.h0000644000000000000000000000013213034342512021665 xustar0030 mtime=1483851082.013718339 30 atime=1483851082.013718339 30 ctime=1488261589.444138094 libinfinity-0.7.1/infinoted/infinoted-parameter.h0000644000175000017500000002200413034342512022415 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INFINOTED_PARAMETER_H__ #define __INFINOTED_PARAMETER_H__ #include #include #include G_BEGIN_DECLS #define INFINOTED_PARAMETER_TYPED_VALUE_TYPE (infinoted_parameter_typed_value_get_type()) /** * InfinotedParameterType: * @INFINOTED_PARAMETER_BOOLEAN: A boolean parameter. * @INFINOTED_PARAMETER_INT: A signed integer parameter. * @INFINOTED_PARAMETER_STRING: A string parameter. * @INFINOTED_PARAMETER_STRING_LIST: An array of strings. * * Allowed types for a parameter that can be given to a infinoted plugin. */ typedef enum _InfinotedParameterType { INFINOTED_PARAMETER_BOOLEAN, INFINOTED_PARAMETER_INT, INFINOTED_PARAMETER_STRING, INFINOTED_PARAMETER_STRING_LIST } InfinotedParameterType; /** * InfinotedParameterFlags: * @INFINOTED_PARAMETER_REQUIRED: The parameter is required and cannot be * omitted. * * Additional flags for parameters that can be given to infinoted plugins. */ typedef enum _InfinotedParameterFlags { INFINOTED_PARAMETER_REQUIRED = 1 << 0 } InfinotedParameterFlags; /** * InfinotedParameterValue: * @yesno: The parameter value for type %INFINOTED_PARAMETER_BOOLEAN. * @number: The parameter value for type %INFINOTED_PARAMETER_INT. * @str: The parameter value for type %INFINOTED_PARAMETER_STRING. * @strv: The parameter value for type %INFINOTED_PARAMETER_STRING_LIST. * * Holds the value of a infinoted parameter. The type of the parameter must * be known. See also #InfinotedParameterTypedValue. */ typedef union _InfinotedParameterValue InfinotedParameterValue; union _InfinotedParameterValue { gboolean yesno; gint number; gchar* str; gchar** strv; }; /** * InfinotedParameterTypedValue: * @type: The type of the parameter. * @value: The value of the parameter. * * Holds the type and value of a parameter that can be passed to an * infinoted plugin. */ typedef struct _InfinotedParameterTypedValue InfinotedParameterTypedValue; struct _InfinotedParameterTypedValue { InfinotedParameterType type; InfinotedParameterValue value; }; /** * InfinotedParameterConvertFunc: * @out: Location where the converted value should be written to. * @in: Location where the original input value should be taken from. * @error: Location for error information, if any, or %NULL. * * Definition of a parameter conversion function. A parameter conversion * function transforms the value of a read which is one of the * @InfinotedParameterValue enumeration to its final internal representation. * It can change the C type of the parameter, and it can also validate the * input and produce an error if the input value is invalid. * * While plugin developers can write their own conversion functions, many are * already provided by libinfinoted-plugin-manager that cover the most basic * usecases. These functions are * infinoted_parameter_convert_string(), * infinoted_parameter_convert_string_list(), * infinoted_parameter_convert_filename(), * infinoted_parameter_convert_boolean(), * infinoted_parameter_convert_port(), * infinoted_parameter_convert_nonnegative(), * infinoted_parameter_convert_positive(), * infinoted_parameter_convert_security_policy() and * infinoted_parameter_convert_ip_address(). * * Returns: %TRUE on success or %FALSE if an error occurred. */ typedef gboolean(*InfinotedParameterConvertFunc)(gpointer out, gpointer in, GError** error); /** * InfinotedParameterInfo: * @name: The name of the parameter. * @type: The input type of the parameter. * @flags: Additional flags for the parameter. * @offset: Offset of the output value in the structure of the plugin. Should * be determined with %G_STRUCT_OFFSET. * @convert: The conversion function for the parameter, see * #InfinotedParameterConvertFunc. * @short_name: A short name (one character) for the parameter, used for * command line option parsing. * @description: A description for the parameter that can be shown in * --help output * @arg_description: A description for the argument of the parameter in * --help output, if any. * * This structure contains generic information about a parameter that can * be passed to an infinoted plugin. */ typedef struct _InfinotedParameterInfo InfinotedParameterInfo; struct _InfinotedParameterInfo { const char* name; InfinotedParameterType type; InfinotedParameterFlags flags; size_t offset; InfinotedParameterConvertFunc convert; char short_name; const char* description; const char* arg_description; }; /** * InfinotedParameterError: * @INFINOTED_PARAMETER_ERROR_REQUIRED: A parameter is required but was not * provided to the plugin. * @INFINOTED_PARAMETER_ERROR_INVALID_NUMBER: The number given as a parameter * is not valid, for example a negative time interval. * @INFINOTED_PARAMETER_ERROR_INVALID_FLAG: The flag with the given name does * not exist. * @INFINOTED_PARAMETER_ERROR_INVALID_SECURITY_POLICY: A security policy given * as a parameter is not valid. The only allowed values are * "no-tls", "allow-tls", and "require-tls". * @INFINOTED_PARAMETER_ERROR_INVALID_IP_ADDRESS: The value given as a * parameter is not a valid IP address. * * Specifies the possible error conditions for errors in the * INFINOTED_PARAMETER_ERROR domain. These typically * occur when parsing and processing input parameters for plugins. */ typedef enum _InfinotedParameterError { INFINOTED_PARAMETER_ERROR_REQUIRED, INFINOTED_PARAMETER_ERROR_INVALID_NUMBER, INFINOTED_PARAMETER_ERROR_INVALID_FLAG, INFINOTED_PARAMETER_ERROR_INVALID_SECURITY_POLICY, INFINOTED_PARAMETER_ERROR_INVALID_IP_ADDRESS } InfinotedParameterError; GQuark infinoted_parameter_error_quark(void); GType infinoted_parameter_typed_value_get_type(void) G_GNUC_CONST; InfinotedParameterTypedValue* infinoted_parameter_typed_value_new(void); InfinotedParameterTypedValue* infinoted_parameter_typed_value_copy(const InfinotedParameterTypedValue* val); void infinoted_parameter_typed_value_free(gpointer data); gboolean infinoted_parameter_load_from_key_file(const InfinotedParameterInfo* infos, GKeyFile* key_file, const gchar* group, gpointer base, GError** error); gboolean infinoted_parameter_convert_string(gpointer out, gpointer in, GError** error); gboolean infinoted_parameter_convert_string_list(gpointer out, gpointer in, GError** error); gboolean infinoted_parameter_convert_filename(gpointer out, gpointer in, GError** error); gboolean infinoted_parameter_convert_boolean(gpointer out, gpointer in, GError** error); gboolean infinoted_parameter_convert_port(gpointer out, gpointer in, GError** error); gboolean infinoted_parameter_convert_nonnegative(gpointer out, gpointer in, GError** error); gboolean infinoted_parameter_convert_positive(gpointer out, gpointer in, GError** error); gboolean infinoted_parameter_convert_security_policy(gpointer out, gpointer in, GError** error); gboolean infinoted_parameter_convert_flags(gpointer out, gpointer in, const GFlagsValue* values, GError** error); gboolean infinoted_parameter_convert_ip_address(gpointer out, gpointer in, GError** error); G_END_DECLS #endif /* __INFINOTED_PARAMETER_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/infinoted/PaxHeaders.26529/infinoted-run.h0000644000000000000000000000013213034342512020511 xustar0030 mtime=1483851082.013718339 30 atime=1483851082.013718339 30 ctime=1488261589.456138068 libinfinity-0.7.1/infinoted/infinoted-run.h0000644000175000017500000000364213034342512021250 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INFINOTED_RUN_H__ #define __INFINOTED_RUN_H__ #include #include #include #include #include #include #include #include G_BEGIN_DECLS typedef struct _InfinotedRun InfinotedRun; struct _InfinotedRun { InfinotedStartup* startup; InfStandaloneIo* io; InfdDirectory* directory; InfdServerPool* pool; InfinotedPluginManager* plugin_manager; InfdXmppServer* xmpp4; InfdXmppServer* xmpp6; gnutls_dh_params_t dh_params; #ifdef LIBINFINITY_HAVE_AVAHI InfDiscoveryAvahi* avahi; #endif }; InfinotedRun* infinoted_run_new(InfinotedStartup* startup, GError** error); void infinoted_run_free(InfinotedRun* run); void infinoted_run_start(InfinotedRun* run); void infinoted_run_stop(InfinotedRun* run); G_END_DECLS #endif /* __INFINOTED_RUN_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/infinoted/PaxHeaders.26529/Makefile.am0000644000000000000000000000013213034544714017623 xustar0030 mtime=1483917772.682920565 30 atime=1483917772.682920565 30 ctime=1488261589.440138103 libinfinity-0.7.1/infinoted/Makefile.am0000644000175000017500000000705613034544714020365 0ustar00arminarmin00000000000000SUBDIRS = . plugins # TODO: Find a way to have the version number set automatically. bin_PROGRAMS = infinoted-0.7 dist_man1_MANS = infinoted-0.7.man plugin_path = infinoted-$(LIBINFINITY_API_VERSION)/plugins # Compile the plugin manager as a shared library: # TODO: Find a way to have the version number set automatically. lib_LTLIBRARIES = libinfinoted-plugin-manager-0.7.la libinfinoted_plugin_manager_0_7_la_CPPFLAGS = \ -I$(top_srcdir) \ $(infinoted_CFLAGS) \ $(infinity_CFLAGS) \ -DPLUGIN_LIBPATH=\"${libdir}\" \ -DPLUGIN_PATH=\"${plugin_path}\" \ -DLOCALSTATEDIR=\"${localstatedir}\" \ -DLIBINFINITY_API_VERSION=\"$(LIBINFINITY_API_VERSION)\" libinfinoted_plugin_manager_0_7_la_LDFLAGS = \ -no-undefined \ -version-info $(LIBINFINITY_LIBTOOL_VERSION) libinfinoted_plugin_manager_0_7_la_LIBADD = \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(infinoted_LIBS) \ $(infinity_LIBS) \ $(libdaemon_LIBS) libinfinoted_plugin_manager_0_7_la_SOURCES = \ infinoted-log.c \ infinoted-parameter.c \ infinoted-plugin-manager.c \ infinoted-util.c libinfinoted_plugin_manager_0_7_la_HEADERS = \ infinoted-log.h \ infinoted-parameter.h \ infinoted-plugin-manager.h \ infinoted-util.h libinfinoted_plugin_manager_0_7_ladir = \ $(includedir)/libinfinoted-plugin-manager-$(LIBINFINITY_API_VERSION)/infinoted # Compile the rest of infinoted as an executable binary infinoted_0_7_CPPFLAGS = \ -I${top_srcdir} \ $(infinoted_CFLAGS) \ $(infinity_CFLAGS) \ -DPLUGIN_LIBPATH=\"${libdir}\" \ -DPLUGIN_PATH=\"${plugin_path}\" \ -DLOCALSTATEDIR=\"${localstatedir}\" \ -DLIBINFINITY_API_VERSION=\"$(LIBINFINITY_API_VERSION)\" infinoted_0_7_LDADD = \ libinfinoted-plugin-manager-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(infinoted_LIBS) \ $(infinity_LIBS) \ $(libdaemon_LIBS) infinoted_0_7_SOURCES = \ infinoted-config-reload.c \ infinoted-dh-params.c \ infinoted-main.c \ infinoted-options.c \ infinoted-pam.c \ infinoted-run.c \ infinoted-signal.c \ infinoted-startup.c noinst_HEADERS = \ infinoted-config-reload.h \ infinoted-dh-params.h \ infinoted-options.h \ infinoted-pam.h \ infinoted-run.h \ infinoted-signal.h \ infinoted-startup.h # Create pid file directory pidfiledir = ${localstatedir}/run/infinoted-$(LIBINFINITY_API_VERSION) pidfile_DATA = if HAVE_INTROSPECTION -include $(INTROSPECTION_MAKEFILE) INTROSPECTION_GIRS = Infinoted-0.7.gir INTROSPECTION_SCANNER_ENV = CC="${CC}" INTROSPECTION_COMPILER_ARGS = \ --includedir=${top_srcdir}/libinfinity \ --includedir=${top_builddir}/libinfinity \ --includedir=${top_builddir}/libinftext Infinoted-0.7.gir: libinfinoted-plugin-manager-0.7.la Infinoted_0_7_gir_SCANNERFLAGS = \ -I${top_srcdir} \ --add-include-path=$(top_srcdir)/libinfinity \ --add-include-path=$(top_builddir)/libinfinity \ -n Infinoted \ --identifier-prefix=Infinoted \ --warn-all Infinoted_0_7_gir_NAMESPACE = Infinoted Infinoted_0_7_gir_VERSION = 0.7 Infinoted_0_7_gir_CFLAGS = $(infinoted_CFLAGS) $(infinity_CFLAGS) Infinoted_0_7_gir_LIBS = libinfinoted-plugin-manager-0.7.la Infinoted_0_7_gir_FILES = \ $(libinfinoted_plugin_manager_0_7_la_SOURCES) \ $(libinfinoted_plugin_manager_0_7_la_HEADERS) Infinoted_0_7_gir_INCLUDES = Infinity-0.7 Infinityd-0.7 Infinoted_0_7_gir_PACKAGES = gobject-2.0 Infinoted_0_7_gir_EXPORT_PACKAGES = libinfinoted-plugin-manager-0.7 girdir = $(datadir)/gir-1.0 gir_DATA = Infinoted-0.7.gir typelibdir = $(libdir)/girepository-1.0 typelib_DATA = Infinoted-0.7.typelib CLEANFILES = \ $(gir_DATA) \ $(typelib_DATA) endif libinfinity-0.7.1/infinoted/PaxHeaders.26529/infinoted-0.7.man0000644000000000000000000000013113051242077020540 xustar0030 mtime=1487225919.854605157 30 atime=1487225919.854605157 29 ctime=1488261589.46013806 libinfinity-0.7.1/infinoted/infinoted-0.7.man0000644000175000017500000000705613051242077021303 0ustar00arminarmin00000000000000.TH INFINOTED "1" "August 2014" "infinoted 0.7" "User Commands" .SH NAME infinoted \- dedicated server for the infinote protocol (e.g. Gobby) .SH SYNOPSIS .B infinoted\-0.7 .RI [ options ] .SH DESCRIPTION .B infinoted is a dedicated server which allows clients to edit plain text documents and source files collaboratively over a network. Changes to the documents are synchronized instantly to the other clients. .PP This server supports the infinote protocol as implemented by libinfinity. Example clients include Gobby 0.5.x, Kobby and a special plugin for gedit. It is .B not compatible to the older libobby protocol. .PP It comes with a list of plugins like autosave, dbus integration and others. For a complete list see https://github.com/gobby/gobby/wiki/Dedicated%20Server. The default plugin is note-text. It needs to be added along with any other plugins that one might want to enable. .SH OPTIONS .SS "Help Options:" .TP \fB\-h\fR, \fB\-\-help\fR Show help options .SS "Application Options:" .TP \fB\-c\fR, \fB\-\-config\-file\fR=\fICONFIG\-FILE\fR Load the given configuration file instead of looking at the standard locations. .TP \fB\-k\fR, \fB\-\-key\-file\fR=\fIKEY\-FILE\fR The server's private key .TP \fB\-c\fR, \fB\-\-certificate\-file\fR=\fICERTIFICATE\-FILE\fR The server's certificate .TP \fB\-\-certificate\-chain\fR The certificate chain to the root certificate, if not included in the file given in \-\-certificate\-file. .TP \fB\-\-create\-key\fR Creates a new random private key .TP \fB\-\-create\-certificate\fR Creates a new self\-signed certificate using the given key .TP \fB\-p\fR, \fB\-\-port\-number\fR=\fIPORT\fR The port number to listen on .TP \fB\-\-listen\-address\fR=\fIADDRESS\fR The IP address to listen on .TP \fB\-\-security\-policy\fR=\fIno\-tls\fR|allow\-tls|require\-tls How to decide whether to use TLS .TP \fB\-r\fR, \fB\-\-root\-directory\fR=\fIDIRECTORY\fR A directory to save the document tree into in infinoted\-xml format. This is the location where the tree is kept persistently so that it is available again after server restart. Usually, documents are saved in this tree 60 seconds after the last user left the session. In addition to this, when the autosave plugin is enabled, it is possible to save sessions into the tree periodically. The default directory is ~/.infinote. .TP \fB\-\-plugins\fR=\fIPLUGIN\fR Additional plugin to load. Repeat the option on the command-line to specify multiple plugins and semi-colons in the configuration file. Plugin options can be configured in the configuration file (one section for each plugin), or with the \-\-plugin\-parameter option. .TP \fB\-\-plugin-parameter\fR=\fIPLUGIN:KEY:VALUE\fR Sets the option KEY for plugin PLUGIN to the given VALUE. Normally, plugin options are specified in the configuration file, but this command line option allows one to set or override plugin options on the command line. .TP \fB\-P\fR, \fB\-\-password\fR=\fIPASSWORD\fR Require given password on connections .TP \fB\-\-pam-service\fR=\fISERVICE\fR Authenticate clients against given pam service on connection .TP \fB\-\-pam-allow-user\fR=\fIUSERS\fR Users allowed to connect after pam authentication. Separate entries with semicolons. .TP \fB\-\-pam-allow-group\fR=\fIGROUPS\fR Group allowed to connect after pam authentication. Separate entries with semicolons. .TP \fB\-d\fR, \fB\-\-daemonize\fR Daemonize the server .TP \fB\-D\fR, \fB\-\-kill\-daemon\fR Kill a running daemon .TP \fB\-v\fR, \fB\-\-version\fR Display version information and exit .SH AUTHOR .B infinoted and .B libinfinity were written by Armin Burgmeier libinfinity-0.7.1/infinoted/PaxHeaders.26529/infinoted-plugin-manager.h0000644000000000000000000000013213034342512022613 xustar0030 mtime=1483851082.013718339 30 atime=1483851082.013718339 30 ctime=1488261589.444138094 libinfinity-0.7.1/infinoted/infinoted-plugin-manager.h0000644000175000017500000002241413034342512023350 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INFINOTED_PLUGIN_MANAGER_H__ #define __INFINOTED_PLUGIN_MANAGER_H__ /* Note that this class is compiled into an own shared library. Therefore, it * must not use any other infinoted API! The reason for this is to allow * loaded plugins to call plugin manager functions. Calling symbols from the * application itself would not be portable, so this needs to reside in a * shared library. * * The only API allowed to be used is what is declared in * infinoted-parameter.h and infinoted-log. The reason for this is that this * code is also included in the shared library. This allows parameter parsing * and central logging for plugins. */ #include #include #include #include G_BEGIN_DECLS #define INFINOTED_TYPE_PLUGIN_MANAGER (infinoted_plugin_manager_get_type()) #define INFINOTED_PLUGIN_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INFINOTED_TYPE_PLUGIN_MANAGER, InfinotedPluginManager)) #define INFINOTED_PLUGIN_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INFINOTED_TYPE_PLUGIN_MANAGER, InfinotedPluginManagerClass)) #define INFINOTED_IS_PLUGIN_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INFINOTED_TYPE_PLUGIN_MANAGER)) #define INFINOTED_IS_PLUGIN_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INFINOTED_TYPE_PLUGIN_MANAGER)) #define INFINOTED_PLUGIN_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INFINOTED_TYPE_PLUGIN_MANAGER, InfinotedPluginManagerClass)) typedef struct _InfinotedPluginManager InfinotedPluginManager; typedef struct _InfinotedPluginManagerClass InfinotedPluginManagerClass; /** * InfinotedPlugin: * @name: The name of the plugin. The filename of the shared object should * be libinfinoted-plugin-<name>. * @description: A human-readable description of what the plugin does. * @options: A 0-terminated list of plugin parameters. The parameters are * provided to the plugin via the infinoted configuration file or the command * line. The last element of the list must have the @name field set to %NULL. * @info_size: The size of the plugin instance structure. When the plugin * is instantiated, this amount of memory will be allocated for the plugin * instance. This field must be different from 0. * @connection_info_size: The size of the plugin's connection info structure. * For each plugin instance, this amount of memory will be allocated for each * connection of the server. The plugin can use it to store * connection-specific data. This field can be 0. * @session_info_size: The size of the plugin's session info structure. For * each plugin instance, this amount of memory will be allocated for each * session that is currently active on the server. The plugin can use it to * store session-specific data. This field can be 0. * @session_type: If non-%NULL, specifies the session type handled by the * plugin. Only for sessions of this type or a derived type a session info * structure is allocated. The @on_session_added and @on_session_removed * callbacks are always made, independent of this field. * @on_info_initialize: Function called after the plugin has been * instantiated. It should initialize all fields of the plugin instance * to a sane default value. * @on_initialize: Function called to initialize the plugin. The function can * return %FALSE and set the @error parameter to prevent the plugin from * being used. The server will not be started in this case. Even if this * function returns %FALSE, @on_deinitialize will be called on the plugin to * clean up partly constructed plugin data by this function. * @on_deinitialize: Function called when the plugin is unloaded. Should clean * up all resources the plugin has allocated. * @on_connection_added: Function called when there is a new connection to the * server. It is also called for all existing connections at the time the * plugin is loaded. * @on_connection_removed: Function called when a client connection has been * dropped. It is also called for all existing connections right before the * plugin is unloaded. * @on_session_added: Function called when a new session has become active on * the server. It is also called for all existing sessions at the time the * plugin is loaded. * @on_session_removed: Function called when a session has become inactive and * the server is freeing resources allocated to it. It is also called for all * existing sessions right before the plugin is unloaded. * * Declares a InfinotedPlugin. If an instance of this structure is called * INFINOTED_PLUGIN and exported from a shared object, it * can be loaded as a plugin by infinoted. */ typedef struct _InfinotedPlugin InfinotedPlugin; struct _InfinotedPlugin { const gchar* name; const gchar* description; const InfinotedParameterInfo* options; gsize info_size; gsize connection_info_size; gsize session_info_size; const gchar* session_type; void(*on_info_initialize)(gpointer plugin_info); gboolean(*on_initialize)(InfinotedPluginManager* manager, gpointer plugin_info, GError** error); void(*on_deinitialize)(gpointer plugin_info); void(*on_connection_added)(InfXmlConnection* connection, gpointer plugin_info, gpointer connection_info); void(*on_connection_removed)(InfXmlConnection* connection, gpointer plugin_info, gpointer connection_info); void(*on_session_added)(const InfBrowserIter* iter, InfSessionProxy* proxy, gpointer plugin_info, gpointer session_info); void(*on_session_removed)(const InfBrowserIter* iter, InfSessionProxy* proxy, gpointer plugin_info, gpointer session_info); }; /** * InfinotedPluginManagerClass: * * This structure does not contain any public fields. */ struct _InfinotedPluginManagerClass { /*< private >*/ GObjectClass parent_class; }; /** * InfinotedPluginManager: * * #InfinotedPluginManager is an opaque data type. You should only access it * via the public API functions. */ struct _InfinotedPluginManager { /*< private >*/ GObject parent; }; /** * InfinotedPluginManagerError: * @INFINOTED_PLUGIN_MANAGER_ERROR_OPEN_FAILED: Failed to open the code module * of a plugin. * @INFINOTED_PLUGIN_MANAGER_ERROR_NO_ENTRY_POINT: The code module of a plugin * does not provide the INFINOTED_PLUGIN symbol. * * Error codes for the INFINOTED_PLUGIN_MANAGER_ERROR * error domain. These errors can occur when loading a plugin with * infinoted_plugin_manager_load(). */ typedef enum _InfinotedPluginManagerError { INFINOTED_PLUGIN_MANAGER_ERROR_OPEN_FAILED, INFINOTED_PLUGIN_MANAGER_ERROR_NO_ENTRY_POINT } InfinotedPluginManagerError; GType infinoted_plugin_manager_get_type(void) G_GNUC_CONST; InfinotedPluginManager* infinoted_plugin_manager_new(InfdDirectory* directory, InfinotedLog* log, InfCertificateCredentials* creds); gboolean infinoted_plugin_manager_load(InfinotedPluginManager* manager, const gchar* plugin_path, const gchar* const* plugins, GKeyFile* options, GError** error); InfdDirectory* infinoted_plugin_manager_get_directory(InfinotedPluginManager* manager); InfIo* infinoted_plugin_manager_get_io(InfinotedPluginManager* manager); InfinotedLog* infinoted_plugin_manager_get_log(InfinotedPluginManager* manager); InfCertificateCredentials* infinoted_plugin_manager_get_credentials(InfinotedPluginManager* manager); GQuark infinoted_plugin_manager_error_quark(void); gpointer infinoted_plugin_manager_get_connection_info(InfinotedPluginManager* mgr, gpointer plugin_info, InfXmlConnection* connection); gpointer infinoted_plugin_manager_get_session_info(InfinotedPluginManager* mgr, gpointer plugin_info, InfSessionProxy* proxy); G_END_DECLS #endif /* __INFINOTED_PLUGIN_MANAGER_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/infinoted/PaxHeaders.26529/infinoted-signal.h0000644000000000000000000000013213034342512021162 xustar0030 mtime=1483851082.013718339 30 atime=1483851082.013718339 30 ctime=1488261589.456138068 libinfinity-0.7.1/infinoted/infinoted-signal.h0000644000175000017500000000330313034342512021713 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INFINOTED_SIGNAL_H__ #define __INFINOTED_SIGNAL_H__ #include #include #include #include G_BEGIN_DECLS /* sighandler_t seems not to be defined for some reason */ typedef void(*InfinotedSignalFunc)(int); typedef struct _InfinotedSignal InfinotedSignal; struct _InfinotedSignal { #ifdef LIBINFINITY_HAVE_LIBDAEMON InfinotedRun* run; int signal_fd; InfIoWatch* watch; #else InfinotedSignalFunc previous_sigint_handler; InfinotedSignalFunc previous_sigterm_handler; InfinotedSignalFunc previous_sigquit_handler; InfinotedSignalFunc previous_sighup_handler; #endif }; InfinotedSignal* infinoted_signal_register(InfinotedRun* run); void infinoted_signal_unregister(InfinotedSignal* sig); G_END_DECLS #endif /* __INFINOTED_SIGNAL_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/infinoted/PaxHeaders.26529/infinoted-pam.c0000644000000000000000000000013213034342512020455 xustar0030 mtime=1483851082.013718339 30 atime=1483851082.013718339 30 ctime=1488261589.472138033 libinfinity-0.7.1/infinoted/infinoted-pam.c0000644000175000017500000001647713034342512021226 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include "config.h" #include #include #include #ifdef LIBINFINITY_HAVE_PAM #include #include #include #include #include #include #include /* cannot use g_strdup because that requires its return value to be free'd * with g_free(), but pam is not aware of that. */ static char* infinoted_pam_strdup(const char* str) { size_t size; char* new_str; size = strlen(str) + 1; new_str = malloc(size); memcpy(new_str, str, size); return new_str; } static int infinoted_pam_conv_func(int num_msg, const struct pam_message** msgs, struct pam_response** resps, void* appdata_ptr) { int i; const struct pam_message* msg; struct pam_response* resp; *resps = malloc(sizeof(struct pam_response) * num_msg); for(i = 0; i < num_msg; ++i) { msg = msgs[i]; resp = &(*resps)[i]; resp->resp_retcode = 0; if(msg->msg_style == PAM_PROMPT_ECHO_OFF) /* looks like password prompt */ resp->resp = infinoted_pam_strdup(appdata_ptr); else resp->resp = NULL; } return PAM_SUCCESS; } #ifdef HAVE_PAM_FAIL_DELAY static void infinoted_pam_delay_func(int retval, unsigned usec_delay, void *appdata_ptr) { /* do not delay */ /* TODO: figure out how to randomly delay a bit without blocking the entire * server. */ } #endif /* HAVE_PAM_FAIL_DELAY */ static void infinoted_pam_log_error(InfinotedLog* log, const char* username, const char* detail, int error_code, GError** error) { const char* msg; if(error_code == 0) msg = _("Entry not found"); else msg = strerror(error_code); infinoted_log_error( log, _("Error while checking groups of user \"%s\", %s: %s."), username, detail, msg ); g_set_error_literal( error, inf_authentication_detail_error_quark(), INF_AUTHENTICATION_DETAIL_ERROR_SERVER_ERROR, inf_authentication_detail_strerror( INF_AUTHENTICATION_DETAIL_ERROR_SERVER_ERROR ) ); } static gboolean infinoted_pam_user_is_in_group(const gchar* username, gchar* required_group, gchar* buf, size_t buf_size, InfinotedLog* log, GError** error) { struct passwd user_entry, *user_pointer; struct group group_entry, *group_pointer; char** iter; char msgbuf[128]; int status; gid_t gid; /* first check against the user's primary group */ status = getpwnam_r(username, &user_entry, buf, buf_size, &user_pointer); if(user_pointer == NULL) { infinoted_pam_log_error( log, username, _("looking up user information"), status, error); return FALSE; } gid = user_entry.pw_gid; status = getgrgid_r(gid, &group_entry, buf, buf_size, &group_pointer); if(group_pointer == NULL) { g_snprintf(msgbuf, sizeof msgbuf, _("looking up group %ld"), (long) gid); infinoted_pam_log_error(log, username, msgbuf, status, error); return FALSE; } if(strcmp(group_entry.gr_name, required_group) == 0) return TRUE; /* now go through all users listed for the required group */ status = getgrnam_r(required_group, &group_entry, buf, buf_size, &group_pointer); if(group_pointer == NULL) { g_snprintf(msgbuf, sizeof msgbuf, _("looking up group \"%s\""), required_group); infinoted_pam_log_error(log, username, msgbuf, status, error); return FALSE; } for(iter = group_entry.gr_mem; *iter; ++iter) { if(strcmp(*iter, username) == 0) return TRUE; } /* Nothing worked. No success, but no error either. */ return FALSE; } gboolean infinoted_pam_user_is_allowed(InfinotedStartup* startup, const gchar* username, GError** error) { InfinotedOptions* options; char* buf; long buf_size_gr, buf_size_pw, buf_size; gboolean status; GError* local_error; gchar** iter; options = startup->options; if(options->pam_allowed_users == NULL && options->pam_allowed_groups == NULL) { return TRUE; } else { if(options->pam_allowed_users != NULL) { for(iter = options->pam_allowed_users; *iter; ++iter) { if(strcmp(*iter, username) == 0) return TRUE; } } if(options->pam_allowed_groups != NULL) { /* avoid reallocating this buffer over and over */ buf_size_pw = sysconf(_SC_GETPW_R_SIZE_MAX); buf_size_gr = sysconf(_SC_GETGR_R_SIZE_MAX); buf_size = MAX(buf_size_pw, buf_size_gr); buf = g_malloc(buf_size); status = FALSE; local_error = NULL; for(iter = options->pam_allowed_groups; *iter; ++iter) { if(infinoted_pam_user_is_in_group( username, *iter, buf, buf_size, startup->log, &local_error)) { status = TRUE; break; } /* do not try to check all other groups on an actual error */ if(local_error) { g_propagate_error(error, local_error); break; } } g_free(buf); return status; } else { return FALSE; } } } gboolean infinoted_pam_authenticate(const char* service, const char* username, const char* password) { pam_handle_t* pamh; struct pam_conv conv; int status; #ifdef HAVE_PAM_FAIL_DELAY void (*delay_fp)(int, unsigned, void*); void* delay_void_ptr; #endif conv.conv = infinoted_pam_conv_func; conv.appdata_ptr = *(void**) (void*) &password; if(pam_start(service, username, &conv, &pamh) != PAM_SUCCESS) return FALSE; status = PAM_SUCCESS; #ifdef HAVE_PAM_FAIL_DELAY delay_fp = infinoted_pam_delay_func; /* avoid warnings for casting func-ptrs to object pointers * and for type-punning pointers */ delay_void_ptr = *(void**) (void*) (char*) &delay_fp; status = pam_set_item(pamh, PAM_FAIL_DELAY, delay_void_ptr); if(status == PAM_SUCCESS) status = pam_authenticate(pamh, 0); #endif /* TODO: consider pam_acct_mgmt */ pam_end(pamh, status); return status == PAM_SUCCESS; } #endif /* LIBINFINITY_HAVE_PAM */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/infinoted/PaxHeaders.26529/infinoted-log.h0000644000000000000000000000013213034342512020466 xustar0030 mtime=1483851082.013718339 30 atime=1483851082.013718339 30 ctime=1488261589.444138094 libinfinity-0.7.1/infinoted/infinoted-log.h0000644000175000017500000000602713034342512021225 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INFINOTED_LOG_H__ #define __INFINOTED_LOG_H__ #include G_BEGIN_DECLS #define INFINOTED_TYPE_LOG (infinoted_log_get_type()) #define INFINOTED_LOG(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INFINOTED_TYPE_LOG, InfinotedLog)) #define INFINOTED_LOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INFINOTED_TYPE_LOG, InfinotedLogClass)) #define INFINOTED_IS_LOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INFINOTED_TYPE_LOG)) #define INFINOTED_IS_LOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INFINOTED_TYPE_LOG)) #define INFINOTED_LOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INFINOTED_TYPE_LOG, InfinotedLogClass)) typedef struct _InfinotedLog InfinotedLog; typedef struct _InfinotedLogClass InfinotedLogClass; /** * InfinotedLogClass: * @log_message: Default signal handler for the #InfinotedLog::log-message * signal. * * This structure contains default signal handlers for #InfinotedLog. */ struct _InfinotedLogClass { /*< private >*/ GObjectClass parent_class; /*< public >*/ void (*log_message)(InfinotedLog* log, guint prio, guint depth, const gchar* text); }; /** * InfinotedLog: * * #InfinotedLog is an opaque data type. You should only access it via the * public API functions. */ struct _InfinotedLog { /*< private >*/ GObject parent; }; GType infinoted_log_get_type(void) G_GNUC_CONST; InfinotedLog* infinoted_log_new(void); gboolean infinoted_log_open(InfinotedLog* log, const gchar* path, GError** error); void infinoted_log_close(InfinotedLog* log); void infinoted_log_log(InfinotedLog* log, guint prio, const char* fmt, ...); void infinoted_log_error(InfinotedLog* log, const char* fmt, ...); void infinoted_log_warning(InfinotedLog* log, const char* fmt, ...); void infinoted_log_info(InfinotedLog* log, const char* fmt, ...); G_END_DECLS #endif /* __INFINOTED_LOG_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/infinoted/PaxHeaders.26529/infinoted-options.c0000644000000000000000000000013213034342512021373 xustar0030 mtime=1483851082.013718339 30 atime=1483851082.013718339 30 ctime=1488261589.472138033 libinfinity-0.7.1/infinoted/infinoted-options.c0000644000175000017500000007173613034342512022143 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include "config.h" #include #include #include #include #include #ifdef LIBINFINITY_HAVE_LIBDAEMON # include #endif #include #include #include #include #include static const gchar INFINOTED_OPTIONS_GROUP[] = "infinoted"; const InfinotedParameterInfo INFINOTED_OPTIONS[] = { { "log-file", INFINOTED_PARAMETER_STRING, 0, offsetof(InfinotedOptions, log_path), infinoted_parameter_convert_filename, 'l', N_("If set, write the server log to the given file, " "in addition to stdout"), N_("LOG-FILE") }, { "key-file", INFINOTED_PARAMETER_STRING, 0, offsetof(InfinotedOptions, key_file), infinoted_parameter_convert_filename, 'k', N_("Path to the server's private key. Must be the key with which the " "given certificate was signed. Not needed when security-policy is " "set to \"no-tls\"."), N_("KEY-FILE") }, { "certificate-file", INFINOTED_PARAMETER_STRING, 0, offsetof(InfinotedOptions, certificate_file), infinoted_parameter_convert_filename, 'c', N_("Path to the server's certificate. Must be signed with the given key " "file. Not needed when security-policy is set to \"no-tls\"."), N_("CERT-FILE"), }, { "certificate-chain", INFINOTED_PARAMETER_STRING, 0, offsetof(InfinotedOptions, certificate_chain_file), infinoted_parameter_convert_filename, 0, N_("Optional file which contains the issuer certificate of the server " "certificate, and the issuer's issuer, and so on. This option can be " "used when the issuer certificates are not stored in the same file as " "the server certificate. If the issuer certificates are not available " "the server will still run, but not show the issuer certificates to " "connecting clients."), N_("CERT-FILE") }, { "port", INFINOTED_PARAMETER_INT, 0, offsetof(InfinotedOptions, port), infinoted_parameter_convert_port, 'p', N_("The TCP port number to listen on."), N_("PORT") }, { "listen-address", INFINOTED_PARAMETER_STRING, 0, offsetof(InfinotedOptions, listen_address), infinoted_parameter_convert_ip_address, 0, N_("The IP address to listen on."), N_("ADDRESS"), }, { "security-policy", INFINOTED_PARAMETER_STRING, 0, offsetof(InfinotedOptions, security_policy), infinoted_parameter_convert_security_policy, 0, N_("Whether to use Transport Layer Security (TLS) or not. Allowed " "values are \"no-tls\", \"allow-tls\" or \"require-tls\". When " "TLS is allowed or required, a server certificate must be provided. " "Infinoted has a built-in option to create a self-signed certificate " "with the --create-key and --create-certificate command line options. " "When TLS is allowed but not required, clients may choose not to use " "TLS. It is strongly encouraged to always require TLS. " "[Default=require-tls]"), N_("no-tls|allow-tls|require-tls") }, { "root-directory", INFINOTED_PARAMETER_STRING, 0, offsetof(InfinotedOptions, root_directory), infinoted_parameter_convert_filename, 'r', N_("The directory which infinoted uses to permanantly store all " "documents on the server, and where they are read from after a " "server restart. [Default=~/.infinote]"), N_("DIRECTORY") }, { "plugins", INFINOTED_PARAMETER_STRING_LIST, 0, offsetof(InfinotedOptions, plugins), infinoted_parameter_convert_string_list, 0, N_("Additional plugins to load. This option can be specified more than " "once to load multiple plugins. Plugin options can be configured in " "the configuration file (one section for each plugin), or with the " "--plugin-parameter option. [Default=note-text]"), N_("PLUGIN-NAME") }, { "password", INFINOTED_PARAMETER_STRING, 0, offsetof(InfinotedOptions, password), infinoted_parameter_convert_string, 'P', N_("If set, require clients to enter a password before being allowed " "to connect to the server. This option cannot be combined with " "--pam-service."), N_("Password") #ifdef LIBINFINITY_HAVE_PAM }, { "pam-service", INFINOTED_PARAMETER_STRING, 0, offsetof(InfinotedOptions, pam_service), infinoted_parameter_convert_string, 0, N_("Authenticate clients using the given PAM service. This option cannot " "be combined with --password. Clients are requested to send their " "user name and then enter the password for their account on " "the server machine with the same name."), N_("SERVICE") }, { "pam-allow-user", INFINOTED_PARAMETER_STRING_LIST, 0, offsetof(InfinotedOptions, pam_allowed_users), infinoted_parameter_convert_string_list, 0, N_("If set, only the given username is allowed to connect to the " "server. This option can be given multiple times to allow multiple " "users."), N_("USER") }, { "pam-allow-group", INFINOTED_PARAMETER_STRING_LIST, 0, offsetof(InfinotedOptions, pam_allowed_groups), infinoted_parameter_convert_string_list, 0, N_("If set, only users belonging to the given group are allowed to " "connect to the server. This option can be given multiple times to " "allow multiple groups."), N_("GROUPS") #endif }, { NULL, 0, 0, 0, NULL } }; static gboolean infinoted_options_validate(InfinotedOptions* options, GError** error) { InfXmppConnectionSecurityPolicy security_policy; gboolean requires_password; security_policy = options->security_policy; #ifdef LIBINFINITY_HAVE_PAM if(options->password != NULL && options->pam_service != NULL) { g_set_error_literal( error, infinoted_options_error_quark(), INFINOTED_OPTIONS_ERROR_INVALID_AUTHENTICATION_SETTINGS, _("Cannot use both server password and system authentication.") ); return FALSE; } if(options->pam_service == NULL && (options->pam_allowed_users != NULL || options->pam_allowed_groups != NULL)) { g_set_error_literal( error, infinoted_options_error_quark(), INFINOTED_OPTIONS_ERROR_INVALID_AUTHENTICATION_SETTINGS, _("Need a pam service to authenticate users.") ); return FALSE; } #endif /* LIBINFINITY_HAVE_PAM */ requires_password = options->password != NULL; #ifdef LIBINFINITY_HAVE_PAM requires_password = requires_password || options->pam_service != NULL; #endif /* LIBINFINITY_HAVE_PAM */ if(options->password != NULL) options->password_len = strlen(options->password); if(requires_password && options->security_policy == INF_XMPP_CONNECTION_SECURITY_ONLY_UNSECURED) { fprintf( stderr, "%s", _("WARNING: Requiring password through unencrypted connection.") ); } if(options->create_key == TRUE && options->create_certificate == FALSE) { g_set_error_literal( error, infinoted_options_error_quark(), INFINOTED_OPTIONS_ERROR_INVALID_CREATE_OPTIONS, _("Creating a new private key also requires creating a new certificate " "signed with it.") ); return FALSE; } else if(security_policy != INF_XMPP_CONNECTION_SECURITY_ONLY_UNSECURED && options->key_file == NULL) { g_set_error_literal( error, infinoted_options_error_quark(), INFINOTED_OPTIONS_ERROR_EMPTY_KEY_FILE, _("No private key file given. If you don't have a suitable key file, " "either create one using the --create-key command line argument, " "or disable TLS by setting the security policy to \"no-tls\".") ); return FALSE; } else if(security_policy != INF_XMPP_CONNECTION_SECURITY_ONLY_UNSECURED && options->certificate_file == NULL) { g_set_error_literal( error, infinoted_options_error_quark(), INFINOTED_OPTIONS_ERROR_EMPTY_CERTIFICATE_FILE, _("No certificate file given. If you don't have a suitable certificate " "file, either create one using the --create-certificate command line " "agument, or disable TLS via by setting the security policy to " "\"no-tls\".") ); return FALSE; } return TRUE; } static GKeyFile* infinoted_options_read_config_into_keyfile(const gchar* const* files, gboolean ignore_nonexisting_files, GError** error) { const gchar* const* file; GKeyFile* key_file; GError* local_error; key_file = g_key_file_new(); local_error = NULL; for(file = files; *file != NULL; ++file) { g_key_file_load_from_file(key_file, *file, G_KEY_FILE_NONE, &local_error); if(local_error != NULL) { if(ignore_nonexisting_files && local_error->domain == G_FILE_ERROR && local_error->code == G_FILE_ERROR_NOENT) { /* ignore this file, try next */ g_error_free(local_error); local_error = NULL; } else { g_key_file_free(key_file); g_propagate_prefixed_error( error, local_error, _("Error reading configuration file \"%s\": "), *file ); return NULL; } } } /* no configuration file exists; that's okay, return empty key file */ return key_file; } static gboolean infinoted_options_parse_arg_func(const gchar* option_name, const gchar* value, gpointer data, GError** error) { const InfinotedParameterInfo* info; GHashTable* options; InfinotedParameterTypedValue* optval; long l_val; char* endptr; gchar* const* str; guint n_strs; options = (GHashTable*)data; /* Find InfinotedOptionsEntry with the option name */ g_assert(option_name[0] == '-'); if(option_name[1] == '-') { for(info = INFINOTED_OPTIONS; info->name != NULL; ++info) if(strcmp(info->name, option_name + 2) == 0) break; } else { for(info = INFINOTED_OPTIONS; info->name != NULL; ++info) if(info->short_name == option_name[1]) break; } g_assert(info->name != NULL); switch(info->type) { case INFINOTED_PARAMETER_BOOLEAN: if(g_hash_table_lookup(options, info) != NULL) { g_set_error( error, infinoted_options_error_quark(), INFINOTED_OPTIONS_ERROR_MULTIPLE_OPTIONS, _("The option \"%s\" can only be given once"), option_name ); return FALSE; } if(strcmp(value, "true") == 0 || strcmp(value, "1") == 0) { optval = infinoted_parameter_typed_value_new(); optval->type = INFINOTED_PARAMETER_BOOLEAN; optval->value.yesno = TRUE; g_hash_table_insert(options, (gpointer)info, optval); return TRUE; } else if(strcmp(value, "false") == 0 || strcmp(value, "0") == 0) { optval = infinoted_parameter_typed_value_new(); optval->type = INFINOTED_PARAMETER_BOOLEAN; optval->value.yesno = FALSE; g_hash_table_insert(options, (gpointer)info, optval); return TRUE; } else { g_set_error( error, infinoted_options_error_quark(), INFINOTED_OPTIONS_ERROR_INVALID_BOOLEAN, _("\"%s\" cannot be interpreted as a boolean value"), value ); return FALSE; } break; case INFINOTED_PARAMETER_INT: if(g_hash_table_lookup(options, info) != NULL) { g_set_error( error, infinoted_options_error_quark(), INFINOTED_OPTIONS_ERROR_MULTIPLE_OPTIONS, _("The option \"%s\" can only be given once"), option_name ); return FALSE; } errno = 0; l_val = strtol(value, &endptr, 10); if(*endptr != '\0') { g_set_error( error, infinoted_options_error_quark(), INFINOTED_OPTIONS_ERROR_INVALID_NUMBER, _("\"%s\" is not a number"), value ); return FALSE; } else if(errno != 0) { g_set_error( error, infinoted_options_error_quark(), INFINOTED_OPTIONS_ERROR_INVALID_NUMBER, _("Could not read the number \"%s\": %s"), value, strerror(errno) ); return FALSE; } else if(l_val < G_MININT) { g_set_error( error, infinoted_options_error_quark(), INFINOTED_OPTIONS_ERROR_INVALID_NUMBER, _("Number \"%s\" is too small"), value ); return FALSE; } else if(l_val > G_MAXINT) { g_set_error( error, infinoted_options_error_quark(), INFINOTED_OPTIONS_ERROR_INVALID_NUMBER, _("Number \"%s\" is too large"), value ); return FALSE; } else { optval = infinoted_parameter_typed_value_new(); optval->type = INFINOTED_PARAMETER_INT; optval->value.number = l_val; g_hash_table_insert(options, (gpointer)info, optval); } return TRUE; case INFINOTED_PARAMETER_STRING: if(g_hash_table_lookup(options, info) != NULL) { g_set_error( error, infinoted_options_error_quark(), INFINOTED_OPTIONS_ERROR_MULTIPLE_OPTIONS, _("The option \"%s\" can only be given once"), option_name ); return FALSE; } optval = infinoted_parameter_typed_value_new(); optval->type = INFINOTED_PARAMETER_STRING; optval->value.str = g_strdup(value); g_hash_table_insert(options, (gpointer)info, optval); return TRUE; case INFINOTED_PARAMETER_STRING_LIST: optval = g_hash_table_lookup(options, info); if(optval == NULL) { optval = infinoted_parameter_typed_value_new(); optval->type = INFINOTED_PARAMETER_STRING_LIST; optval->value.strv = g_malloc(2 * sizeof(gchar*)); optval->value.strv[0] = g_strdup(value); optval->value.strv[1] = NULL; g_hash_table_insert(options, (gpointer)info, optval); } else { g_assert(optval->type == INFINOTED_PARAMETER_STRING_LIST); n_strs = 0; for(str = optval->value.strv; *str != NULL; ++str) ++n_strs; optval->value.strv = g_realloc( optval->value.strv, (n_strs + 2) * sizeof(gchar*) ); optval->value.strv[n_strs] = g_strdup(value); optval->value.strv[n_strs + 1] = NULL; } return TRUE; default: g_assert_not_reached(); return FALSE; } } static void infinoted_options_args_to_keyfile_foreach_func(gpointer key, gpointer value, gpointer user_data) { const InfinotedParameterInfo* info; const InfinotedParameterTypedValue* optval; GKeyFile* key_file; gchar* const* str; guint n_strs; info = (const InfinotedParameterInfo*)key; optval = (const InfinotedParameterTypedValue*)value; key_file = (GKeyFile*)user_data; g_assert(info->type == optval->type); switch(info->type) { case INFINOTED_PARAMETER_BOOLEAN: g_key_file_set_boolean( key_file, INFINOTED_OPTIONS_GROUP, info->name, optval->value.yesno ); break; case INFINOTED_PARAMETER_INT: g_key_file_set_integer( key_file, INFINOTED_OPTIONS_GROUP, info->name, optval->value.number ); break; case INFINOTED_PARAMETER_STRING: g_key_file_set_string( key_file, INFINOTED_OPTIONS_GROUP, info->name, optval->value.str ); break; case INFINOTED_PARAMETER_STRING_LIST: n_strs = 0; for(str = optval->value.strv; *str != NULL; ++str) ++n_strs; g_key_file_set_string_list( key_file, INFINOTED_OPTIONS_GROUP, info->name, (const gchar* const*)optval->value.strv, n_strs ); break; default: g_assert_not_reached(); break; } } static gboolean infinoted_options_override_plugin_parameters(const gchar* const* parameters, GKeyFile* key_file, GError** error) { const gchar* const* parameter; gchar** tokens; for(parameter = parameters; *parameter != NULL; ++parameter) { tokens = g_strsplit(*parameter, ":", 3); if(tokens == NULL || tokens[0] == NULL || tokens[1] == NULL || tokens[2] == NULL) { g_strfreev(tokens); g_set_error( error, infinoted_options_error_quark(), INFINOTED_OPTIONS_ERROR_INVALID_PLUGIN_PARAMETER, "Invalid sequence for specifying a plugin parameter: \"%s\". " "The value must have the form PLUGIN:PARAMETER:VALUE", *parameter ); return FALSE; } g_key_file_set_string( key_file, tokens[0], tokens[1], tokens[2] ); g_strfreev(tokens); } return TRUE; } static gboolean infinoted_options_load(InfinotedOptions* options, const gchar* const* config_files, int* argc, char*** argv, GError** error) { gchar* config_filename[2]; gboolean create_key; gboolean create_certificate; gchar** plugin_parameters; gboolean daemonize; gboolean kill_daemon; gboolean display_version; GOptionContext *context; gchar* desc; const InfinotedParameterInfo* info; GOptionGroup* group; GOptionEntry* entries; guint n_entries; guint index; GHashTable* cmdline_options; GKeyFile* key_file; gboolean result; const GOptionEntry STATIC_ENTRIES[] = { { "config-file", 0, 0, G_OPTION_ARG_FILENAME, &config_filename[0], N_("Configuration file to load, instead of the default " "configuration file"), N_("CONFIG-FILE") }, { "create-key", 0, 0, G_OPTION_ARG_NONE, &create_key, N_("Creates a new random private key. The new key will be stored at " "the given location for the server's private key."), NULL }, { "create-certificate", 0, 0, G_OPTION_ARG_NONE, &create_certificate, N_("Creates a new self-signed certificate signed with the given " "private key. The certificate is stored at the given location " "for the server's certificate."), NULL }, { "plugin-parameter", 0, 0, G_OPTION_ARG_STRING_ARRAY, &plugin_parameters, N_("Allows one to override configuration entries for plugins from the " "command line. The syntax is --plugin-parameter=plugin:key:value, " "where plugin is the name of the plugin for which to override a " "configuration parameter, key is the parameter which to override " "and value is the new value of the parameter"), N_("PLUGIN:PARAMETER:VALUE") }, { #ifdef LIBINFINITY_HAVE_LIBDAEMON "daemonize", 'd', 0, G_OPTION_ARG_NONE, &daemonize, N_("Daemonize the server, i.e. run it in the background"), NULL }, { "kill-daemon", 'D', 0, G_OPTION_ARG_NONE, &kill_daemon, N_("Kill a running daemon and exit"), NULL }, { #endif "version", 'v', 0, G_OPTION_ARG_NONE, &display_version, N_("Display version information and exit"), NULL }, { NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, 0 } }; /* default values */ config_filename[0] = NULL; create_key = options->create_key; create_certificate = options->create_certificate; plugin_parameters = NULL; #ifdef LIBINFINITY_HAVE_LIBDAEMON daemonize = options->daemonize; #endif kill_daemon = FALSE; display_version = FALSE; /* Build an array of all GOptionEntries -- the above static ones, plus one for each * configuration file option. The configuration file options parsed via command line * are stored in a hash table, and after the configuration file has been read, the * elements are replaced in the GKeyFile before the GKeyFile is parsed. */ n_entries = G_N_ELEMENTS(INFINOTED_OPTIONS); entries = g_malloc(n_entries * sizeof(GOptionEntry)); index = 0; for(info = INFINOTED_OPTIONS; info->name != NULL; ++info) { entries[index].long_name = info->name; entries[index].short_name = info->short_name; entries[index].flags = 0; entries[index].arg = G_OPTION_ARG_CALLBACK; entries[index].arg_data = infinoted_options_parse_arg_func; entries[index].description = info->description; entries[index].arg_description = info->arg_description; ++index; } g_assert(index == n_entries - 1); entries[index].long_name = NULL; entries[index].short_name = 0; entries[index].flags = 0; entries[index].arg = 0; entries[index].arg_data = NULL; entries[index].description = NULL; entries[index].arg_description = NULL; /* Now, parse the options */ if(argc != NULL && argv != NULL) { cmdline_options = g_hash_table_new_full( NULL, NULL, NULL, infinoted_parameter_typed_value_free ); /* Note that we take ownership of the hash table ourselves */ group = g_option_group_new( "main", N_("Infinoted Options"), N_("Main Program Options"), cmdline_options, NULL ); g_option_group_set_translation_domain(group, GETTEXT_PACKAGE); g_option_group_add_entries(group, STATIC_ENTRIES); g_option_group_add_entries(group, entries); desc = g_strdup_printf("- %s", _("infinote dedicated server")); context = g_option_context_new(desc); g_free(desc); g_option_context_set_main_group(context, group); if(g_option_context_parse(context, argc, argv, error) == FALSE) { g_option_context_free(context); g_free(entries); g_hash_table_unref(cmdline_options); return FALSE; } if(display_version) { printf("infinoted %s\n", PACKAGE_VERSION); exit(0); } #ifdef LIBINFINITY_HAVE_LIBDAEMON if(kill_daemon) { infinoted_util_daemon_set_global_pid_file_proc(); if(infinoted_util_daemon_pid_file_kill(SIGTERM) != 0) { infinoted_util_daemon_set_local_pid_file_proc(); if(infinoted_util_daemon_pid_file_kill(SIGTERM) != 0) { g_option_context_free(context); g_free(entries); g_hash_table_unref(cmdline_options); g_strfreev(plugin_parameters); infinoted_util_set_errno_error(error, errno, _("Could not kill daemon")); return FALSE; } } exit(0); } #endif g_option_context_free(context); } g_free(entries); options->create_key = create_key; options->create_certificate = create_certificate; #ifdef LIBINFINITY_HAVE_LIBDAEMON options->daemonize = daemonize; #endif /* Next, read the configuration file into a GKeyFile. The configuration file * can be overridden on the command line, so we can only do this after * command line option parsing. */ if(config_filename[0] != NULL) { config_filename[1] = NULL; key_file = infinoted_options_read_config_into_keyfile( (const gchar* const*)config_filename, FALSE, error ); g_free(config_filename[0]); } else { key_file = infinoted_options_read_config_into_keyfile( config_files, TRUE, error ); } if(!key_file) { g_hash_table_unref(cmdline_options); g_strfreev(plugin_parameters); return FALSE; } /* With the key file in hands, we now override any options given on the * command line. */ if(argc != NULL && argv != NULL) { g_hash_table_foreach( cmdline_options, infinoted_options_args_to_keyfile_foreach_func, key_file ); g_hash_table_unref(cmdline_options); } if(plugin_parameters != NULL) { result = infinoted_options_override_plugin_parameters( (const gchar* const*)plugin_parameters, key_file, error ); g_strfreev(plugin_parameters); if(!result) { g_key_file_free(key_file); return FALSE; } } /* Finally, load the key file into the actual options structure */ result = infinoted_parameter_load_from_key_file( INFINOTED_OPTIONS, key_file, INFINOTED_OPTIONS_GROUP, options, error ); if(!result || !infinoted_options_validate(options, error)) { g_key_file_free(key_file); return FALSE; } g_assert(options->config_key_file == NULL); options->config_key_file = key_file; return TRUE; } /** * infinoted_options_new: * @config_files: A %NULL-terminated error of config filenames. * @argc: Pointer to command line argument count, or %NULL. * @argv: Pointer to command line argument vector, or %NULL. * @error: Location to store error information, if any. * * Creates a new #InfinotedOptions structure that contains options infinoted * is supposed to start with. Command line options always overwrite config * file options. * * The config files are checked in order, the first one that exists is being * loaded, and the other ones are being ignored. If the command line array * includes the --config-file option, the @config_files array is overriden * by the command line option. * * Returns: A new #InfinotedOptions, or %NULL in case of error. * Free with infinoted_options_free(). */ InfinotedOptions* infinoted_options_new(const gchar* const* config_files, int* argc, char*** argv, GError** error) { InfinotedOptions* options; options = g_slice_new(InfinotedOptions); options->config_key_file = NULL; /* Default options */ options->log_path = NULL; options->key_file = NULL; options->certificate_file = NULL; options->certificate_chain_file = NULL; options->create_key = FALSE; options->create_certificate = FALSE; options->port = inf_protocol_get_default_port(); options->listen_address = NULL; options->security_policy = INF_XMPP_CONNECTION_SECURITY_ONLY_TLS; options->root_directory = g_build_filename(g_get_home_dir(), ".infinote", NULL); options->plugins = g_malloc(2 * sizeof(gchar*)); options->plugins[0] = g_strdup("note-text"); options->plugins[1] = NULL; options->password = NULL; options->password_len = 0; #ifdef LIBINFINITY_HAVE_PAM options->pam_service = NULL; options->pam_allowed_users = NULL; options->pam_allowed_groups = NULL; #endif /* LIBINFINITY_HAVE_PAM */ #ifdef LIBINFINITY_HAVE_LIBDAEMON options->daemonize = FALSE; #endif if(!infinoted_options_load(options, config_files, argc, argv, error)) { infinoted_options_free(options); return NULL; } return options; } /** * infinoted_options_free: * @options: A #InfinotedOptions. * * Frees @options and clears up all memory allocated by it. */ void infinoted_options_free(InfinotedOptions* options) { g_free(options->log_path); g_free(options->key_file); g_free(options->certificate_file); g_free(options->certificate_chain_file); g_free(options->root_directory); if(options->listen_address != NULL) inf_ip_address_free(options->listen_address); g_strfreev(options->plugins); g_free(options->password); #ifdef LIBINFINITY_HAVE_PAM g_free(options->pam_service); g_strfreev(options->pam_allowed_users); g_strfreev(options->pam_allowed_groups); #endif if(options->config_key_file != NULL) g_key_file_free(options->config_key_file); g_slice_free(InfinotedOptions, options); } /** * infinoted_options_error_quark: * * Returns the #GQuark for errors from the InfinotedOptions module. * * Returns: The error domain for the InfinotedOptions module. */ GQuark infinoted_options_error_quark(void) { return g_quark_from_static_string("INFINOTED_OPTIONS_ERROR"); } /** * infinoted_options_drop_config_file: * @options: The #InfinotedOptions object for which to drop the configuration * file. * * Removes the reference to the configuration #GKeyFile from the * #InfinotedOptions structure. Typically, after options are loaded, the * #GKeyFile is still kept around and can be used to read other options, for * example for activated plugins. * * Once this has happened this function can be called to drop the * configuration file and release the memory that it uses. */ void infinoted_options_drop_config_file(InfinotedOptions* options) { g_assert(options->config_key_file != NULL); g_key_file_free(options->config_key_file); options->config_key_file = NULL; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/infinoted/PaxHeaders.26529/infinoted-main.c0000644000000000000000000000013213034342512020624 xustar0030 mtime=1483851082.013718339 30 atime=1483851082.013718339 30 ctime=1488261589.472138033 libinfinity-0.7.1/infinoted/infinoted-main.c0000644000175000017500000001355213034342512021364 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include #include #include #include #include #ifdef LIBINFINITY_HAVE_LIBDAEMON #include #include #include #include #include #endif #include #include #include /* Takes ownership of startup */ static gboolean infinoted_main_run(InfinotedStartup* startup, GError** error) { InfinotedRun* run; InfinotedSignal* sig; #ifdef LIBINFINITY_HAVE_LIBDAEMON mode_t prev_umask; pid_t pid; int saved_errno; #endif /* infinoted_run_new() takes ownership of startup */ run = infinoted_run_new(startup, error); if(run == NULL) { infinoted_startup_free(startup); return FALSE; } #ifdef LIBINFINITY_HAVE_LIBDAEMON if(startup->options->daemonize) { prev_umask = umask(0777); if(daemon_retval_init() == -1) { infinoted_run_free(run); return FALSE; /* libdaemon already wrote an error message */ } pid = daemon_fork(); if(pid < 0) { /* Translators: fork as in "fork into the background" */ infinoted_util_set_errno_error(error, errno, _("Failed to fork")); infinoted_run_free(run); daemon_retval_done(); return FALSE; } else if(pid > 0) { infinoted_run_free(run); saved_errno = daemon_retval_wait(5); if(saved_errno == 0) { return TRUE; } if(saved_errno == -1) { infinoted_util_set_errno_error(error, errno, _("Failed to wait for daemonized child's return value")); return FALSE; } else { /* on -1, the child process would have subtracted one from * errno before passing it back to us. */ if(saved_errno < 0) ++saved_errno; infinoted_util_set_errno_error( error, saved_errno, _("Failed to create PID file")); return FALSE; } } else { infinoted_util_daemon_set_global_pid_file_proc(); if(daemon_pid_file_create() != 0) { infinoted_util_daemon_set_local_pid_file_proc(); if(daemon_pid_file_create() != 0) { if(daemon_pid_file_create() != 0) { saved_errno = errno; infinoted_util_set_errno_error( error, saved_errno, _("Failed to create PID file") ); if(saved_errno < 0) --saved_errno; daemon_retval_send(saved_errno); infinoted_run_free(run); return FALSE; } } } daemon_retval_send(0); } /* libdaemon sets the umask to either 0777 (< 0.14) or 0077 (>= 0.14). * We don't want either of that, to make sure the directory tree is * always readable by us and potentially by others (for example, a * webserver providing read access to the documents). Therefore, reset * the umask here to what it previously was, so the system administrator * can define the umask by setting it before launching infinoted. * See also http://gobby.0x539.de/trac/ticket/617. */ umask(prev_umask); } #endif sig = infinoted_signal_register(run); /* Now start the server. It can later be stopped by signals. */ infinoted_run_start(run); infinoted_signal_unregister(sig); #ifdef LIBINFINITY_HAVE_LIBDAEMON /* startup might be invalid at this point in case a config reload happened, * so use run->startup instead (which is revalidated by config reload). */ if(run->startup->options->daemonize) daemon_pid_file_remove(); #endif infinoted_run_free(run); return TRUE; } static gboolean infinoted_main(int argc, char* argv[], GError** error) { InfinotedStartup* startup; InfinotedLog* log; GError* local_error; startup = infinoted_startup_new(&argc, &argv, error); if(startup == NULL) return FALSE; log = startup->log; g_object_ref(log); #ifdef LIBINFINITY_HAVE_LIBDAEMON if(startup->options->daemonize) { daemon_pid_file_ident = daemon_ident_from_argv0(argv[0]); daemon_log_ident = daemon_pid_file_ident; } #endif /* If an error happens here, write it to the log file as well, so that * the system administrator is notified for errors that happen after * forking into the background also in the log file. */ local_error = NULL; infinoted_main_run(startup, &local_error); if(local_error != NULL) { infinoted_log_error(log, "%s", local_error->message); g_propagate_error(error, local_error); g_object_unref(log); return FALSE; } g_object_unref(log); return TRUE; } int main(int argc, char* argv[]) { GError* error; setlocale(LC_ALL, ""); error = NULL; if(infinoted_main(argc, argv, &error) == FALSE) { if(error) { fprintf(stderr, "%s\n", error->message); g_error_free(error); } return -1; } return 0; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/infinoted/PaxHeaders.26529/infinoted-run.c0000644000000000000000000000013213034342512020504 xustar0030 mtime=1483851082.013718339 30 atime=1483851082.013718339 30 ctime=1488261589.476138024 libinfinity-0.7.1/infinoted/infinoted-run.c0000644000175000017500000002762713034342512021254 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include #include #include static const guint8 INFINOTED_RUN_IPV6_ANY_ADDR[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static gboolean infinoted_run_load_directory(InfinotedRun* run, InfinotedStartup* startup, GError** error) { InfdFilesystemStorage* storage; InfdFilesystemAccountStorage* account_storage; InfCommunicationManager* communication_manager; #ifdef G_OS_WIN32 gchar* module_path; #endif gchar* plugin_path; gboolean result; storage = infd_filesystem_storage_new(startup->options->root_directory); communication_manager = inf_communication_manager_new(); run->io = inf_standalone_io_new(); run->directory = infd_directory_new( INF_IO(run->io), INFD_STORAGE(storage), communication_manager ); infd_directory_enable_chat(run->directory, TRUE); g_object_unref(communication_manager); /* Load server plugins via plugin manager */ #ifdef G_OS_WIN32 module_path = g_win32_get_package_installation_directory_of_module(NULL); plugin_path = g_build_filename(module_path, "lib", PLUGIN_PATH, NULL); g_free(module_path); #else plugin_path = g_build_filename(PLUGIN_LIBPATH, PLUGIN_PATH, NULL); #endif run->plugin_manager = infinoted_plugin_manager_new( run->directory, startup->log, startup->credentials ); result = infinoted_plugin_manager_load( run->plugin_manager, plugin_path, (const gchar* const*)startup->options->plugins, startup->options->config_key_file, error ); g_free(plugin_path); infinoted_options_drop_config_file(startup->options); if(result == FALSE) { g_object_unref(storage); g_object_unref(run->plugin_manager); g_object_unref(run->directory); g_object_unref(run->io); run->plugin_manager = NULL; run->directory = NULL; run->io = NULL; return FALSE; } /* Set an account storage, too. This can be replaced by something more fancy * by a plugin. */ /* TODO: This filesystem storage should be moved into a plugin, so that * users can enable it optionally. */ g_object_get(G_OBJECT(run->directory), "account-storage", &account_storage, NULL); if(account_storage == NULL) { account_storage = infd_filesystem_account_storage_new(); result = infd_filesystem_account_storage_set_filesystem( account_storage, storage, error ); if(result == FALSE) { g_object_unref(storage); g_object_unref(account_storage); g_object_unref(run->plugin_manager); g_object_unref(run->directory); g_object_unref(run->io); run->plugin_manager = NULL; run->directory = NULL; run->io = NULL; return FALSE; } g_object_set( G_OBJECT(run->directory), "account-storage", account_storage, NULL ); } g_object_unref(storage); g_object_unref(account_storage); return TRUE; } static InfdXmppServer* infinoted_run_create_server(InfinotedRun* run, InfinotedStartup* startup, InfIpAddress* address, GError** error) { InfdTcpServer* tcp; InfdXmppServer* xmpp; tcp = INFD_TCP_SERVER( g_object_new( INFD_TYPE_TCP_SERVER, "io", INF_IO(run->io), "local-address", address, "local-port", startup->options->port, NULL ) ); infd_tcp_server_set_keepalive(tcp, &startup->keepalive); if(!infd_tcp_server_bind(tcp, error)) { g_object_unref(tcp); return NULL; } xmpp = infd_xmpp_server_new( tcp, startup->options->security_policy, startup->credentials, startup->sasl_context, startup->sasl_context ? "PLAIN" : NULL ); infd_server_pool_add_server(run->pool, INFD_XML_SERVER(xmpp)); #ifdef LIBINFINITY_HAVE_AVAHI infd_server_pool_add_local_publisher( run->pool, xmpp, INF_LOCAL_PUBLISHER(run->avahi) ); #endif g_object_unref(tcp); return xmpp; } /** * infinoted_run_new: * @startup: Startup parameters for the Infinote Server. * @error: Location to store error information, if any. * * Creates all necessary ressources for running an Infinote server. The * #InfinotedRun has taken ownership of @startup if this function returns * non-%NULL. * * Use infinoted_run_start() to start the server. * * Returns: A new #InfinotedRun, free with infinoted_run_free(). Or %NULL, * on error. */ InfinotedRun* infinoted_run_new(InfinotedStartup* startup, GError** error) { InfIpAddress* address; #ifdef LIBINFINITY_HAVE_AVAHI InfXmppManager* xmpp_manager; #endif InfinotedRun* run; GError* local_error; run = g_slice_new(InfinotedRun); run->startup = startup; run->dh_params = NULL; if(infinoted_run_load_directory(run, startup, error) == FALSE) { g_slice_free(InfinotedRun, run); return NULL; } run->pool = infd_server_pool_new(run->directory); #ifdef LIBINFINITY_HAVE_AVAHI xmpp_manager = inf_xmpp_manager_new(); run->avahi = inf_discovery_avahi_new( INF_IO(run->io), xmpp_manager, startup->credentials, NULL, NULL ); g_object_unref(xmpp_manager); #endif local_error = NULL; if(startup->options->listen_address != NULL) { /* Use manually specified listen address */ address = inf_ip_address_copy(startup->options->listen_address); switch(inf_ip_address_get_family(address)) { case INF_IP_ADDRESS_IPV4: run->xmpp4 = infinoted_run_create_server(run, startup, address, &local_error); run->xmpp6 = NULL; break; case INF_IP_ADDRESS_IPV6: run->xmpp4 = NULL; run->xmpp6 = infinoted_run_create_server(run, startup, address, &local_error); break; } } else { address = inf_ip_address_new_raw6(INFINOTED_RUN_IPV6_ANY_ADDR); run->xmpp6 = infinoted_run_create_server(run, startup, address, NULL); run->xmpp4 = infinoted_run_create_server(run, startup, NULL, &local_error); } if(run->xmpp4 == NULL) { /* Ignore if we have an IPv6 server running */ if(run->xmpp6 != NULL) { if(local_error != NULL) g_error_free(local_error); } else { g_propagate_error(error, local_error); #ifdef LIBINFINITY_HAVE_AVAHI g_object_unref(run->avahi); #endif g_object_unref(run->pool); g_object_unref(run->directory); g_object_unref(run->io); g_slice_free(InfinotedRun, run); run = NULL; } } inf_ip_address_free(address); return run; } /** * infinoted_run_free: * @run: A #InfinotedRun. * * Frees the given #InfinotedRun, so that it can no longer be used. */ void infinoted_run_free(InfinotedRun* run) { InfdXmlServerStatus status; if(inf_standalone_io_loop_running(run->io)) inf_standalone_io_loop_quit(run->io); if(run->xmpp6 != NULL) { g_object_get(G_OBJECT(run->xmpp6), "status", &status, NULL); infd_server_pool_remove_server(run->pool, INFD_XML_SERVER(run->xmpp6)); if(status != INFD_XML_SERVER_CLOSED) infd_xml_server_close(INFD_XML_SERVER(run->xmpp6)); g_object_unref(run->xmpp6); } if(run->xmpp4 != NULL) { g_object_get(G_OBJECT(run->xmpp4), "status", &status, NULL); infd_server_pool_remove_server(run->pool, INFD_XML_SERVER(run->xmpp4)); if(status != INFD_XML_SERVER_CLOSED) infd_xml_server_close(INFD_XML_SERVER(run->xmpp4)); g_object_unref(run->xmpp4); } #ifdef LIBINFINITY_HAVE_AVAHI g_object_unref(run->avahi); #endif if(run->plugin_manager != NULL) { g_object_unref(run->plugin_manager); run->plugin_manager = NULL; } g_object_unref(run->io); g_object_unref(run->directory); g_object_unref(run->pool); if(run->dh_params != NULL) gnutls_dh_params_deinit(run->dh_params); if(run->startup != NULL) infinoted_startup_free(run->startup); g_slice_free(InfinotedRun, run); } /** * infinoted_run_start: * @run: A #InfinotedRun. * * Starts the infinote server. This runs in a loop until infinoted_run_stop() * is called. This may fail in theory, but hardly does in practise. If it * fails, it prints an error message to stderr and returns. It may also block * before starting to generate DH parameters for key exchange. */ void infinoted_run_start(InfinotedRun* run) { GError* error; GError* error4; GError* error6; guint port; gboolean result; InfdTcpServer* tcp; error = NULL; error4 = NULL; error6 = NULL; /* Load DH parameters */ if(run->startup->credentials) { result = infinoted_dh_params_ensure( run->startup->log, run->startup->credentials, &run->dh_params, &error); if(result == FALSE) { infinoted_log_error( run->startup->log, _("Failed to generate Diffie-Hellman parameters: %s"), error->message ); g_error_free(error); return; } } /* Open server sockets, accepting incoming connections... TODO: Prevent * code duplication here. */ if(run->xmpp6 != NULL) { g_object_get(G_OBJECT(run->xmpp6), "tcp-server", &tcp, NULL); if(infd_tcp_server_open(tcp, &error6) == TRUE) { g_object_get(G_OBJECT(tcp), "local-port", &port, NULL); infinoted_log_info( run->startup->log, _("IPv6 Server running on port %u"), port ); } else { g_object_unref(run->xmpp6); run->xmpp6 = NULL; infd_tcp_server_close(tcp); } g_object_unref(tcp); } if(run->xmpp4 != NULL) { g_object_get(G_OBJECT(run->xmpp4), "tcp-server", &tcp, NULL); if(infd_tcp_server_open(tcp, &error4) == TRUE) { g_object_get(G_OBJECT(tcp), "local-port", &port, NULL); infinoted_log_info( run->startup->log, _("IPv4 Server running on port %u"), port ); } else { g_object_unref(run->xmpp4); run->xmpp4 = NULL; infd_tcp_server_close(tcp); } g_object_unref(tcp); } if(run->xmpp4 == NULL && run->xmpp6 == NULL) { g_assert(error4 != NULL || error6 != NULL); error = error4 != NULL ? error4 : error6; infinoted_log_error( run->startup->log, _("Failed to start server: %s"), error->message ); } if(error4 != NULL) g_error_free(error4); if(error6 != NULL) g_error_free(error6); /* Make sure messages are shown. This explicit flush is for example * required when running in an MSYS shell on Windows. */ fflush(stderr); if(run->xmpp4 != NULL || run->xmpp6 != NULL) { inf_standalone_io_loop(run->io); infinoted_log_info( run->startup->log, _("Infinoted shutting down...") ); } } /** * infinoted_run_stop: * @run: A #InfinotedRun. * * Stops a running infinote server. */ void infinoted_run_stop(InfinotedRun* run) { inf_standalone_io_loop_quit(run->io); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/infinoted/PaxHeaders.26529/infinoted-parameter.c0000644000000000000000000000013113034342512021657 xustar0030 mtime=1483851082.013718339 30 atime=1483851082.013718339 29 ctime=1488261589.46413805 libinfinity-0.7.1/infinoted/infinoted-parameter.c0000644000175000017500000005231013034342512022413 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:infinoted-parameter * @title: InfinotedParameter * @short_description: Declare parameters of infinoted plugins. * @include: infinoted/infinoted-parameter.h * @stability: Unstable * * The #InfinotedParameterInfo structure allows to declare a parameter that * can then be used as an input value to a plugin. While the types for input * data are limited, the mechanism allows to provide a powerful validation and * transformation function which can turn the input value to the final * internal representation in the plugin data structure. * * Parameters are declared by providing a #InfinotedParameterInfo structure, * and an array of such structures is then given to #InfinotedPlugin which * declares a plugin. */ #include "config.h" #include #include #include G_DEFINE_BOXED_TYPE(InfinotedParameterTypedValue, infinoted_parameter_typed_value, infinoted_parameter_typed_value_copy, infinoted_parameter_typed_value_free) static void infinoted_parameter_free_data(InfinotedParameterType type, InfinotedParameterValue* value) { switch(type) { case INFINOTED_PARAMETER_BOOLEAN: case INFINOTED_PARAMETER_INT: break; case INFINOTED_PARAMETER_STRING: g_free(value->str); break; case INFINOTED_PARAMETER_STRING_LIST: g_strfreev(value->strv); break; default: g_assert_not_reached(); break; } } static gboolean infinoted_parameter_load_one_from_key_file(const InfinotedParameterInfo* info, GKeyFile* key_file, const gchar* group, gpointer base, GError** error) { GError* local_error; InfinotedParameterValue v; gpointer in; gpointer out; local_error = NULL; switch(info->type) { case INFINOTED_PARAMETER_BOOLEAN: v.yesno = g_key_file_get_boolean( key_file, group, info->name, &local_error ); in = &v.yesno; break; case INFINOTED_PARAMETER_INT: v.number = g_key_file_get_integer( key_file, group, info->name, &local_error ); in = &v.number; break; case INFINOTED_PARAMETER_STRING: v.str = g_key_file_get_string( key_file, group, info->name, &local_error ); in = &v.str; break; case INFINOTED_PARAMETER_STRING_LIST: v.strv = g_key_file_get_string_list( key_file, group, info->name, NULL, &local_error ); in = &v.strv; break; default: g_assert_not_reached(); break; } if(local_error != NULL) { if(local_error->domain == G_KEY_FILE_ERROR && (local_error->code == G_KEY_FILE_ERROR_GROUP_NOT_FOUND || local_error->code == G_KEY_FILE_ERROR_KEY_NOT_FOUND)) { g_error_free(local_error); local_error = NULL; if(info->flags & INFINOTED_PARAMETER_REQUIRED) { g_set_error( error, infinoted_parameter_error_quark(), INFINOTED_PARAMETER_ERROR_REQUIRED, _("The parameter \"%s\" is required"), info->name ); return FALSE; } return TRUE; } g_propagate_error(error, local_error); return FALSE; } else { out = (char*)base + info->offset; info->convert(out, in, &local_error); infinoted_parameter_free_data(info->type, &v); if(local_error != NULL) { g_propagate_error(error, local_error); return FALSE; } return TRUE; } } /** * infinoted_parameter_error_quark: * * Returns the #GQuark for errors from the InfinotedParameter module. * * Returns: The error domain for the InfinotedParameter module. */ GQuark infinoted_parameter_error_quark(void) { return g_quark_from_static_string("INFINOTED_PARAMETER_ERROR"); } /** * infinoted_parameter_typed_value_new: * * Creates a new instance of a @InfinotedParameterTypedValue. The new instance * will be uninitialized. Its @type and @value members need to be set before * the object can be used or given to infinoted_parameter_typed_value_free(). * * Returns: A new #InfinotedParameterTypedValue. Free with * infinoted_parameter_typed_value_free() when no longer needed. */ InfinotedParameterTypedValue* infinoted_parameter_typed_value_new(void) { return g_slice_new(InfinotedParameterTypedValue); } /** * infinoted_parameter_typed_value_copy: * @val: The value to copy. * * Makes a dynamically allocated copy of @val. * * Returns: A new #InfinotedParameterTypedValue. Free with * infinoted_parameter_typed_value_free() when no longer needed. */ InfinotedParameterTypedValue* infinoted_parameter_typed_value_copy(const InfinotedParameterTypedValue* val) { InfinotedParameterTypedValue* v; v = g_slice_new(InfinotedParameterTypedValue); v->type = val->type; switch(v->type) { case INFINOTED_PARAMETER_BOOLEAN: v->value.yesno = val->value.yesno; break; case INFINOTED_PARAMETER_INT: v->value.number = val->value.number; break; case INFINOTED_PARAMETER_STRING: v->value.str = g_strdup(val->value.str); break; case INFINOTED_PARAMETER_STRING_LIST: v->value.strv = g_strdupv(val->value.strv); break; default: g_assert_not_reached(); break; } return v; } /** * infinoted_parameter_typed_value_free: * @data: The #InfinotedParameterTypedValue to free. * * Frees an instance of #InfinotedParameterTypedValue. Formally the argument * is kept as a generic pointer so that this function can be used as a * #GDestroyNotify callback. * * Note that the #InfinotedParameterTypedValue needs to be correctly * initialized, i.e. its type must be set, before it can be freed. */ void infinoted_parameter_typed_value_free(gpointer data) { InfinotedParameterTypedValue* val; val = (InfinotedParameterTypedValue*)data; infinoted_parameter_free_data(val->type, &val->value); g_slice_free(InfinotedParameterTypedValue, val); } /** * infinoted_parameter_load_from_key_file: * @infos: (array zero-terminated=1): A 0-terminated array of * #InfinotedParameterInfo objects. * @key_file: The #GKeyFile to load parameter values from. * @group: The keyfile group to load the values from. * @base: The instance into which to write the read parameters. * @error: Location to store error information, if any, or %NULL. * * Attempts to read each parameter in @infos from @key_file and store them in * a user-specified structure @base. The @offset field of * #InfinotedParameterInfo specifies where inside @base the read parameter * value will be written, and the @convert field specifies a function which * converts the parameter type (integer, string or string list) into the * type of the field in the target structure. * * If the key file does not have an entry for one of the entries in @infos, * then the current value in the base structure is untouched. This allows * setting default values prior to calling this function. * * If the function fails, for example because the conversion into the target * type failed (which, in turn, might be due to invalid user input), %FALSE * is returned and @error is set. * * Returns: %TRUE on success, otherwise %FALSE. */ gboolean infinoted_parameter_load_from_key_file(const InfinotedParameterInfo* infos, GKeyFile* key_file, const gchar* group, gpointer base, GError** error) { const InfinotedParameterInfo* info; gboolean retval; for(info = infos; info->name != NULL; ++info) { retval = infinoted_parameter_load_one_from_key_file( info, key_file, group, base, error ); if(!retval) return FALSE; } return TRUE; } /** * infinoted_parameter_convert_string: * @out: (type gchar**) (out): The pointer to the output string location. * @in: (type gchar**) (in): A pointer to the input string location. * @error: Location to store error information, if any, or %NULL. * * This is basically a no-op, moving the string from the @in location to the * @out location. In case @in points to the empty string, it is freed and the * output string is set to be %NULL. * * This is a #InfinotedParameterConvertFunc function that can be used for * strings that should not be processed further or validated. * * Returns: This function always returns %TRUE. */ gboolean infinoted_parameter_convert_string(gpointer out, gpointer in, GError** error) { gchar** out_str; gchar** in_str; out_str = (gchar**)out; in_str = (gchar**)in; /* free previous entry */ g_free(*out_str); /* set new value */ *out_str = *in_str; /* reset old value, to avoid it being freed */ *in_str = NULL; /* Set empty strings to NULL */ if(*out_str != NULL && **out_str == '\0') { g_free(*out_str); *out_str = NULL; } return TRUE; } /** * infinoted_parameter_convert_string_list: * @out: (type gchar***) (out): The pointer to the output string list. * @in: (type gchar***) (array zero-terminated=1) (in): The pointer to the input string list. * @error: Location to store error information, if any, or %NULL. * * This is basically a no-op, moving the string list from the @in location to * the @out location. In case @in points to an empty string list, or to a * string list with only one entry which is the empty string, then the string * list is freed and the output string list is set to be %NULL. * * This is a #InfinotedParameterConvertFunc function that can be used for * string lists that should not be processed further or validated. * * Returns: This function always returns %TRUE. */ gboolean infinoted_parameter_convert_string_list(gpointer out, gpointer in, GError** error) { gchar*** out_str; gchar*** in_str; out_str = (gchar***)out; in_str = (gchar***)in; /* free previous entry */ g_strfreev(*out_str); /* set new value */ *out_str = *in_str; /* reset old value, to avoid it being freed */ *in_str = NULL; /* Set empty string lists, or a string list with only one empty string, * to NULL. */ if(*out_str != NULL) { if( (*out_str)[0] != NULL) { if(*(*out_str)[0] == '\0' && (*out_str)[1] == NULL) { g_free( (*out_str)[0]); (*out_str)[0] = NULL; } } if( (*out_str)[0] == NULL) { g_free(*out_str); *out_str = NULL; } } return TRUE; } /** * infinoted_parameter_convert_filename: * @out: (type gchar**) (out): The pointer to the output string location. * @in: (type gchar**) (in): A pointer to the input string location. * @error: Location to store error information, if any, or %NULL. * * This function converts the input string from UTF-8 * to the Glib file name encoding. * * This is a #InfinotedParameterConvertFunc function that can be used for * strings that should be in Glib file name encoding format instead of * UTF-8. * * Returns: %TRUE on success, or %FALSE otherwise. */ gboolean infinoted_parameter_convert_filename(gpointer out, gpointer in, GError** error) { gchar** out_str; gchar** in_str; out_str = (gchar**)out; in_str = (gchar**)in; /* free previous entry */ g_free(*out_str); if(*in_str != NULL && **in_str != '\0') { *out_str = g_filename_from_utf8(*in_str, -1, NULL, NULL, error); if(*out_str == NULL) return FALSE; } else { *out_str = NULL; } return TRUE; } /** * infinoted_parameter_convert_boolean: * @out: (type gboolean*) (out): The pointer to the output #gboolean. * @in: (type gboolean*) (in): The pointer to the input #gboolean. * @error: Location to store error information, if any, or %NULL. * * This function simply writes the boolean value from @in to @out without any * further validation. * * This is a #InfinotedParameterConvertFunc function that can be used for * boolean values. * * Returns: This function always returns %TRUE. */ gboolean infinoted_parameter_convert_boolean(gpointer out, gpointer in, GError** error) { gboolean value; value = *(gboolean*)in; *(gboolean*)out = value; return TRUE; } /** * infinoted_parameter_convert_port: * @out: (type guint*) (out): The pointer to the output #guint. * @in: (type gint*) (in): The pointer to the input #gint. * @error: Location to store error information, if any, or %NULL. * * This function validates the input number to be in the valid range for * TCP or UDP ports between 1 and 65535, and converts it to an unsigned * integer. * * This is a #InfinotedParameterConvertFunc function that can be used for * TCP or UDP port numbers. * * Returns: %TRUE on success, or %FALSE otherwise. */ gboolean infinoted_parameter_convert_port(gpointer out, gpointer in, GError** error) { gint number; number = *(gint*)in; if(number <= 0 || number > 0xffff) { g_set_error( error, infinoted_parameter_error_quark(), INFINOTED_PARAMETER_ERROR_INVALID_NUMBER, _("\"%d\" is not a valid port number. Port numbers range from " "1 to 65535"), number ); return FALSE; } *(guint*)out = number; return TRUE; } /** * infinoted_parameter_convert_ip_address: * @out: (type InfIpAddress**) (out): The pointer to the output #InfIpAddress * location. * @in: (type gchar**) (in): The pointer to the input string location. * @error: Location to store error information, if any, or %NULL. * * Converts the string that @in points to to an #InfIpAddress* value. If the * string can not be converted to an IP address, the functions fails and @error * is set. * * This is a #InfinotedParameterConvertFunc function that can be used for * fields of type #InfIpAddress*. * * Returns: %TRUE on success, or %FALSE otherwise. */ gboolean infinoted_parameter_convert_ip_address(gpointer out, gpointer in, GError** error) { gchar** in_str; InfIpAddress** out_val; in_str = (gchar**) in; out_val = (InfIpAddress**) out; InfIpAddress *address = inf_ip_address_new_from_string(*in_str); if(address == NULL) { g_set_error_literal( error, infinoted_parameter_error_quark(), INFINOTED_PARAMETER_ERROR_INVALID_IP_ADDRESS, _("Invalid IP address") ); return FALSE; } *out_val = address; return TRUE; } /** * infinoted_parameter_convert_nonnegative: * @out: (type guint*) (out): The pointer to the output #guint. * @in: (type gint*) (in): The pointer to the input #gint. * @error: Location to store error information, if any, or %NULL. * * This function validates the input number to be non-negative, and * converts it into an unsigned integer. * * This is a #InfinotedParameterConvertFunc function that can be used for * any non-negative numbers. * * Returns: %TRUE on success, or %FALSE otherwise. */ gboolean infinoted_parameter_convert_nonnegative(gpointer out, gpointer in, GError** error) { gint number; number = *(gint*)in; if(number < 0) { g_set_error_literal( error, infinoted_parameter_error_quark(), INFINOTED_PARAMETER_ERROR_INVALID_NUMBER, _("Number must not be negative") ); return FALSE; } *(guint*)out = number; return TRUE; } /** * infinoted_parameter_convert_positive: * @out: (type guint*) (out): The pointer to the output #guint. * @in: (type gint*) (in): The pointer to the input #gint. * @error: Location to store error information, if any, or %NULL. * * This function validates the input number to be positve, i.e. greater than * zero, and converts it into an unsigned integer. * * This is a #InfinotedParameterConvertFunc function that can be used for * any non-negative numbers. * * Returns: %TRUE on success, or %FALSE otherwise. */ gboolean infinoted_parameter_convert_positive(gpointer out, gpointer in, GError** error) { gint number; number = *(gint*)in; if(number <= 0) { g_set_error_literal( error, infinoted_parameter_error_quark(), INFINOTED_PARAMETER_ERROR_INVALID_NUMBER, _("Number must be positive") ); return FALSE; } *(guint*)out = number; return TRUE; } /** * infinoted_parameter_convert_security_policy: * @out: (type InfXmppConnectionSecurityPolicy*) (out): The pointer to the * output #InfXmppConnectionSecurityPolicy. * @in: (type gchar**) (in): The pointer to the input string location. * @error: Location to store error information, if any, or %NULL. * * Converts the string that @in points to to an * #InfXmppConnectionSecurityPolicy value, by requiring that it is either * "no-tls", "allow-tls" or "require-tls". If the string is none of these * three the function fails and @error is set. * * This is a #InfinotedParameterConvertFunc function that can be used for * fields of type #InfXmppConnectionSecurityPolicy. * * Returns: %TRUE on success, or %FALSE otherwise. */ gboolean infinoted_parameter_convert_security_policy(gpointer out, gpointer in, GError** error) { gchar** in_str; InfXmppConnectionSecurityPolicy* out_val; in_str = (gchar**)in; out_val = (InfXmppConnectionSecurityPolicy*)out; if(strcmp(*in_str, "no-tls") == 0) { *out_val = INF_XMPP_CONNECTION_SECURITY_ONLY_UNSECURED; } else if(strcmp(*in_str, "allow-tls") == 0) { *out_val = INF_XMPP_CONNECTION_SECURITY_BOTH_PREFER_TLS; } else if(strcmp(*in_str, "require-tls") == 0) { *out_val = INF_XMPP_CONNECTION_SECURITY_ONLY_TLS; } else { g_set_error( error, infinoted_parameter_error_quark(), INFINOTED_PARAMETER_ERROR_INVALID_SECURITY_POLICY, _("\"%s\" is not a valid security policy. Allowed values are " "\"no-tls\", \"allow-tls\" or \"require-tls\""), *in_str ); return FALSE; } return TRUE; } /** * infinoted_parameter_convert_flags: * @out: (type gint*) (out): The pointer to the output flags (a #gint). * @in: (type gchar***) (in) (array zero-terminated=1): The pointer to the * input string list. * @values: Allowed flag values. * @error: Location to store error information, if any, or %NULL. * * Converts the string list that @in points to to a bitmask. This function * can not directly be used as a convert function as expected by * #InfinotedParameterInfo since it has an additional argument. However, an * actual convert function can make use of this function. * * Each string entry is interpreted as a value of a bitmask. The @values * list specifies which string constant corresponds to which flag value. * * Returns: %TRUE on success, or %FALSE otherwise. */ gboolean infinoted_parameter_convert_flags(gpointer out, gpointer in, const GFlagsValue* values, GError** error) { GString* error_string; const GFlagsValue* value; gchar*** in_str; gchar** cur; *(gint*)out = 0; in_str = (gchar***)in; if(*in_str != NULL) { for(cur = *in_str; *cur != NULL; ++cur) { if( (*cur)[0] == '\0') continue; for(value = values; value->value_name != NULL; ++value) { if(strcmp(*cur, value->value_nick) == 0 || strcmp(*cur, value->value_name) == 0) { break; } } if(value->value_name == NULL) { error_string = g_string_sized_new(256); for(value = values; value->value_name != NULL; ++value) { if(error_string->len > 0) g_string_append(error_string, ", "); g_string_append(error_string, value->value_nick); } g_set_error( error, infinoted_parameter_error_quark(), INFINOTED_PARAMETER_ERROR_INVALID_FLAG, _("\"%s\" is not a valid value. Allowed values are: %s."), *cur, error_string->str ); g_string_free(error_string, TRUE); return FALSE; } *(gint*)out |= value->value; } } return TRUE; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/infinoted/PaxHeaders.26529/infinoted-pam.h0000644000000000000000000000013213034342512020462 xustar0030 mtime=1483851082.013718339 30 atime=1483851082.013718339 30 ctime=1488261589.456138068 libinfinity-0.7.1/infinoted/infinoted-pam.h0000644000175000017500000000307713034342512021223 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INFINOTED_PAM_H__ #define __INFINOTED_PAM_H__ #include #ifdef LIBINFINITY_HAVE_PAM #include #include #include #include G_BEGIN_DECLS gboolean infinoted_pam_user_is_allowed(InfinotedStartup* startup, const gchar* username, GError** error); gboolean infinoted_pam_authenticate(const char* service, const char* username, const char* password); G_END_DECLS #endif /* LIBINFINITY_HAVE_PAM */ #endif /* __INFINOTED_PAM_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/infinoted/PaxHeaders.26529/infinoted-util.h0000644000000000000000000000013213034342512020662 xustar0030 mtime=1483851082.017718362 30 atime=1483851082.017718362 30 ctime=1488261589.448138086 libinfinity-0.7.1/infinoted/infinoted-util.h0000644000175000017500000000273213034342512021420 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INFINOTED_UTIL_H__ #define __INFINOTED_UTIL_H__ #include #include G_BEGIN_DECLS gboolean infinoted_util_create_dirname(const gchar* path, GError** error); void infinoted_util_set_errno_error(GError** error, int save_errno, const char* prefix); void infinoted_util_daemon_set_global_pid_file_proc(void); void infinoted_util_daemon_set_local_pid_file_proc(void); int infinoted_util_daemon_pid_file_kill(int sig); G_END_DECLS #endif /* __INFINOTED_UTIL_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/infinoted/PaxHeaders.26529/infinoted-options.h0000644000000000000000000000013213034342512021400 xustar0030 mtime=1483851082.013718339 30 atime=1483851082.013718339 30 ctime=1488261589.452138077 libinfinity-0.7.1/infinoted/infinoted-options.h0000644000175000017500000000503213034342512022132 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INFINOTED_OPTIONS_H__ #define __INFINOTED_OPTIONS_H__ #include #include #include G_BEGIN_DECLS typedef struct _InfinotedOptions InfinotedOptions; struct _InfinotedOptions { GKeyFile* config_key_file; gchar* log_path; gchar* key_file; gchar* certificate_file; gchar* certificate_chain_file; gboolean create_key; gboolean create_certificate; guint port; InfIpAddress *listen_address; InfXmppConnectionSecurityPolicy security_policy; gchar* root_directory; gchar** plugins; gchar* password; gsize password_len; #ifdef LIBINFINITY_HAVE_PAM gchar* pam_service; gchar** pam_allowed_users; gchar** pam_allowed_groups; #endif /* LIBINFINITY_HAVE_PAM */ #ifdef LIBINFINITY_HAVE_LIBDAEMON gboolean daemonize; #endif }; typedef enum _InfinotedOptionsError { INFINOTED_OPTIONS_ERROR_MULTIPLE_OPTIONS, INFINOTED_OPTIONS_ERROR_INVALID_BOOLEAN, INFINOTED_OPTIONS_ERROR_INVALID_NUMBER, INFINOTED_OPTIONS_ERROR_INVALID_PLUGIN_PARAMETER, INFINOTED_OPTIONS_ERROR_INVALID_CREATE_OPTIONS, INFINOTED_OPTIONS_ERROR_EMPTY_KEY_FILE, INFINOTED_OPTIONS_ERROR_EMPTY_CERTIFICATE_FILE, INFINOTED_OPTIONS_ERROR_INVALID_AUTHENTICATION_SETTINGS } InfinotedOptionsError; InfinotedOptions* infinoted_options_new(const gchar* const* config_files, int* argc, char*** argv, GError** error); void infinoted_options_free(InfinotedOptions* options); GQuark infinoted_options_error_quark(void); void infinoted_options_drop_config_file(InfinotedOptions* options); G_END_DECLS #endif /* __INFINOTED_OPTIONS_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/infinoted/PaxHeaders.26529/infinoted-util.c0000644000000000000000000000013213034342512020655 xustar0030 mtime=1483851082.017718362 30 atime=1483851082.017718362 30 ctime=1488261589.468138042 libinfinity-0.7.1/infinoted/infinoted-util.c0000644000175000017500000001167113034342512021415 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:infinoted-util * @title: InfinotedUtil * @short_description: Miscellaneous helper functions. * @include: infinoted/infinoted-util.h * @stability: Unstable * * This section contains a few helper functions that are used in the * infinoted implementation and are exposed to the plugin interface for * convenience of plugin developers. */ #include #include #include #include #ifdef LIBINFINITY_HAVE_LIBDAEMON #include #include /* for access(2) */ #define INFINOTED_PID_FILE_DIRECTORY \ LOCALSTATEDIR "/run/infinoted-" LIBINFINITY_API_VERSION #endif #include #include #include #include #include #ifdef LIBINFINITY_HAVE_LIBDAEMON static const gchar* infinoted_util_get_pidfile_path_user(void) { static gchar* path = NULL; if(path) return path; path = g_strdup_printf( "%s/.infinoted/infinoted-" LIBINFINITY_API_VERSION ".pid", g_get_home_dir()); infinoted_util_create_dirname(path, NULL); return path; } static const gchar* infinoted_util_get_pidfile_path_system(void) { return INFINOTED_PID_FILE_DIRECTORY "/infinoted-" LIBINFINITY_API_VERSION ".pid"; } #endif /** * infinoted_util_create_dirname: * @path: (type filename): The filename to create a path to. * @error: Location to store error information, if any. * * Creates directories leading to the given path. Does not create a directory * for the last component of the path, assuming that it is a filename that * you are going to write into that directory later. * * Returns: %TRUE on success, or %FALSE on error in which case @error is set. */ gboolean infinoted_util_create_dirname(const gchar* path, GError** error) { gchar* dirname; gboolean result; dirname = g_path_get_dirname(path); result = inf_file_util_create_directory(dirname, 0777, error); g_free(dirname); return result; } /** * infinoted_util_set_errno_error: * @error: A pointer to a #GError pointer, or %NULL. * @save_errno: An errno variable. * @prefix: (allow-none): A prefix string, or %NULL. * * Sets @error to @save_errno with domain ERRNO_ERROR. If @prefix is * non-%NULL, @prefix is prefixed to @error's message, obtained by strerror(). */ void infinoted_util_set_errno_error(GError** error, int save_errno, const char* prefix) { if(prefix != NULL) { g_set_error( error, g_quark_from_static_string("ERRNO_ERROR"), save_errno, "%s: %s", prefix, strerror(save_errno) ); } else { g_set_error_literal( error, g_quark_from_static_string("ERRNO_ERROR"), save_errno, strerror(save_errno) ); } } /** * infinoted_util_daemon_set_global_pid_file_proc: * * When attempting to read or write the PID file use the global file. */ void infinoted_util_daemon_set_global_pid_file_proc(void) { #ifdef LIBINFINITY_HAVE_LIBDAEMON daemon_pid_file_proc = infinoted_util_get_pidfile_path_system; #endif } /** * infinoted_util_daemon_set_local_pid_file_proc: * * When attempting to read or write the PID file use the local file which is * in the owner's home directory. */ void infinoted_util_daemon_set_local_pid_file_proc(void) { #ifdef LIBINFINITY_HAVE_LIBDAEMON daemon_pid_file_proc = infinoted_util_get_pidfile_path_user; #endif } /** * infinoted_util_daemon_pid_file_kill: * @sig: The signal to send to the daemon process. * * This is a thin wrapper for daemon_pid_file_kill() * which uses daemon_pid_file_kill_wait() if available * with a timeout of 5 seconds. * * Returns: 0 if the signal was sent or nonzero otherwise. */ int infinoted_util_daemon_pid_file_kill(int sig) { #ifdef LIBINFINITY_HAVE_LIBDAEMON # ifdef DAEMON_PID_FILE_KILL_WAIT_AVAILABLE return daemon_pid_file_kill_wait(sig, 5); # else return daemon_pid_file_kill(sig); # endif #else return 0; #endif } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/infinoted/PaxHeaders.26529/infinoted-log.c0000644000000000000000000000013113034342512020460 xustar0030 mtime=1483851082.013718339 30 atime=1483851082.013718339 29 ctime=1488261589.46413805 libinfinity-0.7.1/infinoted/infinoted-log.c0000644000175000017500000003255313034342512021223 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:infinoted-log * @title: InfinotedLog * @short_description: A class to handle logging of messages. * @include: infinoted/infinoted-log.h * @stability: Unstable * * #InfinotedLog manages a message log. Messages can be written to the log * either as informational, warning and error messages. If the log was * successfully opened, also a glib logging handler is installed which * redirects glib logging to this class. Log output is always shown on * stderr and, optionally, can be duplicated to a file as well. **/ #include #include #include #include #include #include #include #ifdef LIBINFINITY_HAVE_LIBDAEMON # include #endif #ifdef G_OS_WIN32 /* Arbitrary; they are not used currently anyway */ # define LOG_ERR 0 # define LOG_WARNING 1 # define LOG_INFO 2 # include #else # include #endif typedef struct _InfinotedLogPrivate InfinotedLogPrivate; struct _InfinotedLogPrivate { gchar* file_path; FILE* log_file; GLogFunc prev_log_handler; GRecMutex mutex; guint recursion_depth; }; enum { PROP_0, /* read only */ PROP_FILE_PATH }; enum { LOG_MESSAGE, LAST_SIGNAL }; #define INFINOTED_LOG_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INFINOTED_TYPE_LOG, InfinotedLogPrivate)) static guint log_signals[LAST_SIGNAL]; G_DEFINE_TYPE_WITH_CODE(InfinotedLog, infinoted_log, G_TYPE_OBJECT, G_ADD_PRIVATE(InfinotedLog)) static void infinoted_log_handler(const gchar* log_domain, GLogLevelFlags log_level, const gchar* message, gpointer user_data) { InfinotedLog* log; log = INFINOTED_LOG(user_data); switch(log_level & G_LOG_LEVEL_MASK) { case G_LOG_LEVEL_ERROR: case G_LOG_LEVEL_CRITICAL: if(log_domain) infinoted_log_error(log, "%s: %s", log_domain, message); else infinoted_log_error(log, "%s", message); break; case G_LOG_LEVEL_WARNING: if(log_domain) infinoted_log_warning(log, "%s: %s", log_domain, message); else infinoted_log_warning(log, "%s", message); break; case G_LOG_LEVEL_MESSAGE: case G_LOG_LEVEL_INFO: case G_LOG_LEVEL_DEBUG: if(log_domain) infinoted_log_info(log, "%s: %s", log_domain, message); else infinoted_log_info(log, "%s", message); break; } if(log_level & G_LOG_FLAG_FATAL) abort(); } static void infinoted_log_write(InfinotedLog* log, guint prio, guint depth, const gchar* text) { InfinotedLogPrivate* priv; time_t cur_time; struct tm* cur_tm; char time_msg[128]; gchar* final_text; priv = INFINOTED_LOG_PRIVATE(log); if(depth == 0) { cur_time = time(NULL); cur_tm = localtime(&cur_time); switch(prio) { case LOG_ERR: strftime(time_msg, 128, "[%c] ERROR", cur_tm); break; case LOG_WARNING: strftime(time_msg, 128, "[%c] WARNING", cur_tm); break; case LOG_INFO: strftime(time_msg, 128, "[%c] INFO", cur_tm); break; default: g_assert_not_reached(); break; } final_text = g_strdup_printf("%s: %s", time_msg, text); } else { final_text = g_strdup_printf("\t%s", text); } #ifdef LIBINFINITY_HAVE_LIBDAEMON daemon_log(prio, "%s", final_text); #else #ifdef G_OS_WIN32 /* On Windows, convert to the character set of the console */ gchar* codeset; gchar* converted; codeset = g_strdup_printf("CP%u", (guint)GetConsoleOutputCP()); converted = g_convert(final_text, -1, codeset, "UTF-8", NULL, NULL, NULL); g_free(codeset); fprintf(stderr, "%s\n", converted); g_free(converted); #else fprintf(stderr, "%s\n", final_text); #endif /* !G_OS_WIN32 */ #endif /* !LIBINFINITY_HAVE_LIBDAEMON */ if(priv->log_file != NULL) { fprintf(priv->log_file, "%s\n", final_text); fflush(priv->log_file); } g_free(final_text); } static void infinoted_log_entry(InfinotedLog* log, guint prio, const gchar* fmt, va_list args) { /* This is an entry point for the three public functions. */ InfinotedLogPrivate* priv; gchar* text; guint depth; priv = INFINOTED_LOG_PRIVATE(log); text = g_strdup_vprintf(fmt, args); g_rec_mutex_lock(&priv->mutex); depth = priv->recursion_depth++; g_signal_emit(log, log_signals[LOG_MESSAGE], 0, prio, depth, text); g_assert(priv->recursion_depth == depth + 1); --priv->recursion_depth; g_rec_mutex_unlock(&priv->mutex); g_free(text); } static void infinoted_log_init(InfinotedLog* log) { InfinotedLogPrivate* priv; priv = INFINOTED_LOG_PRIVATE(log); priv->file_path = NULL; priv->log_file = NULL; priv->prev_log_handler = NULL; priv->recursion_depth = 0; g_rec_mutex_init(&priv->mutex); } static void infinoted_log_finalize(GObject* object) { InfinotedLog* log; InfinotedLogPrivate* priv; log = INFINOTED_LOG(object); priv = INFINOTED_LOG_PRIVATE(log); if(priv->log_file != NULL) infinoted_log_close(log); g_rec_mutex_clear(&priv->mutex); G_OBJECT_CLASS(infinoted_log_parent_class)->finalize(object); } static void infinoted_log_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfinotedLog* log; InfinotedLogPrivate* priv; log = INFINOTED_LOG(object); priv = INFINOTED_LOG_PRIVATE(log); switch(prop_id) { case PROP_FILE_PATH: /* read only */ default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void infinoted_log_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfinotedLog* log; InfinotedLogPrivate* priv; log = INFINOTED_LOG(object); priv = INFINOTED_LOG_PRIVATE(log); switch(prop_id) { case PROP_FILE_PATH: g_value_set_string(value, priv->file_path); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void infinoted_log_log_message(InfinotedLog* log, guint prio, guint depth, const gchar* text) { InfinotedLogPrivate* priv; priv = INFINOTED_LOG_PRIVATE(log); g_assert(priv->recursion_depth == depth+1); infinoted_log_write(log, prio, depth, text); } static void infinoted_log_class_init(InfinotedLogClass* log_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(log_class); object_class->finalize = infinoted_log_finalize; object_class->set_property = infinoted_log_set_property; object_class->get_property = infinoted_log_get_property; log_class->log_message = infinoted_log_log_message; g_object_class_install_property( object_class, PROP_FILE_PATH, g_param_spec_string( "file-path", "File Path", "Path to the log file", NULL, G_PARAM_READABLE ) ); /** * InfinotedLog::log-message: * @log: The #InfinotedLog that is logging a message. * @prio: The priority of the logged message. * @depth: The recursion depth of the logged message. * @text: The logged message text. * * This signal is emitted when a new line of log message is written to the * log. */ log_signals[LOG_MESSAGE] = g_signal_new( "log-message", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET(InfinotedLogClass, log_message), NULL, NULL, NULL, G_TYPE_NONE, 3, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_STRING ); } /** * infinoted_log_new: (constructor) * * Creates a new #InfinotedLog. * * Returns: (transfer full): A new #InfinotedLog. Free with g_object_unref() * when no longer needed. */ InfinotedLog* infinoted_log_new(void) { GObject* object = g_object_new(INFINOTED_TYPE_LOG, NULL); return INFINOTED_LOG(object); } /** * infinoted_log_open: * @log: A #InfinotedLog. * @path: (type filename) (allow-none): The path to the log file to write, * or %NULL. * @error: Location to store error information, if any, or %NULL. * * Attempts to open the log file at the given path. If the log file could not * be opened the function returns %FALSE and @error is set. If the log file * exists already then new log messages will be appended. * * If @path is %NULL no log file is opened and logging only occurs to stderr. * * Returns: %TRUE on success, or %FALSE otherwise. */ gboolean infinoted_log_open(InfinotedLog* log, const gchar* path, GError** error) { InfinotedLogPrivate* priv; g_return_val_if_fail(INFINOTED_IS_LOG(log), FALSE); g_return_val_if_fail(error == NULL || *error == NULL, FALSE); priv = INFINOTED_LOG_PRIVATE(log); g_rec_mutex_lock(&priv->mutex); g_assert(priv->prev_log_handler == NULL); if(path != NULL) { g_assert(priv->log_file == NULL); priv->log_file = fopen(path, "a"); if(priv->log_file == NULL) { infinoted_util_set_errno_error(error, errno, "Failed to open log file"); return FALSE; } g_assert(priv->file_path == NULL); priv->file_path = g_strdup(path); } priv->prev_log_handler = g_log_set_default_handler( infinoted_log_handler, log ); g_rec_mutex_unlock(&priv->mutex); if(path != NULL) g_object_notify(G_OBJECT(log), "file-path"); return TRUE; } /** * infinoted_log_close: * @log: A #InfinotedLog. * * Closes a #InfinotedLog object opened with infinoted_log_open(). After the * log was closed it can be opened again with a different file. The log is * closed automatically on destruction. */ void infinoted_log_close(InfinotedLog* log) { InfinotedLogPrivate* priv; g_return_if_fail(INFINOTED_IS_LOG(log)); priv = INFINOTED_LOG_PRIVATE(log); g_rec_mutex_lock(&priv->mutex); g_assert(priv->prev_log_handler != NULL); if(priv->log_file != NULL) { g_assert(priv->file_path != NULL); fclose(priv->log_file); priv->log_file = NULL; g_free(priv->file_path); priv->file_path = NULL; } g_assert(priv->file_path == NULL); g_log_set_default_handler(priv->prev_log_handler, NULL); priv->prev_log_handler = NULL; g_rec_mutex_unlock(&priv->mutex); g_object_notify(G_OBJECT(log), "file-path"); } /** * infinoted_log_log: * @log: A #InfinotedLog. * @prio: Priority of the logged message. * @fmt: A printf-style format string. * @...: Format arguments. * * Logs a message with the given priority. The priority is one of %LOG_ERR, * %LOG_WARNING or %LOG_INFO. If the server is daemonized, log to syslog, * otherwise log to stderr. If a logfile is given in the options when @log * was created, the logfile is written to as well. */ void infinoted_log_log(InfinotedLog* log, guint prio, const char* fmt, ...) { va_list ap; va_start(ap, fmt); infinoted_log_entry(log, prio, fmt, ap); va_end(ap); } /** * infinoted_log_error: * @log: A #InfinotedLog. * @fmt: A printf-style format string. * @...: Format arguments. * * Logs an error message. If the server is daemonized, log to syslog, * otherwise log to stderr. If a logfile is given in the options when @log * was created, the logfile is written to as well. */ void infinoted_log_error(InfinotedLog* log, const char* fmt, ...) { va_list ap; va_start(ap, fmt); infinoted_log_entry(log, LOG_ERR, fmt, ap); va_end(ap); } /** * infinoted_log_warning: * @log: A #InfinotedLog. * @fmt: A printf-style format string. * @...: Format arguments. * * Logs a warning message. If the server is daemonized, log to syslog, * otherwise log to stderr. If a logfile is given in the options when @log * was created, the logfile is written to as well. */ void infinoted_log_warning(InfinotedLog* log, const char* fmt, ...) { va_list ap; va_start(ap, fmt); infinoted_log_entry(log, LOG_WARNING, fmt, ap); va_end(ap); } /** * infinoted_log_info: * @log: A #InfinotedLog. * @fmt: A printf-style format string. * @...: Format arguments. * * Logs an info message. If the server is daemonized, log to syslog, * otherwise log to stderr. If a logfile is given in the options when @log * was created, the logfile is written to as well. */ void infinoted_log_info(InfinotedLog* log, const char* fmt, ...) { va_list ap; va_start(ap, fmt); infinoted_log_entry(log, LOG_INFO, fmt, ap); va_end(ap); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/infinoted/PaxHeaders.26529/infinoted-dh-params.h0000644000000000000000000000013213034342512021561 xustar0030 mtime=1483851082.013718339 30 atime=1483851082.013718339 30 ctime=1488261589.452138077 libinfinity-0.7.1/infinoted/infinoted-dh-params.h0000644000175000017500000000256113034342512022317 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INFINOTED_DH_PARAMS_H__ #define __INFINOTED_DH_PARAMS_H__ #include #include #include #include G_BEGIN_DECLS gboolean infinoted_dh_params_ensure(InfinotedLog* log, InfCertificateCredentials* creds, gnutls_dh_params_t* dh_params, GError** error); G_END_DECLS #endif /* __INFINOTED_DH_PARAMS_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/infinoted/PaxHeaders.26529/infinoted-plugin-manager.c0000644000000000000000000000013113034342512022605 xustar0030 mtime=1483851082.013718339 30 atime=1483851082.013718339 29 ctime=1488261589.46413805 libinfinity-0.7.1/infinoted/infinoted-plugin-manager.c0000644000175000017500000007715513034342512023357 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:infinoted-plugin-manager * @title: InfinotedPluginManager * @short_description: Loads and propagates events to infinoted plugins. * @include: infinoted/infinoted-plugin-manager.h * @stability: Unstable * * #InfinotedPluginManager handles the loading of plugins for the infinoted * server. It initializes and deinitializes plugins, and it makes callbacks * when connections or sessions are added or removed. Furthermore, it provides * an interface for plugins to obtain and interact with the server itself, * most notable its #InfdDirectory instance. */ #include #include #include #include typedef struct _InfinotedPluginManagerPrivate InfinotedPluginManagerPrivate; struct _InfinotedPluginManagerPrivate { InfdDirectory* directory; InfinotedLog* log; InfCertificateCredentials* credentials; gchar* path; GSList* plugins; GHashTable* connections; /* plugin + connection -> PluginConnectionInfo */ GHashTable* sessions; /* plugin + session -> PluginSessionInfo */ }; typedef struct _InfinotedPluginInstance InfinotedPluginInstance; struct _InfinotedPluginInstance { GModule* module; const InfinotedPlugin* plugin; }; typedef struct _InfinotedPluginManagerForeachConnectionData InfinotedPluginManagerForeachConnectionData; struct _InfinotedPluginManagerForeachConnectionData { InfinotedPluginManager* manager; InfinotedPluginInstance* instance; }; typedef void(*InfinotedPluginManagerWalkDirectoryFunc)( InfinotedPluginManager*, InfinotedPluginInstance*, const InfBrowserIter*, InfSessionProxy*); enum { PROP_0, PROP_DIRECTORY, PROP_LOG, PROP_CREDENTIALS, PROP_PATH }; #define INFINOTED_PLUGIN_MANAGER_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INFINOTED_TYPE_PLUGIN_MANAGER, InfinotedPluginManagerPrivate)) G_DEFINE_TYPE_WITH_CODE(InfinotedPluginManager, infinoted_plugin_manager, G_TYPE_OBJECT, G_ADD_PRIVATE(InfinotedPluginManager)) static gpointer infinoted_plugin_manager_hash(gpointer first, gpointer second) { /* This function creates a hash out of two pointer values */ /* TODO: Switch to guintptr with glib 2.18 */ gsize hash = 5381; hash = hash * 33 + (gsize)first; hash = hash * 33 + (gsize)second; return (gpointer)hash; } static void infinoted_plugin_manager_add_connection(InfinotedPluginManager* manager, InfinotedPluginInstance* instance, InfXmlConnection* connection) { InfinotedPluginManagerPrivate* priv; gpointer plugin_info; gpointer hash; gpointer connection_info; priv = INFINOTED_PLUGIN_MANAGER_PRIVATE(manager); plugin_info = instance+1; hash = infinoted_plugin_manager_hash(plugin_info, connection); g_assert(g_hash_table_lookup(priv->connections, hash) == NULL); if(instance->plugin->connection_info_size > 0) { connection_info = g_slice_alloc(instance->plugin->connection_info_size); g_hash_table_insert(priv->connections, hash, connection_info); } if(instance->plugin->on_connection_added != NULL) { instance->plugin->on_connection_added( connection, plugin_info, connection_info ); } } static void infinoted_plugin_manager_remove_connection(InfinotedPluginManager* manager, InfinotedPluginInstance* instance, InfXmlConnection* connection) { InfinotedPluginManagerPrivate* priv; gpointer plugin_info; gpointer hash; gpointer connection_info; priv = INFINOTED_PLUGIN_MANAGER_PRIVATE(manager); plugin_info = instance+1; hash = infinoted_plugin_manager_hash(plugin_info, connection); connection_info = g_hash_table_lookup(priv->connections, hash); g_assert( instance->plugin->connection_info_size == 0 || connection_info != NULL ); if(instance->plugin->on_connection_removed != NULL) { instance->plugin->on_connection_removed( connection, plugin_info, connection_info ); } if(instance->plugin->connection_info_size > 0) { g_hash_table_remove(priv->connections, hash); g_slice_free1(instance->plugin->connection_info_size, connection_info); } } static gboolean infinoted_plugin_manager_check_session_type(InfinotedPluginInstance* instance, InfSessionProxy* proxy) { GType session_type; InfSession* session; gboolean result; if(instance->plugin->session_type == NULL) return TRUE; /* If the type was not registered yet the passed session cannot have the * correct type. */ session_type = g_type_from_name(instance->plugin->session_type); if(session_type == 0) return FALSE; g_object_get(G_OBJECT(proxy), "session", &session, NULL); result = g_type_is_a(G_TYPE_FROM_INSTANCE(session), session_type); g_object_unref(session); return result; } static void infinoted_plugin_manager_add_session(InfinotedPluginManager* manager, InfinotedPluginInstance* instance, const InfBrowserIter* iter, InfSessionProxy* proxy) { InfinotedPluginManagerPrivate* priv; gpointer plugin_info; gpointer hash; gpointer session_info; priv = INFINOTED_PLUGIN_MANAGER_PRIVATE(manager); if(infinoted_plugin_manager_check_session_type(instance, proxy)) { plugin_info = instance+1; hash = infinoted_plugin_manager_hash(plugin_info, proxy); g_assert(g_hash_table_lookup(priv->sessions, hash) == NULL); if(instance->plugin->session_info_size > 0) { session_info = g_slice_alloc(instance->plugin->session_info_size); g_hash_table_insert(priv->sessions, hash, session_info); } if(instance->plugin->on_session_added != NULL) { instance->plugin->on_session_added( iter, proxy, plugin_info, session_info ); } } } static void infinoted_plugin_manager_remove_session(InfinotedPluginManager* manager, InfinotedPluginInstance* instance, const InfBrowserIter* iter, InfSessionProxy* proxy) { InfinotedPluginManagerPrivate* priv; gpointer plugin_info; gpointer hash; gpointer session_info; priv = INFINOTED_PLUGIN_MANAGER_PRIVATE(manager); if(infinoted_plugin_manager_check_session_type(instance, proxy)) { plugin_info = instance+1; hash = infinoted_plugin_manager_hash(plugin_info, proxy); session_info = g_hash_table_lookup(priv->sessions, hash); g_assert( instance->plugin->session_info_size == 0 || session_info != NULL ); if(instance->plugin->on_session_removed != NULL) { instance->plugin->on_session_removed( iter, proxy, plugin_info, session_info ); } if(instance->plugin->session_info_size > 0) { g_hash_table_remove(priv->sessions, hash); g_slice_free1(instance->plugin->session_info_size, session_info); } } } static void infinoted_plugin_manager_walk_directory( InfinotedPluginManager* manager, const InfBrowserIter* iter, InfinotedPluginInstance* instance, InfinotedPluginManagerWalkDirectoryFunc func) { /* This function walks the whole directory tree recursively and * registers running sessions with the given plugin instance. */ InfinotedPluginManagerPrivate* priv; InfBrowser* browser; InfBrowserIter child; InfSessionProxy* proxy; priv = INFINOTED_PLUGIN_MANAGER_PRIVATE(manager); browser = INF_BROWSER(priv->directory); if(inf_browser_is_subdirectory(browser, iter) == TRUE) { if(inf_browser_get_explored(browser, iter) == TRUE) { child = *iter; if(inf_browser_get_child(browser, &child)) { do { infinoted_plugin_manager_walk_directory( manager, &child, instance, func ); } while(inf_browser_get_next(browser, &child)); } } } else { proxy = inf_browser_get_session(browser, iter); if(proxy != NULL) { func(manager, instance, iter, proxy); } } } static void infinoted_plugin_manager_load_plugin_foreach_connection_func( InfXmlConnection* connection, gpointer user_data) { InfinotedPluginManagerForeachConnectionData* data; data = (InfinotedPluginManagerForeachConnectionData*)user_data; infinoted_plugin_manager_add_connection( data->manager, data->instance, connection ); } static void infinoted_plugin_manager_unload_plugin_foreach_connection_func( InfXmlConnection* connection, gpointer user_data) { InfinotedPluginManagerForeachConnectionData* data; data = (InfinotedPluginManagerForeachConnectionData*)user_data; infinoted_plugin_manager_remove_connection( data->manager, data->instance, connection ); } static gboolean infinoted_plugin_manager_load_plugin(InfinotedPluginManager* manager, const gchar* plugin_path, const gchar* plugin_name, GKeyFile* key_file, GError** error) { InfinotedPluginManagerPrivate* priv; gchar* plugin_basename; gchar* plugin_filename; GModule* module; const InfinotedPlugin* plugin; InfinotedPluginInstance* instance; gboolean result; GError* local_error; InfBrowserIter root; InfinotedPluginManagerForeachConnectionData data; priv = INFINOTED_PLUGIN_MANAGER_PRIVATE(manager); plugin_basename = g_strdup_printf( "libinfinoted-plugin-%s.%s", plugin_name, G_MODULE_SUFFIX ); plugin_filename = g_build_filename(plugin_path, plugin_basename, NULL); g_free(plugin_basename); module = g_module_open(plugin_filename, G_MODULE_BIND_LOCAL); g_free(plugin_filename); if(module == NULL) { g_set_error_literal( error, infinoted_plugin_manager_error_quark(), INFINOTED_PLUGIN_MANAGER_ERROR_OPEN_FAILED, g_module_error() ); return FALSE; } if(g_module_symbol(module, "INFINOTED_PLUGIN", (gpointer*)&plugin) == FALSE) { g_set_error_literal( error, infinoted_plugin_manager_error_quark(), INFINOTED_PLUGIN_MANAGER_ERROR_NO_ENTRY_POINT, g_module_error() ); g_module_close(module); return FALSE; } instance = g_malloc(sizeof(InfinotedPluginInstance) + plugin->info_size); instance->module = module; instance->plugin = plugin; /* Call on_info_initialize, allowing the plugin to set default values */ if(plugin->on_info_initialize != NULL) plugin->on_info_initialize(instance+1); /* Next, parse options from keyfile */ if(plugin->options != NULL) { local_error = NULL; result = infinoted_parameter_load_from_key_file( plugin->options, key_file, plugin->name, instance+1, &local_error ); if(result == FALSE) { g_free(instance); g_module_close(module); g_propagate_prefixed_error( error, local_error, "Failed to initialize plugin \"%s\": ", plugin_name ); return FALSE; } } /* Finally, call on_initialize, which allows the plugin to initialize * itself with the plugin options. */ if(plugin->on_initialize != NULL) { local_error = NULL; result = plugin->on_initialize(manager, instance+1, &local_error); if(local_error != NULL) { if(instance->plugin->on_deinitialize != NULL) instance->plugin->on_deinitialize(instance+1); g_free(instance); g_module_close(module); g_propagate_prefixed_error( error, local_error, "Failed to initialize plugin \"%s\": ", plugin_name ); return FALSE; } } /* Register initial connections with plugin */ data.manager = manager; data.instance = instance; infd_directory_foreach_connection( priv->directory, infinoted_plugin_manager_load_plugin_foreach_connection_func, &data ); /* Register initial sessions with plugin */ inf_browser_get_root(INF_BROWSER(priv->directory), &root); infinoted_plugin_manager_walk_directory( manager, &root, instance, infinoted_plugin_manager_add_session ); infinoted_log_info( priv->log, _("Loaded plugin \"%s\" from \"%s\""), plugin_name, g_module_name(module) ); priv->plugins = g_slist_prepend(priv->plugins, instance); return TRUE; } static void infinoted_plugin_manager_unload_plugin(InfinotedPluginManager* manager, InfinotedPluginInstance* instance) { InfinotedPluginManagerPrivate* priv; InfinotedPluginManagerForeachConnectionData data; InfBrowserIter root; priv = INFINOTED_PLUGIN_MANAGER_PRIVATE(manager); priv->plugins = g_slist_remove(priv->plugins, instance); /* Unregister all sessions with the plugin */ inf_browser_get_root(INF_BROWSER(priv->directory), &root); infinoted_plugin_manager_walk_directory( manager, &root, instance, infinoted_plugin_manager_remove_session ); /* Unregister all connections with the plugin */ data.manager = manager; data.instance = instance; infd_directory_foreach_connection( priv->directory, infinoted_plugin_manager_unload_plugin_foreach_connection_func, &data ); if(instance->plugin->on_deinitialize != NULL) instance->plugin->on_deinitialize(instance+1); infinoted_log_info( priv->log, _("Unloaded plugin \"%s\" from \"%s\""), instance->plugin->name, g_module_name(instance->module) ); g_module_close(instance->module); g_free(instance); } static void infinoted_plugin_manager_connection_added_cb(InfdDirectory* directory, InfXmlConnection* connection, gpointer user_data) { InfinotedPluginManager* manager; InfinotedPluginManagerPrivate* priv; GSList* item; manager = (InfinotedPluginManager*)user_data; priv = INFINOTED_PLUGIN_MANAGER_PRIVATE(manager); for(item = priv->plugins; item != NULL; item = item->next) { infinoted_plugin_manager_add_connection( manager, (InfinotedPluginInstance*)item->data, connection ); } } static void infinoted_plugin_manager_connection_removed_cb(InfdDirectory* directory, InfXmlConnection* connection, gpointer user_data) { InfinotedPluginManager* manager; InfinotedPluginManagerPrivate* priv; GSList* item; manager = (InfinotedPluginManager*)user_data; priv = INFINOTED_PLUGIN_MANAGER_PRIVATE(manager); for(item = priv->plugins; item != NULL; item = item->next) { infinoted_plugin_manager_remove_connection( manager, (InfinotedPluginInstance*)item->data, connection ); } } static void infinoted_plugin_manager_subscribe_session_cb(InfBrowser* browser, const InfBrowserIter* iter, InfSessionProxy* proxy, InfRequest* request, gpointer user_data) { InfinotedPluginManager* manager; InfinotedPluginManagerPrivate* priv; GSList* item; manager = (InfinotedPluginManager*)user_data; priv = INFINOTED_PLUGIN_MANAGER_PRIVATE(manager); for(item = priv->plugins; item != NULL; item = item->next) { infinoted_plugin_manager_add_session( manager, (InfinotedPluginInstance*)item->data, iter, proxy ); } } static void infinoted_plugin_manager_unsubscribe_session_cb(InfBrowser* browser, const InfBrowserIter* iter, InfSessionProxy* proxy, InfRequest* request, gpointer user_data) { InfinotedPluginManager* manager; InfinotedPluginManagerPrivate* priv; GSList* item; manager = (InfinotedPluginManager*)user_data; priv = INFINOTED_PLUGIN_MANAGER_PRIVATE(manager); for(item = priv->plugins; item != NULL; item = item->next) { infinoted_plugin_manager_remove_session( manager, (InfinotedPluginInstance*)item->data, iter, proxy ); } } static void infinoted_plugin_manager_set_directory(InfinotedPluginManager* manager, InfdDirectory* directory) { InfinotedPluginManagerPrivate* priv; priv = INFINOTED_PLUGIN_MANAGER_PRIVATE(manager); /* Directory can only be changed while no plugins are loaded. */ g_assert(priv->plugins == NULL); if(priv->directory != NULL) { inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->directory), G_CALLBACK(infinoted_plugin_manager_connection_added_cb), manager ); inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->directory), G_CALLBACK(infinoted_plugin_manager_connection_removed_cb), manager ); inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->directory), G_CALLBACK(infinoted_plugin_manager_subscribe_session_cb), manager ); inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->directory), G_CALLBACK(infinoted_plugin_manager_unsubscribe_session_cb), manager ); g_object_unref(priv->directory); } priv->directory = directory; if(directory != NULL) { g_object_ref(priv->directory); g_signal_connect_after( G_OBJECT(directory), "connection-added", G_CALLBACK(infinoted_plugin_manager_connection_added_cb), manager ); g_signal_connect_after( G_OBJECT(directory), "connection-removed", G_CALLBACK(infinoted_plugin_manager_connection_removed_cb), manager ); g_signal_connect_after( G_OBJECT(directory), "subscribe-session", G_CALLBACK(infinoted_plugin_manager_subscribe_session_cb), manager ); g_signal_connect_after( G_OBJECT(directory), "unsubscribe-session", G_CALLBACK(infinoted_plugin_manager_unsubscribe_session_cb), manager ); } g_object_notify(G_OBJECT(manager), "directory"); } static void infinoted_plugin_manager_init(InfinotedPluginManager* manager) { InfinotedPluginManagerPrivate* priv; priv = INFINOTED_PLUGIN_MANAGER_PRIVATE(manager); priv->directory = NULL; priv->log = NULL; priv->credentials = NULL; priv->path = NULL; priv->plugins = NULL; priv->connections = g_hash_table_new(NULL, NULL); priv->sessions = g_hash_table_new(NULL, NULL); } static void infinoted_plugin_manager_dispose(GObject* object) { InfinotedPluginManager* manager; InfinotedPluginManagerPrivate* priv; manager = INFINOTED_PLUGIN_MANAGER(object); priv = INFINOTED_PLUGIN_MANAGER_PRIVATE(manager); while(priv->plugins != NULL) { infinoted_plugin_manager_unload_plugin( manager, (InfinotedPluginInstance*)priv->plugins->data ); } if(priv->directory != NULL) infinoted_plugin_manager_set_directory(manager, NULL); if(priv->log != NULL) { g_object_unref(priv->log); priv->log = NULL; } if(priv->credentials != NULL) { inf_certificate_credentials_unref(priv->credentials); priv->credentials = NULL; } G_OBJECT_CLASS(infinoted_plugin_manager_parent_class)->dispose(object); } static void infinoted_plugin_manager_finalize(GObject* object) { InfinotedPluginManager* manager; InfinotedPluginManagerPrivate* priv; manager = INFINOTED_PLUGIN_MANAGER(object); priv = INFINOTED_PLUGIN_MANAGER_PRIVATE(manager); g_assert(g_hash_table_size(priv->connections) == 0); g_assert(g_hash_table_size(priv->sessions) == 0); g_hash_table_unref(priv->connections); g_hash_table_unref(priv->sessions); g_free(priv->path); G_OBJECT_CLASS(infinoted_plugin_manager_parent_class)->finalize(object); } static void infinoted_plugin_manager_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfinotedPluginManager* manager; InfinotedPluginManagerPrivate* priv; manager = INFINOTED_PLUGIN_MANAGER(object); priv = INFINOTED_PLUGIN_MANAGER_PRIVATE(manager); switch(prop_id) { case PROP_DIRECTORY: g_assert(priv->directory == NULL); /* construct only */ infinoted_plugin_manager_set_directory( manager, INFD_DIRECTORY(g_value_get_object(value)) ); break; case PROP_LOG: g_assert(priv->log == NULL); /* construct only */ priv->log = INFINOTED_LOG(g_value_dup_object(value)); break; case PROP_CREDENTIALS: g_assert(priv->credentials == NULL); /* construct only */ priv->credentials = (InfCertificateCredentials*)g_value_dup_boxed(value); break; case PROP_PATH: /* read only */ default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void infinoted_plugin_manager_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfinotedPluginManager* manager; InfinotedPluginManagerPrivate* priv; manager = INFINOTED_PLUGIN_MANAGER(object); priv = INFINOTED_PLUGIN_MANAGER_PRIVATE(manager); switch(prop_id) { case PROP_DIRECTORY: g_value_set_object(value, priv->directory); break; case PROP_LOG: g_value_set_object(value, priv->log); break; case PROP_CREDENTIALS: g_value_set_boxed(value, priv->credentials); break; case PROP_PATH: g_value_set_string(value, priv->path); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void infinoted_plugin_manager_class_init( InfinotedPluginManagerClass* manager_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(manager_class); object_class->dispose = infinoted_plugin_manager_dispose; object_class->finalize = infinoted_plugin_manager_finalize; object_class->set_property = infinoted_plugin_manager_set_property; object_class->get_property = infinoted_plugin_manager_get_property; g_object_class_install_property( object_class, PROP_DIRECTORY, g_param_spec_object( "directory", "Directory", "The infinote directory served by the server", INFD_TYPE_DIRECTORY, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_LOG, g_param_spec_object( "log", "Log", "The log object into which to write log messages", INFINOTED_TYPE_LOG, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_CREDENTIALS, g_param_spec_boxed( "credentials", "Credentials", "The server's TLS credentials", INF_TYPE_CERTIFICATE_CREDENTIALS, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_PATH, g_param_spec_string( "path", "Path", "The path from which plugins are loaded", NULL, G_PARAM_READABLE ) ); } /** * infinoted_plugin_manager_new: (constructor) * @directory: The #InfdDirectory on which plugins should operate. * @log: The #InfinotedLog to write log messages to. * @creds: (allow-none): The #InfCertificateCredentials used to secure data * transfer with the clients, or %NULL. * * Creates a new #InfinotedPluginManager with the given directory, log * and credentials. These three objects will be available for plugins * to enhance the infinoted functionality. Plugins can be loaded * with infinoted_plugin_manager_load(). * * Returns: (transfer full): A new #InfinotedPluginManager. */ InfinotedPluginManager* infinoted_plugin_manager_new(InfdDirectory* directory, InfinotedLog* log, InfCertificateCredentials* creds) { GObject* object; g_return_val_if_fail(INFD_IS_DIRECTORY(directory), NULL); g_return_val_if_fail(INFINOTED_IS_LOG(log), NULL); object = g_object_new( INFINOTED_TYPE_PLUGIN_MANAGER, "directory", directory, "log", log, "credentials", creds, NULL ); return INFINOTED_PLUGIN_MANAGER(object); } /** * infinoted_plugin_manager_load: * @manager: A #InfinotedPluginManager. * @plugin_path: The path from which to load plugins. * @plugins: (array zero-terminated=1) (allow-none): A list of plugins to * load, or %NULL. * @options: A #GKeyFile with configuration options for the plugins. * @error: Location to store error information, if any, or %NULL. * * Loads all plugins specified in @plugins from the location at @plugin_path. * If loading one of the module fails the function sets @error and returns * %FALSE, and the object ends up with no plugins loaded. If @plugins is * %NULL, no plugins are loaded. * * If this function is called while there are already plugins loaded, all * existing plugins are unloaded first. * * Returns: %TRUE on success or %FALSE on error. */ gboolean infinoted_plugin_manager_load(InfinotedPluginManager* manager, const gchar* plugin_path, const gchar* const* plugins, GKeyFile* options, GError** error) { InfinotedPluginManagerPrivate* priv; const gchar* const* plugin; gboolean result; g_return_val_if_fail(INFINOTED_IS_PLUGIN_MANAGER(manager), FALSE); g_return_val_if_fail(plugin_path != NULL, FALSE); g_return_val_if_fail(options != NULL, FALSE); g_return_val_if_fail(error == NULL || *error == NULL, FALSE); priv = INFINOTED_PLUGIN_MANAGER_PRIVATE(manager); /* Unload existing plugins */ g_free(priv->path); while(priv->plugins != NULL) { infinoted_plugin_manager_unload_plugin( manager, (InfinotedPluginInstance*)priv->plugins->data ); } /* Load new plugins */ priv->path = g_strdup(plugin_path); if(plugins != NULL) { for(plugin = plugins; *plugin != NULL; ++plugin) { result = infinoted_plugin_manager_load_plugin( manager, plugin_path, *plugin, options, error ); if(result == FALSE) { while(priv->plugins != NULL) { infinoted_plugin_manager_unload_plugin( manager, (InfinotedPluginInstance*)priv->plugins->data ); } return FALSE; } } } return TRUE; } /** * infinoted_plugin_manager_get_directory: * @manager: A #InfinotedPluginManager. * * Returns the #InfdDirectory used by the plugin manager. * * Returns: (transfer none): A #InfdDirectory owned by the plugin manager. */ InfdDirectory* infinoted_plugin_manager_get_directory(InfinotedPluginManager* manager) { g_return_val_if_fail(INFINOTED_IS_PLUGIN_MANAGER(manager), NULL); return INFINOTED_PLUGIN_MANAGER_PRIVATE(manager)->directory; } /** * infinoted_plugin_manager_get_io: * @manager: A #InfinotedPluginManager. * * Returns the #InfIo of the #InfdDirectory used by the plugin manager. * * Returns: (transfer none): A #InfIo owned by the plugin manager. */ InfIo* infinoted_plugin_manager_get_io(InfinotedPluginManager* manager) { InfinotedPluginManagerPrivate* priv; g_return_val_if_fail(INFINOTED_IS_PLUGIN_MANAGER(manager), NULL); priv = INFINOTED_PLUGIN_MANAGER_PRIVATE(manager); return infd_directory_get_io(priv->directory); } /** * infinoted_plugin_manager_get_log: * @manager: A #InfinotedPluginManager. * * Returns the #InfinotedLog that the plugin manager and the plugins do * write log messages to. * * Returns: (transfer none): A #InfinotedLog owned by the plugin manager. */ InfinotedLog* infinoted_plugin_manager_get_log(InfinotedPluginManager* manager) { g_return_val_if_fail(INFINOTED_IS_PLUGIN_MANAGER(manager), NULL); return INFINOTED_PLUGIN_MANAGER_PRIVATE(manager)->log; } /** * infinoted_plugin_manager_get_credentials: * @manager: A #InfinotedPluginManager. * * Returns the #InfCertificateCredentials used for securing the data transfer * with all clients. * * Returns: (transfer none): A #InfCertificateCredentials object owned by the * plugin manager. */ InfCertificateCredentials* infinoted_plugin_manager_get_credentials(InfinotedPluginManager* manager) { g_return_val_if_fail(INFINOTED_IS_PLUGIN_MANAGER(manager), NULL); return INFINOTED_PLUGIN_MANAGER_PRIVATE(manager)->credentials; } /** * infinoted_plugin_manager_error_quark: * * Returns the #GQuark for errors from the InfinotedPluginManager module. * * Returns: The error domain for the InfinotedPluginManager module. */ GQuark infinoted_plugin_manager_error_quark(void) { return g_quark_from_static_string("INFINOTED_PLUGIN_MANAGER_ERROR"); } /** * infinoted_plugin_manager_get_connection_info: * @mgr: A #InfinotedPluginManager. * @plugin_info: The @plugin_info pointer of a plugin instance. * @connection: The #InfXmlConnection for which to retrieve plugin data. * * Queries the connection-specfic plugin data for the plugin instance * @plugin_info. Returns %NULL if no such object exists, i.e. when the * plugin's @connection_info_size is set to 0. * * Returns: (transfer none) (allow-none): A pointer to the connection-specific * plugin data, or %NULL. */ gpointer infinoted_plugin_manager_get_connection_info(InfinotedPluginManager* mgr, gpointer plugin_info, InfXmlConnection* connection) { InfinotedPluginManagerPrivate* priv; g_return_val_if_fail(INFINOTED_IS_PLUGIN_MANAGER(mgr), NULL); g_return_val_if_fail(INF_IS_XML_CONNECTION(connection), NULL); priv = INFINOTED_PLUGIN_MANAGER_PRIVATE(mgr); return g_hash_table_lookup( priv->connections, infinoted_plugin_manager_hash(plugin_info, connection) ); } /** * infinoted_plugin_manager_get_session_info: * @mgr: A #InfinotedPluginManager. * @plugin_info: The @plugin_info pointer of a plugin instance. * @proxy: The #InfSessionProxy for which to retrieve plugin data. * * Queries the session-specfic plugin data for the plugin instance * @plugin_info. Returns %NULL if no such object exists, i.e. when the * plugin's @session_info_size is set to 0. * * Returns: (transfer none) (allow-none): A pointer to the session-specific * plugin data, or %NULL. */ gpointer infinoted_plugin_manager_get_session_info(InfinotedPluginManager* mgr, gpointer plugin_info, InfSessionProxy* proxy) { InfinotedPluginManagerPrivate* priv; g_return_val_if_fail(INFINOTED_IS_PLUGIN_MANAGER(mgr), NULL); g_return_val_if_fail(INF_IS_SESSION_PROXY(proxy), NULL); priv = INFINOTED_PLUGIN_MANAGER_PRIVATE(mgr); return g_hash_table_lookup( priv->sessions, infinoted_plugin_manager_hash(plugin_info, proxy) ); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/infinoted/PaxHeaders.26529/infinoted-startup.h0000644000000000000000000000013213034342512021407 xustar0030 mtime=1483851082.017718362 30 atime=1483851082.017718362 30 ctime=1488261589.456138068 libinfinity-0.7.1/infinoted/infinoted-startup.h0000644000175000017500000000321013034342512022135 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INFINOTED_STARTUP_H__ #define __INFINOTED_STARTUP_H__ #include #include #include #include G_BEGIN_DECLS typedef struct _InfinotedStartup InfinotedStartup; struct _InfinotedStartup { InfinotedOptions* options; InfinotedLog* log; gnutls_x509_privkey_t private_key; InfCertificateChain* certificates; InfCertificateCredentials* credentials; InfSaslContext* sasl_context; InfKeepalive keepalive; }; InfinotedStartup* infinoted_startup_new(int* argc, char*** argv, GError** error); void infinoted_startup_free(InfinotedStartup* startup); G_END_DECLS #endif /* __INFINOTED_STARTUP_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/PaxHeaders.26529/config.sub0000644000000000000000000000013213036062707015567 xustar0030 mtime=1484285383.715895807 30 atime=1484285383.715895807 30 ctime=1488261588.780139546 libinfinity-0.7.1/config.sub0000755000175000017500000010676313036062707016341 0ustar00arminarmin00000000000000#! /bin/sh # Configuration validation subroutine script. # Copyright 1992-2016 Free Software Foundation, Inc. timestamp='2016-11-04' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # Please send patches to . # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS Canonicalize a configuration name. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright 1992-2016 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" exit 1 ;; *local*) # First pass through any local machine types. echo $1 exit ;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \ kopensolaris*-gnu* | cloudabi*-eabi* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; android-linux) os=-linux-android basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown ;; *) basic_machine=`echo $1 | sed 's/-[^-]*$//'` if [ $basic_machine != $1 ] then os=`echo $1 | sed 's/.*-/-/'` else os=; fi ;; esac ### Let's recognize common machines as not being operating systems so ### that things like config.sub decstation-3100 work. We also ### recognize some manufacturers as not being operating systems, so we ### can provide default operating systems below. case $os in -sun*os*) # Prevent following clause from handling this invalid input. ;; -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ -apple | -axis | -knuth | -cray | -microblaze*) os= basic_machine=$1 ;; -bluegene*) os=-cnk ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 ;; -scout) ;; -wrs) os=-vxworks basic_machine=$1 ;; -chorusos*) os=-chorusos basic_machine=$1 ;; -chorusrdb) os=-chorusrdb basic_machine=$1 ;; -hiux*) os=-hiuxwe2 ;; -sco6) os=-sco5v6 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5) os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco5v6*) # Don't forget version if it is 3.2v4 or newer. basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -udk*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -lynx*178) os=-lynxos178 ;; -lynx*5) os=-lynxos5 ;; -lynx*) os=-lynxos ;; -ptx*) basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` ;; -windowsnt*) os=`echo $os | sed -e 's/windowsnt/winnt/'` ;; -psos*) os=-psos ;; -mint | -mint[0-9]*) basic_machine=m68k-atari os=-mint ;; esac # Decode aliases for certain CPU-COMPANY combinations. case $basic_machine in # Recognize the basic CPU types without company name. # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ | aarch64 | aarch64_be \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ | arc | arceb \ | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ | avr | avr32 \ | ba \ | be32 | be64 \ | bfin \ | c4x | c8051 | clipper \ | d10v | d30v | dlx | dsp16xx \ | e2k | epiphany \ | fido | fr30 | frv | ft32 \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | hexagon \ | i370 | i860 | i960 | ia64 \ | ip2k | iq2000 \ | k1om \ | le32 | le64 \ | lm32 \ | m32c | m32r | m32rle | m68000 | m68k | m88k \ | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ | mips64octeon | mips64octeonel \ | mips64orion | mips64orionel \ | mips64r5900 | mips64r5900el \ | mips64vr | mips64vrel \ | mips64vr4100 | mips64vr4100el \ | mips64vr4300 | mips64vr4300el \ | mips64vr5000 | mips64vr5000el \ | mips64vr5900 | mips64vr5900el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ | mipsisa32r6 | mipsisa32r6el \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ | mipsisa64r6 | mipsisa64r6el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ | mipsr5900 | mipsr5900el \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | moxie \ | mt \ | msp430 \ | nds32 | nds32le | nds32be \ | nios | nios2 | nios2eb | nios2el \ | ns16k | ns32k \ | open8 | or1k | or1knd | or32 \ | pdp10 | pdp11 | pj | pjl \ | powerpc | powerpc64 | powerpc64le | powerpcle \ | pru \ | pyramid \ | riscv32 | riscv64 \ | rl78 | rx \ | score \ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ | spu \ | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ | ubicom32 \ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ | visium \ | we32k \ | x86 | xc16x | xstormy16 | xtensa \ | z8k | z80) basic_machine=$basic_machine-unknown ;; c54x) basic_machine=tic54x-unknown ;; c55x) basic_machine=tic55x-unknown ;; c6x) basic_machine=tic6x-unknown ;; leon|leon[3-9]) basic_machine=sparc-$basic_machine ;; m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) basic_machine=$basic_machine-unknown os=-none ;; m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) ;; ms1) basic_machine=mt-unknown ;; strongarm | thumb | xscale) basic_machine=arm-unknown ;; xgate) basic_machine=$basic_machine-unknown os=-none ;; xscaleeb) basic_machine=armeb-unknown ;; xscaleel) basic_machine=armel-unknown ;; # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. i*86 | x86_64) basic_machine=$basic_machine-pc ;; # Object if more than one company name word. *-*-*) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ | aarch64-* | aarch64_be-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ | ba-* \ | be32-* | be64-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* \ | c8051-* | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ | e2k-* | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | hexagon-* \ | i*86-* | i860-* | i960-* | ia64-* \ | ip2k-* | iq2000-* \ | k1om-* \ | le32-* | le64-* \ | lm32-* \ | m32c-* | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ | microblaze-* | microblazeel-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ | mips64octeon-* | mips64octeonel-* \ | mips64orion-* | mips64orionel-* \ | mips64r5900-* | mips64r5900el-* \ | mips64vr-* | mips64vrel-* \ | mips64vr4100-* | mips64vr4100el-* \ | mips64vr4300-* | mips64vr4300el-* \ | mips64vr5000-* | mips64vr5000el-* \ | mips64vr5900-* | mips64vr5900el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ | mipsisa32r6-* | mipsisa32r6el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64r2-* | mipsisa64r2el-* \ | mipsisa64r6-* | mipsisa64r6el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ | mipsr5900-* | mipsr5900el-* \ | mipstx39-* | mipstx39el-* \ | mmix-* \ | mt-* \ | msp430-* \ | nds32-* | nds32le-* | nds32be-* \ | nios-* | nios2-* | nios2eb-* | nios2el-* \ | none-* | np1-* | ns16k-* | ns32k-* \ | open8-* \ | or1k*-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ | pru-* \ | pyramid-* \ | riscv32-* | riscv64-* \ | rl78-* | romp-* | rs6000-* | rx-* \ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \ | tahoe-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tile*-* \ | tron-* \ | ubicom32-* \ | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ | vax-* \ | visium-* \ | we32k-* \ | x86-* | x86_64-* | xc16x-* | xps100-* \ | xstormy16-* | xtensa*-* \ | ymp-* \ | z8k-* | z80-*) ;; # Recognize the basic CPU types without company name, with glob match. xtensa*) basic_machine=$basic_machine-unknown ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) basic_machine=i386-unknown os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) basic_machine=m68000-att ;; 3b*) basic_machine=we32k-att ;; a29khif) basic_machine=a29k-amd os=-udi ;; abacus) basic_machine=abacus-unknown ;; adobe68k) basic_machine=m68010-adobe os=-scout ;; alliant | fx80) basic_machine=fx80-alliant ;; altos | altos3068) basic_machine=m68k-altos ;; am29k) basic_machine=a29k-none os=-bsd ;; amd64) basic_machine=x86_64-pc ;; amd64-*) basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; amdahl) basic_machine=580-amdahl os=-sysv ;; amiga | amiga-*) basic_machine=m68k-unknown ;; amigaos | amigados) basic_machine=m68k-unknown os=-amigaos ;; amigaunix | amix) basic_machine=m68k-unknown os=-sysv4 ;; apollo68) basic_machine=m68k-apollo os=-sysv ;; apollo68bsd) basic_machine=m68k-apollo os=-bsd ;; aros) basic_machine=i386-pc os=-aros ;; asmjs) basic_machine=asmjs-unknown ;; aux) basic_machine=m68k-apple os=-aux ;; balance) basic_machine=ns32k-sequent os=-dynix ;; blackfin) basic_machine=bfin-unknown os=-linux ;; blackfin-*) basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; bluegene*) basic_machine=powerpc-ibm os=-cnk ;; c54x-*) basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c55x-*) basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c6x-*) basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` ;; c90) basic_machine=c90-cray os=-unicos ;; cegcc) basic_machine=arm-unknown os=-cegcc ;; convex-c1) basic_machine=c1-convex os=-bsd ;; convex-c2) basic_machine=c2-convex os=-bsd ;; convex-c32) basic_machine=c32-convex os=-bsd ;; convex-c34) basic_machine=c34-convex os=-bsd ;; convex-c38) basic_machine=c38-convex os=-bsd ;; cray | j90) basic_machine=j90-cray os=-unicos ;; craynv) basic_machine=craynv-cray os=-unicosmp ;; cr16 | cr16-*) basic_machine=cr16-unknown os=-elf ;; crds | unos) basic_machine=m68k-crds ;; crisv32 | crisv32-* | etraxfs*) basic_machine=crisv32-axis ;; cris | cris-* | etrax*) basic_machine=cris-axis ;; crx) basic_machine=crx-unknown os=-elf ;; da30 | da30-*) basic_machine=m68k-da30 ;; decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) basic_machine=mips-dec ;; decsystem10* | dec10*) basic_machine=pdp10-dec os=-tops10 ;; decsystem20* | dec20*) basic_machine=pdp10-dec os=-tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) basic_machine=m68k-motorola ;; delta88) basic_machine=m88k-motorola os=-sysv3 ;; dicos) basic_machine=i686-pc os=-dicos ;; djgpp) basic_machine=i586-pc os=-msdosdjgpp ;; dpx20 | dpx20-*) basic_machine=rs6000-bull os=-bosx ;; dpx2* | dpx2*-bull) basic_machine=m68k-bull os=-sysv3 ;; e500v[12]) basic_machine=powerpc-unknown os=$os"spe" ;; e500v[12]-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` os=$os"spe" ;; ebmon29k) basic_machine=a29k-amd os=-ebmon ;; elxsi) basic_machine=elxsi-elxsi os=-bsd ;; encore | umax | mmax) basic_machine=ns32k-encore ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson os=-ose ;; fx2800) basic_machine=i860-alliant ;; genix) basic_machine=ns32k-ns ;; gmicro) basic_machine=tron-gmicro os=-sysv ;; go32) basic_machine=i386-pc os=-go32 ;; h3050r* | hiux*) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; h8300hms) basic_machine=h8300-hitachi os=-hms ;; h8300xray) basic_machine=h8300-hitachi os=-xray ;; h8500hms) basic_machine=h8500-hitachi os=-hms ;; harris) basic_machine=m88k-harris os=-sysv3 ;; hp300-*) basic_machine=m68k-hp ;; hp300bsd) basic_machine=m68k-hp os=-bsd ;; hp300hpux) basic_machine=m68k-hp os=-hpux ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) basic_machine=hppa1.0-hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) basic_machine=hppa1.1-hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp basic_machine=hppa1.1-hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; hppa-next) os=-nextstep3 ;; hppaosf) basic_machine=hppa1.1-hp os=-osf ;; hppro) basic_machine=hppa1.1-hp os=-proelf ;; i370-ibm* | ibm*) basic_machine=i370-ibm ;; i*86v32) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; i386-vsta | vsta) basic_machine=i386-unknown os=-vsta ;; iris | iris4d) basic_machine=mips-sgi case $os in -irix*) ;; *) os=-irix4 ;; esac ;; isi68 | isi) basic_machine=m68k-isi os=-sysv ;; leon-*|leon[3-9]-*) basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'` ;; m68knommu) basic_machine=m68k-unknown os=-linux ;; m68knommu-*) basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; m88k-omron*) basic_machine=m88k-omron ;; magnum | m3230) basic_machine=mips-mips os=-sysv ;; merlin) basic_machine=ns32k-utek os=-sysv ;; microblaze*) basic_machine=microblaze-xilinx ;; mingw64) basic_machine=x86_64-pc os=-mingw64 ;; mingw32) basic_machine=i686-pc os=-mingw32 ;; mingw32ce) basic_machine=arm-unknown os=-mingw32ce ;; miniframe) basic_machine=m68000-convergent ;; *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) basic_machine=m68k-atari os=-mint ;; mips3*-*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` ;; mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; monitor) basic_machine=m68k-rom68k os=-coff ;; morphos) basic_machine=powerpc-unknown os=-morphos ;; moxiebox) basic_machine=moxie-unknown os=-moxiebox ;; msdos) basic_machine=i386-pc os=-msdos ;; ms1-*) basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` ;; msys) basic_machine=i686-pc os=-msys ;; mvs) basic_machine=i370-ibm os=-mvs ;; nacl) basic_machine=le32-unknown os=-nacl ;; ncr3000) basic_machine=i486-ncr os=-sysv4 ;; netbsd386) basic_machine=i386-unknown os=-netbsd ;; netwinder) basic_machine=armv4l-rebel os=-linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony os=-newsos ;; news1000) basic_machine=m68030-sony os=-newsos ;; news-3600 | risc-news) basic_machine=mips-sony os=-newsos ;; necv70) basic_machine=v70-nec os=-sysv ;; next | m*-next ) basic_machine=m68k-next case $os in -nextstep* ) ;; -ns2*) os=-nextstep2 ;; *) os=-nextstep3 ;; esac ;; nh3000) basic_machine=m68k-harris os=-cxux ;; nh[45]000) basic_machine=m88k-harris os=-cxux ;; nindy960) basic_machine=i960-intel os=-nindy ;; mon960) basic_machine=i960-intel os=-mon960 ;; nonstopux) basic_machine=mips-compaq os=-nonstopux ;; np1) basic_machine=np1-gould ;; neo-tandem) basic_machine=neo-tandem ;; nse-tandem) basic_machine=nse-tandem ;; nsr-tandem) basic_machine=nsr-tandem ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf ;; openrisc | openrisc-*) basic_machine=or32-unknown ;; os400) basic_machine=powerpc-ibm os=-os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson os=-ose ;; os68k) basic_machine=m68k-none os=-os68k ;; pa-hitachi) basic_machine=hppa1.1-hitachi os=-hiuxwe2 ;; paragon) basic_machine=i860-intel os=-osf ;; parisc) basic_machine=hppa-unknown os=-linux ;; parisc-*) basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` os=-linux ;; pbd) basic_machine=sparc-tti ;; pbb) basic_machine=m68k-tti ;; pc532 | pc532-*) basic_machine=ns32k-pc532 ;; pc98) basic_machine=i386-pc ;; pc98-*) basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc ;; pentiumpro | p6 | 6x86 | athlon | athlon_*) basic_machine=i686-pc ;; pentiumii | pentium2 | pentiumiii | pentium3) basic_machine=i686-pc ;; pentium4) basic_machine=i786-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentium4-*) basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; ppc | ppcbe) basic_machine=powerpc-unknown ;; ppc-* | ppcbe-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppcle | powerpclittle) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ppc64le | powerpc64little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm ;; pw32) basic_machine=i586-unknown os=-pw32 ;; rdos | rdos64) basic_machine=x86_64-pc os=-rdos ;; rdos32) basic_machine=i386-pc os=-rdos ;; rom68k) basic_machine=m68k-rom68k os=-coff ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; s390 | s390-*) basic_machine=s390-ibm ;; s390x | s390x-*) basic_machine=s390x-ibm ;; sa29200) basic_machine=a29k-amd os=-udi ;; sb1) basic_machine=mipsisa64sb1-unknown ;; sb1el) basic_machine=mipsisa64sb1el-unknown ;; sde) basic_machine=mipsisa32-sde os=-elf ;; sei) basic_machine=mips-sei os=-seiux ;; sequent) basic_machine=i386-sequent ;; sh) basic_machine=sh-hitachi os=-hms ;; sh5el) basic_machine=sh5le-unknown ;; sh64) basic_machine=sh64-unknown ;; sparclite-wrs | simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; sps7) basic_machine=m68k-bull os=-sysv2 ;; spur) basic_machine=spur-unknown ;; st2000) basic_machine=m68k-tandem ;; stratus) basic_machine=i860-stratus os=-sysv4 ;; strongarm-* | thumb-*) basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` ;; sun2) basic_machine=m68000-sun ;; sun2os3) basic_machine=m68000-sun os=-sunos3 ;; sun2os4) basic_machine=m68000-sun os=-sunos4 ;; sun3os3) basic_machine=m68k-sun os=-sunos3 ;; sun3os4) basic_machine=m68k-sun os=-sunos4 ;; sun4os3) basic_machine=sparc-sun os=-sunos3 ;; sun4os4) basic_machine=sparc-sun os=-sunos4 ;; sun4sol2) basic_machine=sparc-sun os=-solaris2 ;; sun3 | sun3-*) basic_machine=m68k-sun ;; sun4) basic_machine=sparc-sun ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun ;; sv1) basic_machine=sv1-cray os=-unicos ;; symmetry) basic_machine=i386-sequent os=-dynix ;; t3e) basic_machine=alphaev5-cray os=-unicos ;; t90) basic_machine=t90-cray os=-unicos ;; tile*) basic_machine=$basic_machine-unknown os=-linux-gnu ;; tx39) basic_machine=mipstx39-unknown ;; tx39el) basic_machine=mipstx39el-unknown ;; toad1) basic_machine=pdp10-xkl os=-tops20 ;; tower | tower-32) basic_machine=m68k-ncr ;; tpf) basic_machine=s390x-ibm os=-tpf ;; udi29k) basic_machine=a29k-amd os=-udi ;; ultra3) basic_machine=a29k-nyu os=-sym1 ;; v810 | necv810) basic_machine=v810-nec os=-none ;; vaxv) basic_machine=vax-dec os=-sysv ;; vms) basic_machine=vax-dec os=-vms ;; vpp*|vx|vx-*) basic_machine=f301-fujitsu ;; vxworks960) basic_machine=i960-wrs os=-vxworks ;; vxworks68) basic_machine=m68k-wrs os=-vxworks ;; vxworks29k) basic_machine=a29k-wrs os=-vxworks ;; w65*) basic_machine=w65-wdc os=-none ;; w89k-*) basic_machine=hppa1.1-winbond os=-proelf ;; xbox) basic_machine=i686-pc os=-mingw32 ;; xps | xps100) basic_machine=xps100-honeywell ;; xscale-* | xscalee[bl]-*) basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` ;; ymp) basic_machine=ymp-cray os=-unicos ;; z8k-*-coff) basic_machine=z8k-unknown os=-sim ;; z80-*-coff) basic_machine=z80-unknown os=-sim ;; none) basic_machine=none-none os=-none ;; # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) basic_machine=hppa1.1-winbond ;; op50n) basic_machine=hppa1.1-oki ;; op60c) basic_machine=hppa1.1-oki ;; romp) basic_machine=romp-ibm ;; mmix) basic_machine=mmix-knuth ;; rs6000) basic_machine=rs6000-ibm ;; vax) basic_machine=vax-dec ;; pdp10) # there are many clones, so DEC is not a safe bet basic_machine=pdp10-unknown ;; pdp11) basic_machine=pdp11-dec ;; we32k) basic_machine=we32k-att ;; sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) basic_machine=sparc-sun ;; cydra) basic_machine=cydra-cydrome ;; orion) basic_machine=orion-highlevel ;; orion105) basic_machine=clipper-highlevel ;; mac | mpw | mac-mpw) basic_machine=m68k-apple ;; pmac | pmac-mpw) basic_machine=powerpc-apple ;; *-unknown) # Make sure to match an already-canonicalized machine name. ;; *) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 ;; esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` ;; *-commodore*) basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if [ x"$os" != x"" ] then case $os in # First match some system type aliases # that might get confused with valid system types. # -solaris* is a basic system type, with this one exception. -auroraux) os=-auroraux ;; -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; -solaris) os=-solaris2 ;; -svr4*) os=-sysv4 ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; # First accept the basic system types. # The portable systems comes first. # Each alternative MUST END IN A *, to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ | -sym* | -kopensolaris* | -plan9* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ | -aos* | -aros* | -cloudabi* | -sortix* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -chorusos* | -chorusrdb* | -cegcc* \ | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ | -linux-newlib* | -linux-musl* | -linux-uclibc* \ | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \ | -onefs* | -tirtos* | -phoenix* | -fuchsia*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) case $basic_machine in x86-* | i*86-*) ;; *) os=-nto$os ;; esac ;; -nto-qnx*) ;; -nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) os=`echo $os | sed -e 's|mac|macos|'` ;; -linux-dietlibc) os=-linux-dietlibc ;; -linux*) os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) os=`echo $os | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) os=`echo $os | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition ;; -os400*) os=-os400 ;; -wince*) os=-wince ;; -osfrose*) os=-osfrose ;; -osf*) os=-osf ;; -utek*) os=-bsd ;; -dynix*) os=-bsd ;; -acis*) os=-aos ;; -atheos*) os=-atheos ;; -syllable*) os=-syllable ;; -386bsd) os=-bsd ;; -ctix* | -uts*) os=-sysv ;; -nova*) os=-rtmk-nova ;; -ns2 ) os=-nextstep2 ;; -nsk*) os=-nsk ;; # Preserve the version number of sinix5. -sinix5.*) os=`echo $os | sed -e 's|sinix|sysv|'` ;; -sinix*) os=-sysv4 ;; -tpf*) os=-tpf ;; -triton*) os=-sysv3 ;; -oss*) os=-sysv3 ;; -svr4) os=-sysv4 ;; -svr3) os=-sysv3 ;; -sysvr4) os=-sysv4 ;; # This must come after -sysvr4. -sysv*) ;; -ose*) os=-ose ;; -es1800*) os=-ose ;; -xenix) os=-xenix ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; -aros*) os=-aros ;; -zvmoe) os=-zvmoe ;; -dicos*) os=-dicos ;; -nacl*) ;; -ios) ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 exit 1 ;; esac else # Here we handle the default operating systems that come with various machines. # The value should be what the vendor currently ships out the door with their # machine or put another way, the most popular os provided with the machine. # Note that if you're going to try to match "-MANUFACTURER" here (say, # "-sun"), then you have to tell the case statement up towards the top # that MANUFACTURER isn't an operating system. Otherwise, code above # will signal an error saying that MANUFACTURER isn't an operating # system, and we'll never get to this point. case $basic_machine in score-*) os=-elf ;; spu-*) os=-elf ;; *-acorn) os=-riscix1.2 ;; arm*-rebel) os=-linux ;; arm*-semi) os=-aout ;; c4x-* | tic4x-*) os=-coff ;; c8051-*) os=-elf ;; hexagon-*) os=-elf ;; tic54x-*) os=-coff ;; tic55x-*) os=-coff ;; tic6x-*) os=-coff ;; # This must come before the *-dec entry. pdp10-*) os=-tops20 ;; pdp11-*) os=-none ;; *-dec | vax-*) os=-ultrix4.2 ;; m68*-apollo) os=-domain ;; i386-sun) os=-sunos4.0.2 ;; m68000-sun) os=-sunos3 ;; m68*-cisco) os=-aout ;; mep-*) os=-elf ;; mips*-cisco) os=-elf ;; mips*-*) os=-elf ;; or32-*) os=-coff ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; sparc-* | *-sun) os=-sunos4.1.1 ;; *-be) os=-beos ;; *-haiku) os=-haiku ;; *-ibm) os=-aix ;; *-knuth) os=-mmixware ;; *-wec) os=-proelf ;; *-winbond) os=-proelf ;; *-oki) os=-proelf ;; *-hp) os=-hpux ;; *-hitachi) os=-hiux ;; i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) os=-sysv ;; *-cbm) os=-amigaos ;; *-dg) os=-dgux ;; *-dolphin) os=-sysv3 ;; m68k-ccur) os=-rtu ;; m88k-omron*) os=-luna ;; *-next ) os=-nextstep ;; *-sequent) os=-ptx ;; *-crds) os=-unos ;; *-ns) os=-genix ;; i370-*) os=-mvs ;; *-next) os=-nextstep3 ;; *-gould) os=-sysv ;; *-highlevel) os=-bsd ;; *-encore) os=-bsd ;; *-sgi) os=-irix ;; *-siemens) os=-sysv4 ;; *-masscomp) os=-rtu ;; f30[01]-fujitsu | f700-fujitsu) os=-uxpv ;; *-rom68k) os=-coff ;; *-*bug) os=-coff ;; *-apple) os=-macos ;; *-atari*) os=-mint ;; *) os=-none ;; esac fi # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. vendor=unknown case $basic_machine in *-unknown) case $os in -riscix*) vendor=acorn ;; -sunos*) vendor=sun ;; -cnk*|-aix*) vendor=ibm ;; -beos*) vendor=be ;; -hpux*) vendor=hp ;; -mpeix*) vendor=hp ;; -hiux*) vendor=hitachi ;; -unos*) vendor=crds ;; -dgux*) vendor=dg ;; -luna*) vendor=omron ;; -genix*) vendor=ns ;; -mvs* | -opened*) vendor=ibm ;; -os400*) vendor=ibm ;; -ptx*) vendor=sequent ;; -tpf*) vendor=ibm ;; -vxsim* | -vxworks* | -windiss*) vendor=wrs ;; -aux*) vendor=apple ;; -hms*) vendor=hitachi ;; -mpw* | -macos*) vendor=apple ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) vendor=atari ;; -vos*) vendor=stratus ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; esac echo $basic_machine$os exit # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: libinfinity-0.7.1/PaxHeaders.26529/libinfinoted-plugin-manager.pc.in0000644000000000000000000000013112400102201022063 xustar0030 mtime=1409320065.127132027 30 atime=1409320065.127132027 29 ctime=1488261588.76013959 libinfinity-0.7.1/libinfinoted-plugin-manager.pc.in0000644000175000017500000000057612400102201022626 0ustar00arminarmin00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: libinfinoted-plugin-manager Description: Infinoted API accessible to plugins Requires: libinfinity-@LIBINFINITY_API_VERSION@ Version: @VERSION@ Libs: -L${libdir} -linfinoted-plugin-manager-@LIBINFINITY_API_VERSION@ Cflags: -I${includedir}/libinfinoted-plugin-manager-@LIBINFINITY_API_VERSION@ libinfinity-0.7.1/PaxHeaders.26529/config.h.in0000644000000000000000000000013213055210722015623 xustar0030 mtime=1488261586.324144906 30 atime=1488261586.324144906 30 ctime=1488261588.756139598 libinfinity-0.7.1/config.h.in0000644000175000017500000000726613055210722016370 0ustar00arminarmin00000000000000/* config.h.in. Generated from configure.ac by autoheader. */ /* always defined to indicate that i18n is enabled */ #undef ENABLE_NLS /* The domain name to use with gettext. */ #undef GETTEXT_PACKAGE /* Define to 1 if you have the `bind_textdomain_codeset' function. */ #undef HAVE_BIND_TEXTDOMAIN_CODESET /* Define to 1 if you have the `dcgettext' function. */ #undef HAVE_DCGETTEXT /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H /* Define this symbol if your struct dirent has the d_type field */ #undef HAVE_D_TYPE /* Define if the GNU gettext() function is already present or preinstalled. */ #undef HAVE_GETTEXT /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define if your file defines LC_MESSAGES. */ #undef HAVE_LC_MESSAGES /* Define to 1 if you have the header file. */ #undef HAVE_LOCALE_H /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define this symbol if you have MSG_NOSIGNAL */ #undef HAVE_MSG_NOSIGNAL /* Define this symbol if the O_NOFOLLOW flag is supported on your system */ #undef HAVE_O_NOFOLLOW /* Define this symbol if your pam has PAM_FAIL_DELAY */ #undef HAVE_PAM_FAIL_DELAY /* Define this symbol if you have SO_REUSEADDR */ #undef HAVE_SO_REUSEADDR /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Define the location where the catalogs will be installed */ #undef INF_LOCALEDIR /* Whether avahi support is enabled */ #undef LIBINFINITY_HAVE_AVAHI /* Whether gio support is enabled */ #undef LIBINFINITY_HAVE_GIO /* Whether libdaemon support is enabled */ #undef LIBINFINITY_HAVE_LIBDAEMON /* Define this symbol if you have pam */ #undef LIBINFINITY_HAVE_PAM /* Define to the sub-directory where libtool stores uninstalled libraries. */ #undef LT_OBJDIR /* Name of package */ #undef PACKAGE /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the home page for this package. */ #undef PACKAGE_URL /* Define to the version of this package. */ #undef PACKAGE_VERSION /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* Enable extensions on AIX 3, Interix. */ #ifndef _ALL_SOURCE # undef _ALL_SOURCE #endif /* Enable GNU extensions on systems that have them. */ #ifndef _GNU_SOURCE # undef _GNU_SOURCE #endif /* Enable threading extensions on Solaris. */ #ifndef _POSIX_PTHREAD_SEMANTICS # undef _POSIX_PTHREAD_SEMANTICS #endif /* Enable extensions on HP NonStop. */ #ifndef _TANDEM_SOURCE # undef _TANDEM_SOURCE #endif /* Enable general extensions on Solaris. */ #ifndef __EXTENSIONS__ # undef __EXTENSIONS__ #endif /* Version number of package */ #undef VERSION /* Define to 1 if on MINIX. */ #undef _MINIX /* Define to 2 if the system does not provide POSIX.1 features except with this defined. */ #undef _POSIX_1_SOURCE /* Define to 1 if you need to in order for `stat' and other things to work. */ #undef _POSIX_SOURCE libinfinity-0.7.1/PaxHeaders.26529/gtk-doc.make0000644000000000000000000000013113036062665016000 xustar0030 mtime=1484285365.811881364 30 atime=1484285365.811881364 29 ctime=1488261590.87213497 libinfinity-0.7.1/gtk-doc.make0000644000175000017500000002351413036062665016540 0ustar00arminarmin00000000000000# -*- mode: makefile -*- #################################### # Everything below here is generic # #################################### if GTK_DOC_USE_LIBTOOL GTKDOC_CC = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(INCLUDES) $(GTKDOC_DEPS_CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) GTKDOC_LD = $(LIBTOOL) --tag=CC --mode=link $(CC) $(GTKDOC_DEPS_LIBS) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) GTKDOC_RUN = $(LIBTOOL) --mode=execute else GTKDOC_CC = $(CC) $(INCLUDES) $(GTKDOC_DEPS_CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) GTKDOC_LD = $(CC) $(GTKDOC_DEPS_LIBS) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) GTKDOC_RUN = endif # We set GPATH here; this gives us semantics for GNU make # which are more like other make's VPATH, when it comes to # whether a source that is a target of one rule is then # searched for in VPATH/GPATH. # GPATH = $(srcdir) TARGET_DIR=$(HTML_DIR)/$(DOC_MODULE) SETUP_FILES = \ $(content_files) \ $(expand_content_files) \ $(DOC_MAIN_SGML_FILE) \ $(DOC_MODULE)-sections.txt \ $(DOC_MODULE)-overrides.txt EXTRA_DIST = \ $(HTML_IMAGES) \ $(SETUP_FILES) DOC_STAMPS=setup-build.stamp scan-build.stamp sgml-build.stamp \ html-build.stamp pdf-build.stamp \ sgml.stamp html.stamp pdf.stamp SCANOBJ_FILES = \ $(DOC_MODULE).args \ $(DOC_MODULE).hierarchy \ $(DOC_MODULE).interfaces \ $(DOC_MODULE).prerequisites \ $(DOC_MODULE).signals REPORT_FILES = \ $(DOC_MODULE)-undocumented.txt \ $(DOC_MODULE)-undeclared.txt \ $(DOC_MODULE)-unused.txt gtkdoc-check.test: Makefile $(AM_V_GEN)echo "#!/bin/sh -e" > $@; \ echo "$(GTKDOC_CHECK_PATH) || exit 1" >> $@; \ chmod +x $@ CLEANFILES = $(SCANOBJ_FILES) $(REPORT_FILES) $(DOC_STAMPS) gtkdoc-check.test if GTK_DOC_BUILD_HTML HTML_BUILD_STAMP=html-build.stamp else HTML_BUILD_STAMP= endif if GTK_DOC_BUILD_PDF PDF_BUILD_STAMP=pdf-build.stamp else PDF_BUILD_STAMP= endif all-gtk-doc: $(HTML_BUILD_STAMP) $(PDF_BUILD_STAMP) .PHONY: all-gtk-doc if ENABLE_GTK_DOC all-local: all-gtk-doc endif docs: $(HTML_BUILD_STAMP) $(PDF_BUILD_STAMP) $(REPORT_FILES): sgml-build.stamp #### setup #### GTK_DOC_V_SETUP=$(GTK_DOC_V_SETUP_$(V)) GTK_DOC_V_SETUP_=$(GTK_DOC_V_SETUP_$(AM_DEFAULT_VERBOSITY)) GTK_DOC_V_SETUP_0=@echo " DOC Preparing build"; setup-build.stamp: -$(GTK_DOC_V_SETUP)if test "$(abs_srcdir)" != "$(abs_builddir)" ; then \ files=`echo $(SETUP_FILES) $(DOC_MODULE).types`; \ if test "x$$files" != "x" ; then \ for file in $$files ; do \ destdir=`dirname $(abs_builddir)/$$file`; \ test -d "$$destdir" || mkdir -p "$$destdir"; \ test -f $(abs_srcdir)/$$file && \ cp -pf $(abs_srcdir)/$$file $(abs_builddir)/$$file || true; \ done; \ fi; \ fi $(AM_V_at)touch setup-build.stamp #### scan #### GTK_DOC_V_SCAN=$(GTK_DOC_V_SCAN_$(V)) GTK_DOC_V_SCAN_=$(GTK_DOC_V_SCAN_$(AM_DEFAULT_VERBOSITY)) GTK_DOC_V_SCAN_0=@echo " DOC Scanning header files"; GTK_DOC_V_INTROSPECT=$(GTK_DOC_V_INTROSPECT_$(V)) GTK_DOC_V_INTROSPECT_=$(GTK_DOC_V_INTROSPECT_$(AM_DEFAULT_VERBOSITY)) GTK_DOC_V_INTROSPECT_0=@echo " DOC Introspecting gobjects"; scan-build.stamp: setup-build.stamp $(HFILE_GLOB) $(CFILE_GLOB) $(GTK_DOC_V_SCAN)_source_dir='' ; \ for i in $(DOC_SOURCE_DIR) ; do \ _source_dir="$${_source_dir} --source-dir=$$i" ; \ done ; \ gtkdoc-scan --module=$(DOC_MODULE) --ignore-headers="$(IGNORE_HFILES)" $${_source_dir} $(SCAN_OPTIONS) $(EXTRA_HFILES) $(GTK_DOC_V_INTROSPECT)if grep -l '^..*$$' $(DOC_MODULE).types > /dev/null 2>&1 ; then \ scanobj_options=""; \ gtkdoc-scangobj 2>&1 --help | grep >/dev/null "\-\-verbose"; \ if test "$$?" = "0"; then \ if test "x$(V)" = "x1"; then \ scanobj_options="--verbose"; \ fi; \ fi; \ CC="$(GTKDOC_CC)" LD="$(GTKDOC_LD)" RUN="$(GTKDOC_RUN)" CFLAGS="$(GTKDOC_CFLAGS) $(CFLAGS)" LDFLAGS="$(GTKDOC_LIBS) $(LDFLAGS)" \ gtkdoc-scangobj $(SCANGOBJ_OPTIONS) $$scanobj_options --module=$(DOC_MODULE); \ else \ for i in $(SCANOBJ_FILES) ; do \ test -f $$i || touch $$i ; \ done \ fi $(AM_V_at)touch scan-build.stamp $(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(DOC_MODULE)-sections.txt $(DOC_MODULE)-overrides.txt: scan-build.stamp @true #### xml #### GTK_DOC_V_XML=$(GTK_DOC_V_XML_$(V)) GTK_DOC_V_XML_=$(GTK_DOC_V_XML_$(AM_DEFAULT_VERBOSITY)) GTK_DOC_V_XML_0=@echo " DOC Building XML"; sgml-build.stamp: setup-build.stamp $(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(HFILE_GLOB) $(CFILE_GLOB) $(DOC_MODULE)-sections.txt $(DOC_MODULE)-overrides.txt $(expand_content_files) xml/gtkdocentities.ent $(GTK_DOC_V_XML)_source_dir='' ; \ for i in $(DOC_SOURCE_DIR) ; do \ _source_dir="$${_source_dir} --source-dir=$$i" ; \ done ; \ gtkdoc-mkdb --module=$(DOC_MODULE) --output-format=xml --expand-content-files="$(expand_content_files)" --main-sgml-file=$(DOC_MAIN_SGML_FILE) $${_source_dir} $(MKDB_OPTIONS) $(AM_V_at)touch sgml-build.stamp sgml.stamp: sgml-build.stamp @true xml/gtkdocentities.ent: Makefile $(GTK_DOC_V_XML)$(MKDIR_P) $(@D) && ( \ echo ""; \ echo ""; \ echo ""; \ echo ""; \ echo ""; \ echo ""; \ echo ""; \ ) > $@ #### html #### GTK_DOC_V_HTML=$(GTK_DOC_V_HTML_$(V)) GTK_DOC_V_HTML_=$(GTK_DOC_V_HTML_$(AM_DEFAULT_VERBOSITY)) GTK_DOC_V_HTML_0=@echo " DOC Building HTML"; GTK_DOC_V_XREF=$(GTK_DOC_V_XREF_$(V)) GTK_DOC_V_XREF_=$(GTK_DOC_V_XREF_$(AM_DEFAULT_VERBOSITY)) GTK_DOC_V_XREF_0=@echo " DOC Fixing cross-references"; html-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) $(expand_content_files) $(GTK_DOC_V_HTML)rm -rf html && mkdir html && \ mkhtml_options=""; \ gtkdoc-mkhtml 2>&1 --help | grep >/dev/null "\-\-verbose"; \ if test "$$?" = "0"; then \ if test "x$(V)" = "x1"; then \ mkhtml_options="$$mkhtml_options --verbose"; \ fi; \ fi; \ gtkdoc-mkhtml 2>&1 --help | grep >/dev/null "\-\-path"; \ if test "$$?" = "0"; then \ mkhtml_options="$$mkhtml_options --path=\"$(abs_srcdir)\""; \ fi; \ cd html && gtkdoc-mkhtml $$mkhtml_options $(MKHTML_OPTIONS) $(DOC_MODULE) ../$(DOC_MAIN_SGML_FILE) -@test "x$(HTML_IMAGES)" = "x" || \ for file in $(HTML_IMAGES) ; do \ if test -f $(abs_srcdir)/$$file ; then \ cp $(abs_srcdir)/$$file $(abs_builddir)/html; \ fi; \ if test -f $(abs_builddir)/$$file ; then \ cp $(abs_builddir)/$$file $(abs_builddir)/html; \ fi; \ done; $(GTK_DOC_V_XREF)gtkdoc-fixxref --module=$(DOC_MODULE) --module-dir=html --html-dir=$(HTML_DIR) $(FIXXREF_OPTIONS) $(AM_V_at)touch html-build.stamp #### pdf #### GTK_DOC_V_PDF=$(GTK_DOC_V_PDF_$(V)) GTK_DOC_V_PDF_=$(GTK_DOC_V_PDF_$(AM_DEFAULT_VERBOSITY)) GTK_DOC_V_PDF_0=@echo " DOC Building PDF"; pdf-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) $(expand_content_files) $(GTK_DOC_V_PDF)rm -f $(DOC_MODULE).pdf && \ mkpdf_options=""; \ gtkdoc-mkpdf 2>&1 --help | grep >/dev/null "\-\-verbose"; \ if test "$$?" = "0"; then \ if test "x$(V)" = "x1"; then \ mkpdf_options="$$mkpdf_options --verbose"; \ fi; \ fi; \ if test "x$(HTML_IMAGES)" != "x"; then \ for img in $(HTML_IMAGES); do \ part=`dirname $$img`; \ echo $$mkpdf_options | grep >/dev/null "\-\-imgdir=$$part "; \ if test $$? != 0; then \ mkpdf_options="$$mkpdf_options --imgdir=$$part"; \ fi; \ done; \ fi; \ gtkdoc-mkpdf --path="$(abs_srcdir)" $$mkpdf_options $(DOC_MODULE) $(DOC_MAIN_SGML_FILE) $(MKPDF_OPTIONS) $(AM_V_at)touch pdf-build.stamp ############## clean-local: @rm -f *~ *.bak @rm -rf .libs @if echo $(SCAN_OPTIONS) | grep -q "\-\-rebuild-types" ; then \ rm -f $(DOC_MODULE).types; \ fi @if echo $(SCAN_OPTIONS) | grep -q "\-\-rebuild-sections" ; then \ rm -f $(DOC_MODULE)-sections.txt; \ fi distclean-local: @rm -rf xml html $(REPORT_FILES) $(DOC_MODULE).pdf \ $(DOC_MODULE)-decl-list.txt $(DOC_MODULE)-decl.txt @if test "$(abs_srcdir)" != "$(abs_builddir)" ; then \ rm -f $(SETUP_FILES) $(DOC_MODULE).types; \ fi maintainer-clean-local: @rm -rf xml html install-data-local: @installfiles=`echo $(builddir)/html/*`; \ if test "$$installfiles" = '$(builddir)/html/*'; \ then echo 1>&2 'Nothing to install' ; \ else \ if test -n "$(DOC_MODULE_VERSION)"; then \ installdir="$(DESTDIR)$(TARGET_DIR)-$(DOC_MODULE_VERSION)"; \ else \ installdir="$(DESTDIR)$(TARGET_DIR)"; \ fi; \ $(mkinstalldirs) $${installdir} ; \ for i in $$installfiles; do \ echo ' $(INSTALL_DATA) '$$i ; \ $(INSTALL_DATA) $$i $${installdir}; \ done; \ if test -n "$(DOC_MODULE_VERSION)"; then \ mv -f $${installdir}/$(DOC_MODULE).devhelp2 \ $${installdir}/$(DOC_MODULE)-$(DOC_MODULE_VERSION).devhelp2; \ fi; \ $(GTKDOC_REBASE) --relative --dest-dir=$(DESTDIR) --html-dir=$${installdir}; \ fi uninstall-local: @if test -n "$(DOC_MODULE_VERSION)"; then \ installdir="$(DESTDIR)$(TARGET_DIR)-$(DOC_MODULE_VERSION)"; \ else \ installdir="$(DESTDIR)$(TARGET_DIR)"; \ fi; \ rm -rf $${installdir} # # Require gtk-doc when making dist # if HAVE_GTK_DOC dist-check-gtkdoc: docs else dist-check-gtkdoc: @echo "*** gtk-doc is needed to run 'make dist'. ***" @echo "*** gtk-doc was not found when 'configure' ran. ***" @echo "*** please install gtk-doc and rerun 'configure'. ***" @false endif dist-hook: dist-check-gtkdoc all-gtk-doc dist-hook-local @mkdir $(distdir)/html @cp ./html/* $(distdir)/html @-cp ./$(DOC_MODULE).pdf $(distdir)/ @-cp ./$(DOC_MODULE).types $(distdir)/ @-cp ./$(DOC_MODULE)-sections.txt $(distdir)/ @cd $(distdir) && rm -f $(DISTCLEANFILES) @$(GTKDOC_REBASE) --online --relative --html-dir=$(distdir)/html .PHONY : dist-hook-local docs libinfinity-0.7.1/PaxHeaders.26529/compile0000644000000000000000000000012613036062707015165 xustar0028 mtime=1484285383.7078958 28 atime=1484285383.7078958 30 ctime=1488261588.776139555 libinfinity-0.7.1/compile0000755000175000017500000001624513036062707015727 0ustar00arminarmin00000000000000#! /bin/sh # Wrapper for compilers which do not understand '-c -o'. scriptversion=2012-10-14.11; # UTC # Copyright (C) 1999-2014 Free Software Foundation, Inc. # Written by Tom Tromey . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # This file is maintained in Automake, please report # bugs to or send patches to # . nl=' ' # We need space, tab and new line, in precisely that order. Quoting is # there to prevent tools from complaining about whitespace usage. IFS=" "" $nl" file_conv= # func_file_conv build_file lazy # Convert a $build file to $host form and store it in $file # Currently only supports Windows hosts. If the determined conversion # type is listed in (the comma separated) LAZY, no conversion will # take place. func_file_conv () { file=$1 case $file in / | /[!/]*) # absolute file, and not a UNC file if test -z "$file_conv"; then # lazily determine how to convert abs files case `uname -s` in MINGW*) file_conv=mingw ;; CYGWIN*) file_conv=cygwin ;; *) file_conv=wine ;; esac fi case $file_conv/,$2, in *,$file_conv,*) ;; mingw/*) file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` ;; cygwin/*) file=`cygpath -m "$file" || echo "$file"` ;; wine/*) file=`winepath -w "$file" || echo "$file"` ;; esac ;; esac } # func_cl_dashL linkdir # Make cl look for libraries in LINKDIR func_cl_dashL () { func_file_conv "$1" if test -z "$lib_path"; then lib_path=$file else lib_path="$lib_path;$file" fi linker_opts="$linker_opts -LIBPATH:$file" } # func_cl_dashl library # Do a library search-path lookup for cl func_cl_dashl () { lib=$1 found=no save_IFS=$IFS IFS=';' for dir in $lib_path $LIB do IFS=$save_IFS if $shared && test -f "$dir/$lib.dll.lib"; then found=yes lib=$dir/$lib.dll.lib break fi if test -f "$dir/$lib.lib"; then found=yes lib=$dir/$lib.lib break fi if test -f "$dir/lib$lib.a"; then found=yes lib=$dir/lib$lib.a break fi done IFS=$save_IFS if test "$found" != yes; then lib=$lib.lib fi } # func_cl_wrapper cl arg... # Adjust compile command to suit cl func_cl_wrapper () { # Assume a capable shell lib_path= shared=: linker_opts= for arg do if test -n "$eat"; then eat= else case $1 in -o) # configure might choose to run compile as 'compile cc -o foo foo.c'. eat=1 case $2 in *.o | *.[oO][bB][jJ]) func_file_conv "$2" set x "$@" -Fo"$file" shift ;; *) func_file_conv "$2" set x "$@" -Fe"$file" shift ;; esac ;; -I) eat=1 func_file_conv "$2" mingw set x "$@" -I"$file" shift ;; -I*) func_file_conv "${1#-I}" mingw set x "$@" -I"$file" shift ;; -l) eat=1 func_cl_dashl "$2" set x "$@" "$lib" shift ;; -l*) func_cl_dashl "${1#-l}" set x "$@" "$lib" shift ;; -L) eat=1 func_cl_dashL "$2" ;; -L*) func_cl_dashL "${1#-L}" ;; -static) shared=false ;; -Wl,*) arg=${1#-Wl,} save_ifs="$IFS"; IFS=',' for flag in $arg; do IFS="$save_ifs" linker_opts="$linker_opts $flag" done IFS="$save_ifs" ;; -Xlinker) eat=1 linker_opts="$linker_opts $2" ;; -*) set x "$@" "$1" shift ;; *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) func_file_conv "$1" set x "$@" -Tp"$file" shift ;; *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) func_file_conv "$1" mingw set x "$@" "$file" shift ;; *) set x "$@" "$1" shift ;; esac fi shift done if test -n "$linker_opts"; then linker_opts="-link$linker_opts" fi exec "$@" $linker_opts exit 1 } eat= case $1 in '') echo "$0: No command. Try '$0 --help' for more information." 1>&2 exit 1; ;; -h | --h*) cat <<\EOF Usage: compile [--help] [--version] PROGRAM [ARGS] Wrapper for compilers which do not understand '-c -o'. Remove '-o dest.o' from ARGS, run PROGRAM with the remaining arguments, and rename the output as expected. If you are trying to build a whole package this is not the right script to run: please start by reading the file 'INSTALL'. Report bugs to . EOF exit $? ;; -v | --v*) echo "compile $scriptversion" exit $? ;; cl | *[/\\]cl | cl.exe | *[/\\]cl.exe ) func_cl_wrapper "$@" # Doesn't return... ;; esac ofile= cfile= for arg do if test -n "$eat"; then eat= else case $1 in -o) # configure might choose to run compile as 'compile cc -o foo foo.c'. # So we strip '-o arg' only if arg is an object. eat=1 case $2 in *.o | *.obj) ofile=$2 ;; *) set x "$@" -o "$2" shift ;; esac ;; *.c) cfile=$1 set x "$@" "$1" shift ;; *) set x "$@" "$1" shift ;; esac fi shift done if test -z "$ofile" || test -z "$cfile"; then # If no '-o' option was seen then we might have been invoked from a # pattern rule where we don't need one. That is ok -- this is a # normal compilation that the losing compiler can handle. If no # '.c' file was seen then we are probably linking. That is also # ok. exec "$@" fi # Name of file we expect compiler to create. cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` # Create the lock directory. # Note: use '[/\\:.-]' here to ensure that we don't use the same name # that we are using for the .o file. Also, base the name on the expected # object file name, since that is what matters with a parallel build. lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d while true; do if mkdir "$lockdir" >/dev/null 2>&1; then break fi sleep 1 done # FIXME: race condition here if user kills between mkdir and trap. trap "rmdir '$lockdir'; exit 1" 1 2 15 # Run the compile. "$@" ret=$? if test -f "$cofile"; then test "$cofile" = "$ofile" || mv "$cofile" "$ofile" elif test -f "${cofile}bj"; then test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" fi rmdir "$lockdir" exit $ret # Local Variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC" # time-stamp-end: "; # UTC" # End: libinfinity-0.7.1/PaxHeaders.26529/test0000644000000000000000000000013213055210725014505 xustar0030 mtime=1488261589.888137123 30 atime=1488261589.660137622 30 ctime=1488261589.888137123 libinfinity-0.7.1/test/0000755000175000017500000000000013055210725015314 5ustar00arminarmin00000000000000libinfinity-0.7.1/test/PaxHeaders.26529/inf-test-traffic-replay.c0000644000000000000000000000013213051240623021361 xustar0030 mtime=1487225235.440756142 30 atime=1487225235.440756142 30 ctime=1488261589.740137447 libinfinity-0.7.1/test/inf-test-traffic-replay.c0000644000175000017500000007020313051240623022115 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #define _XOPEN_SOURCE 700 #include "util/inf-test-util.h" #include #include #include #include #include #include #include #include #include #include #include #include typedef struct _InfTestTrafficReplay InfTestTrafficReplay; struct _InfTestTrafficReplay { InfStandaloneIo* io; guint port; InfdXmppServer* xmpp; const gchar* filename; GSList* conns; }; typedef enum _InfTestTrafficReplayMessageType { INF_TEST_TRAFFIC_REPLAY_MESSAGE_INCOMING, INF_TEST_TRAFFIC_REPLAY_MESSAGE_OUTGOING, INF_TEST_TRAFFIC_REPLAY_MESSAGE_CONNECT, INF_TEST_TRAFFIC_REPLAY_MESSAGE_DISCONNECT, INF_TEST_TRAFFIC_REPLAY_MESSAGE_ERROR } InfTestTrafficReplayMessageType; typedef struct _InfTestTrafficReplayMessage InfTestTrafficReplayMessage; struct _InfTestTrafficReplayMessage { gint64 timestamp; /* microseconds since the epoch */ InfTestTrafficReplayMessageType type; xmlNodePtr xml; xmlNodePtr xml_iter; }; typedef struct _InfTestTrafficReplayConnection InfTestTrafficReplayConnection; struct _InfTestTrafficReplayConnection { gchar* name; InfTestTrafficReplay* replay; InfCertificateCredentials* creds; InfXmppConnection* xmpp; FILE* file; InfTestTrafficReplayMessage* message; GHashTable* group_queues; /* group name -> GQueue */ }; typedef enum _InfTestTrafficReplayError { INF_TEST_TRAFFIC_REPLAY_ERROR_INVALID_LINE, INF_TEST_TRAFFIC_REPLAY_ERROR_UNEXPECTED_EOF } InfTestTrafficReplayError; static GQuark inf_test_traffic_replay_error_quark() { return g_quark_from_static_string("INF_TEST_TRAFFIC_REPLAY_ERROR"); } static void inf_test_traffic_replay_received_cb(InfXmppConnection* connection, xmlNodePtr xml, gpointer user_data); static void inf_test_traffic_replay_notify_status_cb(GObject* object, GParamSpec* pspec, gpointer user_data); static void inf_test_traffic_replay_queue_free(GQueue* queue) { g_queue_free_full(queue, (GDestroyNotify)xmlFreeDoc); } static void inf_test_traffic_replay_message_free(InfTestTrafficReplayMessage* message) { if(message->type == INF_TEST_TRAFFIC_REPLAY_MESSAGE_INCOMING || message->type == INF_TEST_TRAFFIC_REPLAY_MESSAGE_OUTGOING) { if(message->xml != NULL) xmlFreeNode(message->xml); } g_slice_free(InfTestTrafficReplayMessage, message); } static char* inf_test_traffic_replay_get_next_line(InfTestTrafficReplayConnection* conn, size_t* len, GError** error) { char* line; size_t n; ssize_t len_; int err; line = NULL; n = 0; len_ = getline(&line, &n, conn->file); if(len_ >= 0) { *len = len_; return line; } else { if(feof(conn->file)) { /* TODO: We should treat this is a "log closed" event */ g_set_error( error, inf_test_traffic_replay_error_quark(), INF_TEST_TRAFFIC_REPLAY_ERROR_UNEXPECTED_EOF, "Unexpected end of file" ); } else { err = ferror(conn->file); g_set_error_literal( error, G_FILE_ERROR, g_file_error_from_errno(err), strerror(err) ); } return NULL; } } static InfTestTrafficReplayMessage* inf_test_traffic_replay_get_next_message(InfTestTrafficReplayConnection* conn, GError** error) { char* line; size_t len; size_t n; struct tm tm; char* end; gulong msecs; InfTestTrafficReplayMessageType type; xmlDocPtr xml; GString* str; InfTestTrafficReplayMessage* message; line = inf_test_traffic_replay_get_next_line(conn, &len, error); if(!line) return NULL; /* Jump timestamp */ if(line[0] != '[') { g_set_error( error, inf_test_traffic_replay_error_quark(), INF_TEST_TRAFFIC_REPLAY_ERROR_INVALID_LINE, "Line does not start with a timestamp" ); free(line); return FALSE; } /* Parse timestamp */ end = strptime(&line[1], "%a %d %b %Y %I:%M:%S %p %Z", &tm); if(end == NULL || *end != ' ' || *(end+1) != '.') { g_set_error( error, inf_test_traffic_replay_error_quark(), INF_TEST_TRAFFIC_REPLAY_ERROR_INVALID_LINE, "Failed to parse timestamp" ); free(line); return FALSE; } errno = 0; msecs = strtoul(&end[2], &end, 10); if(errno != 0 || *end != ']' || msecs >= 1000000) { g_set_error( error, inf_test_traffic_replay_error_quark(), INF_TEST_TRAFFIC_REPLAY_ERROR_INVALID_LINE, "Failed to parse timestamp" ); free(line); return FALSE; } /* skip ']' */ ++end; /* This seems to be set at random -- for the moment assume there are no * timestamps with different timezones */ tm.tm_isdst = 1; /* interpret message */ n = (end - line) + 1; if(line[n] == '!') { if(strstr(line + n + 4, "connected") != NULL) type = INF_TEST_TRAFFIC_REPLAY_MESSAGE_CONNECT; else if(strstr(line + n + 4, "Connection error") != NULL) type = INF_TEST_TRAFFIC_REPLAY_MESSAGE_ERROR; else if(strstr(line + n + 4, "closed") != NULL) type = INF_TEST_TRAFFIC_REPLAY_MESSAGE_DISCONNECT; else { g_set_error( error, inf_test_traffic_replay_error_quark(), INF_TEST_TRAFFIC_REPLAY_ERROR_INVALID_LINE, "Unknown connection event \"%s\"", line + n + 4 ); free(line); return FALSE; } } else if(line[n] == '<') { if(FALSE) /* TODO as_server) */ type = INF_TEST_TRAFFIC_REPLAY_MESSAGE_INCOMING; else type = INF_TEST_TRAFFIC_REPLAY_MESSAGE_OUTGOING; } else if(line[n] == '>') { if(FALSE) /* TODO as_server)*/ type = INF_TEST_TRAFFIC_REPLAY_MESSAGE_OUTGOING; else type = INF_TEST_TRAFFIC_REPLAY_MESSAGE_INCOMING; } else { g_set_error( error, inf_test_traffic_replay_error_quark(), INF_TEST_TRAFFIC_REPLAY_ERROR_INVALID_LINE, "Unknown control character \"%c\" (%d)", line[n], (int)line[n] ); free(line); return FALSE; } if(type == INF_TEST_TRAFFIC_REPLAY_MESSAGE_INCOMING || type == INF_TEST_TRAFFIC_REPLAY_MESSAGE_OUTGOING) { str = g_string_new_len(line + n + 4, len - n - 5); xml = xmlReadDoc(str->str, NULL, "UTF-8", XML_PARSE_NOWARNING | XML_PARSE_NOERROR); while(!xml) { /* It might happen that we could not parse this if there is a newline * character in the XML. * TODO: We should use a SAX parser for this stuff... */ free(line); line = inf_test_traffic_replay_get_next_line(conn, &len, error); if(!line) { g_string_free(str, TRUE); return NULL; } g_string_append_c(str, '\n'); g_string_append_len(str, line, len - 1); xml = xmlReadDoc(str->str, NULL, "UTF-8", XML_PARSE_NOWARNING | XML_PARSE_NOERROR); } g_string_free(str, TRUE); } free(line); message = g_slice_new(InfTestTrafficReplayMessage); message->timestamp = (gint64)mktime(&tm) * 1000000 + msecs; message->type = type; if(type == INF_TEST_TRAFFIC_REPLAY_MESSAGE_INCOMING || type == INF_TEST_TRAFFIC_REPLAY_MESSAGE_OUTGOING) { message->xml = xmlCopyNode(xmlDocGetRootElement(xml), 1); if(type == INF_TEST_TRAFFIC_REPLAY_MESSAGE_INCOMING) message->xml_iter = message->xml->children; xmlFreeDoc(xml); } return message; } static void inf_test_traffic_replay_connection_close(InfTestTrafficReplayConnection* conn) { InfXmlConnectionStatus status; g_signal_handlers_disconnect_by_func( G_OBJECT(conn->xmpp), G_CALLBACK(inf_test_traffic_replay_received_cb), conn ); g_signal_handlers_disconnect_by_func( G_OBJECT(conn->xmpp), G_CALLBACK(inf_test_traffic_replay_notify_status_cb), conn ); if(conn->xmpp != NULL) { g_object_get(G_OBJECT(conn->xmpp), "status", &status, NULL); if(status == INF_XML_CONNECTION_OPEN || status == INF_XML_CONNECTION_OPENING) { inf_xml_connection_close(INF_XML_CONNECTION(conn->xmpp)); } } if(conn->creds != NULL) inf_certificate_credentials_unref(conn->creds); g_object_unref(conn->xmpp); if(conn->file != NULL) fclose(conn->file); g_hash_table_destroy(conn->group_queues); fprintf(stderr, "[%s] Disconnected\n", conn->name); g_free(conn->name); conn->replay->conns = g_slist_remove(conn->replay->conns, conn); if(conn->replay->conns == NULL) inf_standalone_io_loop_quit(conn->replay->io); g_slice_free(InfTestTrafficReplayConnection, conn); } static void inf_test_traffic_replay_connection_check_message( InfTestTrafficReplayConnection* conn, xmlNodePtr xml) { xmlBufferPtr received_buffer; xmlBufferPtr expected_buffer; xmlSaveCtxtPtr ctx; received_buffer = xmlBufferCreate(); expected_buffer = xmlBufferCreate(); /* Remove time field from chat messages, as this is not synchronized */ if(strcmp(conn->message->xml_iter->name, "message") == 0) xmlSetProp(conn->message->xml_iter, "time", NULL); if(strcmp(xml->name, "message") == 0) xmlSetProp(xml, "time", NULL); ctx = xmlSaveToBuffer(expected_buffer, "UTF-8", 0); xmlSaveTree(ctx, conn->message->xml_iter); xmlSaveClose(ctx); ctx = xmlSaveToBuffer(received_buffer, "UTF-8", 0); xmlSaveTree(ctx, xml); xmlSaveClose(ctx); if(strcmp(xmlBufferContent(expected_buffer), xmlBufferContent(received_buffer)) != 0) { fprintf( stderr, "[WARNING] [%s] Mismatch between expected and received: " "\n\n\"%s\"\n\nvs.\n\n\"%s\"\n", conn->name, (const gchar*)xmlBufferContent(expected_buffer), (const gchar*)xmlBufferContent(received_buffer) ); xmlBufferFree(expected_buffer); xmlBufferFree(received_buffer); if(inf_standalone_io_loop_running(conn->replay->io)) inf_standalone_io_loop_quit(conn->replay->io); return; } xmlBufferFree(expected_buffer); xmlBufferFree(received_buffer); } static gboolean inf_test_traffic_replay_connection_process_next_message( InfTestTrafficReplayConnection* conn) { InfIpAddress* addr; InfTcpConnection* tcp; GError* error; xmlChar* group; GQueue* queue; switch(conn->message->type) { case INF_TEST_TRAFFIC_REPLAY_MESSAGE_CONNECT: /* If we are already connecting, just wait until the connection has * finished. This can happen when we are connecting, and then another * connection receives something, after which messages are processed * again. */ if(conn->xmpp != NULL) return FALSE; fprintf(stderr, "[%s] Connecting...\n", conn->name); addr = inf_ip_address_new_loopback4(); tcp = inf_tcp_connection_new( INF_IO(conn->replay->io), addr, conn->replay->port ); inf_ip_address_free(addr); conn->xmpp = inf_xmpp_connection_new( tcp, INF_XMPP_CONNECTION_CLIENT, NULL, "localhost", INF_XMPP_CONNECTION_SECURITY_ONLY_TLS, conn->creds, NULL, NULL ); g_signal_connect( G_OBJECT(conn->xmpp), "received", G_CALLBACK(inf_test_traffic_replay_received_cb), conn ); g_signal_connect( G_OBJECT(conn->xmpp), "notify::status", G_CALLBACK(inf_test_traffic_replay_notify_status_cb), conn ); error = NULL; if(!inf_tcp_connection_open(tcp, &error)) { fprintf(stderr, "[ERROR] [%s] %s\n", conn->name, error->message); g_error_free(error); if(inf_standalone_io_loop_running(conn->replay->io)) inf_standalone_io_loop_quit(conn->replay->io); return FALSE; } g_object_unref(tcp); /* return false, to wait until the connection was established */ return FALSE; case INF_TEST_TRAFFIC_REPLAY_MESSAGE_DISCONNECT: g_assert(conn->xmpp != NULL); inf_test_traffic_replay_connection_close(conn); return TRUE; case INF_TEST_TRAFFIC_REPLAY_MESSAGE_ERROR: g_assert(conn->xmpp != NULL); fprintf(stderr, "[%s] Recorded connection error, ignored\n", conn->name); return TRUE; case INF_TEST_TRAFFIC_REPLAY_MESSAGE_INCOMING: g_assert(conn->xmpp != NULL); group = xmlGetProp(conn->message->xml, "name"); fprintf(stderr, "[%s] Expecting data (%s, %s)\n", conn->name, group, conn->message->xml_iter->name); /* TODO: write what data? */ queue = g_hash_table_lookup(conn->group_queues, group); xmlFree(group); /* Queued data should have been processed before this function was called */ g_assert(queue == NULL || g_queue_is_empty(queue)); /* wait for data to arrive */ return FALSE; case INF_TEST_TRAFFIC_REPLAY_MESSAGE_OUTGOING: g_assert(conn->xmpp != NULL); group = xmlGetProp(conn->message->xml, "name"); fprintf(stderr, "[%s] Sending data (%s, %s)\n", conn->name, group, conn->message->xml->children->name); /* TODO: write what data? */ xmlFree(group); /* send the data */ inf_xml_connection_send( INF_XML_CONNECTION(conn->xmpp), conn->message->xml ); conn->message->xml = NULL; return TRUE; default: g_assert_not_reached(); break; } } static void inf_test_traffic_replay_process_next_message(InfTestTrafficReplay* replay); static void inf_test_traffic_replay_connection_fetch_next_message( InfTestTrafficReplayConnection* conn) { xmlChar* group; GQueue* queue; xmlNodePtr xml; if(!inf_standalone_io_loop_running(conn->replay->io)) return; if(conn->message->type == INF_TEST_TRAFFIC_REPLAY_MESSAGE_INCOMING && conn->message->xml_iter->next != NULL) { conn->message->xml_iter = conn->message->xml_iter->next; } else { GError* error; inf_test_traffic_replay_message_free(conn->message); /* Fetch the next message for this connection */ error = NULL; conn->message = inf_test_traffic_replay_get_next_message(conn, &error); if(error != NULL) { fprintf( stderr, "[ERROR] [%s] Failed to fetch message: %s\n", conn->name, error->message ); g_error_free(error); if(inf_standalone_io_loop_running(conn->replay->io)) inf_standalone_io_loop_quit(conn->replay->io); return; } } /* Check queued received messages -- these should be delivered immediately, * and not when the timestamp expires; since they have been * received already. */ if(conn->message->type == INF_TEST_TRAFFIC_REPLAY_MESSAGE_INCOMING) { group = xmlGetProp(conn->message->xml, "name"); queue = g_hash_table_lookup(conn->group_queues, group); if(queue != NULL && !g_queue_is_empty(queue)) { xml = g_queue_pop_head(queue); fprintf(stderr, "[%s] Replay data (%s, %s)\n", conn->name, group, xml->name); inf_test_traffic_replay_connection_check_message(conn, xml); inf_test_traffic_replay_connection_fetch_next_message(conn); xmlFree(group); return; } xmlFree(group); } /* Then, evaluate next message among all connections */ inf_test_traffic_replay_process_next_message(conn->replay); } static void inf_test_traffic_replay_process_next_message(InfTestTrafficReplay* replay) { /* Find the connection with the next event, and process it */ GSList* item; InfTestTrafficReplayConnection* conn; InfTestTrafficReplayConnection* low; if(!inf_standalone_io_loop_running(replay->io)) return; low = NULL; for(item = replay->conns; item != NULL; item = item->next) { conn = (InfTestTrafficReplayConnection*)item->data; if(low == NULL || conn->message->timestamp < low->message->timestamp) low = conn; else if(conn->message->timestamp == low->message->timestamp) { /* If there are two messages with the same timestamp, then make sure we * first send data before we wait for data. */ if(conn->message->type == INF_TEST_TRAFFIC_REPLAY_MESSAGE_OUTGOING && low->message->type == INF_TEST_TRAFFIC_REPLAY_MESSAGE_INCOMING) { low = conn; } } } if(inf_test_traffic_replay_connection_process_next_message(low)) { if(g_slist_find(replay->conns, low)) inf_test_traffic_replay_connection_fetch_next_message(low); else inf_test_traffic_replay_process_next_message(replay); } } static void inf_test_traffic_replay_received_cb(InfXmppConnection* connection, xmlNodePtr xml, gpointer user_data) { InfTestTrafficReplayConnection* conn; xmlBufferPtr buffer; xmlSaveCtxtPtr ctx; xmlNodePtr child; GQueue* queue; xmlChar* received_group; xmlChar* expected_group; conn = (InfTestTrafficReplayConnection*)user_data; g_assert(strcmp(xml->name, "group") == 0); for(child = xml->children; child != NULL; child = child->next) { if(!inf_standalone_io_loop_running(conn->replay->io)) break; if(!conn->message || conn->message->type != INF_TEST_TRAFFIC_REPLAY_MESSAGE_INCOMING) { buffer = xmlBufferCreate(); ctx = xmlSaveToBuffer(buffer, "UTF-8", 0); xmlSaveTree(ctx, child); xmlSaveClose(ctx); fprintf( stderr, "[ERROR] [%s] Received text \"%s\" without expecting any\n", conn->name, (const gchar*)xmlBufferContent(buffer) ); xmlBufferFree(buffer); inf_standalone_io_loop_quit(conn->replay->io); return; } received_group = xmlGetProp(xml, "name"); expected_group = xmlGetProp(conn->message->xml, "name"); fprintf( stderr, "[%s] Received data (%s, %s), expected %s\n", conn->name, received_group, child->name, expected_group ); /* TODO: Figure out why this assertion fires */ queue = g_hash_table_lookup(conn->group_queues, expected_group); g_assert(queue == NULL || g_queue_is_empty(queue)); if(strcmp(received_group, expected_group) != 0) { /* We received a message for a different group than what we expected. Cache * the message for later, in case the server schedules message delivery * differently. */ queue = g_hash_table_lookup(conn->group_queues, received_group); if(!queue) { queue = g_queue_new(); g_hash_table_insert( conn->group_queues, g_strdup(received_group), queue ); } g_queue_push_tail(queue, xmlCopyNode(child, 1)); xmlFree(received_group); xmlFree(expected_group); } else { /* We received a message for the expected group; so check whether it is * also the message that we expected. */ xmlFree(received_group); xmlFree(expected_group); inf_test_traffic_replay_connection_check_message(conn, child); inf_test_traffic_replay_connection_fetch_next_message(conn); } } } static void inf_test_traffic_replay_notify_status_cb(GObject* object, GParamSpec* pspec, gpointer user_data) { InfTestTrafficReplayConnection* conn; InfXmlConnectionStatus status; conn = (InfTestTrafficReplayConnection*)user_data; g_object_get(object, "status", &status, NULL); switch(status) { case INF_XML_CONNECTION_OPENING: /* wait for it to open */ break; case INF_XML_CONNECTION_OPEN: fprintf(stderr, "[%s] Connected\n", conn->name); inf_test_traffic_replay_connection_fetch_next_message(conn); break; case INF_XML_CONNECTION_CLOSING: case INF_XML_CONNECTION_CLOSED: fprintf(stderr, "[ERROR] [%s] Remote connection closed\n", conn->name); inf_standalone_io_loop_quit(conn->replay->io); /*inf_test_traffic_replay_connection_close(conn);*/ break; } } static void inf_test_traffic_replay_new_connection_cb(InfdXmppServer* server, InfXmppConnection* xmpp, gpointer user_data) { InfTestTrafficReplayConnection* conn; InfTestTrafficReplay* replay; InfXmlConnectionStatus status; GError* error; conn = g_slice_new(InfTestTrafficReplayConnection); replay = (InfTestTrafficReplay*)user_data; conn->name = g_strdup("server"); conn->replay = replay; conn->creds = NULL; conn->xmpp = xmpp; conn->group_queues = g_hash_table_new_full( g_str_hash, g_str_equal, g_free, (GDestroyNotify)inf_test_traffic_replay_queue_free ); error = NULL; conn->message = inf_test_traffic_replay_get_next_message(conn, &error); if(error != NULL) { fprintf( stderr, "Failed to read initial message for %s: %s\n", conn->name, error->message ); inf_test_traffic_replay_connection_close(conn); } replay->conns = g_slist_prepend(replay->conns, conn); g_object_ref(xmpp); g_signal_connect( G_OBJECT(xmpp), "received", G_CALLBACK(inf_test_traffic_replay_received_cb), conn ); g_signal_connect( G_OBJECT(conn->xmpp), "notify::status", G_CALLBACK(inf_test_traffic_replay_notify_status_cb), conn ); conn->file = fopen(replay->filename, "r"); if(!conn->file) { fprintf( stderr, "Failed to open %s: %s\n", replay->filename, strerror(errno) ); inf_test_traffic_replay_connection_close(conn); } else { g_object_get(G_OBJECT(conn->xmpp), "status", &status, NULL); if(status == INF_XML_CONNECTION_OPEN) { /* TODO: Consume first connection message */ inf_test_traffic_replay_connection_fetch_next_message(conn); } } /* TODO: Shut down server after first client connected! */ } static InfCertificateCredentials* inf_test_traffic_replay_load_server_credentials(GError** error) { GPtrArray* array; gnutls_x509_privkey_t key; InfCertificateCredentials* creds; gnutls_certificate_credentials_t gcreds; guint i; /* TODO: Paths should be configurable */ key = inf_cert_util_read_private_key( "/home/armin/kombia/kombia.cert", error ); if(!key) return NULL; array = inf_cert_util_read_certificate( "/home/armin/kombia/kombia.cert", NULL, error ); if(!array) return NULL; creds = inf_certificate_credentials_new(); gcreds = inf_certificate_credentials_get(creds); gnutls_certificate_set_x509_key( gcreds, (gnutls_x509_crt_t*)array->pdata, array->len, key ); gnutls_certificate_set_x509_trust( gcreds, (gnutls_x509_crt_t*)array->pdata, array->len ); gnutls_x509_privkey_deinit(key); for(i = 0; i < array->len; ++i) gnutls_x509_crt_deinit(array->pdata[i]); g_ptr_array_free(array, TRUE); return creds; } static InfCertificateCredentials* inf_test_traffic_replay_load_client_credentials(const gchar* path, GError** error) { gchar* basename; gchar* dirname; gchar* full; GPtrArray* array; gnutls_x509_privkey_t key; InfCertificateCredentials* creds; gnutls_certificate_credentials_t gcreds; guint i; basename = g_path_get_basename(path); dirname = g_path_get_dirname(path); full = g_build_filename(dirname, "certs", basename, NULL); g_free(basename); g_free(dirname); /* TODO: Paths should be configurable */ key = inf_cert_util_read_private_key(full, error); if(!key) { g_free(full); return NULL; } array = inf_cert_util_read_certificate(full, NULL, error); if(!array) { g_free(full); return NULL; } g_free(full); creds = inf_certificate_credentials_new(); gcreds = inf_certificate_credentials_get(creds); gnutls_certificate_set_x509_key( gcreds, (gnutls_x509_crt_t*)array->pdata, array->len, key ); gnutls_certificate_set_x509_trust( gcreds, (gnutls_x509_crt_t*)&array->pdata[array->len - 1], 1 ); gnutls_x509_privkey_deinit(key); for(i = 0; i < array->len; ++i) gnutls_x509_crt_deinit(array->pdata[i]); g_ptr_array_free(array, TRUE); return creds; } static void inf_test_traffic_replay_start_func(gpointer user_data) { inf_test_traffic_replay_process_next_message(user_data); } int main(int argc, char* argv[]) { InfTestTrafficReplay replay; InfdTcpServer* server; InfCertificateCredentials* creds; GError* error; gboolean as_server; guint port; int i; FILE* f; InfTestTrafficReplayConnection* conn; as_server = FALSE; port = 6524; if(argc < 2) { fprintf(stderr, "Usage: %s \n", argv[0]); return -1; } error = NULL; if(!inf_init(&error)) { fprintf(stderr, "%s\n", error->message); g_error_free(error); return -1; } replay.io = inf_standalone_io_new(); replay.port = port; replay.xmpp = NULL; replay.conns = NULL; if(as_server == TRUE) { replay.filename = argv[1]; creds = inf_test_traffic_replay_load_server_credentials(&error); if(!creds) { fprintf(stderr, "%s\n", error->message); g_error_free(error); return -1; } /* Start a server listening on port 6524 */ server = g_object_new( INFD_TYPE_TCP_SERVER, "io", replay.io, "local-address", NULL, "local-port", port, NULL ); replay.xmpp = infd_xmpp_server_new( server, INF_XMPP_CONNECTION_SECURITY_ONLY_TLS, creds, NULL, NULL ); inf_certificate_credentials_unref(creds); g_signal_connect( G_OBJECT(replay.xmpp), "new-connection", G_CALLBACK(inf_test_traffic_replay_new_connection_cb), &replay ); if(!infd_tcp_server_open(server, &error)) { fprintf(stderr, "%s\n", error->message); g_error_free(error); return 1; } g_object_unref(server); } else { replay.filename = NULL; for(i = 1; i < argc; ++i) { f = fopen(argv[i], "r"); if(!f) { fprintf( stderr, "Failed to open %s: %s\n", argv[i], strerror(errno) ); return 1; } conn = g_slice_new(InfTestTrafficReplayConnection); conn->replay = &replay; conn->name = g_strdup_printf("client %d (%s)", i, argv[i]); conn->xmpp = NULL; conn->file = f; conn->group_queues = g_hash_table_new_full( g_str_hash, g_str_equal, g_free, (GDestroyNotify)inf_test_traffic_replay_queue_free ); conn->creds = inf_test_traffic_replay_load_client_credentials(argv[i], &error); if(error != NULL) { if(error->domain == G_FILE_ERROR && error->code == G_FILE_ERROR_NOENT) { printf("No client credentials for %s\n", conn->name); /* no credentials, that's okay */ g_error_free(error); error = NULL; } else { fprintf( stderr, "Failed to load client credentials for %s: %s\n", conn->name, error->message ); return 1; } } else { printf("Loaded client credentials for %s\n", conn->name); } replay.conns = g_slist_prepend(replay.conns, conn); conn->message = inf_test_traffic_replay_get_next_message(conn, &error); if(error != NULL) { fprintf( stderr, "Failed to read initial message for %s: %s\n", conn->name, error->message ); return 1; } } inf_io_add_dispatch( INF_IO(replay.io), inf_test_traffic_replay_start_func, &replay, NULL ); } inf_standalone_io_loop(replay.io); /* TODO: cleanup... */ return 0; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/test/PaxHeaders.26529/inf-test-state-vector.c0000644000000000000000000000013213034342512021072 xustar0030 mtime=1483851082.053718557 30 atime=1483851082.053718557 30 ctime=1488261589.728137474 libinfinity-0.7.1/test/inf-test-state-vector.c0000644000175000017500000001111013034342512021616 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include #include static void cmp(const char* should_be, InfAdoptedStateVector* vec) { char* is; InfAdoptedStateVector* should_be_vec; is = inf_adopted_state_vector_to_string(vec); if (strcmp(should_be, is) != 0) { printf("should be: %s\n" "is: %s\n" "strcmp failed\n", should_be, is); g_assert_not_reached(); } should_be_vec = inf_adopted_state_vector_from_string(should_be, NULL); if (!should_be_vec || inf_adopted_state_vector_compare(vec, should_be_vec) != 0 || inf_adopted_state_vector_compare(should_be_vec, vec) != 0) { printf("should be: %s\n" "is: %s\n" "compare failed\n", should_be, is); g_assert_not_reached(); } g_free(is); inf_adopted_state_vector_free(should_be_vec); printf("ok!\n"); } #define apply(op, args) inf_adopted_state_vector_##op args static void l_test() { InfAdoptedStateVector* vec, * vec_; int i; char* str; vec = inf_adopted_state_vector_new(); apply(set, (vec, 10, 14)); cmp("10:14", vec); apply(set, (vec, 4, 5)); cmp("4:5;10:14", vec); apply(set, (vec, 4, 8)); cmp("4:8;10:14", vec); for (i = 0; i < 10; ++i) apply(set, (vec, i, i*10)); cmp("1:10;2:20;3:30;4:40;5:50;6:60;7:70;8:80;9:90;10:14", vec); apply(free, (vec)); vec = apply(from_string, ("1:10;2:5", NULL)); vec_ = apply(from_string, ("1:10;2:10;4:10", NULL)); g_assert(apply(causally_before, (vec, vec))); g_assert(apply(causally_before, (vec, vec_))); g_assert(apply(causally_before, (vec_, vec_))); apply(free, (vec)); apply(free, (vec_)); vec = apply(from_string, ("1:10;2:15", NULL)); vec_ = apply(from_string, ("1:10;2:10;4:10", NULL)); g_assert(!apply(causally_before, (vec, vec_))); g_assert( apply(causally_before, (vec, vec))); apply(free, (vec)); vec = apply(from_string, ("1:10;3:15", NULL)); g_assert(!apply(causally_before, (vec, vec_))); g_assert( apply(causally_before, (vec, vec))); apply(free, (vec_)); apply(free, (vec)); vec = apply(from_string, ("1:10", NULL)); vec_ = apply(from_string, ("1:7", NULL)); str = apply(to_string_diff, (vec, vec_)); g_assert(strcmp("1:3", str) == 0); apply(free, (vec_)); vec_ = apply(from_string_diff, (str, vec, NULL)); g_free(str); g_assert(vec_ != NULL); cmp("1:13", vec_); apply(free, (vec_)); for (i = 0; i < 100; ++i) { apply(set, (vec, rand(), i)); } str = apply(to_string, (vec)); /* printf("%s\n", str); */ g_free(str); apply(free, (vec)); vec = apply(from_string, ("1:0;5:0", NULL)); vec_ = apply(new, ()); g_assert(apply(compare, (vec, vec_)) == 0); apply(free, (vec)); apply(free, (vec_)); } int main(int argc, char* argv[]) { guint users[2]; InfAdoptedStateVector* vec; InfAdoptedStateVector* vec2; users[0] = 1; users[1] = 2; /* Note we do not need to allocate users since the state vector does not * touch them. */ vec = inf_adopted_state_vector_new(); vec2 = inf_adopted_state_vector_new(); g_assert(inf_adopted_state_vector_causally_before_inc(vec, vec2, 1) == FALSE); inf_adopted_state_vector_free(vec2); inf_adopted_state_vector_set(vec, users[0], 2); g_assert(inf_adopted_state_vector_get(vec, users[0]) == 2); inf_adopted_state_vector_add(vec, users[0], 4); g_assert(inf_adopted_state_vector_get(vec, users[0]) == 6); inf_adopted_state_vector_add(vec, users[1], 3); g_assert(inf_adopted_state_vector_get(vec, users[1]) == 3); inf_adopted_state_vector_set(vec, users[1], 5); g_assert(inf_adopted_state_vector_get(vec, users[1]) == 5); inf_adopted_state_vector_free(vec); l_test(); return 0; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/test/PaxHeaders.26529/inf-test-reduce-replay.c0000644000000000000000000000013213034342512021213 xustar0030 mtime=1483851082.053718557 30 atime=1483851082.053718557 30 ctime=1488261589.724137482 libinfinity-0.7.1/test/inf-test-reduce-replay.c0000644000175000017500000004554713034342512021764 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /* Cuts away front and back of a replay, so that it still fails. It's very * primitive, and more sophisticated methods can still be implemented. */ /* TODO: Break as soon as either (stderr) output or exit status changes */ #include "util/inf-test-util.h" #include #include #include #include #include #include #include #ifndef G_OS_WIN32 # include #endif #include static const gchar REPLAY[] = ".libs/inf-test-text-replay"; typedef struct _InfTestReduceReplayValidateUserData InfTestReduceReplayValidateUserData; struct _InfTestReduceReplayValidateUserData { guint undo_cur; guint undo_max; InfAdoptedStateVector* time; }; static InfTestReduceReplayValidateUserData* inf_test_reduce_replay_validate_user_data_new(const gchar* time_string, GError** error) { InfTestReduceReplayValidateUserData* data; InfAdoptedStateVector* time; time = inf_adopted_state_vector_from_string(time_string, error); if(time == NULL) return NULL; data = g_slice_new(InfTestReduceReplayValidateUserData); data->undo_cur = 0; data->undo_max = 0; data->time = time; return data; } static void inf_test_reduce_replay_valiadate_user_data_free( InfTestReduceReplayValidateUserData* data) { inf_adopted_state_vector_free(data->time); g_slice_free(InfTestReduceReplayValidateUserData, data); } static InfTestReduceReplayValidateUserData* inf_test_reduce_replay_add_validate_user_from_xml(GHashTable* table, InfAdoptedStateVector* time, xmlNodePtr xml, GError** error) { InfTestReduceReplayValidateUserData* data; xmlChar* time_str; guint user_id; /* The XML node can either be a or a element */ if(!inf_xml_util_get_attribute_uint_required(xml, "id", &user_id, error)) return NULL; time_str = inf_xml_util_get_attribute_required(xml, "time", error); if(time_str == NULL) return NULL; data = inf_test_reduce_replay_validate_user_data_new( (const char*)time_str, error ); xmlFree(time_str); if(data == NULL) return NULL; if(time != NULL) { inf_adopted_state_vector_set( time, user_id, inf_adopted_state_vector_get(data->time, user_id) ); } g_hash_table_insert(table, GUINT_TO_POINTER(user_id), data); return data; } static InfSession* inf_test_reduce_replay_session_new(InfIo* io, InfCommunicationManager* manager, InfSessionStatus status, InfCommunicationGroup* sync_group, InfXmlConnection* sync_connection, const gchar* path, gpointer user_data) { InfTextDefaultBuffer* buffer; InfTextSession* session; buffer = inf_text_default_buffer_new("UTF-8"); session = inf_text_session_new( manager, INF_TEXT_BUFFER(buffer), io, status, sync_group, sync_connection ); g_object_unref(buffer); return INF_SESSION(session); } /* TODO: This should maybe go to inf-test-util */ static const InfcNotePlugin INF_TEST_REDUCE_REPLAY_TEXT_PLUGIN = { NULL, "InfText", inf_test_reduce_replay_session_new }; static xmlNodePtr inf_test_reduce_replay_find_node(xmlNodePtr xml, const gchar* name) { xmlNodePtr child; for(child = xml->children; child != NULL; child = child->next) if(child->type == XML_ELEMENT_NODE) if(strcmp((const char*)child->name, name) == 0) return child; return NULL; } static xmlNodePtr inf_test_reduce_replay_next_node(xmlNodePtr xml) { do { xml = xml->next; } while(xml && xml->type != XML_ELEMENT_NODE); return xml; } static xmlNodePtr inf_test_reduce_replay_first_node(xmlNodePtr xml) { while(xml && xml->type != XML_ELEMENT_NODE) xml = xml->next; return xml; } static gboolean inf_test_reduce_replay_validate_test(xmlDocPtr doc, GError** error) { GHashTable* table; xmlNodePtr root; xmlNodePtr cur; xmlNodePtr child; InfTestReduceReplayValidateUserData* data; InfAdoptedStateVector* initial_time; InfAdoptedStateVector* vector; xmlChar* time_str; guint user_id; gboolean result; root = xmlDocGetRootElement(doc); cur = inf_test_reduce_replay_find_node(root, "initial"); g_assert(cur != NULL); table = g_hash_table_new_full( NULL, NULL, NULL, (GDestroyNotify)inf_test_reduce_replay_valiadate_user_data_free ); /* Insert initial users into table */ initial_time = inf_adopted_state_vector_new(); for(child = cur->children; child != NULL; child = inf_test_reduce_replay_next_node(child)) { if(strcmp((const char*)child->name, "sync-user") == 0) { data = inf_test_reduce_replay_add_validate_user_from_xml( table, initial_time, child, error ); if(data == NULL) { inf_adopted_state_vector_free(initial_time); g_hash_table_unref(table); return FALSE; } } } /* Check all requests */ while( (cur = inf_test_reduce_replay_next_node(cur)) != NULL) { if(strcmp((const char*)cur->name, "user") == 0) { data = inf_test_reduce_replay_add_validate_user_from_xml( table, NULL, cur, error ); if(data == NULL) { inf_adopted_state_vector_free(initial_time); g_hash_table_unref(table); return FALSE; } } else if(strcmp((const char*)cur->name, "request") == 0) { child = cur->children; g_assert(child); if(child->type != XML_ELEMENT_NODE) child = inf_test_reduce_replay_next_node(child); result = inf_xml_util_get_attribute_uint_required( cur, "user", &user_id, error ); if(result == FALSE) { inf_adopted_state_vector_free(initial_time); g_hash_table_unref(table); return FALSE; } data = g_hash_table_lookup(table, GUINT_TO_POINTER(user_id)); g_assert(data != NULL); /* Check the vector time */ time_str = inf_xml_util_get_attribute_required(cur, "time", error); if(time_str == NULL) { inf_adopted_state_vector_free(initial_time); g_hash_table_unref(table); return FALSE; } vector = inf_adopted_state_vector_from_string_diff( (const char*)time_str, data->time, error ); xmlFree(time_str); if(vector == NULL) { inf_adopted_state_vector_free(initial_time); g_hash_table_unref(table); return FALSE; } if(!inf_adopted_state_vector_causally_before(initial_time, vector)) { g_set_error( error, g_quark_from_static_string("INF_TEST_REDUCE_REPLAY_ERROR"), 0, "Concurrent request at line %d", cur->line ); inf_adopted_state_vector_free(vector); inf_adopted_state_vector_free(initial_time); g_hash_table_unref(table); return FALSE; } inf_adopted_state_vector_add(vector, user_id, 1); inf_adopted_state_vector_free(data->time); data->time = vector; /* Check undo/redo counts */ if(strcmp((const char*)child->name, "move") != 0 && strcmp((const char*)child->name, "no-op") != 0) { if(strcmp((const char*)child->name, "undo") == 0 || strcmp((const char*)child->name, "undo-caret") == 0) { if(data->undo_cur == 0) { g_set_error( error, g_quark_from_static_string("INF_TEST_REDUCE_REPLAY_ERROR"), 1, "Dangling undo request at line %d", child->line ); inf_adopted_state_vector_free(initial_time); g_hash_table_unref(table); return FALSE; } --data->undo_cur; } else if(strcmp((const char*)child->name, "redo") == 0 || strcmp((const char*)child->name, "redo-caret") == 0) { if(data->undo_cur == data->undo_max) { g_set_error( error, g_quark_from_static_string("INF_TEST_REDUCE_REPLAY_ERROR"), 2, "Dangling redo request at line %d", child->line ); inf_adopted_state_vector_free(initial_time); g_hash_table_unref(table); return FALSE; } ++data->undo_cur; } else { data->undo_max = data->undo_cur + 1; data->undo_cur = data->undo_max; } } } } inf_adopted_state_vector_free(initial_time); g_hash_table_unref(table); return TRUE; } static gboolean inf_test_reduce_replay_run_test(xmlDocPtr doc) { GError* error; gchar* cmd; gchar* stdout_buf; gchar* stderr_buf; int ret; xmlSaveFile("test.xml", doc); /*cmd = g_strdup_printf("(%s %s 2>&1) > /dev/null", REPLAY, "test.xml");*/ cmd = g_strdup_printf("%s %s", REPLAY, "test.xml"); /* make it die on algorithm errors */ g_setenv("G_DEBUG", "fatal-warnings", TRUE); error = NULL; if(!g_spawn_command_line_sync(cmd, &stdout_buf, &stderr_buf, &ret, &error)) { g_unlink("test.xml"); g_free(cmd); fprintf(stderr, "Failed to run test: %s\n", error->message); g_error_free(error); return FALSE; } /* Reset, so that we don't die ourselves */ g_setenv("G_DEBUG", "", TRUE); /* These are just dummy variables to suppress the console output */ g_free(stdout_buf); g_free(stderr_buf); /*g_unlink("test.xml");*/ #ifndef G_OS_WIN32 if(WIFSIGNALED(ret) && (WTERMSIG(ret) == SIGABRT || WTERMSIG(ret) == SIGSEGV || WTERMSIG(ret) == SIGTRAP)) { return FALSE; } else if(WIFEXITED(ret)) { if(WEXITSTATUS(ret)) return FALSE; else return TRUE; } else #endif { /* what happen? */ g_assert_not_reached(); } } static void inf_test_reduce_replay_remove_sync_requests(xmlNodePtr initial) { xmlNodePtr child; xmlNodePtr next; xmlNodePtr prev; xmlNodePtr sync_begin; guint count; count = 0; for(child = inf_test_reduce_replay_first_node(initial->children); child != NULL; child = next) { next = inf_test_reduce_replay_next_node(child); if(strcmp((const char*)child->name, "sync-request") == 0) { while(child != next) { prev = child; child = child->next; xmlUnlinkNode(prev); xmlFreeNode(prev); } } else { if(strcmp((const char*)child->name, "sync-begin") == 0) sync_begin = child; else if(strcmp((const char*)child->name, "sync-end") != 0) ++count; } } g_assert(sync_begin != NULL); inf_xml_util_set_attribute_uint(sync_begin, "num-messages", count); } static gboolean inf_test_reduce_replay_reduce(xmlDocPtr doc, const char* filename, guint skip) { InfAdoptedSessionReplay* local_replay; InfAdoptedSession* session; InfSessionClass* session_class; xmlDocPtr last_fail; xmlDocPtr back_doc; gboolean result; xmlNodePtr root; xmlNodePtr initial; xmlNodePtr next; xmlNodePtr request; xmlNodePtr sync_begin; GError* error; guint i; error = NULL; root = xmlDocGetRootElement(doc); if(inf_test_reduce_replay_run_test(doc) == TRUE) { fprintf(stderr, "Test does not initially fail\n"); return FALSE; } if(!inf_test_reduce_replay_validate_test(doc, &error)) { fprintf(stderr, "Test does not initially validate: %s\n", error->message); g_error_free(error); return FALSE; } initial = inf_test_reduce_replay_find_node(root, "initial"); if(!initial) { fprintf(stderr, "Test has no initial\n"); return FALSE; } /* Remove all sync-requests. We require test to work without for now. */ inf_test_reduce_replay_remove_sync_requests(initial); root = xmlDocGetRootElement(doc); if(inf_test_reduce_replay_run_test(doc) == TRUE) { fprintf(stderr, "Test does not fail without sync-requests anymore\n"); return FALSE; } /* Initialize local replay */ error = NULL; local_replay = inf_adopted_session_replay_new(); inf_adopted_session_replay_set_record( local_replay, filename, &INF_TEST_REDUCE_REPLAY_TEXT_PLUGIN, &error ); session = inf_adopted_session_replay_get_session(local_replay); session_class = INF_SESSION_GET_CLASS(session); if(error) { fprintf(stderr, "Creating local replay failed: %s\n", error->message); g_error_free(error); return FALSE; } last_fail = xmlCopyDoc(doc, 1); request = inf_test_reduce_replay_next_node(initial); i = 0; for(;;) { /* Play next request */ if(inf_adopted_session_replay_play_next(local_replay, &error)) { /* The InfAdoptedSessionReply is synchronized with our request * variable, so if we could play another step, request cannot be * NULL at this point. */ g_assert(request != NULL); ++i; fprintf(stderr, "%.6u... ", i); fflush(stderr); if(strcmp((const char*)request->name, "request") != 0 && strcmp((const char*)request->name, "user") != 0) { fprintf(stderr, "NOREQ <%s>\n", request->name); request = inf_test_reduce_replay_next_node(request); } else { fprintf(stderr, "REQ %8s ", request->name); fflush(stderr); /* Get rid of next request, and see if test still fails */ do { next = request->next; xmlUnlinkNode(request); xmlFreeNode(request); request = next; } while(next && next->type != XML_ELEMENT_NODE); /* Rewrite initial */ xmlFreeNodeList(initial->children); initial->children = NULL; sync_begin = xmlNewChild(initial, NULL, (const xmlChar*)"sync-begin", NULL); session_class->to_xml_sync(INF_SESSION(session), initial); xmlNewChild(initial, NULL, (const xmlChar*)"sync-end", NULL); /* this sets num-messages: */ inf_test_reduce_replay_remove_sync_requests(initial); if(inf_test_reduce_replay_validate_test(doc, &error)) { if(i % skip != 0) { /* Simply continue */ fprintf(stderr, "SKIP\n"); } else if(inf_test_reduce_replay_run_test(doc)) { fprintf(stderr, "OK!\n"); result = TRUE; break; } else { fprintf(stderr, "FAIL\n"); xmlFreeDoc(last_fail); last_fail = xmlCopyDoc(doc, 1); } } else { /* Continue when test is invalid; we probably removed an undo's * associated request, so just wait until we remove the undo request * itself. */ fprintf(stderr, "INVALID %s\n", error->message); g_error_free(error); error = NULL; } } } else { if(error) { fprintf(stderr, "Playing local replay failed: %s\n", error->message); g_error_free(error); result = FALSE; break; } else { fprintf(stderr, "Played all records and the error still occurs\n"); result = FALSE; break; } } } g_object_unref(local_replay); if(result) { /* Also reduce from back */ i = 0; back_doc = xmlCopyDoc(last_fail, 1); root = xmlDocGetRootElement(back_doc); initial = inf_test_reduce_replay_find_node(root, "initial"); g_assert(initial); next = initial; do { request = next; next = inf_test_reduce_replay_next_node(request); ++i; } while(next != NULL); for(;;) { g_assert(i > 1); --i; fprintf(stderr, "%.6u... ", i); fflush(stderr); do { next = request; request = request->prev; xmlUnlinkNode(next); xmlFreeNode(next); } while(request && request->type != XML_ELEMENT_NODE); if(inf_test_reduce_replay_validate_test(back_doc, &error)) { if(i % skip != 0) { /* Simply continue */ fprintf(stderr, "SKIP\n"); } else if(inf_test_reduce_replay_run_test(back_doc)) { fprintf(stderr, "OK!\n"); result = TRUE; break; } else { fprintf(stderr, "FAIL\n"); xmlFreeDoc(last_fail); last_fail = xmlCopyDoc(back_doc, 1); } } else { fprintf(stderr, "INVALID %s\n", error->message); g_error_free(error); error = NULL; result = FALSE; break; } } xmlFreeDoc(back_doc); } /* Save last failing record in each case */ xmlSaveFile("last_fail.record.xml", last_fail); printf("Last failing record in last_fail.record.xml\n"); xmlFreeDoc(last_fail); return result; } int main(int argc, char* argv[]) { GError* error = NULL; xmlDocPtr doc; gboolean ret; guint skip; if(!inf_init(&error)) { fprintf(stderr, "%s\n", error->message); return -1; } if(!g_file_test(REPLAY, G_FILE_TEST_IS_EXECUTABLE)) { fprintf(stderr, "Replay tool not available. Run \"make\" first."); return -1; } if(argc < 2) { fprintf(stderr, "Usage: %s []\n", argv[0]); return -1; } doc = xmlReadFile(argv[1], "UTF-8", XML_PARSE_NOERROR | XML_PARSE_NOWARNING); if(!doc || !xmlDocGetRootElement(doc)) { if(doc) xmlFreeDoc(doc); fprintf(stderr, "%s\n", xmlGetLastError()->message); return -1; } skip = 1; if(argc > 2) skip = strtol(argv[2], NULL, 10); ret = inf_test_reduce_replay_reduce(doc, argv[1], skip); xmlFreeDoc(doc); return ret ? 0 : -1; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/test/PaxHeaders.26529/inf-test-daemon.c0000644000000000000000000000013213034342512017715 xustar0030 mtime=1483851082.053718557 30 atime=1483851082.053718557 30 ctime=1488261589.720137491 libinfinity-0.7.1/test/inf-test-daemon.c0000644000175000017500000000704513034342512020455 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include #include #include #ifdef LIBINFINITY_HAVE_AVAHI #include #endif int main(int argc, char* argv[]) { InfStandaloneIo* io; InfdTcpServer* server; InfdXmppServer* xmpp; InfCommunicationManager* manager; InfdServerPool* pool; InfdFilesystemStorage* storage; InfdDirectory* directory; gchar* root_directory; #ifdef LIBINFINITY_HAVE_AVAHI InfDiscoveryAvahi* avahi; InfXmppManager* xmpp_manager; #endif GError* error; error = NULL; if(!inf_init(&error)) { fprintf(stderr, "%s\n", error->message); return 1; } io = inf_standalone_io_new(); server = g_object_new( INFD_TYPE_TCP_SERVER, "io", io, "local-port", inf_protocol_get_default_port(), NULL ); if(infd_tcp_server_open(server, &error) == FALSE) { fprintf(stderr, "Could not open server: %s\n", error->message); g_error_free(error); } else { root_directory = g_build_filename(g_get_home_dir(), ".infinote", NULL); manager = inf_communication_manager_new(); storage = infd_filesystem_storage_new(root_directory); directory = infd_directory_new( INF_IO(io), INFD_STORAGE(storage), manager ); infd_directory_enable_chat(directory, TRUE); g_free(root_directory); g_object_unref(G_OBJECT(storage)); g_object_unref(G_OBJECT(manager)); pool = infd_server_pool_new(directory); g_object_unref(G_OBJECT(directory)); xmpp = infd_xmpp_server_new( server, INF_XMPP_CONNECTION_SECURITY_ONLY_UNSECURED, NULL, NULL, NULL ); g_object_unref(G_OBJECT(server)); infd_server_pool_add_server(pool, INFD_XML_SERVER(xmpp)); #ifdef LIBINFINITY_HAVE_AVAHI xmpp_manager = inf_xmpp_manager_new(); avahi = inf_discovery_avahi_new(INF_IO(io), xmpp_manager, NULL, NULL, NULL); g_object_unref(G_OBJECT(xmpp_manager)); infd_server_pool_add_local_publisher( pool, INFD_XMPP_SERVER(xmpp), INF_LOCAL_PUBLISHER(avahi) ); g_object_unref(G_OBJECT(avahi)); #endif g_object_unref(G_OBJECT(xmpp)); inf_standalone_io_loop(io); g_object_unref(G_OBJECT(pool)); } g_object_unref(G_OBJECT(io)); return 0; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/test/PaxHeaders.26529/inf-test-tcp-server.c0000644000000000000000000000013213034342512020544 xustar0030 mtime=1483851082.053718557 30 atime=1483851082.053718557 30 ctime=1488261589.728137474 libinfinity-0.7.1/test/inf-test-tcp-server.c0000644000175000017500000001206213034342512021277 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include static void conn_notify_status_cb(InfTcpConnection* connection, GParamSpec* spec, gpointer user_data) { InfIpAddress* addr; InfTcpConnectionStatus status; gchar* str; g_object_get( G_OBJECT(connection), "remote-address", &addr, "status", &status, NULL ); str = inf_ip_address_to_string(addr); inf_ip_address_free(addr); if(status == INF_TCP_CONNECTION_CLOSED) printf("Connection close from %s\n", str); g_free(str); } static void conn_error_cb(InfTcpConnection* connection, GError* error, gpointer user_data) { InfIpAddress* addr; gchar* str; g_object_get(G_OBJECT(connection), "remote-address", &addr, NULL); str = inf_ip_address_to_string(addr); inf_ip_address_free(addr); printf("Error from %s: %s\n", str, error->message); g_free(str); g_object_unref(G_OBJECT(connection)); } static void conn_received_cb(InfTcpConnection* connection, gconstpointer data, guint len, gpointer user_data) { InfIpAddress* addr; gchar* str; g_object_get(G_OBJECT(connection), "remote-address", &addr, NULL); str = inf_ip_address_to_string(addr); inf_ip_address_free(addr); printf("Data from %s: %.*s\n", str, (int)len, (const char*)data); g_free(str); } static void new_connection_cb(InfdTcpServer* server, InfTcpConnection* connection, gpointer user_data) { InfIpAddress* addr; gchar* str; g_object_get(G_OBJECT(connection), "remote-address", &addr, NULL); str = inf_ip_address_to_string(addr); inf_ip_address_free(addr); printf("Connection from %s\n", str); g_free(str); g_signal_connect( G_OBJECT(connection), "received", G_CALLBACK(conn_received_cb), NULL ); g_signal_connect( G_OBJECT(connection), "error", G_CALLBACK(conn_error_cb), NULL ); g_signal_connect( G_OBJECT(connection), "notify::status", G_CALLBACK(conn_notify_status_cb), NULL ); g_object_ref(G_OBJECT(connection)); } static void error_cb(InfdTcpServer* server, GError* error, gpointer user_data) { fprintf(stderr, "Error occured: %s\n", error->message); if(inf_standalone_io_loop_running(INF_STANDALONE_IO(user_data))) inf_standalone_io_loop_quit(INF_STANDALONE_IO(user_data)); } static void notify_status_cb(InfdTcpServer* server, GParamSpec* pspec, gpointer user_data) { InfdTcpServerStatus status; InfIpAddress* addr; guint port; gchar* addr_str; g_object_get( G_OBJECT(server), "status", &status, "local-address", &addr, "local-port", &port, NULL ); addr_str = inf_ip_address_to_string(addr); inf_ip_address_free(addr); switch(status) { case INFD_TCP_SERVER_CLOSED: printf("Server closed\n"); break; case INFD_TCP_SERVER_OPEN: printf("Server listening on %s:%u\n", addr_str, port); break; default: g_assert_not_reached(); break; } g_free(addr_str); } int main(int argc, char* argv[]) { InfStandaloneIo* io; InfdTcpServer* server; GError* error; error = NULL; if(!inf_init(&error)) { fprintf(stderr, "%s", error->message); return 1; } io = inf_standalone_io_new(); server = g_object_new( INFD_TYPE_TCP_SERVER, "io", io, "local-port", 5223, NULL ); g_signal_connect( G_OBJECT(server), "error", G_CALLBACK(error_cb), io ); g_signal_connect( G_OBJECT(server), "new-connection", G_CALLBACK(new_connection_cb), io ); g_signal_connect( G_OBJECT(server), "notify::status", G_CALLBACK(notify_status_cb), io ); if(infd_tcp_server_open(server, &error) == FALSE) { fprintf(stderr, "Could not open server: %s\n", error->message); g_error_free(error); } else { inf_standalone_io_loop(io); } g_object_unref(G_OBJECT(io)); g_object_unref(G_OBJECT(server)); return 0; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/test/PaxHeaders.26529/inf-test-text-fixline.c0000644000000000000000000000013213034342512021072 xustar0030 mtime=1483851082.053718557 30 atime=1483851082.053718557 30 ctime=1488261589.732137464 libinfinity-0.7.1/test/inf-test-text-fixline.c0000644000175000017500000002152313034342512021627 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include #include #include typedef enum _InfTestTextFixlineTarget { TG_BASE, TG_BUF } InfTestTextFixlineTarget; typedef enum _InfTestTextFixlineOperation { OP_NONE, OP_INS, OP_DEL } InfTestTextFixlineOperation; typedef struct _InfTestTextFixlineTest { const gchar* initial_buffer; const gchar* initial_base; guint n_lines; InfTestTextFixlineOperation operation; InfTestTextFixlineTarget target; guint pos; gchar* text; const gchar* final_buffer; const gchar* final_base; } InfTestTextFixlineTest; #define MKNOOP OP_NONE,TG_BUF,0,NULL #define MKBASEINOP(pos,text) OP_INS,TG_BASE,pos,text #define MKBASEDLOP(pos,len) OP_DEL,TG_BASE,pos,GUINT_TO_POINTER(len) #define MKBUFINOP(pos,text) OP_INS,TG_BUF,pos,text #define MKBUFDLOP(pos,len) OP_DEL,TG_BUF,pos,GUINT_TO_POINTER(len) static gboolean check_buffer(InfTextBuffer* buffer, const gchar* check_text, const gchar* buffer_name) { InfTextChunk* chunk; gpointer text; gsize len; gboolean result; chunk = inf_text_buffer_get_slice( buffer, 0, inf_text_buffer_get_length(buffer) ); text = inf_text_chunk_get_text(chunk, &len); inf_text_chunk_free(chunk); if(strlen(check_text) != len || strncmp(check_text, text, len) != 0) { printf( "%s Buffer has text \"%.*s\" but should have \"%s\"\n", buffer_name, (int)len, (gchar*)text, check_text ); result = FALSE; } else { result = TRUE; } g_free(text); return result; } static gboolean test_fixline(const gchar* initial_buffer_content, const gchar* initial_base_content, guint n_lines, InfTestTextFixlineOperation operation, InfTestTextFixlineTarget target, guint pos, gchar* text, const gchar* final_buffer_content, const gchar* final_base_content) { InfStandaloneIo* io; InfTextBuffer* base; InfTextBuffer* buffer; /* Create the initial state */ io = inf_standalone_io_new(); base = INF_TEXT_BUFFER(inf_text_default_buffer_new("UTF-8")); inf_text_buffer_insert_text( base, 0, initial_buffer_content, strlen(initial_buffer_content), strlen(initial_buffer_content), 0 ); buffer = INF_TEXT_BUFFER( inf_text_fixline_buffer_new(INF_IO(io), base, n_lines) ); /* Check the initial state */ if(!check_buffer(base, initial_base_content, "Initial base")) { g_object_unref(io); g_object_unref(base); g_object_unref(buffer); return FALSE; } if(!check_buffer(buffer, initial_buffer_content, "Initial buf")) { g_object_unref(io); g_object_unref(base); g_object_unref(buffer); return FALSE; } /* Apply the operation */ switch(operation) { case OP_NONE: break; case OP_INS: if(target == TG_BASE) { inf_text_buffer_insert_text( base, pos, text, strlen(text), strlen(text), 0 ); } else if(target == TG_BUF) { inf_text_buffer_insert_text( buffer, pos, text, strlen(text), strlen(text), 0 ); } break; case OP_DEL: if(target == TG_BASE) inf_text_buffer_erase_text(base, pos, GPOINTER_TO_UINT(text), 0); else if(target == TG_BUF) inf_text_buffer_erase_text(buffer, pos, GPOINTER_TO_UINT(text), 0); break; default: g_assert_not_reached(); break; } /* Run any delayed action */ inf_standalone_io_iteration_timeout(io, 0); /* Check the final state */ if(!check_buffer(base, final_base_content, "Final base")) { g_object_unref(io); g_object_unref(base); g_object_unref(buffer); return FALSE; } if(!check_buffer(buffer, final_buffer_content, "Final buf")) { g_object_unref(io); g_object_unref(base); g_object_unref(buffer); return FALSE; } g_object_unref(io); g_object_unref(base); g_object_unref(buffer); return TRUE; } static gboolean test_fixline_struct(const InfTestTextFixlineTest* test) { return test_fixline( test->initial_buffer, test->initial_base, test->n_lines, test->operation, test->target, test->pos, test->text, test->final_buffer, test->final_base ); } int main() { const InfTestTextFixlineTest TESTS[] = { { "", "", 0, MKNOOP, "", "" }, { "", "\n", 1, MKNOOP, "", "\n" }, { "", "\n\n", 2, MKNOOP, "", "\n\n" }, { "\n\n\n\n", "\n\n", 2, MKNOOP, "\n\n\n\n", "\n\n" }, { "", "\n\n", 2, MKBASEINOP(0, "\n"), "", "\n\n" }, { "", "\n\n", 2, MKBASEINOP(1, "\n"), "", "\n\n" }, { "", "\n\n", 2, MKBASEINOP(2, "\n"), "", "\n\n" }, { "", "\n\n", 2, MKBASEINOP(0, "A"), "A", "A\n\n" }, { "", "\n\n", 2, MKBASEINOP(1, "A"), "\nA", "\nA\n\n" }, { "", "\n\n", 2, MKBASEINOP(2, "A"), "\n\nA", "\n\nA\n\n" }, /* 10: */ { "", "\n\n", 2, MKBUFINOP(0, "\n"), "\n", "\n\n" }, { "", "\n\n", 2, MKBUFINOP(0, "\n\n\n"), "\n\n\n", "\n\n" }, { "\n\n\n\n", "\n\n", 2, MKBUFINOP(0, "\n"), "\n\n\n\n\n", "\n\n" }, { "\n\n\n\n", "\n\n", 2, MKBUFINOP(0, "A"), "A\n\n\n\n", "A\n\n" }, { "\n\n\n\n", "\n\n", 2, MKBUFINOP(1, "A"), "\nA\n\n\n", "\nA\n\n" }, { "\n\n\n\n", "\n\n", 2, MKBUFINOP(2, "A"), "\n\nA\n\n", "\n\nA\n\n" }, { "\n\n\n\n", "\n\n", 2, MKBUFINOP(3, "A"), "\n\n\nA\n", "\n\n\nA\n\n" }, { "\n\n\n\n", "\n\n", 2, MKBUFINOP(4, "A"), "\n\n\n\nA", "\n\n\n\nA\n\n" }, { "\n\n\n\n\n", "\n\n", 2, MKBUFINOP(3, "A"), "\n\n\nA\n\n", "\n\n\nA\n\n" }, /* 18: */ { "", "\n\n", 2, MKBASEDLOP(0, 1), "", "\n\n" }, { "", "\n\n", 2, MKBASEDLOP(1, 1), "", "\n\n" }, { "", "\n\n", 2, MKBASEDLOP(0, 2), "", "\n\n" }, { "A", "A\n\n", 2, MKBASEDLOP(0, 1), "", "\n\n" }, { "A", "A\n\n", 2, MKBASEDLOP(1, 1), "A", "A\n\n" }, { "A", "A\n\n", 2, MKBASEDLOP(2, 1), "A", "A\n\n" }, { "A", "A\n\n", 2, MKBASEDLOP(0, 2), "", "\n\n" }, { "A", "A\n\n", 2, MKBASEDLOP(0, 3), "", "\n\n" }, { "\nA", "\nA\n\n", 2, MKBASEDLOP(0, 1), "A", "A\n\n" }, { "\nA", "\nA\n\n", 2, MKBASEDLOP(1, 1), "\n", "\n\n" }, { "\nA\n", "\nA\n\n", 2, MKBASEDLOP(0, 1), "A\n", "A\n\n" }, { "\nA\n", "\nA\n\n", 2, MKBASEDLOP(1, 1), "\n\n", "\n\n" }, { "\nA\n", "\nA\n\n", 2, MKBASEDLOP(2, 1), "\nA\n" /* \nA would be reasonable, too... */, "\nA\n\n" }, { "\nA\n", "\nA\n\n", 2, MKBASEDLOP(3, 1), "\nA\n", "\nA\n\n" }, { "\nA\n", "\nA\n\n", 2, MKBASEDLOP(0, 2), "\n", "\n\n" }, { "\nA\n", "\nA\n\n", 2, MKBASEDLOP(1, 2), "\n", "\n\n" }, { "\nA\n", "\nA\n\n", 2, MKBASEDLOP(2, 2), "\nA\n" /* \nA would be reasonable, too... */, "\nA\n\n" }, { "\nA\n", "\nA\n\n", 2, MKBUFDLOP(0, 1), "A\n", "A\n\n" }, { "\nA\n", "\nA\n\n", 2, MKBUFDLOP(1, 1), "\n\n", "\n\n" }, { "\nA\n", "\nA\n\n", 2, MKBUFDLOP(2, 1), "\nA", "\nA\n\n" }, { "\n\n\n\nA", "\n\n\n\nA\n\n", 2, MKBUFDLOP(0, 1), "\n\n\nA", "\n\n\nA\n\n" }, { "\n\n\n\nA", "\n\n\n\nA\n\n", 2, MKBUFDLOP(0, 2), "\n\nA", "\n\nA\n\n" }, { "\n\n\n\nA", "\n\n\n\nA\n\n", 2, MKBUFDLOP(0, 3), "\nA", "\nA\n\n" }, { "\n\n\n\nA", "\n\n\n\nA\n\n", 2, MKBUFDLOP(0, 4), "A", "A\n\n" }, { "\n\n\n\nA", "\n\n\n\nA\n\n", 2, MKBUFDLOP(0, 5), "", "\n\n" }, { "\n\n\n\nA", "\n\n\n\nA\n\n", 2, MKBUFDLOP(1, 1), "\n\n\nA", "\n\n\nA\n\n" }, { "\n\n\n\nA", "\n\n\n\nA\n\n", 2, MKBUFDLOP(2, 1), "\n\n\nA", "\n\n\nA\n\n" }, { "\n\n\n\nA", "\n\n\n\nA\n\n", 2, MKBUFDLOP(3, 1), "\n\n\nA", "\n\n\nA\n\n" }, { "\n\n\n\nA", "\n\n\n\nA\n\n", 2, MKBUFDLOP(4, 1), "\n\n\n\n", "\n\n" }, { "\n\n\n\nA", "\n\n\n\nA\n\n", 2, MKBUFDLOP(2, 2), "\n\nA", "\n\nA\n\n" }, { "\n\n\n\nA", "\n\n\n\nA\n\n", 2, MKBUFDLOP(2, 3), "\n\n", "\n\n" }, { "\n\n\n\nA", "\n\n\n\nA\n\n", 2, MKBUFDLOP(3, 2), "\n\n\n", "\n\n" }, }; guint i; for(i = 0; i < sizeof(TESTS)/sizeof(TESTS[0]); ++i) { printf("Test %u... ", i); if(!test_fixline_struct(&TESTS[i])) return 1; printf("OK\n"); } return 0; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/test/PaxHeaders.26529/Makefile.in0000644000000000000000000000013213051241010016612 xustar0030 mtime=1487225352.597151258 30 atime=1487225352.597151258 30 ctime=1488261589.708137517 libinfinity-0.7.1/test/Makefile.in0000644000175000017500000020322213051241010017345 0ustar00arminarmin00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 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__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) 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@ TESTS = inf-test-state-vector$(EXEEXT) inf-test-chunk$(EXEEXT) \ inf-test-text-session$(EXEEXT) inf-test-text-cleanup$(EXEEXT) \ inf-test-text-fixline$(EXEEXT) \ inf-test-certificate-validate$(EXEEXT) @WITH_INFGTK_TRUE@am__append_1 = \ @WITH_INFGTK_TRUE@ ${infgtk_CFLAGS} @WITH_INFTEXTGTK_TRUE@am__append_2 = \ @WITH_INFTEXTGTK_TRUE@ ${inftextgtk_CFLAGS} noinst_PROGRAMS = inf-test-tcp-connection$(EXEEXT) \ inf-test-xmpp-connection$(EXEEXT) inf-test-tcp-server$(EXEEXT) \ inf-test-xmpp-server$(EXEEXT) inf-test-daemon$(EXEEXT) \ inf-test-browser$(EXEEXT) \ inf-test-certificate-request$(EXEEXT) \ inf-test-set-acl$(EXEEXT) inf-test-chat$(EXEEXT) \ inf-test-state-vector$(EXEEXT) inf-test-chunk$(EXEEXT) \ inf-test-text-operations$(EXEEXT) \ inf-test-text-session$(EXEEXT) inf-test-text-cleanup$(EXEEXT) \ inf-test-text-recover$(EXEEXT) inf-test-text-replay$(EXEEXT) \ inf-test-reduce-replay$(EXEEXT) inf-test-mass-join$(EXEEXT) \ inf-test-text-fixline$(EXEEXT) \ inf-test-traffic-replay$(EXEEXT) \ inf-test-certificate-validate$(EXEEXT) \ inf-test-text-quick-write$(EXEEXT) $(am__EXEEXT_1) @WITH_INFTEXTGTK_TRUE@am__append_3 = inf-test-gtk-browser subdir = test ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/gtk-doc.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/libinfinity/inf-config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = @WITH_INFTEXTGTK_TRUE@am__EXEEXT_1 = inf-test-gtk-browser$(EXEEXT) PROGRAMS = $(noinst_PROGRAMS) am_inf_test_browser_OBJECTS = inf-test-browser.$(OBJEXT) inf_test_browser_OBJECTS = $(am_inf_test_browser_OBJECTS) am__DEPENDENCIES_1 = inf_test_browser_DEPENDENCIES = ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(am__DEPENDENCIES_1) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = am_inf_test_certificate_request_OBJECTS = \ inf-test-certificate-request.$(OBJEXT) inf_test_certificate_request_OBJECTS = \ $(am_inf_test_certificate_request_OBJECTS) inf_test_certificate_request_DEPENDENCIES = util/libinftestutil.a \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(am__DEPENDENCIES_1) am_inf_test_certificate_validate_OBJECTS = inf_test_certificate_validate-inf-test-certificate-validate.$(OBJEXT) inf_test_certificate_validate_OBJECTS = \ $(am_inf_test_certificate_validate_OBJECTS) inf_test_certificate_validate_DEPENDENCIES = ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(am__DEPENDENCIES_1) inf_test_certificate_validate_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(inf_test_certificate_validate_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ am_inf_test_chat_OBJECTS = inf-test-chat.$(OBJEXT) inf_test_chat_OBJECTS = $(am_inf_test_chat_OBJECTS) inf_test_chat_DEPENDENCIES = ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(am__DEPENDENCIES_1) am_inf_test_chunk_OBJECTS = inf-test-chunk.$(OBJEXT) inf_test_chunk_OBJECTS = $(am_inf_test_chunk_OBJECTS) inf_test_chunk_DEPENDENCIES = ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_inf_test_daemon_OBJECTS = inf-test-daemon.$(OBJEXT) inf_test_daemon_OBJECTS = $(am_inf_test_daemon_OBJECTS) inf_test_daemon_DEPENDENCIES = ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(am__DEPENDENCIES_1) am__inf_test_gtk_browser_SOURCES_DIST = inf-test-gtk-browser.c @WITH_INFTEXTGTK_TRUE@am_inf_test_gtk_browser_OBJECTS = \ @WITH_INFTEXTGTK_TRUE@ inf-test-gtk-browser.$(OBJEXT) inf_test_gtk_browser_OBJECTS = $(am_inf_test_gtk_browser_OBJECTS) @WITH_INFTEXTGTK_TRUE@inf_test_gtk_browser_DEPENDENCIES = ${top_builddir}/libinftextgtk/libinftextgtk-$(LIBINFINITY_API_VERSION).la \ @WITH_INFTEXTGTK_TRUE@ ${top_builddir}/libinfgtk/libinfgtk-$(LIBINFINITY_API_VERSION).la \ @WITH_INFTEXTGTK_TRUE@ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ @WITH_INFTEXTGTK_TRUE@ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ @WITH_INFTEXTGTK_TRUE@ $(am__DEPENDENCIES_1) \ @WITH_INFTEXTGTK_TRUE@ $(am__DEPENDENCIES_1) \ @WITH_INFTEXTGTK_TRUE@ $(am__DEPENDENCIES_1) \ @WITH_INFTEXTGTK_TRUE@ $(am__DEPENDENCIES_1) am_inf_test_mass_join_OBJECTS = inf-test-mass-join.$(OBJEXT) inf_test_mass_join_OBJECTS = $(am_inf_test_mass_join_OBJECTS) inf_test_mass_join_DEPENDENCIES = util/libinftestutil.a \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_inf_test_reduce_replay_OBJECTS = inf-test-reduce-replay.$(OBJEXT) inf_test_reduce_replay_OBJECTS = $(am_inf_test_reduce_replay_OBJECTS) inf_test_reduce_replay_DEPENDENCIES = util/libinftestutil.a \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_inf_test_set_acl_OBJECTS = inf-test-set-acl.$(OBJEXT) inf_test_set_acl_OBJECTS = $(am_inf_test_set_acl_OBJECTS) inf_test_set_acl_DEPENDENCIES = util/libinftestutil.a \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(am__DEPENDENCIES_1) am_inf_test_state_vector_OBJECTS = inf-test-state-vector.$(OBJEXT) inf_test_state_vector_OBJECTS = $(am_inf_test_state_vector_OBJECTS) inf_test_state_vector_DEPENDENCIES = ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(am__DEPENDENCIES_1) am_inf_test_tcp_connection_OBJECTS = \ inf-test-tcp-connection.$(OBJEXT) inf_test_tcp_connection_OBJECTS = \ $(am_inf_test_tcp_connection_OBJECTS) inf_test_tcp_connection_DEPENDENCIES = ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(am__DEPENDENCIES_1) am_inf_test_tcp_server_OBJECTS = inf-test-tcp-server.$(OBJEXT) inf_test_tcp_server_OBJECTS = $(am_inf_test_tcp_server_OBJECTS) inf_test_tcp_server_DEPENDENCIES = ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(am__DEPENDENCIES_1) am_inf_test_text_cleanup_OBJECTS = inf-test-text-cleanup.$(OBJEXT) inf_test_text_cleanup_OBJECTS = $(am_inf_test_text_cleanup_OBJECTS) inf_test_text_cleanup_DEPENDENCIES = util/libinftestutil.a \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_inf_test_text_fixline_OBJECTS = inf-test-text-fixline.$(OBJEXT) inf_test_text_fixline_OBJECTS = $(am_inf_test_text_fixline_OBJECTS) inf_test_text_fixline_DEPENDENCIES = util/libinftestutil.a \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_inf_test_text_operations_OBJECTS = \ inf-test-text-operations.$(OBJEXT) inf_test_text_operations_OBJECTS = \ $(am_inf_test_text_operations_OBJECTS) inf_test_text_operations_DEPENDENCIES = ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_inf_test_text_quick_write_OBJECTS = \ inf-test-text-quick-write.$(OBJEXT) inf_test_text_quick_write_OBJECTS = \ $(am_inf_test_text_quick_write_OBJECTS) inf_test_text_quick_write_DEPENDENCIES = ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_inf_test_text_recover_OBJECTS = inf-test-text-recover.$(OBJEXT) inf_test_text_recover_OBJECTS = $(am_inf_test_text_recover_OBJECTS) inf_test_text_recover_DEPENDENCIES = util/libinftestutil.a \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_inf_test_text_replay_OBJECTS = inf-test-text-replay.$(OBJEXT) inf_test_text_replay_OBJECTS = $(am_inf_test_text_replay_OBJECTS) inf_test_text_replay_DEPENDENCIES = util/libinftestutil.a \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_inf_test_text_session_OBJECTS = inf-test-text-session.$(OBJEXT) inf_test_text_session_OBJECTS = $(am_inf_test_text_session_OBJECTS) inf_test_text_session_DEPENDENCIES = util/libinftestutil.a \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_inf_test_traffic_replay_OBJECTS = \ inf-test-traffic-replay.$(OBJEXT) inf_test_traffic_replay_OBJECTS = \ $(am_inf_test_traffic_replay_OBJECTS) inf_test_traffic_replay_DEPENDENCIES = ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(am__DEPENDENCIES_1) am_inf_test_xmpp_connection_OBJECTS = \ inf-test-xmpp-connection.$(OBJEXT) inf_test_xmpp_connection_OBJECTS = \ $(am_inf_test_xmpp_connection_OBJECTS) inf_test_xmpp_connection_DEPENDENCIES = ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(am__DEPENDENCIES_1) am_inf_test_xmpp_server_OBJECTS = inf-test-xmpp-server.$(OBJEXT) inf_test_xmpp_server_OBJECTS = $(am_inf_test_xmpp_server_OBJECTS) inf_test_xmpp_server_DEPENDENCIES = ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(am__DEPENDENCIES_1) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) -I$(top_builddir)/libinfinity 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_CC_1 = 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_CCLD_1 = SOURCES = $(inf_test_browser_SOURCES) \ $(inf_test_certificate_request_SOURCES) \ $(inf_test_certificate_validate_SOURCES) \ $(inf_test_chat_SOURCES) $(inf_test_chunk_SOURCES) \ $(inf_test_daemon_SOURCES) $(inf_test_gtk_browser_SOURCES) \ $(inf_test_mass_join_SOURCES) \ $(inf_test_reduce_replay_SOURCES) $(inf_test_set_acl_SOURCES) \ $(inf_test_state_vector_SOURCES) \ $(inf_test_tcp_connection_SOURCES) \ $(inf_test_tcp_server_SOURCES) \ $(inf_test_text_cleanup_SOURCES) \ $(inf_test_text_fixline_SOURCES) \ $(inf_test_text_operations_SOURCES) \ $(inf_test_text_quick_write_SOURCES) \ $(inf_test_text_recover_SOURCES) \ $(inf_test_text_replay_SOURCES) \ $(inf_test_text_session_SOURCES) \ $(inf_test_traffic_replay_SOURCES) \ $(inf_test_xmpp_connection_SOURCES) \ $(inf_test_xmpp_server_SOURCES) DIST_SOURCES = $(inf_test_browser_SOURCES) \ $(inf_test_certificate_request_SOURCES) \ $(inf_test_certificate_validate_SOURCES) \ $(inf_test_chat_SOURCES) $(inf_test_chunk_SOURCES) \ $(inf_test_daemon_SOURCES) \ $(am__inf_test_gtk_browser_SOURCES_DIST) \ $(inf_test_mass_join_SOURCES) \ $(inf_test_reduce_replay_SOURCES) $(inf_test_set_acl_SOURCES) \ $(inf_test_state_vector_SOURCES) \ $(inf_test_tcp_connection_SOURCES) \ $(inf_test_tcp_server_SOURCES) \ $(inf_test_text_cleanup_SOURCES) \ $(inf_test_text_fixline_SOURCES) \ $(inf_test_text_operations_SOURCES) \ $(inf_test_text_quick_write_SOURCES) \ $(inf_test_text_recover_SOURCES) \ $(inf_test_text_replay_SOURCES) \ $(inf_test_text_session_SOURCES) \ $(inf_test_traffic_replay_SOURCES) \ $(inf_test_xmpp_connection_SOURCES) \ $(inf_test_xmpp_server_SOURCES) RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ check recheck distdir am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__tty_colors_dummy = \ mgn= red= grn= lgn= blu= brg= std=; \ am__color_tests=no am__tty_colors = { \ $(am__tty_colors_dummy); \ if test "X$(AM_COLOR_TESTS)" = Xno; then \ am__color_tests=no; \ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ am__color_tests=yes; \ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ am__color_tests=yes; \ fi; \ if test $$am__color_tests = yes; then \ red=''; \ grn=''; \ lgn=''; \ blu=''; \ mgn=''; \ brg=''; \ std=''; \ fi; \ } am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__recheck_rx = ^[ ]*:recheck:[ ]* am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* # A command that, given a newline-separated list of test names on the # standard input, print the name of the tests that are to be re-run # upon "make recheck". am__list_recheck_tests = $(AWK) '{ \ recheck = 1; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ { \ if ((getline line2 < ($$0 ".log")) < 0) \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ { \ recheck = 0; \ break; \ } \ else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ { \ break; \ } \ }; \ if (recheck) \ print $$0; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # A command that, given a newline-separated list of test names on the # standard input, create the global log from their .trs and .log files. am__create_global_log = $(AWK) ' \ function fatal(msg) \ { \ print "fatal: making $@: " msg | "cat >&2"; \ exit 1; \ } \ function rst_section(header) \ { \ print header; \ len = length(header); \ for (i = 1; i <= len; i = i + 1) \ printf "="; \ printf "\n\n"; \ } \ { \ copy_in_global_log = 1; \ global_test_result = "RUN"; \ while ((rc = (getline line < ($$0 ".trs"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".trs"); \ if (line ~ /$(am__global_test_result_rx)/) \ { \ sub("$(am__global_test_result_rx)", "", line); \ sub("[ ]*$$", "", line); \ global_test_result = line; \ } \ else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ copy_in_global_log = 0; \ }; \ if (copy_in_global_log) \ { \ rst_section(global_test_result ": " $$0); \ while ((rc = (getline line < ($$0 ".log"))) != 0) \ { \ if (rc < 0) \ fatal("failed to read from " $$0 ".log"); \ print line; \ }; \ printf "\n"; \ }; \ close ($$0 ".trs"); \ close ($$0 ".log"); \ }' # Restructured Text title. am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } # Solaris 10 'make', and several other traditional 'make' implementations, # pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it # by disabling -e (using the XSI extension "set +e") if it's set. am__sh_e_setup = case $$- in *e*) set +e;; esac # Default flags passed to test drivers. am__common_driver_flags = \ --color-tests "$$am__color_tests" \ --enable-hard-errors "$$am__enable_hard_errors" \ --expect-failure "$$am__expect_failure" # To be inserted before the command running the test. Creates the # directory for the log if needed. Stores in $dir the directory # containing $f, in $tst the test, in $log the log. Executes the # developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and # passes TESTS_ENVIRONMENT. Set up options for the wrapper that # will run the test scripts (or their associated LOG_COMPILER, if # thy have one). am__check_pre = \ $(am__sh_e_setup); \ $(am__vpath_adj_setup) $(am__vpath_adj) \ $(am__tty_colors); \ srcdir=$(srcdir); export srcdir; \ case "$@" in \ */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ *) am__odir=.;; \ esac; \ test "x$$am__odir" = x"." || test -d "$$am__odir" \ || $(MKDIR_P) "$$am__odir" || exit $$?; \ if test -f "./$$f"; then dir=./; \ elif test -f "$$f"; then dir=; \ else dir="$(srcdir)/"; fi; \ tst=$$dir$$f; log='$@'; \ if test -n '$(DISABLE_HARD_ERRORS)'; then \ am__enable_hard_errors=no; \ else \ am__enable_hard_errors=yes; \ fi; \ case " $(XFAIL_TESTS) " in \ *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ am__expect_failure=yes;; \ *) \ am__expect_failure=no;; \ esac; \ $(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) # A shell command to get the names of the tests scripts with any registered # extension removed (i.e., equivalently, the names of the test logs, with # the '.log' extension removed). The result is saved in the shell variable # '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, # we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", # since that might cause problem with VPATH rewrites for suffix-less tests. # See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. am__set_TESTS_bases = \ bases='$(TEST_LOGS)'; \ bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ bases=`echo $$bases` RECHECK_LOGS = $(TEST_LOGS) TEST_SUITE_LOG = test-suite.log TEST_EXTENSIONS = @EXEEXT@ .test LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) am__set_b = \ case '$@' in \ */*) \ case '$*' in \ */*) b='$*';; \ *) b=`echo '$@' | sed 's/\.log$$//'`; \ esac;; \ *) \ b='$*';; \ esac am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) TEST_LOGS = $(am__test_logs2:.test.log=.log) TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ $(TEST_LOG_FLAGS) DIST_SUBDIRS = $(SUBDIRS) am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp \ $(top_srcdir)/test-driver README DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ 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@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIRNAME = @DATADIRNAME@ 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@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ GTKDOC_CHECK = @GTKDOC_CHECK@ GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ GTKDOC_MKPDF = @GTKDOC_MKPDF@ GTKDOC_REBASE = @GTKDOC_REBASE@ HTML_DIR = @HTML_DIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INSTOBJEXT = @INSTOBJEXT@ INTLLIBS = @INTLLIBS@ INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBINFINITY_API_VERSION = @LIBINFINITY_API_VERSION@ LIBINFINITY_LIBTOOL_VERSION = @LIBINFINITY_LIBTOOL_VERSION@ LIBINFINITY_VERSION = @LIBINFINITY_VERSION@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGFMT_OPTS = @MSGFMT_OPTS@ 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@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ 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@ avahi_CFLAGS = @avahi_CFLAGS@ avahi_LIBS = @avahi_LIBS@ 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@ gio_CFLAGS = @gio_CFLAGS@ gio_LIBS = @gio_LIBS@ gtk_requirement = @gtk_requirement@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infgtk_CFLAGS = @infgtk_CFLAGS@ infgtk_LIBS = @infgtk_LIBS@ infinity_CFLAGS = @infinity_CFLAGS@ infinity_LIBS = @infinity_LIBS@ infinoted_CFLAGS = @infinoted_CFLAGS@ infinoted_LIBS = @infinoted_LIBS@ infodir = @infodir@ inftext_CFLAGS = @inftext_CFLAGS@ inftext_LIBS = @inftext_LIBS@ inftextgtk_CFLAGS = @inftextgtk_CFLAGS@ inftextgtk_LIBS = @inftextgtk_LIBS@ install_sh = @install_sh@ libdaemon_CFLAGS = @libdaemon_CFLAGS@ libdaemon_LIBS = @libdaemon_LIBS@ 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@ runstatedir = @runstatedir@ 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@ SUBDIRS = util session cleanup certs AM_CPPFLAGS = -I${top_srcdir} ${infinity_CFLAGS} $(am__append_1) \ $(am__append_2) inf_test_tcp_connection_SOURCES = \ inf-test-tcp-connection.c inf_test_tcp_connection_LDADD = \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ ${infinity_LIBS} inf_test_xmpp_connection_SOURCES = \ inf-test-xmpp-connection.c inf_test_xmpp_connection_LDADD = \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ ${infinity_LIBS} inf_test_tcp_server_SOURCES = \ inf-test-tcp-server.c inf_test_tcp_server_LDADD = \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ ${infinity_LIBS} inf_test_xmpp_server_SOURCES = \ inf-test-xmpp-server.c inf_test_xmpp_server_LDADD = \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ ${infinity_LIBS} inf_test_daemon_SOURCES = \ inf-test-daemon.c inf_test_daemon_LDADD = \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ ${infinity_LIBS} inf_test_browser_SOURCES = \ inf-test-browser.c inf_test_browser_LDADD = \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ ${infinity_LIBS} inf_test_certificate_request_SOURCES = \ inf-test-certificate-request.c inf_test_certificate_request_LDADD = \ util/libinftestutil.a \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ ${infinity_LIBS} inf_test_set_acl_SOURCES = \ inf-test-set-acl.c inf_test_set_acl_LDADD = \ util/libinftestutil.a \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ ${infinity_LIBS} inf_test_chat_SOURCES = \ inf-test-chat.c inf_test_chat_LDADD = \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ ${infinity_LIBS} inf_test_state_vector_SOURCES = \ inf-test-state-vector.c inf_test_state_vector_LDADD = \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ ${infinity_LIBS} inf_test_chunk_SOURCES = \ inf-test-chunk.c inf_test_chunk_LDADD = \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ ${inftext_LIBS} ${infinity_LIBS} inf_test_text_operations_SOURCES = \ inf-test-text-operations.c inf_test_text_operations_LDADD = \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ ${inftext_LIBS} ${infinity_LIBS} inf_test_text_session_SOURCES = \ inf-test-text-session.c inf_test_text_session_LDADD = \ util/libinftestutil.a \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ ${inftext_LIBS} ${infinity_LIBS} inf_test_text_cleanup_SOURCES = \ inf-test-text-cleanup.c inf_test_text_cleanup_LDADD = \ util/libinftestutil.a \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ ${inftext_LIBS} ${infinity_LIBS} inf_test_text_replay_SOURCES = \ inf-test-text-replay.c inf_test_text_replay_LDADD = \ util/libinftestutil.a \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ ${inftext_LIBS} ${infinity_LIBS} inf_test_text_recover_SOURCES = \ inf-test-text-recover.c inf_test_text_recover_LDADD = \ util/libinftestutil.a \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ ${inftext_LIBS} ${infinity_LIBS} inf_test_reduce_replay_SOURCES = \ inf-test-reduce-replay.c inf_test_reduce_replay_LDADD = \ util/libinftestutil.a \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ ${inftext_LIBS} ${infinity_LIBS} inf_test_mass_join_SOURCES = \ inf-test-mass-join.c inf_test_mass_join_LDADD = \ util/libinftestutil.a \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ ${inftext_LIBS} ${infinity_LIBS} inf_test_text_fixline_SOURCES = \ inf-test-text-fixline.c inf_test_text_fixline_LDADD = \ util/libinftestutil.a \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ ${inftext_LIBS} ${infinity_LIBS} @WITH_INFTEXTGTK_TRUE@inf_test_gtk_browser_SOURCES = \ @WITH_INFTEXTGTK_TRUE@ inf-test-gtk-browser.c @WITH_INFTEXTGTK_TRUE@inf_test_gtk_browser_LDADD = \ @WITH_INFTEXTGTK_TRUE@ ${top_builddir}/libinftextgtk/libinftextgtk-$(LIBINFINITY_API_VERSION).la \ @WITH_INFTEXTGTK_TRUE@ ${top_builddir}/libinfgtk/libinfgtk-$(LIBINFINITY_API_VERSION).la \ @WITH_INFTEXTGTK_TRUE@ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ @WITH_INFTEXTGTK_TRUE@ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ @WITH_INFTEXTGTK_TRUE@ ${inftextgtk_LIBS} ${infgtk_LIBS} ${inftext_LIBS} ${infinity_LIBS} inf_test_traffic_replay_SOURCES = \ inf-test-traffic-replay.c inf_test_traffic_replay_LDADD = \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ ${infinity_LIBS} inf_test_certificate_validate_SOURCES = \ inf-test-certificate-validate.c inf_test_certificate_validate_CFLAGS = \ -DCERTS_DIR="\"${abs_srcdir}/certs\"" inf_test_certificate_validate_LDADD = \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ ${infinity_LIBS} inf_test_text_quick_write_SOURCES = \ inf-test-text-quick-write.c inf_test_text_quick_write_LDADD = \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ ${inftext_LIBS} ${infinity_LIBS} all: all-recursive .SUFFIXES: .SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(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) --foreign test/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign test/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: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstPROGRAMS: @list='$(noinst_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 inf-test-browser$(EXEEXT): $(inf_test_browser_OBJECTS) $(inf_test_browser_DEPENDENCIES) $(EXTRA_inf_test_browser_DEPENDENCIES) @rm -f inf-test-browser$(EXEEXT) $(AM_V_CCLD)$(LINK) $(inf_test_browser_OBJECTS) $(inf_test_browser_LDADD) $(LIBS) inf-test-certificate-request$(EXEEXT): $(inf_test_certificate_request_OBJECTS) $(inf_test_certificate_request_DEPENDENCIES) $(EXTRA_inf_test_certificate_request_DEPENDENCIES) @rm -f inf-test-certificate-request$(EXEEXT) $(AM_V_CCLD)$(LINK) $(inf_test_certificate_request_OBJECTS) $(inf_test_certificate_request_LDADD) $(LIBS) inf-test-certificate-validate$(EXEEXT): $(inf_test_certificate_validate_OBJECTS) $(inf_test_certificate_validate_DEPENDENCIES) $(EXTRA_inf_test_certificate_validate_DEPENDENCIES) @rm -f inf-test-certificate-validate$(EXEEXT) $(AM_V_CCLD)$(inf_test_certificate_validate_LINK) $(inf_test_certificate_validate_OBJECTS) $(inf_test_certificate_validate_LDADD) $(LIBS) inf-test-chat$(EXEEXT): $(inf_test_chat_OBJECTS) $(inf_test_chat_DEPENDENCIES) $(EXTRA_inf_test_chat_DEPENDENCIES) @rm -f inf-test-chat$(EXEEXT) $(AM_V_CCLD)$(LINK) $(inf_test_chat_OBJECTS) $(inf_test_chat_LDADD) $(LIBS) inf-test-chunk$(EXEEXT): $(inf_test_chunk_OBJECTS) $(inf_test_chunk_DEPENDENCIES) $(EXTRA_inf_test_chunk_DEPENDENCIES) @rm -f inf-test-chunk$(EXEEXT) $(AM_V_CCLD)$(LINK) $(inf_test_chunk_OBJECTS) $(inf_test_chunk_LDADD) $(LIBS) inf-test-daemon$(EXEEXT): $(inf_test_daemon_OBJECTS) $(inf_test_daemon_DEPENDENCIES) $(EXTRA_inf_test_daemon_DEPENDENCIES) @rm -f inf-test-daemon$(EXEEXT) $(AM_V_CCLD)$(LINK) $(inf_test_daemon_OBJECTS) $(inf_test_daemon_LDADD) $(LIBS) inf-test-gtk-browser$(EXEEXT): $(inf_test_gtk_browser_OBJECTS) $(inf_test_gtk_browser_DEPENDENCIES) $(EXTRA_inf_test_gtk_browser_DEPENDENCIES) @rm -f inf-test-gtk-browser$(EXEEXT) $(AM_V_CCLD)$(LINK) $(inf_test_gtk_browser_OBJECTS) $(inf_test_gtk_browser_LDADD) $(LIBS) inf-test-mass-join$(EXEEXT): $(inf_test_mass_join_OBJECTS) $(inf_test_mass_join_DEPENDENCIES) $(EXTRA_inf_test_mass_join_DEPENDENCIES) @rm -f inf-test-mass-join$(EXEEXT) $(AM_V_CCLD)$(LINK) $(inf_test_mass_join_OBJECTS) $(inf_test_mass_join_LDADD) $(LIBS) inf-test-reduce-replay$(EXEEXT): $(inf_test_reduce_replay_OBJECTS) $(inf_test_reduce_replay_DEPENDENCIES) $(EXTRA_inf_test_reduce_replay_DEPENDENCIES) @rm -f inf-test-reduce-replay$(EXEEXT) $(AM_V_CCLD)$(LINK) $(inf_test_reduce_replay_OBJECTS) $(inf_test_reduce_replay_LDADD) $(LIBS) inf-test-set-acl$(EXEEXT): $(inf_test_set_acl_OBJECTS) $(inf_test_set_acl_DEPENDENCIES) $(EXTRA_inf_test_set_acl_DEPENDENCIES) @rm -f inf-test-set-acl$(EXEEXT) $(AM_V_CCLD)$(LINK) $(inf_test_set_acl_OBJECTS) $(inf_test_set_acl_LDADD) $(LIBS) inf-test-state-vector$(EXEEXT): $(inf_test_state_vector_OBJECTS) $(inf_test_state_vector_DEPENDENCIES) $(EXTRA_inf_test_state_vector_DEPENDENCIES) @rm -f inf-test-state-vector$(EXEEXT) $(AM_V_CCLD)$(LINK) $(inf_test_state_vector_OBJECTS) $(inf_test_state_vector_LDADD) $(LIBS) inf-test-tcp-connection$(EXEEXT): $(inf_test_tcp_connection_OBJECTS) $(inf_test_tcp_connection_DEPENDENCIES) $(EXTRA_inf_test_tcp_connection_DEPENDENCIES) @rm -f inf-test-tcp-connection$(EXEEXT) $(AM_V_CCLD)$(LINK) $(inf_test_tcp_connection_OBJECTS) $(inf_test_tcp_connection_LDADD) $(LIBS) inf-test-tcp-server$(EXEEXT): $(inf_test_tcp_server_OBJECTS) $(inf_test_tcp_server_DEPENDENCIES) $(EXTRA_inf_test_tcp_server_DEPENDENCIES) @rm -f inf-test-tcp-server$(EXEEXT) $(AM_V_CCLD)$(LINK) $(inf_test_tcp_server_OBJECTS) $(inf_test_tcp_server_LDADD) $(LIBS) inf-test-text-cleanup$(EXEEXT): $(inf_test_text_cleanup_OBJECTS) $(inf_test_text_cleanup_DEPENDENCIES) $(EXTRA_inf_test_text_cleanup_DEPENDENCIES) @rm -f inf-test-text-cleanup$(EXEEXT) $(AM_V_CCLD)$(LINK) $(inf_test_text_cleanup_OBJECTS) $(inf_test_text_cleanup_LDADD) $(LIBS) inf-test-text-fixline$(EXEEXT): $(inf_test_text_fixline_OBJECTS) $(inf_test_text_fixline_DEPENDENCIES) $(EXTRA_inf_test_text_fixline_DEPENDENCIES) @rm -f inf-test-text-fixline$(EXEEXT) $(AM_V_CCLD)$(LINK) $(inf_test_text_fixline_OBJECTS) $(inf_test_text_fixline_LDADD) $(LIBS) inf-test-text-operations$(EXEEXT): $(inf_test_text_operations_OBJECTS) $(inf_test_text_operations_DEPENDENCIES) $(EXTRA_inf_test_text_operations_DEPENDENCIES) @rm -f inf-test-text-operations$(EXEEXT) $(AM_V_CCLD)$(LINK) $(inf_test_text_operations_OBJECTS) $(inf_test_text_operations_LDADD) $(LIBS) inf-test-text-quick-write$(EXEEXT): $(inf_test_text_quick_write_OBJECTS) $(inf_test_text_quick_write_DEPENDENCIES) $(EXTRA_inf_test_text_quick_write_DEPENDENCIES) @rm -f inf-test-text-quick-write$(EXEEXT) $(AM_V_CCLD)$(LINK) $(inf_test_text_quick_write_OBJECTS) $(inf_test_text_quick_write_LDADD) $(LIBS) inf-test-text-recover$(EXEEXT): $(inf_test_text_recover_OBJECTS) $(inf_test_text_recover_DEPENDENCIES) $(EXTRA_inf_test_text_recover_DEPENDENCIES) @rm -f inf-test-text-recover$(EXEEXT) $(AM_V_CCLD)$(LINK) $(inf_test_text_recover_OBJECTS) $(inf_test_text_recover_LDADD) $(LIBS) inf-test-text-replay$(EXEEXT): $(inf_test_text_replay_OBJECTS) $(inf_test_text_replay_DEPENDENCIES) $(EXTRA_inf_test_text_replay_DEPENDENCIES) @rm -f inf-test-text-replay$(EXEEXT) $(AM_V_CCLD)$(LINK) $(inf_test_text_replay_OBJECTS) $(inf_test_text_replay_LDADD) $(LIBS) inf-test-text-session$(EXEEXT): $(inf_test_text_session_OBJECTS) $(inf_test_text_session_DEPENDENCIES) $(EXTRA_inf_test_text_session_DEPENDENCIES) @rm -f inf-test-text-session$(EXEEXT) $(AM_V_CCLD)$(LINK) $(inf_test_text_session_OBJECTS) $(inf_test_text_session_LDADD) $(LIBS) inf-test-traffic-replay$(EXEEXT): $(inf_test_traffic_replay_OBJECTS) $(inf_test_traffic_replay_DEPENDENCIES) $(EXTRA_inf_test_traffic_replay_DEPENDENCIES) @rm -f inf-test-traffic-replay$(EXEEXT) $(AM_V_CCLD)$(LINK) $(inf_test_traffic_replay_OBJECTS) $(inf_test_traffic_replay_LDADD) $(LIBS) inf-test-xmpp-connection$(EXEEXT): $(inf_test_xmpp_connection_OBJECTS) $(inf_test_xmpp_connection_DEPENDENCIES) $(EXTRA_inf_test_xmpp_connection_DEPENDENCIES) @rm -f inf-test-xmpp-connection$(EXEEXT) $(AM_V_CCLD)$(LINK) $(inf_test_xmpp_connection_OBJECTS) $(inf_test_xmpp_connection_LDADD) $(LIBS) inf-test-xmpp-server$(EXEEXT): $(inf_test_xmpp_server_OBJECTS) $(inf_test_xmpp_server_DEPENDENCIES) $(EXTRA_inf_test_xmpp_server_DEPENDENCIES) @rm -f inf-test-xmpp-server$(EXEEXT) $(AM_V_CCLD)$(LINK) $(inf_test_xmpp_server_OBJECTS) $(inf_test_xmpp_server_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/inf-test-browser.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/inf-test-certificate-request.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/inf-test-chat.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/inf-test-chunk.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/inf-test-daemon.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/inf-test-gtk-browser.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/inf-test-mass-join.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/inf-test-reduce-replay.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/inf-test-set-acl.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/inf-test-state-vector.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/inf-test-tcp-connection.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/inf-test-tcp-server.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/inf-test-text-cleanup.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/inf-test-text-fixline.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/inf-test-text-operations.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/inf-test-text-quick-write.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/inf-test-text-recover.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/inf-test-text-replay.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/inf-test-text-session.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/inf-test-traffic-replay.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/inf-test-xmpp-connection.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/inf-test-xmpp-server.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/inf_test_certificate_validate-inf-test-certificate-validate.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.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 -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.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 -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.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 $@ $< inf_test_certificate_validate-inf-test-certificate-validate.o: inf-test-certificate-validate.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(inf_test_certificate_validate_CFLAGS) $(CFLAGS) -MT inf_test_certificate_validate-inf-test-certificate-validate.o -MD -MP -MF $(DEPDIR)/inf_test_certificate_validate-inf-test-certificate-validate.Tpo -c -o inf_test_certificate_validate-inf-test-certificate-validate.o `test -f 'inf-test-certificate-validate.c' || echo '$(srcdir)/'`inf-test-certificate-validate.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/inf_test_certificate_validate-inf-test-certificate-validate.Tpo $(DEPDIR)/inf_test_certificate_validate-inf-test-certificate-validate.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='inf-test-certificate-validate.c' object='inf_test_certificate_validate-inf-test-certificate-validate.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) $(inf_test_certificate_validate_CFLAGS) $(CFLAGS) -c -o inf_test_certificate_validate-inf-test-certificate-validate.o `test -f 'inf-test-certificate-validate.c' || echo '$(srcdir)/'`inf-test-certificate-validate.c inf_test_certificate_validate-inf-test-certificate-validate.obj: inf-test-certificate-validate.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(inf_test_certificate_validate_CFLAGS) $(CFLAGS) -MT inf_test_certificate_validate-inf-test-certificate-validate.obj -MD -MP -MF $(DEPDIR)/inf_test_certificate_validate-inf-test-certificate-validate.Tpo -c -o inf_test_certificate_validate-inf-test-certificate-validate.obj `if test -f 'inf-test-certificate-validate.c'; then $(CYGPATH_W) 'inf-test-certificate-validate.c'; else $(CYGPATH_W) '$(srcdir)/inf-test-certificate-validate.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/inf_test_certificate_validate-inf-test-certificate-validate.Tpo $(DEPDIR)/inf_test_certificate_validate-inf-test-certificate-validate.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='inf-test-certificate-validate.c' object='inf_test_certificate_validate-inf-test-certificate-validate.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) $(inf_test_certificate_validate_CFLAGS) $(CFLAGS) -c -o inf_test_certificate_validate-inf-test-certificate-validate.obj `if test -f 'inf-test-certificate-validate.c'; then $(CYGPATH_W) 'inf-test-certificate-validate.c'; else $(CYGPATH_W) '$(srcdir)/inf-test-certificate-validate.c'; fi` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ 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-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ 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" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags # Recover from deleted '.trs' file; this should ensure that # "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create # both 'foo.log' and 'foo.trs'. Break the recipe in two subshells # to avoid problems with "make -n". .log.trs: rm -f $< $@ $(MAKE) $(AM_MAKEFLAGS) $< # Leading 'am--fnord' is there to ensure the list of targets does not # expand to empty, as could happen e.g. with make check TESTS=''. am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) am--force-recheck: @: $(TEST_SUITE_LOG): $(TEST_LOGS) @$(am__set_TESTS_bases); \ am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ redo_bases=`for i in $$bases; do \ am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ done`; \ if test -n "$$redo_bases"; then \ redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ if $(am__make_dryrun); then :; else \ rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ fi; \ fi; \ if test -n "$$am__remaking_logs"; then \ echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ "recursion detected" >&2; \ elif test -n "$$redo_logs"; then \ am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ fi; \ if $(am__make_dryrun); then :; else \ st=0; \ errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ for i in $$redo_bases; do \ test -f $$i.trs && test -r $$i.trs \ || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ test -f $$i.log && test -r $$i.log \ || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ test $$st -eq 0 || exit 1; \ fi @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ ws='[ ]'; \ results=`for b in $$bases; do echo $$b.trs; done`; \ test -n "$$results" || results=/dev/null; \ all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ if test `expr $$fail + $$xpass + $$error` -eq 0; then \ success=true; \ else \ success=false; \ fi; \ br='==================='; br=$$br$$br$$br$$br; \ result_count () \ { \ if test x"$$1" = x"--maybe-color"; then \ maybe_colorize=yes; \ elif test x"$$1" = x"--no-color"; then \ maybe_colorize=no; \ else \ echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ shift; \ desc=$$1 count=$$2; \ if test $$maybe_colorize = yes && test $$count -gt 0; then \ color_start=$$3 color_end=$$std; \ else \ color_start= color_end=; \ fi; \ echo "$${color_start}# $$desc $$count$${color_end}"; \ }; \ create_testsuite_report () \ { \ result_count $$1 "TOTAL:" $$all "$$brg"; \ result_count $$1 "PASS: " $$pass "$$grn"; \ result_count $$1 "SKIP: " $$skip "$$blu"; \ result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ result_count $$1 "FAIL: " $$fail "$$red"; \ result_count $$1 "XPASS:" $$xpass "$$red"; \ result_count $$1 "ERROR:" $$error "$$mgn"; \ }; \ { \ echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ $(am__rst_title); \ create_testsuite_report --no-color; \ echo; \ echo ".. contents:: :depth: 2"; \ echo; \ for b in $$bases; do echo $$b; done \ | $(am__create_global_log); \ } >$(TEST_SUITE_LOG).tmp || exit 1; \ mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ if $$success; then \ col="$$grn"; \ else \ col="$$red"; \ test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ fi; \ echo "$${col}$$br$${std}"; \ echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ echo "$${col}$$br$${std}"; \ create_testsuite_report --maybe-color; \ echo "$$col$$br$$std"; \ if $$success; then :; else \ echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ if test -n "$(PACKAGE_BUGREPORT)"; then \ echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ fi; \ echo "$$col$$br$$std"; \ fi; \ $$success || exit 1 check-TESTS: @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ log_list=`for i in $$bases; do echo $$i.log; done`; \ trs_list=`for i in $$bases; do echo $$i.trs; done`; \ log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ exit $$?; recheck: all @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) @set +e; $(am__set_TESTS_bases); \ bases=`for i in $$bases; do echo $$i; done \ | $(am__list_recheck_tests)` || exit 1; \ log_list=`for i in $$bases; do echo $$i.log; done`; \ log_list=`echo $$log_list`; \ $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ am__force_recheck=am--force-recheck \ TEST_LOGS="$$log_list"; \ exit $$? inf-test-state-vector.log: inf-test-state-vector$(EXEEXT) @p='inf-test-state-vector$(EXEEXT)'; \ b='inf-test-state-vector'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) inf-test-chunk.log: inf-test-chunk$(EXEEXT) @p='inf-test-chunk$(EXEEXT)'; \ b='inf-test-chunk'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) inf-test-text-session.log: inf-test-text-session$(EXEEXT) @p='inf-test-text-session$(EXEEXT)'; \ b='inf-test-text-session'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) inf-test-text-cleanup.log: inf-test-text-cleanup$(EXEEXT) @p='inf-test-text-cleanup$(EXEEXT)'; \ b='inf-test-text-cleanup'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) inf-test-text-fixline.log: inf-test-text-fixline$(EXEEXT) @p='inf-test-text-fixline$(EXEEXT)'; \ b='inf-test-text-fixline'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) inf-test-certificate-validate.log: inf-test-certificate-validate$(EXEEXT) @p='inf-test-certificate-validate$(EXEEXT)'; \ b='inf-test-certificate-validate'; \ $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) .test.log: @p='$<'; \ $(am__set_b); \ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ --log-file $$b.log --trs-file $$b.trs \ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ "$$tst" $(AM_TESTS_FD_REDIRECT) @am__EXEEXT_TRUE@.test$(EXEEXT).log: @am__EXEEXT_TRUE@ @p='$<'; \ @am__EXEEXT_TRUE@ $(am__set_b); \ @am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ @am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ @am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ @am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) 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 @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am $(MAKE) $(AM_MAKEFLAGS) check-TESTS check: check-recursive all-am: Makefile $(PROGRAMS) installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive 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: -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: 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." clean: clean-recursive clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \ mostlyclean-am distclean: distclean-recursive -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: .MAKE: $(am__recursive_targets) check-am install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-TESTS check-am clean clean-generic clean-libtool \ clean-noinstPROGRAMS cscopelist-am ctags ctags-am 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-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ installdirs-am maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am recheck tags tags-am \ uninstall uninstall-am .PRECIOUS: Makefile # 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: libinfinity-0.7.1/test/PaxHeaders.26529/inf-test-text-replay.c0000644000000000000000000000013213034342512020730 xustar0030 mtime=1483851082.053718557 30 atime=1483851082.053718557 30 ctime=1488261589.736137456 libinfinity-0.7.1/test/inf-test-text-replay.c0000644000175000017500000003073713034342512021474 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include "util/inf-test-util.h" #include #include #include #include #include #include #include #include #include #include #include #include typedef struct _InfTestTextReplayUndoGroupingInfo InfTestTextReplayUndoGroupingInfo; struct _InfTestTextReplayUndoGroupingInfo { InfAdoptedAlgorithm* algorithm; GSList* undo_groupings; }; static InfSession* inf_test_text_replay_session_new(InfIo* io, InfCommunicationManager* manager, InfSessionStatus status, InfCommunicationGroup* sync_group, InfXmlConnection* sync_connection, const gchar* path, gpointer user_data) { InfTextDefaultBuffer* buffer; InfTextSession* session; buffer = inf_text_default_buffer_new("UTF-8"); session = inf_text_session_new( manager, INF_TEXT_BUFFER(buffer), io, status, sync_group, sync_connection ); g_object_unref(buffer); return INF_SESSION(session); } static const InfcNotePlugin INF_TEST_TEXT_REPLAY_TEXT_PLUGIN = { NULL, "InfText", inf_test_text_replay_session_new }; /* * String check */ /* These functions assume that buffer and chunks contain UTF-8 */ static GString* inf_test_text_replay_load_buffer(InfTextBuffer* buffer) { InfTextBufferIter* iter; GString* result; gchar* text; gsize bytes; result = g_string_sized_new(inf_text_buffer_get_length(buffer)); g_assert(strcmp(inf_text_buffer_get_encoding(buffer), "UTF-8") == 0); iter = inf_text_buffer_create_begin_iter(buffer); if(iter != NULL) { do { text = inf_text_buffer_iter_get_text(buffer, iter); bytes = inf_text_buffer_iter_get_bytes(buffer, iter); g_string_append_len(result, text, bytes); g_free(text); } while(inf_text_buffer_iter_next(buffer, iter)); inf_text_buffer_destroy_iter(buffer, iter); } return result; } static void inf_test_text_replay_text_inserted_cb(InfTextBuffer* buffer, guint pos, InfTextChunk* chunk, InfUser* user, gpointer user_data) { GString* own_content; InfTextChunkIter iter; gsize bpos; GString* buffer_content; own_content = (GString*)user_data; /* apply operation to string */ if(inf_text_chunk_iter_init_begin(chunk, &iter)) { /* Convert from pos to byte */ bpos = g_utf8_offset_to_pointer(own_content->str, pos) - own_content->str; do { g_string_insert_len( own_content, bpos, inf_text_chunk_iter_get_text(&iter), inf_text_chunk_iter_get_bytes(&iter) ); bpos += inf_text_chunk_iter_get_bytes(&iter); } while(inf_text_chunk_iter_next(&iter)); } /* Compare with buffer content */ buffer_content = inf_test_text_replay_load_buffer(buffer); g_assert(strcmp(buffer_content->str, own_content->str) == 0); g_string_free(buffer_content, TRUE); } static void inf_test_text_replay_text_erased_cb(InfTextBuffer* buffer, guint pos, InfTextChunk* chunk, InfUser* user, gpointer user_data) { GString* own_content; guint beg; guint end; gsize bbeg; gsize bend; GString* buffer_content; own_content = (GString*)user_data; /* apply operation to string */ beg = pos; end = beg + inf_text_chunk_get_length(chunk); bbeg = g_utf8_offset_to_pointer(own_content->str, pos) - own_content->str; bend = g_utf8_offset_to_pointer(own_content->str, end) - own_content->str; g_string_erase(own_content, bbeg, bend - bbeg); /* Compare with buffer content */ buffer_content = inf_test_text_replay_load_buffer(buffer); g_assert(strcmp(buffer_content->str, own_content->str) == 0); g_string_free(buffer_content, TRUE); } static const gchar* inf_test_text_replay_request_typestring(InfAdoptedRequest* request) { switch(inf_adopted_request_get_request_type(request)) { case INF_ADOPTED_REQUEST_DO: return "DO"; case INF_ADOPTED_REQUEST_UNDO: return "UNDO"; case INF_ADOPTED_REQUEST_REDO: return "REDO"; default: g_assert_not_reached(); return NULL; } } static gint64 test; static void inf_test_text_replay_begin_execute_request_cb(InfAdoptedAlgorithm* algorithm, InfAdoptedUser* user, InfAdoptedRequest* request, gpointer user_data) { gchar* current_str; gchar* request_str; guint vdiff; vdiff = inf_adopted_state_vector_vdiff( inf_adopted_request_get_vector(request), inf_adopted_algorithm_get_current(algorithm) ); if(vdiff > 10) { current_str = inf_adopted_state_vector_to_string( inf_adopted_algorithm_get_current(algorithm) ); request_str = inf_adopted_state_vector_to_string( inf_adopted_request_get_vector(request) ); fprintf( stderr, "WARNING: Transforming %s request \"%s\" of user \"%s\" to state \"%s\"" ", vdiff=%u\n", inf_test_text_replay_request_typestring(request), request_str, inf_user_get_name(INF_USER(user)), current_str, vdiff ); g_free(current_str); g_free(request_str); } test = g_get_monotonic_time(); } static void inf_test_text_replay_end_execute_request_cb(InfAdoptedAlgorithm* algorithm, InfAdoptedUser* user, InfAdoptedRequest* request, InfAdoptedRequest* translated, const GError* error, gpointer user_data) { InfAdoptedStateVector* current; gchar* current_str; gchar* request_str; gint64 time; time = g_get_monotonic_time(); if(error == NULL) { if(time - test > 10000.) { current_str = inf_adopted_state_vector_to_string( inf_adopted_request_get_vector(translated) ); request_str = inf_adopted_state_vector_to_string( inf_adopted_request_get_vector(request) ); fprintf( stderr, "WARNING: Transforming %s request \"%s\" of user \"%s\" to state " "\"%s\" took %.3g ms\n", inf_test_text_replay_request_typestring(request), request_str, inf_user_get_name(INF_USER(user)), current_str, (time - test)/1000. ); g_free(current_str); g_free(request_str); } } else { g_assert(error != NULL); current_str = inf_adopted_state_vector_to_string( inf_adopted_algorithm_get_current(algorithm) ); request_str = inf_adopted_state_vector_to_string( inf_adopted_request_get_vector(request) ); fprintf( stderr, "WARNING: Transforming %s request \"%s\" of user \"%s\" to " "state \"%s\" failed: %s\n", inf_test_text_replay_request_typestring(request), request_str, inf_user_get_name(INF_USER(user)), current_str, error->message ); g_free(current_str); g_free(request_str); } } /* * Undo grouping */ static void inf_test_text_replay_add_undo_grouping(InfTestTextReplayUndoGroupingInfo* fo, InfAdoptedUser* user) { InfTextUndoGrouping* grouping; grouping = inf_text_undo_grouping_new(); inf_adopted_undo_grouping_set_algorithm(INF_ADOPTED_UNDO_GROUPING(grouping), fo->algorithm, user); fo->undo_groupings = g_slist_prepend(fo->undo_groupings, grouping); } static void inf_test_text_replay_add_user_cb(InfUserTable* user_table, InfUser* user, gpointer user_data) { inf_test_text_replay_add_undo_grouping(user_data, INF_ADOPTED_USER(user)); } static void inf_test_text_replay_play_user_table_foreach_func(InfUser* user, gpointer user_data) { inf_test_text_replay_add_undo_grouping(user_data, INF_ADOPTED_USER(user)); } /* * Entry point */ int main(int argc, char* argv[]) { InfAdoptedSessionReplay* replay; InfAdoptedSession* session; GError* error; int i; int ret; GString* content; InfBuffer* buffer; InfUserTable* user_table; InfTestTextReplayUndoGroupingInfo data; GSList* item; if(argc < 2) { fprintf(stderr, "Usage: %s ...\n", argv[0]); return -1; } error = NULL; if(!inf_init(&error)) { fprintf(stderr, "%s\n", error->message); g_error_free(error); return -1; } ret = 0; for(i = 1; i < argc; ++ i) { fprintf(stderr, "%s... ", argv[i]); fflush(stderr); replay = inf_adopted_session_replay_new(); inf_adopted_session_replay_set_record( replay, argv[i], &INF_TEST_TEXT_REPLAY_TEXT_PLUGIN, &error ); if(error != NULL) { fprintf(stderr, "%s\n", error->message); g_error_free(error); error = NULL; ret = -1; } else { session = inf_adopted_session_replay_get_session(replay); buffer = inf_session_get_buffer(INF_SESSION(session)); content = inf_test_text_replay_load_buffer(INF_TEXT_BUFFER(buffer)); user_table = inf_session_get_user_table(INF_SESSION(session)); data.algorithm = inf_adopted_session_get_algorithm(session); data.undo_groupings = NULL; g_signal_connect( inf_session_get_buffer(INF_SESSION(session)), "text-inserted", G_CALLBACK(inf_test_text_replay_text_inserted_cb), content ); g_signal_connect( inf_session_get_buffer(INF_SESSION(session)), "text-erased", G_CALLBACK(inf_test_text_replay_text_erased_cb), content ); g_signal_connect( data.algorithm, "begin-execute-request", G_CALLBACK(inf_test_text_replay_begin_execute_request_cb), content ); g_signal_connect( data.algorithm, "end-execute-request", G_CALLBACK(inf_test_text_replay_end_execute_request_cb), content ); /* Let an undo grouper group stuff, just as a consistency check * that it does not crash or behave otherwise badly. */ inf_user_table_foreach_user( user_table, inf_test_text_replay_play_user_table_foreach_func, &data ); g_signal_connect_after( user_table, "add-user", G_CALLBACK(inf_test_text_replay_add_user_cb), &data ); if(!inf_adopted_session_replay_play_to_end(replay, &error)) { fprintf(stderr, "%s\n", error->message); g_error_free(error); error = NULL; ret = -1; } else { fprintf(stderr, "\n"); inf_test_util_print_buffer(INF_TEXT_BUFFER(buffer)); } g_string_free(content, TRUE); for(item = data.undo_groupings; item != NULL; item = item->next) g_object_unref(item->data); g_slist_free(data.undo_groupings); } g_object_unref(replay); } return ret; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/test/PaxHeaders.26529/Makefile.am0000644000000000000000000000013213034544714016623 xustar0030 mtime=1483917772.686920573 30 atime=1483917772.686920573 30 ctime=1488261589.708137517 libinfinity-0.7.1/test/Makefile.am0000644000175000017500000001473413034544714017366 0ustar00arminarmin00000000000000SUBDIRS = util session cleanup certs TESTS = inf-test-state-vector inf-test-chunk inf-test-text-session \ inf-test-text-cleanup inf-test-text-fixline \ inf-test-certificate-validate AM_CPPFLAGS = \ -I${top_srcdir} \ ${infinity_CFLAGS} if WITH_INFGTK AM_CPPFLAGS += \ ${infgtk_CFLAGS} endif if WITH_INFTEXTGTK AM_CPPFLAGS += \ ${inftextgtk_CFLAGS} endif noinst_PROGRAMS = inf-test-tcp-connection inf-test-xmpp-connection \ inf-test-tcp-server inf-test-xmpp-server inf-test-daemon \ inf-test-browser inf-test-certificate-request inf-test-set-acl \ inf-test-chat inf-test-state-vector inf-test-chunk \ inf-test-text-operations inf-test-text-session \ inf-test-text-cleanup inf-test-text-recover \ inf-test-text-replay inf-test-reduce-replay inf-test-mass-join \ inf-test-text-fixline inf-test-traffic-replay \ inf-test-certificate-validate inf-test-text-quick-write if WITH_INFTEXTGTK noinst_PROGRAMS += inf-test-gtk-browser endif inf_test_tcp_connection_SOURCES = \ inf-test-tcp-connection.c inf_test_tcp_connection_LDADD = \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ ${infinity_LIBS} inf_test_xmpp_connection_SOURCES = \ inf-test-xmpp-connection.c inf_test_xmpp_connection_LDADD = \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ ${infinity_LIBS} inf_test_tcp_server_SOURCES = \ inf-test-tcp-server.c inf_test_tcp_server_LDADD = \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ ${infinity_LIBS} inf_test_xmpp_server_SOURCES = \ inf-test-xmpp-server.c inf_test_xmpp_server_LDADD = \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ ${infinity_LIBS} inf_test_daemon_SOURCES = \ inf-test-daemon.c inf_test_daemon_LDADD = \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ ${infinity_LIBS} inf_test_browser_SOURCES = \ inf-test-browser.c inf_test_browser_LDADD = \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ ${infinity_LIBS} inf_test_certificate_request_SOURCES = \ inf-test-certificate-request.c inf_test_certificate_request_LDADD = \ util/libinftestutil.a \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ ${infinity_LIBS} inf_test_set_acl_SOURCES = \ inf-test-set-acl.c inf_test_set_acl_LDADD = \ util/libinftestutil.a \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ ${infinity_LIBS} inf_test_chat_SOURCES = \ inf-test-chat.c inf_test_chat_LDADD = \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ ${infinity_LIBS} inf_test_state_vector_SOURCES = \ inf-test-state-vector.c inf_test_state_vector_LDADD = \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ ${infinity_LIBS} inf_test_chunk_SOURCES = \ inf-test-chunk.c inf_test_chunk_LDADD = \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ ${inftext_LIBS} ${infinity_LIBS} inf_test_text_operations_SOURCES = \ inf-test-text-operations.c inf_test_text_operations_LDADD = \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ ${inftext_LIBS} ${infinity_LIBS} inf_test_text_session_SOURCES = \ inf-test-text-session.c inf_test_text_session_LDADD = \ util/libinftestutil.a \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ ${inftext_LIBS} ${infinity_LIBS} inf_test_text_cleanup_SOURCES = \ inf-test-text-cleanup.c inf_test_text_cleanup_LDADD = \ util/libinftestutil.a \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ ${inftext_LIBS} ${infinity_LIBS} inf_test_text_replay_SOURCES = \ inf-test-text-replay.c inf_test_text_replay_LDADD = \ util/libinftestutil.a \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ ${inftext_LIBS} ${infinity_LIBS} inf_test_text_recover_SOURCES = \ inf-test-text-recover.c inf_test_text_recover_LDADD = \ util/libinftestutil.a \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ ${inftext_LIBS} ${infinity_LIBS} inf_test_reduce_replay_SOURCES = \ inf-test-reduce-replay.c inf_test_reduce_replay_LDADD = \ util/libinftestutil.a \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ ${inftext_LIBS} ${infinity_LIBS} inf_test_mass_join_SOURCES = \ inf-test-mass-join.c inf_test_mass_join_LDADD = \ util/libinftestutil.a \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ ${inftext_LIBS} ${infinity_LIBS} inf_test_text_fixline_SOURCES = \ inf-test-text-fixline.c inf_test_text_fixline_LDADD = \ util/libinftestutil.a \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ ${inftext_LIBS} ${infinity_LIBS} if WITH_INFTEXTGTK inf_test_gtk_browser_SOURCES = \ inf-test-gtk-browser.c inf_test_gtk_browser_LDADD = \ ${top_builddir}/libinftextgtk/libinftextgtk-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinfgtk/libinfgtk-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ ${inftextgtk_LIBS} ${infgtk_LIBS} ${inftext_LIBS} ${infinity_LIBS} endif inf_test_traffic_replay_SOURCES = \ inf-test-traffic-replay.c inf_test_traffic_replay_LDADD = \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ ${infinity_LIBS} inf_test_certificate_validate_SOURCES = \ inf-test-certificate-validate.c inf_test_certificate_validate_CFLAGS = \ -DCERTS_DIR="\"${abs_srcdir}/certs\"" inf_test_certificate_validate_LDADD = \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ ${infinity_LIBS} inf_test_text_quick_write_SOURCES = \ inf-test-text-quick-write.c inf_test_text_quick_write_LDADD = \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ ${inftext_LIBS} ${infinity_LIBS} libinfinity-0.7.1/test/PaxHeaders.26529/inf-test-certificate-validate.c0000644000000000000000000000013013034544714022531 xustar0030 mtime=1483917772.686920573 30 atime=1483917772.686920573 28 ctime=1488261589.7161375 libinfinity-0.7.1/test/inf-test-certificate-validate.c0000644000175000017500000004737113034544714023301 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include typedef enum _InfTestCertificateValidateExpectation { INF_TEST_CERTIFICATE_VALIDATE_EXPECT_ACCEPT, INF_TEST_CERTIFICATE_VALIDATE_EXPECT_REJECT, INF_TEST_CERTIFICATE_VALIDATE_EXPECT_QUERY_ACCEPT, INF_TEST_CERTIFICATE_VALIDATE_EXPECT_QUERY_REJECT, } InfTestCertificateValidateExpectation; typedef struct _InfTestCertificateValidateDesc InfTestCertificateValidateDesc; struct _InfTestCertificateValidateDesc { /* Name of the test */ const gchar* name; /* server settings */ const gchar* key_file; const gchar* cert_file; /* client settings */ const gchar* ca_file; /* CA file */ const gchar* hostname; /* Connected server hostname */ const gchar* pinned_certificate; /* Expected result */ InfTestCertificateValidateExpectation expectation; gboolean accept_query; /* If there is a query, accept it? */ gboolean expect_pinned; /* Whether the cert should end up pinned or not */ }; typedef struct _InfTestCertificateValidateCheckCertificateData InfTestCertificateValidateCheckCertificateData; struct _InfTestCertificateValidateCheckCertificateData { gboolean accept_query; gboolean did_query; }; const InfTestCertificateValidateDesc TESTS[] = { { "expired-trusted", "test-expire-key.pem", "test-expire-crt.pem", "ca-crt.pem", "expire-test.gobby.0x539.de", NULL, INF_TEST_CERTIFICATE_VALIDATE_EXPECT_REJECT, FALSE, FALSE }, { "expired-pinned", "test-expire-key.pem", "test-expire-crt.pem", NULL, "expire-test.gobby.0x539.de", "test-expire-crt.pem", INF_TEST_CERTIFICATE_VALIDATE_EXPECT_REJECT, FALSE, TRUE /* cert was pinned before, and rejection doesn't un-pin it. That's good so that if the server gets an updated certificate we remember that the previous one has expired. */ }, { "expired-pinned-to-good", "test-expire-good-key.pem", "test-expire-good-crt.pem", "ca-crt.pem", "expire-test.gobby.0x539.de", "test-expire-crt.pem", INF_TEST_CERTIFICATE_VALIDATE_EXPECT_ACCEPT, FALSE, FALSE }, { "expired-pinned-to-good-mismatch-query-accept", "test-expire-good-key.pem", "test-expire-good-crt.pem", "ca-crt.pem", "expire-test-mismatch.gobby.0x539.de", "test-expire-crt.pem", INF_TEST_CERTIFICATE_VALIDATE_EXPECT_QUERY_ACCEPT, TRUE, TRUE }, { "expired-pinned-to-good-mismatch-query-reject", "test-expire-good-key.pem", "test-expire-good-crt.pem", "ca-crt.pem", "expire-test-mismatch.gobby.0x539.de", "test-expire-crt.pem", INF_TEST_CERTIFICATE_VALIDATE_EXPECT_QUERY_REJECT, FALSE, FALSE /* The old certificate will remain pinned, but not the new one */ }, { "good", "test-good-key.pem", "test-good-crt.pem", "ca-crt.pem", "test-good.gobby.0x539.de", NULL, INF_TEST_CERTIFICATE_VALIDATE_EXPECT_ACCEPT, FALSE, FALSE }, { "good-pinned", "test-good-key.pem", "test-good-crt.pem", "ca-crt.pem", "test-good.gobby.0x539.de", "test-good-crt.pem", INF_TEST_CERTIFICATE_VALIDATE_EXPECT_ACCEPT, FALSE, FALSE }, { "good-pinned-to-other", "test-good-key.pem", "test-good-crt.pem", "ca-crt.pem", "test-good.gobby.0x539.de", "test-expire-good-crt.pem", INF_TEST_CERTIFICATE_VALIDATE_EXPECT_ACCEPT, FALSE, FALSE }, { "good-pinned-mismatch", "test-good-key.pem", "test-good-crt.pem", "ca-crt.pem", "good-test-mismatch.gobby.0x539.de", "test-good-crt.pem", INF_TEST_CERTIFICATE_VALIDATE_EXPECT_ACCEPT, FALSE, TRUE }, { "good-pinned-to-other-mismatch-query-accept", "test-good-key.pem", "test-good-crt.pem", "ca-crt.pem", "good-test-mismatch.gobby.0x539.de", "test-expire-good-crt.pem", INF_TEST_CERTIFICATE_VALIDATE_EXPECT_QUERY_ACCEPT, TRUE, TRUE }, { "good-pinned-to-other-mismatch-query-reject", "test-good-key.pem", "test-good-crt.pem", "ca-crt.pem", "good-test-mismatch.gobby.0x539.de", "test-expire-good-crt.pem", INF_TEST_CERTIFICATE_VALIDATE_EXPECT_QUERY_REJECT, FALSE, FALSE /* The old certificate will remain pinned, but not the new one */ }, { "good-mismatch-query-accept", "test-good-key.pem", "test-good-crt.pem", "ca-crt.pem", "good-test-mismatch.gobby.0x539.de", NULL, INF_TEST_CERTIFICATE_VALIDATE_EXPECT_QUERY_ACCEPT, TRUE, TRUE }, { "good-mismatch-query-reject", "test-good-key.pem", "test-good-crt.pem", "ca-crt.pem", "good-test-mismatch.gobby.0x539.de", NULL, INF_TEST_CERTIFICATE_VALIDATE_EXPECT_QUERY_REJECT, FALSE, FALSE }, { "good-untrusted-query-accept", "test-good-key.pem", "test-good-crt.pem", NULL, "test-good.gobby.0x539.de", NULL, INF_TEST_CERTIFICATE_VALIDATE_EXPECT_QUERY_ACCEPT, TRUE, TRUE }, { "good-untrusted-query-reject", "test-good-key.pem", "test-good-crt.pem", NULL, "test-good.gobby.0x539.de", NULL, INF_TEST_CERTIFICATE_VALIDATE_EXPECT_QUERY_REJECT, FALSE, FALSE }, { "good-pinned-untrusted", "test-good-key.pem", "test-good-crt.pem", NULL, "test-good.gobby.0x539.de", "test-good-crt.pem", INF_TEST_CERTIFICATE_VALIDATE_EXPECT_ACCEPT, FALSE, TRUE }, { NULL } }; static GQuark inf_test_certificate_validate_error() { return g_quark_from_static_string("INF_CERTIFICATE_VALIDATE_TEST_ERROR"); } static void inf_test_certificate_validate_new_connection_cb(InfdXmlServer* server, InfXmlConnection* conn, gpointer user_data) { g_object_ref(conn); g_object_set_data_full( G_OBJECT(server), "client-connection", conn, g_object_unref ); } static InfdXmppServer* inf_test_certificate_setup_server(InfIo* io, const char* key_file, const char* cert_file, GError** error) { InfdTcpServer* tcp; InfdXmppServer* xmpp; gnutls_x509_privkey_t key; GPtrArray* certs; InfCertificateCredentials* creds; guint i; int res; key = inf_cert_util_read_private_key(key_file, error); if(!key) return NULL; certs = inf_cert_util_read_certificate(cert_file, NULL, error); if(!certs) { gnutls_x509_privkey_deinit(key); return NULL; } creds = inf_certificate_credentials_new(); res = gnutls_certificate_set_x509_key( inf_certificate_credentials_get(creds), (gnutls_x509_crt_t*)certs->pdata, certs->len, key ); gnutls_x509_privkey_deinit(key); for(i = 0; i < certs->len; ++i) gnutls_x509_crt_deinit(certs->pdata[i]); g_ptr_array_free(certs, TRUE); if(res != 0) { inf_certificate_credentials_unref(creds); inf_gnutls_set_error(error, res); return NULL; } tcp = g_object_new( INFD_TYPE_TCP_SERVER, "io", io, "local-port", 6524, NULL ); if(infd_tcp_server_open(tcp, error) == FALSE) { inf_certificate_credentials_unref(creds); return NULL; } xmpp = infd_xmpp_server_new( tcp, INF_XMPP_CONNECTION_SECURITY_ONLY_TLS, creds, NULL, NULL ); /* Keep client connections alive */ g_signal_connect( G_OBJECT(xmpp), "new-connection", G_CALLBACK(inf_test_certificate_validate_new_connection_cb), NULL ); inf_certificate_credentials_unref(creds); return xmpp; } static InfXmppConnection* inf_test_certificate_validate_setup_client(InfIo* io, const gchar* ca_file, const gchar* remote_hostname, GError** error) { InfIpAddress* addr; InfTcpConnection* conn; InfXmppConnection* xmpp; InfCertificateCredentials* creds; GPtrArray* cas; int res; guint i; creds = inf_certificate_credentials_new(); if(ca_file != NULL) { cas = inf_cert_util_read_certificate(ca_file, NULL, error); if(cas == NULL) { inf_certificate_credentials_unref(creds); return NULL; } res = gnutls_certificate_set_x509_trust( inf_certificate_credentials_get(creds), (gnutls_x509_crt_t*)cas->pdata, cas->len ); for(i = 0; i < cas->len; ++i) gnutls_x509_crt_deinit(cas->pdata[i]); g_ptr_array_free(cas, TRUE); } addr = inf_ip_address_new_loopback4(); conn = inf_tcp_connection_new(io, addr, 6524); inf_ip_address_free(addr); xmpp = inf_xmpp_connection_new( conn, INF_XMPP_CONNECTION_CLIENT, g_get_host_name(), remote_hostname, INF_XMPP_CONNECTION_SECURITY_ONLY_TLS, creds, NULL, NULL ); inf_certificate_credentials_unref(creds); if(inf_tcp_connection_open(conn, error) == FALSE) { g_object_unref(conn); g_object_unref(xmpp); return NULL; } g_object_unref(conn); return xmpp; } static gchar* inf_test_validate_setup_pin(const gchar* pinned_hostname, const gchar* pinned_certificate, GError** error) { GPtrArray* certs; gchar* target_file; GHashTable* table; guint i; gboolean result; if(pinned_hostname != NULL && pinned_certificate != NULL) { certs = inf_cert_util_read_certificate(pinned_certificate, NULL, error); if(certs == NULL) return NULL; } else { certs = g_ptr_array_new(); } target_file = g_build_filename(g_get_tmp_dir(), "pinned-test", NULL); table = g_hash_table_new_full( g_str_hash, g_str_equal, NULL, (GDestroyNotify)gnutls_x509_crt_deinit ); for(i = 0; i < certs->len; ++i) g_hash_table_insert(table, (gpointer)pinned_hostname, certs->pdata[i]); g_ptr_array_free(certs, TRUE); result = inf_cert_util_write_certificate_map(table, target_file, error); g_hash_table_destroy(table); if(result == FALSE) { g_free(target_file); target_file = NULL; } return target_file; } static void inf_test_validate_certificate_notify_status_cb(GObject* object, GParamSpec* pspec, gpointer user_data) { InfStandaloneIo* io; InfXmlConnectionStatus status; io = INF_STANDALONE_IO(user_data); g_object_get(G_OBJECT(object), "status", &status, NULL); if(status == INF_XML_CONNECTION_OPEN || status == INF_XML_CONNECTION_CLOSING || status == INF_XML_CONNECTION_CLOSED) { if(inf_standalone_io_loop_running(io)) inf_standalone_io_loop_quit(io); } } static void inf_test_validate_certificate_error_cb(InfXmlConnection* conn, const GError* error, gpointer user_data) { GError** out_error; out_error = (GError**)user_data; if(*out_error == NULL) *out_error = g_error_copy(error); } static void inf_test_certificate_validate_check_certificate(InfCertificateVerify* verify, InfXmppConnection* conn, InfCertificateChain* chain, gnutls_x509_crt_t pinned, InfCertificateVerifyFlags flg, gpointer user_data) { InfTestCertificateValidateCheckCertificateData* data; data = (InfTestCertificateValidateCheckCertificateData*)user_data; data->did_query = TRUE; /* Close the connection so that we return from the IO loop */ if(data->accept_query) inf_certificate_verify_checked(verify, conn, TRUE); else inf_certificate_verify_checked(verify, conn, FALSE); } static gboolean inf_test_certificate_validate_run(const InfTestCertificateValidateDesc* desc, GError** error) { InfIo* io; InfdXmppServer* server; InfXmppManager* xmpp_manager; InfCertificateVerify* verify; InfXmppConnection* client; gchar* pinned_file; InfXmlConnectionStatus status; InfTestCertificateValidateCheckCertificateData check_certificate_data; gboolean result; GError* conn_error; GHashTable* pinned; gnutls_x509_crt_t pinned_cert; InfCertificateChain* current_cert; gboolean cert_equal; /* Setup server */ io = INF_IO(inf_standalone_io_new()); server = inf_test_certificate_setup_server( io, desc->key_file, desc->cert_file, error ); if(server == NULL) { g_object_unref(io); return FALSE; } /* Create client */ pinned_file = inf_test_validate_setup_pin( desc->hostname, desc->pinned_certificate, error ); if(pinned_file == NULL) { g_object_unref(server); g_object_unref(io); return FALSE; } xmpp_manager = inf_xmpp_manager_new(); verify = inf_certificate_verify_new(xmpp_manager, pinned_file); check_certificate_data.did_query = FALSE; check_certificate_data.accept_query = desc->accept_query; g_signal_connect( G_OBJECT(verify), "check-certificate", G_CALLBACK(inf_test_certificate_validate_check_certificate), &check_certificate_data ); client = inf_test_certificate_validate_setup_client( io, desc->ca_file, desc->hostname, error ); if(client == NULL) { g_unlink(pinned_file); g_free(pinned_file); g_object_unref(io); g_object_unref(xmpp_manager); g_object_unref(verify); g_object_unref(server); return FALSE; } inf_xmpp_manager_add_connection(xmpp_manager, client); /* Okay, now watch for status changes on the client or whether a dialog * appears. */ g_signal_connect( G_OBJECT(client), "notify::status", G_CALLBACK(inf_test_validate_certificate_notify_status_cb), io ); conn_error = NULL; g_signal_connect( G_OBJECT(client), "error", G_CALLBACK(inf_test_validate_certificate_error_cb), &conn_error ); inf_standalone_io_loop(INF_STANDALONE_IO(io)); g_object_unref(io); /* Evaluate result */ result = TRUE; g_object_get(G_OBJECT(client), "status", &status, NULL); if(status == INF_XML_CONNECTION_OPEN) { g_assert(conn_error == NULL); if(check_certificate_data.did_query == TRUE && desc->expectation != INF_TEST_CERTIFICATE_VALIDATE_EXPECT_QUERY_ACCEPT) { g_set_error( error, inf_test_certificate_validate_error(), 3, "Certificate queried and accepted but not expected to" ); result = FALSE; } else if(check_certificate_data.did_query == FALSE && desc->expectation != INF_TEST_CERTIFICATE_VALIDATE_EXPECT_ACCEPT) { g_set_error( error, inf_test_certificate_validate_error(), 0, "Certificate accepted but not expected to" ); result = FALSE; } } else { g_assert(check_certificate_data.did_query || conn_error != NULL); /* TODO: The certificate verification result is not preserved at * the moment. We could change this in * inf_xmpp_connection_certificate_verify_cancel such that the existing * error is used if any, or otherwise our own is created. */ if(conn_error != NULL && conn_error->domain != inf_xmpp_connection_error_quark() && conn_error->code != INF_XMPP_CONNECTION_ERROR_CERTIFICATE_NOT_TRUSTED) { g_propagate_error(error, conn_error); conn_error = NULL; result = FALSE; } else if(check_certificate_data.did_query == TRUE && desc->expectation != INF_TEST_CERTIFICATE_VALIDATE_EXPECT_QUERY_REJECT) { g_set_error( error, inf_test_certificate_validate_error(), 2, "Certificate queried and rejected but not expected to" ); result = FALSE; } else if(check_certificate_data.did_query == FALSE && desc->expectation != INF_TEST_CERTIFICATE_VALIDATE_EXPECT_REJECT) { g_set_error( error, inf_test_certificate_validate_error(), 1, "Certificate rejected but not expected to" ); result = FALSE; } if(conn_error != NULL) { g_error_free(conn_error); conn_error = NULL; } } /* If we got the expected result, check whether the host was correctly * pinned or not. */ if(result == TRUE) { pinned = inf_cert_util_read_certificate_map(pinned_file, error); if(pinned == NULL) { result = FALSE; } else { pinned_cert = g_hash_table_lookup(pinned, desc->hostname); cert_equal = FALSE; if(pinned_cert != NULL) { g_object_get( G_OBJECT(client), "remote-certificate", ¤t_cert, NULL ); cert_equal = inf_cert_util_compare_fingerprint( pinned_cert, inf_certificate_chain_get_own_certificate(current_cert), &conn_error ); inf_certificate_chain_unref(current_cert); } if(conn_error != NULL) { g_propagate_error(error, conn_error); conn_error = NULL; } else if(cert_equal == TRUE && desc->expect_pinned == FALSE) { g_set_error( error, inf_test_certificate_validate_error(), 4, "Certificate was pinned but not expected to" ); result = FALSE; } else if(pinned_cert == NULL && desc->expect_pinned == TRUE) { g_set_error( error, inf_test_certificate_validate_error(), 5, "Certificate was not pinned but expected to" ); result = FALSE; } g_hash_table_destroy(pinned); } } g_unlink(pinned_file); g_free(pinned_file); g_object_unref(xmpp_manager); g_object_unref(verify); g_object_unref(server); g_object_unref(client); return result; } int main(int argc, char** argv) { const InfTestCertificateValidateDesc* test; GError* error; int res; error = NULL; if(inf_init(&error) == FALSE) { fprintf(stderr, "%s\n", error->message); g_error_free(error); return EXIT_FAILURE; } /* So that the certificate files are found */ printf("%s\n", CERTS_DIR); if(chdir(CERTS_DIR) != 0) { fprintf(stderr, "%s\n", strerror(errno)); return EXIT_FAILURE; } res = EXIT_SUCCESS; for(test = TESTS; test->name != NULL; ++test) { printf("%s...", test->name); error = NULL; if(inf_test_certificate_validate_run(test, &error) == FALSE) { printf(" %s\n", error->message); g_error_free(error); res = EXIT_FAILURE; } else { printf(" OK\n"); } } return res; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/test/PaxHeaders.26529/inf-test-chunk.c0000644000000000000000000000013013034342512017560 xustar0030 mtime=1483851082.053718557 30 atime=1483851082.053718557 28 ctime=1488261589.7161375 libinfinity-0.7.1/test/inf-test-chunk.c0000644000175000017500000000252213034342512020315 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include int main() { InfTextChunk* chunk; InfTextChunk* chunk2; chunk2 = inf_text_chunk_new("UTF-8"); inf_text_chunk_insert_text(chunk2, 0, "a", 1, 1, 500); inf_text_chunk_insert_text(chunk2, 0, "b", 1, 1, 501); inf_text_chunk_insert_text(chunk2, 0, "c", 1, 1, 502); inf_text_chunk_insert_text(chunk2, 3, "ü", 2, 1, 503); chunk = inf_text_chunk_substring(chunk2, 0, 3); inf_text_chunk_free(chunk); inf_text_chunk_free(chunk2); return 0; } libinfinity-0.7.1/test/PaxHeaders.26529/inf-test-xmpp-connection.c0000644000000000000000000000013213034342512021573 xustar0030 mtime=1483851082.053718557 30 atime=1483851082.053718557 30 ctime=1488261589.740137447 libinfinity-0.7.1/test/inf-test-xmpp-connection.c0000644000175000017500000000672313034342512022335 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include #include static void error_cb(InfTcpConnection* connection, GError* error, gpointer user_data) { fprintf(stderr, "Error occured: %s\n", error->message); /* if(inf_standalone_io_loop_running(INF_STANDALONE_IO(user_data))) inf_standalone_io_loop_quit(INF_STANDALONE_IO(user_data));*/ } static void notify_status_cb(InfXmppConnection* xmpp, const gchar* property, gpointer user_data) { InfXmlConnectionStatus status; g_object_get(G_OBJECT(xmpp), "status", &status,NULL); switch(status) { case INF_XML_CONNECTION_OPENING: printf("Opening\n"); break; case INF_XML_CONNECTION_OPEN: printf("Opened\n"); inf_xml_connection_close(INF_XML_CONNECTION(xmpp)); break; case INF_XML_CONNECTION_CLOSING: printf("Closing\n"); break; case INF_XML_CONNECTION_CLOSED: printf("Closed\n"); inf_standalone_io_loop_quit(INF_STANDALONE_IO(user_data)); break; default: g_assert_not_reached(); break; } } int main(int argc, char* argv[]) { InfIpAddress* addr; InfStandaloneIo* io; InfTcpConnection* connection; InfXmppConnection* xmpp; GError* error; error = NULL; if(!inf_init(&error)) { fprintf(stderr, "%s\n", error->message); return 1; } #if 0 addr = inf_ip_address_new_from_string("88.198.49.206"); /* This is jabber.0x539.de aka durotan.0x539.de */ #else addr = inf_ip_address_new_from_string("127.0.0.1"); /* This is localhost aka loopback */ #endif io = inf_standalone_io_new(); connection = inf_tcp_connection_new_and_open(INF_IO(io), addr, 5223, &error); inf_ip_address_free(addr); if(connection == NULL) { fprintf(stderr, "Could not open connection: %s\n", error->message); g_error_free(error); } else { xmpp = inf_xmpp_connection_new( connection, INF_XMPP_CONNECTION_CLIENT, NULL, "jabber.0x539.de", INF_XMPP_CONNECTION_SECURITY_BOTH_PREFER_TLS, NULL, NULL, NULL ); g_signal_connect(G_OBJECT(xmpp), "error", G_CALLBACK(error_cb), io); g_signal_connect(G_OBJECT(xmpp), "notify::status", G_CALLBACK(notify_status_cb), io); inf_standalone_io_loop(io); } g_object_unref(G_OBJECT(io)); if(connection) g_object_unref(G_OBJECT(connection)); return 0; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/test/PaxHeaders.26529/README0000644000000000000000000000013012400102201015416 xustar0029 mtime=1409320065.13113192 29 atime=1409320065.13113192 30 ctime=1488261589.712137508 libinfinity-0.7.1/test/README0000644000175000017500000000407712400102201016162 0ustar00arminarmin00000000000000These are various applications to test different aspects of the infinote API. They are different in nature and depend on each other (meaning that if inf-test-browser fails, inf-test-gtk-browser probably won't work either). Here is a rough overview of the tests: (NI=Non-Interactive, I=Interactive) NI inf-test-state-vector: Verifies that basic inf_adopted_state_vector functions work. I inf-test-tcp-connection: Connects to localhost on port 5223, sending "Hello World" and printing everything it receives to stdout. I inf-test-tcp-server: Listens on 5223, accepting every connection and printing anything it receives from all connections. I inf-test-browser: Connects to a infinote server at localhost on port 6523, providing a simple command line interface to list, explore, add and remove subdirectory nodes on the server. NI inf-test-chunk: Verifies that basic InfTextChunk operations do not cause a segfault. NI inf-test-text-session: Reads all test files in the session/ subdirectory and performs the tests. The test files contain a number of requests from different users, a beginning state and an end state of the text buffer. It applies all requests from all users in a random order to the beginning buffer and verifies that at the end the buffer matches the end state. NI inf-test-text-cleanup: Performs all test files in the cleanup/ subdirectory. This basically checks that cleaning up the request log works correctly in certain situations. Again, the test files contain a number of requests from different users. This time, however, they are always applied in order. In between the requests, there are tags that verify that the request log of the given user has a specified size or that the user can or can not issue Undo/Redo in the current situation. This is to ensure that the algorithm correctly shrinks the request log. NI inf-test-text-replay Replays a record as recorded with InfAdoptedSessionRecord. A few records that should play without problems are contained in the replay/ subdirectory. libinfinity-0.7.1/test/PaxHeaders.26529/certs0000644000000000000000000000013213055210725015625 xustar0030 mtime=1488261589.928137036 30 atime=1488261589.888137123 30 ctime=1488261589.928137036 libinfinity-0.7.1/test/certs/0000755000175000017500000000000013055210725016434 5ustar00arminarmin00000000000000libinfinity-0.7.1/test/certs/PaxHeaders.26529/test-expire-good-key.pem0000644000000000000000000000013213034342512022367 xustar0030 mtime=1483851082.049718536 30 atime=1483851082.049718536 30 ctime=1488261589.920137054 libinfinity-0.7.1/test/certs/test-expire-good-key.pem0000644000175000017500000000625313034342512023127 0ustar00arminarmin00000000000000-----BEGIN RSA PRIVATE KEY----- MIIJJwIBAAKCAgEAv0etQ5w+cd2paTeCkp2QDeO+GwncRtfgcR2U8XGU+PtF/KH6 hNaWvJ8dlqacgcKz58iFM2IOGaglmBX4ammasnzGp6kIh64YZHCnIIx6RXj4g4sG wTHIULgnZnFzRBQv2INROyDN0iLtOfago5vQqPf8EyxtF4kawxHMjrqeSSDfwQTv jXl69Eu6Iiu4wTGqxeq7UqxeCumI2B3e3MSqJYZhs0dUXexXEIzfDzZ+Kuc3b5jl OU52MqQtN6vGWDxj97EOMwgV1Sa5MMV3s21cAgdwpDLDsqG7/erxliOB0KCRJIca A6Luhf2O0k8c7cMBIVWPGplB8wBtoY3b6T5/4O1gX8Fc4e6D4ayGUceWDikaa0+R eKwkGB8mD4KguFN5z9/9SLWLvUMRmE2UjFhPPJHPsoLs2U9IyNLfN229b/p4DtTl rkAzrmEThQQAH8tBTpY+hWF/vxVX6krrAP/KYKM60LF5YdS3z/7JwIWAl8wthLrp y1KRXzFu7I5/PvgqNLDvcZlQGH4RNJ1iiiL2nDwrjOBzNfibQqgOfrm4nOAJTRSV RqB/8qMha36QgaOv0XwVcM2rlK/9InG6qesIU5XXrt5sjrDPZY9/092DcnRkygIk o6aKDDpAK6QF1AZ9ue3IQsBIMzM4lxCnrBkulyKHxHY4Cb1032jAc3I6d3UCAwEA AQKCAgBg2Yr6I79eagygMLIVSGArGDgmepyk5iNHQuIqSgdS9e9e1ikBX6HdCXey 0tOFxC7RWi9PcAORrBi049LvFl90pkbzl1uxT04cdQm6KkayrGiwOhGGeo1hiYyx ixoAy3PaXcsgdCCimHqjEaQOkxNYqo9gqermss3xHS8EyarhfhqtIbGlYXAHB9zL 9nVKpLpCEfMdDhdj0REv1BgGkjFQZLVNT/2AvOzsfVdn3YCOepoQEEtn87lXNNeM S5ZXEOTRAj4dSqe7UCsObb2JBQNEJ7459VYvOUL1cyM1kO7m0pYK97kNRE8fWt4Y 0GPmYwlMdoTJw/Wnc30PAsPpWnLmcOkkttjS55a9/QM6ZMZq7hy38WOzzMI+5+EU mP7YLAJ61VTiXhXHjIJ+LXAm8crD0VKue1IcM/zdV2FSMh4svgfVrJ3PYBMuz5NW 3+51ZL/g35PqjsaOaQ+ClWjRd6oFuypSW5eW6zoNR8vB9pMdQWAayHU1BjYdRJOm iah4AZC4efni0aT9DGD3Op4Il8J18mJK4CESITFDj0jZHn/TRwibxGXm1PYYNCat 6bTGNgP7fyve2x9Dt3Lm+EJsDelOyYErZckThG7JXSIJuF+GXepnDTTS/PVnNP0V SNzl1LR4Zm6SHSvSxqqxdCWO92B3PDPdqaO/9SpPIpXhleIa4QKCAQEA6zJWji1h md4kyIqTSEV+v5kT9pNKx7pCV4Ffy74yXCCl3cRk2lVnHGAdxWHJ2K7hCQMBOoQ/ 96PSvU0iX40kHt2oloKhwYaabgYGFQVdpcG8MgUkz83nu1Fef4gyEXpooEuFvSXa P48PDNFq9XeMYAtj4dD87m2fKsXIcE6gzKEHSXhQA+WIa1+I2xOb4t9Tk7q42591 qYnyQvDC1/1vXBMUb+SMcqYuYJ8HmjZIBdS0XK6ZkuYVET229meTh6KBr4xD3S7o UgRWFkJsZRzsK3TK8CDyhmarjBiuXuya0XLsis0nY537ItSMDs2IaZ5359rsrUTg y8wRFONp3f5bXQKCAQEA0DLqIe5eAR1GLV1lFTT1fX1Aft4Xi/CXiyzDkloV/LKE ntG85ZZnaiS1jvYsKyLfKduDnnRv6cUPWyUu+UdZZUzOZ8XmBaRgY7P2UV8WNoXU 2dZ49zZ49tBeKX7iJwcbc6e58KmDx9pzzGYSQZc4zAp1Rj7xxpRQHhtJzWSQbAqV wb23JXH6pHEZ5BLuXCY03O4rH5MjR6iMjvVCTTjIuQhiKBVjW52JNXjkjm1vf5Th zWvmxGkB0TKdKew5Q6gB6QKy+AKhHsvxBh/TqM8VzMEVPOzQ54oZTsYmUR/eRqca a2vM5ZRwx4dWVfF5zH9yEr4cEom/g6bvyZdPTqJi+QKCAQAQMUcEQtuVXFXr+J5r O12ek0tsjnd3iLtIiv+tZ0rQTO8edYb8ASU4LuXd0P20jVWw6SQMg05kHkNEBSt4 qJ70AQ66TgQU7s9zA7cne1cXMl9ikjgWlnZ9zvxSi23nBiZt4sUyYIjGF3NRzpku jSx88EvQIDNJtwJeT3+dO8yWSf/WbxITMppRyiIB8zeoRvfaE+DmPfQ71+N1+F1x wWEJVcbybSm+OvK2dDxxwYrz29EPEHZCRtTsevM9w6PEksua6m1BrRkRjHrgzXHp BDS+SSwvnBUWa7sjyg83OdLu2Jqwc69ijF3d6AQ8gKoDm4Vl0Qy6YSOY5FPIvF9t iTWBAoIBAFKekcjrRcSdcFbaRB25SV4GEU0HJ0LyM8EX/3gZZbZExVodEx/sopc9 gAr+Z6KqkPKUWNPNkweqmqBpzg1AIhqP8yy9HL3KcDHAnZPG7xKt4zya3qADrtcK 8wL2hhpEuMEZozD8o/3wE5neO4ppzzExST6aBenuuyhnXc8zBBjLzof2mDI02+jb tRGL7akFxF6T6Or7wblTCoxEiY4JZaX/zKvpaOdXSba9hb17cg6n7z9MfWQd44m3 0yRqyIKvripgVtMSgAuvlLMAeEb5/sWlLZ9ivrfTVp2rBlOVGOjisRpFyiak1Ghp rXonfFUJkiQb6xn0Ldq5qVhPQjqLOEkCggEAL8AgQL48ejFKlFkpykDeClhUzqod wa6Lktk74ugMTO3CKL2pNDsajPipQbiEHsqnDs2N3Q2uXOSuwoXZ67Gi7yMhrOQN vFgca9kxIRVemse5YXTO0i2M/EvXE6EL4FszIcZGw+MH+ffSXhhO6EGk4QXf5Qf6 6MKaEmO7U0QiGal0m0OffFSFf5NuUxE0serlw7WCfsAgiCab2zklXhT3CuPH1jAJ tsaJWVIh/dm/QhGyZgL9y8AXkqcB1MWJbVrAIqBLcgnje0TM0RQxxXUc13NviI0+ Jut+QkKHyuHauV20HBj99cpKdANBeUvb64YC596waEVjWuI9Y7MLMaLPsg== -----END RSA PRIVATE KEY----- libinfinity-0.7.1/test/certs/PaxHeaders.26529/Makefile.in0000644000000000000000000000013213051241010017732 xustar0030 mtime=1487225352.625151347 30 atime=1487225352.625151347 30 ctime=1488261589.912137071 libinfinity-0.7.1/test/certs/Makefile.in0000644000175000017500000003347713051241010020502 0ustar00arminarmin00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 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__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) 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@ subdir = test/certs ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/gtk-doc.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/libinfinity/inf-config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ 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@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIRNAME = @DATADIRNAME@ 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@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ GTKDOC_CHECK = @GTKDOC_CHECK@ GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ GTKDOC_MKPDF = @GTKDOC_MKPDF@ GTKDOC_REBASE = @GTKDOC_REBASE@ HTML_DIR = @HTML_DIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INSTOBJEXT = @INSTOBJEXT@ INTLLIBS = @INTLLIBS@ INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBINFINITY_API_VERSION = @LIBINFINITY_API_VERSION@ LIBINFINITY_LIBTOOL_VERSION = @LIBINFINITY_LIBTOOL_VERSION@ LIBINFINITY_VERSION = @LIBINFINITY_VERSION@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGFMT_OPTS = @MSGFMT_OPTS@ 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@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ 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@ avahi_CFLAGS = @avahi_CFLAGS@ avahi_LIBS = @avahi_LIBS@ 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@ gio_CFLAGS = @gio_CFLAGS@ gio_LIBS = @gio_LIBS@ gtk_requirement = @gtk_requirement@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infgtk_CFLAGS = @infgtk_CFLAGS@ infgtk_LIBS = @infgtk_LIBS@ infinity_CFLAGS = @infinity_CFLAGS@ infinity_LIBS = @infinity_LIBS@ infinoted_CFLAGS = @infinoted_CFLAGS@ infinoted_LIBS = @infinoted_LIBS@ infodir = @infodir@ inftext_CFLAGS = @inftext_CFLAGS@ inftext_LIBS = @inftext_LIBS@ inftextgtk_CFLAGS = @inftextgtk_CFLAGS@ inftextgtk_LIBS = @inftextgtk_LIBS@ install_sh = @install_sh@ libdaemon_CFLAGS = @libdaemon_CFLAGS@ libdaemon_LIBS = @libdaemon_LIBS@ 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@ runstatedir = @runstatedir@ 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 = \ ca-key.pem \ ca-crt.pem \ test-expire-key.pem \ test-expire-crt.pem \ test-expire-good-key.pem \ test-expire-good-crt.pem \ test-good-key.pem \ test-good-crt.pem all: all-am .SUFFIXES: $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(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) --foreign test/certs/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign test/certs/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: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs tags TAGS: ctags CTAGS: cscope cscopelist: 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: check-am all-am: Makefile installdirs: install: 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: 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." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic 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-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 -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool 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-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags-am uninstall uninstall-am .PRECIOUS: Makefile # 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: libinfinity-0.7.1/test/certs/PaxHeaders.26529/test-expire-good-crt.pem0000644000000000000000000000013213034342512022367 xustar0030 mtime=1483851082.049718536 30 atime=1483851082.049718536 30 ctime=1488261589.928137036 libinfinity-0.7.1/test/certs/test-expire-good-crt.pem0000644000175000017500000000372013034342512023123 0ustar00arminarmin00000000000000-----BEGIN CERTIFICATE----- MIIFlzCCA38CAQIwDQYJKoZIhvcNAQELBQAwgYAxCzAJBgNVBAYTAlVTMRYwFAYD VQQIDA1NYXNzYWNodXNldHRzMRAwDgYDVQQHDAdCZWxtb250MQ4wDAYDVQQKDAUw eDUzOTEXMBUGA1UEAwwOZ29iYnkuMHg1MzkuZGUxHjAcBgkqhkiG9w0BCQEWD2Fy bWluQGFyYnVyLm5ldDAgFw0xNTEwMTMwMTE5MzBaGA8zMDE0MDIxMzAxMTkzMFow gZ8xCzAJBgNVBAYTAlVTMRYwFAYDVQQIDA1NYXNzYWNodXNldHRzMRAwDgYDVQQH DAdCZWxtb250MSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxIzAh BgNVBAMMGmV4cGlyZS10ZXN0LmdvYmJ5LjB4NTM5LmRlMR4wHAYJKoZIhvcNAQkB Fg9hcm1pbkBhcmJ1ci5uZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC AQC/R61DnD5x3alpN4KSnZAN474bCdxG1+BxHZTxcZT4+0X8ofqE1pa8nx2WppyB wrPnyIUzYg4ZqCWYFfhqaZqyfManqQiHrhhkcKcgjHpFePiDiwbBMchQuCdmcXNE FC/Yg1E7IM3SIu059qCjm9Co9/wTLG0XiRrDEcyOup5JIN/BBO+NeXr0S7oiK7jB MarF6rtSrF4K6YjYHd7cxKolhmGzR1Rd7FcQjN8PNn4q5zdvmOU5TnYypC03q8ZY PGP3sQ4zCBXVJrkwxXezbVwCB3CkMsOyobv96vGWI4HQoJEkhxoDou6F/Y7STxzt wwEhVY8amUHzAG2hjdvpPn/g7WBfwVzh7oPhrIZRx5YOKRprT5F4rCQYHyYPgqC4 U3nP3/1ItYu9QxGYTZSMWE88kc+yguzZT0jI0t83bb1v+ngO1OWuQDOuYROFBAAf y0FOlj6FYX+/FVfqSusA/8pgozrQsXlh1LfP/snAhYCXzC2EuunLUpFfMW7sjn8+ +Co0sO9xmVAYfhE0nWKKIvacPCuM4HM1+JtCqA5+ubic4AlNFJVGoH/yoyFrfpCB o6/RfBVwzauUr/0icbqp6whTldeu3myOsM9lj3/T3YNydGTKAiSjpooMOkArpAXU Bn257chCwEgzMziXEKesGS6XIofEdjgJvXTfaMBzcjp3dQIDAQABMA0GCSqGSIb3 DQEBCwUAA4ICAQCcvQEpLbucfdhAJi9/GmzxRwki+Oly/Gxv09T2Xf8VlyDYJaRf IDuxaCl+pWBMV2XQf1+RJxEFhGHyMhlhWQSBAuS+K3mYqdv9N+oOQbt/IjHHj60+ 5IGnXgChwE+Bl6/q0a08NifnumKHClSvEfC1FsIpXyAFpgcRIKizrC3ymWJgm9C8 a5V3iySnFZEHgbLfUhLRg6RAUifiebhYcFqA0pt6aqHcCOLfDB7QtTrrGp1vj0S6 cqxHpJfosaDSy+gF/lAHTRsuYOq3RFTg0Fd9Wa9f67gZsFr7lgJBMqwMOdYwja6G 4/id/c45Gv4MOzmHva+gxtn/Unk5hRN4nc1bymO7g4EfQ96O3ZDYETzWZq5zJfck CKtc1JMJkOe28myNNSg1n25whdn9AQwv6JWPKj0r9j1qxZHA0sLG/EK50cdmqynj x19dtrvwJLhiD5d0VHL4uoV+R2V4By/gOliFaHdfsmluV/eWMxS89pQWo3sf7pkC 3ukxM7CP6Q8VBLiovYob2WZ2pMKOn7tQhm3C4uUUsRhCC5qHST+5b1DlIaK99jKA PHUs24aRijJSVbc1ZC8Ecm5LDbdzpC06MTjGd55fjMCzvTS8NOQjroccf+IsMukW QQI6XEc6VJsFvEOZu55IV6GHXNCem4ocwAjTIe4hHkMc623ZN4BP8tiUJA== -----END CERTIFICATE----- libinfinity-0.7.1/test/certs/PaxHeaders.26529/Makefile.am0000644000000000000000000000013213034544714017743 xustar0030 mtime=1483917772.614920442 30 atime=1483917772.614920442 30 ctime=1488261589.912137071 libinfinity-0.7.1/test/certs/Makefile.am0000644000175000017500000000027113034544714020475 0ustar00arminarmin00000000000000EXTRA_DIST = \ ca-key.pem \ ca-crt.pem \ test-expire-key.pem \ test-expire-crt.pem \ test-expire-good-key.pem \ test-expire-good-crt.pem \ test-good-key.pem \ test-good-crt.pem libinfinity-0.7.1/test/certs/PaxHeaders.26529/ca-key.pem0000644000000000000000000000013213034342512017553 xustar0030 mtime=1483851082.049718536 30 atime=1483851082.049718536 30 ctime=1488261589.912137071 libinfinity-0.7.1/test/certs/ca-key.pem0000644000175000017500000000625313034342512020313 0ustar00arminarmin00000000000000-----BEGIN RSA PRIVATE KEY----- MIIJKAIBAAKCAgEA+Xc2ONjb1wOVibJqWvaruN6dm8hJWBY0T5R9rtnhRki2lSvg DIfCEEMDtfumuWimKMi27X0OKIzEFnZHAbtr9J8HCWTIxNac7a9LMomNEPu8MM8p YsFLgwN8SNDgZi0OXuc6Ox81D0iT6xlNi1uLiaRRPjIMxlsF7oM4OL1QZkL9FChc sIO8Xx7lg0FgfBlY4UFCoFBQDYQDIfXZKmPG3uh+I07uB20hEv7ki4kgvusZmJgf ONB/meBt4rwH6XkrxR69phdph7SOB+CiE9H/TOup0wrOl6nzmYsp4+j3GrLW3iay EjfYtz12fmyBatdHElxVNOJZ99rFpnhLHBnc0B7BZ4pDj41lkytd47gGV6azLxVy m6IBzO+RsQQ7AhSznKnfnAyw4w5ryMjVLBOXJOzWwtchaD55lQLjveMosiFc/ipl ehFyFkCadENw+ttjnXqwfHHbAFB6GVzDKUa2I3XYNW5Ec+WP3ee7y3KBHuflMXUL 9FaHjVUlp/bKyiSNak9Ky1bXYTR7XUzrrqqY3tI2qT5XkJISgfbVTfWAa0am2jIt j7wfsw0rjmD7G6cFTLxj3do13C8mlV758Jn99kpxArSZjN5enPFRXD0ROJq7XGFl riQaHO+S2ehZauGY2wRKIYiy7FB+TrqMAfmc5/bIU6kGVpOWP0hU4ZkWwQ0CAwEA AQKCAgAf8av3y40bE1Jqt3X2/+8tVRRJhnQd23oHVrRhV3UJUvZOU7f04s1u16X5 /6dxxnzAbDNAZesSNjRFzA97oUxJnrN/+G/dBL5DkVbHueVeb13BwkVCaA4LUL7x dA3IB6z3ahSCzZQ1yM1oJW1QkwBjN69Pj4kjPTSdPiBM47EP5zQRCLoVwEi2xXYO QKjiOzyuW3T0olQd5vGfv6N3Uh99G7hLPSgtu0Oo8wrA82ZGDETSzWfyFoDAa4Sm q/03YFTCgRU313ej8PLe/1zBvPo8F1E/vPqHYTPYTYGntYUu3ge1mq7itlQB4tTx i2NnEvn+1+PxSarLmjAFCRJVHtqvawemGs7JqEz5jpsbpaZPIWUpIIGx2C0E5dh9 o2ZjrJd5CVt4rBHmpOcuDac4YCUFu/mZ6zYoTg6Pk3cill6mfhDG8WS21AL88drb n1jStgMl8xWSiRtwt08jOI7TjFlCSahYWdv83MOlxO7TOLN0AsZ3gf9vApYaqeP3 v4ry7oRjxTL+6MfKkyfDBOZLVe7CFB5pCixkeqUZT5l506T+wb1m2O4l3owrinOB 61XE02x7b9Yva/h9TKdDkddgUTIa+Km4nlbyG0Vpqg2GPnTWPsu5Ca6TcK1QtaSx iSg+UsoUCgWF4Y8OzV4J4tWy/kvB6FEmMhhzB8JeQqBwq9Zo4QKCAQEA/xYBOiPE Q31CJUbIfMR3J6ojK5y/GxEgM0A6JJIaMgl6mUNLI0gJHfhDwXyxOoKJdnZzUj9C H4OsJuhIbDBM3mkeQ82WL36TWy0Y9UKrvZScmTT+SqSYTB7PHwvdFmX1/bG/uD3V 1U/+XssbRBgufAiyWhXLZ8BYLcAlgtZ21u6CX/eXx71uiuO+E2Cz+vYZvM0BYcdX p0mdmZd7782UI9Y6P8xy95wNlOhbLHushCCI+QhO+nGO8qeziTCU0RKK1XTcoW5R 9E93YdYHBPl05SnSuMhfpYgVtR15Qqw4wiJ0bHMjzfzRdO/gDcvyL92gXobVH8uF idUEZaFqCQg0OwKCAQEA+lwNKakNsie18qsrzZ9xd1bRqJcSKMZM+9lKGGYRCZ2D 5n91C0C+4xhm3TWkWr8DZNNRkZI9a5/VwyEZx/RXsgOVpVKTU56ON+tb+GL1lqy3 emOmN2GLzqv9nwa64wyenacCNkJyW2YcSJ30ChaNo21jRTaOZH6RKGoYrPpZ2P1H y30NIRP9EP6p0gdu9xOEUyPyRszJLN85JcJKqrT2p+9bLYd2rQYlJVE4m/sokmGB QIBuWcpdL6qPEjgWdaCdpSmAXljaNMArrYYPyi4SqwPBIqWxHDLPQKOGyIUwUnR7 8Zl+2wSs513kCEdTwP/xz83dIBbJOO8rmkKeepvzVwKCAQBqLy3JlvPvKCgtvj5c +aekQkWrtO80hDeEPhs19/+hjqKTRBj2EdmBuUPzOkXIVmiEgKBWv3B2D+jMtWrY Zm7JMrbfgKghEy6iCK7YAa3eGAvsFsw4JDYlkbmkcdrRpRX2SlTFjDAEQO1hZmju Oqa3CSO9Lk9i3AWY3eB/i2ki5VwuOLHc+rUWaeFIzbt+H43tMuV9X27Ue2d4dT+p PkmJdXb/8cp12mco8mRpqv3Qbn62M8g0pqrbxgWNeUSpl29lleT16ieBbMcEWgTI BFOtxXArbXWrQW/P2foNUAW8gn02W+Ourqw+YlBBTgF9/WLxlm0HdEAddSgEamHq apjbAoIBAQC1MzSPp3xzKgylM0BD1ZehASRDefu5qTSEv1LCb/T62Zdil3NWDqlZ 4gppJm7rAv7o1Y1e59IueAOV8/od33otLCz999MLnWFflaf+EVmgkSdGnKLryF0Q 2yh4Fb3joPmYLw0JynPMNQ5ZfIDpYENpOj20FXVfxL842fk8EQJAa6iv3bVH8Jij 2T199sVYbDbEmeq7VXJxWKqa6pFyFgHDsBh0zmuVdTIjXTK0qkZGE+4hihLUSAPE ARUF4bRXtEUFChGPt41OypuSPspk0Y3PWqtJcVTLjPa12OUvcj50Hzypsye+Sxb9 adYmK8GxmU0h0uStWfCPlYMgZgEfyomHAoIBACTcmd/iMIY/3YXdGakxjZwML38A IdXer5BPt+f+oMHsogJwRTAoLmcAPHKEGLbxSfJFLZJ1F0WyB5BkxyDqiXSehYkq YP/2l9s2/3hK/IjgdYM5dwXBWA98tKc0A2RcOnIALmWFTFgTDQ0l5yRdo+wc7bmE RIHRwBY/AfaDeyXNB2kEoOg3w8WjgsP7JNfDo+eflJiAyOkHzYt7zFuoA5wzw8z3 xy+dQAt+fJQX/PdUST5AeI7wDfc1jFAjnZvbGAI+Wrw/cQG2O+Gf3vIJrr5m0f/O Xujsj41KF80hPdKHpgPjpIhAtcsjgaFvXpgMTDONxSYDCjvbmvNDTJTT2Co= -----END RSA PRIVATE KEY----- libinfinity-0.7.1/test/certs/PaxHeaders.26529/test-expire-key.pem0000644000000000000000000000013213034342512021441 xustar0030 mtime=1483851082.049718536 30 atime=1483851082.049718536 30 ctime=1488261589.916137062 libinfinity-0.7.1/test/certs/test-expire-key.pem0000644000175000017500000000625313034342512022201 0ustar00arminarmin00000000000000-----BEGIN RSA PRIVATE KEY----- MIIJKAIBAAKCAgEAvIsDCePg6HKUhTy8mEwXlNQ0rmCEzan6npxhrhDJebdvR5Nb Kqe/HwaSb9HlONvAY5Q/yd1m3iGao8O42B21KE04Ux51OQ38o1yMbOr4od4tLKuq un7Yew4FrZTUHKSkHhSMkMlS13Z9Bjfucvoj/dmtPzDoS3+twnVrTnSR53k9+nUB mPMVWB0Pk9rz6sUHgnJhjYJgs/hVIKPXy1qePe1PFvr8NDxfJ4vjTN8QeLxqta65 cViPrtFpMOMuixrk5zKDmSh1GSFbO2zFHDiPHV5nNQ5yGVUCoMUVA9QQ0Y/urgVD lxSiJvrpo0P/yk0UdMKfoR+pMna79mFtrZLMxZNhXSdtPQv0oYbW8OJCPD3czuVk UbSEbv7SQdkHWqjjwmW/XMhzTF5fVuSME20ez++0s4stqCgTfxRyXTzf+T/ahEBm +//KRmvw0CkXQ0yTKoNQHUFor5kPGhRC4dEzS+ZbnoeFA+G/swK2ZqgZBWCop7fV a27OSBRisNBBRhquI+1kzUGxiTriwRWgBBHmRLIA01J77Km8W8ByaB8Tu9X2HfBF MaZZi4FKo1DLRtTyp15pDHPBKswGlFjJloKoYAQy+GZOcd8+iTc1XHC9HOw0Zsch 7hQ58rZ/HSr1bZymmZYEz6LS99cMAryalC/h5vnH8Yb5ZyrVaZpfDWYOE/8CAwEA AQKCAgBl7mWjKC7EnIWNDswLLkAldyBQEeBabAYRUAxDFdJG2pPvx0unYO8jr+Ll Tz20oqF9dH2T/f2KI/K9jKfXNyBkfHLyBOptARHPo85LaDEpGbukhd6UWtVgmbEa KfcO0TflB0kDUcRWtjlbbkucn31r1Q4jtqYvgwSGuAJedQkYcmS+jhlh/jFQ5M0y K1JpX0HzFTGGVrE/OweS0OFukDwy0KRMkT5eYzEyaR9mxMXb8ElkleSt0apEYfST uI7GJ7EPCTE6UTQVdQIku2ZJHo7I2uvDNF8dMOdt0X7OBg1dronkTPZArKgJmOdN HAsi7M8dXMb+TeakYKq3xe6Mw2uui4lPc+7fG/mZwIXJr8EcJAo24M1UVtKcri+d gDQYGX4b9jQyWrl5DujWsnPN7nV275e8Mb9Q8gqftwEyiwpNmLWR5eH8AzorZ4/B 7CJgLa/UWb/zGXBKMfR/zYf3Ock0tIXusXnt4uAr1DOMoXLe6hOaumdz4Macimq5 0xH6EGhDayuOdCSL82sLqV6w+gra6KRFWbMC1s/UA9m5NaSeoHZ+/Dwz65bZms92 UjfE3w5N3uRxWf4ZZY7pjBJx4kS7p66rKb65rWmo3+ycDKaxE9jEVqgKLFpcgf06 RcTrqRKXCRu/LuwNRR0owV83F135JSFwq/hrtUm2ht/G9kNU+QKCAQEA5C1tbLsL fKJy/k46vzjJPlU0W9l3lOMJzobjTv0NnXuI+8MaaITR1QJUmXveF80Fnra86YPV TI1fRfVqOad+51DXiSrx51iAeh8cmM1znT2mZ37613myc/eWh6QH3b5d4TrVYe8T FP2t61nv2BA+KfV7USTOnnAbU5in9+xPtL4JO5X9n4bMQpeAeoYIjvAKLQKnhw7y hCw1wVEatCw3HaiobQaXbZVTBXsHwurtCqAkgi5okcncYEgSIMF3yKqeoElYbXmB heudSf7HGQd6i+XwllTDi9+k/zTMHsWC+xwsUZnKZUN0h+t2FPJWYMGs0sH/GR1a kgqH9OiEc1NqcwKCAQEA04hkp5yW8HXPzwF8/sRvDVPVu+/71BrIudrfmzQKFVcl x9ObC1iZLv9Bk96ArUrB2Q+9PMPz3gx1gGA5hc4F1m4vaUCqFYJ3Yr/lDstNELWi U/SXEiSpPiieMFVSNfv7UuO1Z4FEMh8Rz/U65n6BOPNQXmElg+JpATcij7gMqBcq YoKfdQ8v99xHOn1DUZIhJdlBy8FkztyboIJhmjs8dYDxgD6jLsD9UWmQSPfJ/HjQ JeOLZJiuS8b0TKce29DQhjknrpmJWeKSudZ3GlFikqOeLCVF12pb9jXRBbgYmTch 9cPPag9BSkwraa+X7RptwxfLgOA8J+xBqMUgN4xRRQKCAQEAuFU6oSw6C2XxICBy tSha61BKDCmSwWTo9z9hQt6LsT2rXDgxjV4/ZaWMUrIOqYunjqBx3PPzzPQok4u/ VPRLQPO+K8HVyt9ka0PXBlpznAPB+rpKSui1kZnisZGCCVFQ5jNxTryk3cBSUF9H s3Trw1ndVaA2iyhl6xLYHyF5ArrDGrABRG7RdLqPwGunXlHs5o/OZv1cTgqpIpMy z3soy30FE47PpmeLulG5422GMZ9N3x0+vQgmUGHowy2IZ0PvAe4+0bHnQRkm6DA7 B61TAtGvmsK/drAly0YL4JAPUG1iIEntiAEGkwdVTXa48VGFHH48Zz2ffXukeeWd ms04oQKCAQA6lR17JezPb3E73SemzvQKdttMjyvpE/nfLvSaYREh097MtpfLzp+t 2ldpAkgUtg11ddxsxb/2EPFBumRz4BjRx/YtahEwn888c/SV4kvXgtYP9j8YcTrF 0i3tKNP5y21RCWsl3TDryJsAQuQrDYHwKcJqQPFI0x1Njt1tfAVVUAUW/yH2I1yf gkvfsO1B2/x+JOsJ6OdoOsSG8VTih+E4kZtQbwh2XFBLibbB3o378+GBfMEP/RDY P6NMz0PGkNAPPCj3O+JEGHGWMgUOLtfj0JhvlWsAO554U3Mt6Ew3soMfMzlwIAVu 9CVZwZ2LtrQLQb3EVVWToOSWPvGrMJsZAoIBAAEdAF259ST+IzZP4iezaRVn/eKm cTexsPp+ZxJDi6D16AgaRbwQ433c62DRTSysZNE4K3LIhKzpDaWX6WMNF1Lggdi7 GRhx3Ucj5E/N5zFyBmryzhUPcUSZRbj+pr0QKeFngsFm9nJyHC5iuZA4Srwgv6P6 q2DRA9xv74KqFTVSbKUkoFhJyzAosCVq6E8l1PRVam3OYEtoRD/eS0x1qxuF2PB6 7YY/59gZfZ77OoGBlk9FfpvorSyCkbSvVA0OIX8JWdxJfCkafQQgyP2vubBu//Or PL5Sk81WbIp2GzD5FzO8qvWb/JNvsJi/cPnmKn7wPFP7giChlXF304IPaIk= -----END RSA PRIVATE KEY----- libinfinity-0.7.1/test/certs/PaxHeaders.26529/test-expire-crt.pem0000644000000000000000000000013213034342512021441 xustar0030 mtime=1483851082.049718536 30 atime=1483851082.049718536 30 ctime=1488261589.916137062 libinfinity-0.7.1/test/certs/test-expire-crt.pem0000644000175000017500000000366413034342512022204 0ustar00arminarmin00000000000000-----BEGIN CERTIFICATE----- MIIFgjCCA2oCAQEwDQYJKoZIhvcNAQELBQAwgYAxCzAJBgNVBAYTAlVTMRYwFAYD VQQIDA1NYXNzYWNodXNldHRzMRAwDgYDVQQHDAdCZWxtb250MQ4wDAYDVQQKDAUw eDUzOTEXMBUGA1UEAwwOZ29iYnkuMHg1MzkuZGUxHjAcBgkqhkiG9w0BCQEWD2Fy bWluQGFyYnVyLm5ldDAeFw0xNTA1MTAyMTQ3NTJaFw0xNTA1MTEyMTQ3NTJaMIGM MQswCQYDVQQGEwJVUzEWMBQGA1UECAwNTWFzc2FjaHVzZXR0czEQMA4GA1UEBwwH QmVsbW9udDEOMAwGA1UECgwFMHg1MzkxIzAhBgNVBAMMGmV4cGlyZS10ZXN0Lmdv YmJ5LjB4NTM5LmRlMR4wHAYJKoZIhvcNAQkBFg9hcm1pbkBhcmJ1ci5uZXQwggIi MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC8iwMJ4+DocpSFPLyYTBeU1DSu YITNqfqenGGuEMl5t29Hk1sqp78fBpJv0eU428BjlD/J3WbeIZqjw7jYHbUoTThT HnU5DfyjXIxs6vih3i0sq6q6fth7DgWtlNQcpKQeFIyQyVLXdn0GN+5y+iP92a0/ MOhLf63CdWtOdJHneT36dQGY8xVYHQ+T2vPqxQeCcmGNgmCz+FUgo9fLWp497U8W +vw0PF8ni+NM3xB4vGq1rrlxWI+u0Wkw4y6LGuTnMoOZKHUZIVs7bMUcOI8dXmc1 DnIZVQKgxRUD1BDRj+6uBUOXFKIm+umjQ//KTRR0wp+hH6kydrv2YW2tkszFk2Fd J209C/Shhtbw4kI8PdzO5WRRtIRu/tJB2QdaqOPCZb9cyHNMXl9W5IwTbR7P77Sz iy2oKBN/FHJdPN/5P9qEQGb7/8pGa/DQKRdDTJMqg1AdQWivmQ8aFELh0TNL5lue h4UD4b+zArZmqBkFYKint9Vrbs5IFGKw0EFGGq4j7WTNQbGJOuLBFaAEEeZEsgDT UnvsqbxbwHJoHxO71fYd8EUxplmLgUqjUMtG1PKnXmkMc8EqzAaUWMmWgqhgBDL4 Zk5x3z6JNzVccL0c7DRmxyHuFDnytn8dKvVtnKaZlgTPotL31wwCvJqUL+Hm+cfx hvlnKtVpml8NZg4T/wIDAQABMA0GCSqGSIb3DQEBCwUAA4ICAQC5jiwHw6ZfJ2Be PWXmaTf6omM457YG/ATl3QFUFwuffaFne396lJAuh/I7Oq8nFfObp081WNlohjk8 OfleGjEV0U5yhq/ZB35MVLt5SLRFOrKw5H6FeZawKxnz4PFuGsPNIvynagsDatzT 2iBPk4C+WsM1mF6NgErH9MNh7Cwo5g6inAzezXIgX+GsMTNaRS5Uhef38+jbxLbT qE1EpU/hG6vMIWWDmceF3OLaliwnofeoTisx3hhKMyunRrhR8daqwfyEVLxtFrtI akW1atOBI+t3PqaDghBeP3O1yJtaRlZy1S4V1UPng7USOXSpu3I+qkULz+6EmCbq fOhVSsuYxnRJHML1PAkDon++ADrwc+U0ayIxTUYi/Nf0IqAh+VYPu7/OG9eHu/EG sWmvwufPinVxHyU9D1T/lLSdb4agakqGm6q8L9KOcl/NhWLHfdxqFlgGevuyhUrJ m3dLcaEyNJZa23oDY4H7WyyRHO3LNBhW19Cq437s2eOYfiy/XTu8fLlJvT+cZbWo nyh1Q2cxgaN15Jw2EQJArlSUTxg2yW7VqpSdKZGtfKHClHqspvCJpX2yyecBRMLB fsMXXqzWFTZlkFN26h+zZAHkgbMqs9iIOv8SAqirRvJuuKJn3CaqAM5TmRRBEC/J DGpwUXBuSftA9SnrD7a885n9QsA8CQ== -----END CERTIFICATE----- libinfinity-0.7.1/test/certs/PaxHeaders.26529/ca-crt.pem0000644000000000000000000000013213034342512017553 xustar0030 mtime=1483851082.049718536 30 atime=1483851082.049718536 30 ctime=1488261589.916137062 libinfinity-0.7.1/test/certs/ca-crt.pem0000644000175000017500000000404213034342512020305 0ustar00arminarmin00000000000000-----BEGIN CERTIFICATE----- MIIF1TCCA72gAwIBAgIJANHP24YS11wSMA0GCSqGSIb3DQEBCwUAMIGAMQswCQYD VQQGEwJVUzEWMBQGA1UECAwNTWFzc2FjaHVzZXR0czEQMA4GA1UEBwwHQmVsbW9u dDEOMAwGA1UECgwFMHg1MzkxFzAVBgNVBAMMDmdvYmJ5LjB4NTM5LmRlMR4wHAYJ KoZIhvcNAQkBFg9hcm1pbkBhcmJ1ci5uZXQwHhcNMTUwNTEwMjEzNTQzWhcNMjUw NTA3MjEzNTQzWjCBgDELMAkGA1UEBhMCVVMxFjAUBgNVBAgMDU1hc3NhY2h1c2V0 dHMxEDAOBgNVBAcMB0JlbG1vbnQxDjAMBgNVBAoMBTB4NTM5MRcwFQYDVQQDDA5n b2JieS4weDUzOS5kZTEeMBwGCSqGSIb3DQEJARYPYXJtaW5AYXJidXIubmV0MIIC IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA+Xc2ONjb1wOVibJqWvaruN6d m8hJWBY0T5R9rtnhRki2lSvgDIfCEEMDtfumuWimKMi27X0OKIzEFnZHAbtr9J8H CWTIxNac7a9LMomNEPu8MM8pYsFLgwN8SNDgZi0OXuc6Ox81D0iT6xlNi1uLiaRR PjIMxlsF7oM4OL1QZkL9FChcsIO8Xx7lg0FgfBlY4UFCoFBQDYQDIfXZKmPG3uh+ I07uB20hEv7ki4kgvusZmJgfONB/meBt4rwH6XkrxR69phdph7SOB+CiE9H/TOup 0wrOl6nzmYsp4+j3GrLW3iayEjfYtz12fmyBatdHElxVNOJZ99rFpnhLHBnc0B7B Z4pDj41lkytd47gGV6azLxVym6IBzO+RsQQ7AhSznKnfnAyw4w5ryMjVLBOXJOzW wtchaD55lQLjveMosiFc/iplehFyFkCadENw+ttjnXqwfHHbAFB6GVzDKUa2I3XY NW5Ec+WP3ee7y3KBHuflMXUL9FaHjVUlp/bKyiSNak9Ky1bXYTR7XUzrrqqY3tI2 qT5XkJISgfbVTfWAa0am2jItj7wfsw0rjmD7G6cFTLxj3do13C8mlV758Jn99kpx ArSZjN5enPFRXD0ROJq7XGFlriQaHO+S2ehZauGY2wRKIYiy7FB+TrqMAfmc5/bI U6kGVpOWP0hU4ZkWwQ0CAwEAAaNQME4wHQYDVR0OBBYEFAtpZdHL1tG5lgY1pebQ HV9BqRtEMB8GA1UdIwQYMBaAFAtpZdHL1tG5lgY1pebQHV9BqRtEMAwGA1UdEwQF MAMBAf8wDQYJKoZIhvcNAQELBQADggIBAK8C9a/73E9KsFjhmbMRHyFQh0DqtC9R 1tketMDNkYXuYuCPb/Oyl4vtWcADA3DnEv8P1RZqt2w6Ke58cJJ/YFBWrgxDeaIa UFdRRwzWYwzBRFUFVBjb2G00PdosQi55lsizxLgZVeH9k745ZIGx18oo6nEXHNZ8 Ig0YKHwTVSS0eJ55RzR+CwaGwDXvezMNPVqPXtKOt39WLDyjlqSfi0naMNTyyJW1 uSZIc9AH/xu/okoJUt+dllrr/j0k01JgS16N/dquaaXGXAzrszAnG4YWjPgySik+ zxnQYBXpL+bzCGtB/0CxyajaANg4Q8n6CCr0fQ97DgRfBSLlH1MUHzK2zSdVDq+b NV+CtJ2U94AigaVDgfFCKZGRxZklnz56QL37oawi3yRh/Ba7GGCEplgYQc3pjGqc Wd+zD2e9vp5LI1POHBCeAp/4j3Kgx/uOCpiXJfBVfkQwZ032I1E1DzrJkYEuXg/Q +07MWPxiJLBqr0ROgq2pj3i5bwIIaf/yubeQG3ftFmW2AcovZZTFz6QQr789+EgY K5u4dT/rQIOhbWZuDfP3/RCE727xCjheGpNM6d6458mf33u6wvo0aRUjl3fIhgJ2 M3X5hm3SjorN2oeCTXVDIMazjfPZQYAcKgSWhn/UjLK87vnECk5ABuxb8ycAcEd2 HM48UDyzAu7J -----END CERTIFICATE----- libinfinity-0.7.1/test/certs/PaxHeaders.26529/test-good-key.pem0000644000000000000000000000013213034342512021075 xustar0030 mtime=1483851082.049718536 30 atime=1483851082.049718536 30 ctime=1488261589.928137036 libinfinity-0.7.1/test/certs/test-good-key.pem0000644000175000017500000000625713034342512021641 0ustar00arminarmin00000000000000-----BEGIN RSA PRIVATE KEY----- MIIJKgIBAAKCAgEA5ZJghSodeZLfSqSaFoV8LlWK2mDXERzW+uSr38bn0LkCwMmb Pq7ThLzm+Glq5ArnbCByZo6BVHB4MjhdUS0o8fiKXkMjJ/HlrC4WPmvrnA1bEOeG t9EjXDcfAAAWUjma2BtDv9N7ZKI0LMaqTFg05vmItyCMGNILdFHkZO7fgy1OXw20 g4xPILLuvIIe4ciNeMpQyCTYl+eZ7EAhXjDNZp62EOohZPj04jZllbZwUsDVbFdm 38RM+TXNXcs6gZKHYlQVXFZXfQKvof2hGT2sNl8h/ZKOiCCKtSdQK7j4i+QiKsu7 oWh/uSyU8d/c3ddSe23Zxro7pqKeJLIu1a9qC1QzcV2K7sKXUR3+7P2DEDQKupgv w3esAsjXfvqutiNKGax2yY0WzQ5UrwTuwqxnCM25j3oPrKd8jheUJWsBCjfT/+Vc McLylQXrZm4AKtuSj3H6GhNCOSZakZghNwmYFB3jwF9egkb6qpy8yat1Q9ZS6MYT QPQQrL4363LFEc/ULOz65ZXSwifdvD3jp/BSH+I3jGThYPHriZOzfnEuEVw2qqbz MjX7M9iG0k5GBLDbo/j/21Yje5PS/Gq9PMiMezQOZAvBC4PAZ/dRRqGEiqvApdx4 pRtKl44OaLOfQPk0OoE5Wd0SUEuaVZ9UMZbxsEuQzbK2xG3lql9Nw6kLSvECAwEA AQKCAgEAita63u44gzULK+Zedi5mitMbNbUJfIT3kybGt4Bg5D9v5c5HwGIU9BsW iLegeKgLi74X0eRvXPTkDGNANH7eW3CXpihuU5Mc9sOsmjXEeU0ufQu40uR9wSBo 9CQZW8MQ3Y+nqpSo9JSQf1/q0F8sJ2BUiYP6lmw5lzCLs2sv6/JzilMMj95EYJ82 ePUs3hnfTWT19AUspLnhwhqK058qKdzkeVhPt/REjaaeSyvZxIJw0KQPSFc8wh8C w63MBV7r19DIVl61bJo6Q/rS+iPtSbjBIs0GvFcJ7EMJXlfwoRHog/9Qy24aiI/o yFs+BUBa1uD5qxEoUD/a6pCEeKEsvOXW+M2PMHfuSY+TjXlECIiWqpaDtDX7hz2b XkBdYGHd9aazhiEnItkEDrS+vBLjRl/HUCuQIru6Kbqf0tJ8oLWPER5Tk6A68FZf VWn2IDZBYrmT9QAMZYbu61vAxLv3EqAlSZ5ESQ9GpQ6W4gVObOvlE/rR7IQGcRup e2Buk5YsHqeJk6svmhXWXMwkC3+SY9y1ue7XDmgeiUDT3K6//pmPyOf/7HC/Fdb0 /KR/CPm96p7eP7Hw5j9QB4EX8lHs7qZe3eV+n486juRrPDmpS3BM8E+ZHadAc0bi Oz+ETDG91n4219zVBoPpDfYE1e11YvcmF4UHxl3rvwfQUr5sDsECggEBAPsfmBD2 tsgk6Ds6hwlJ39ix2vku9wvysAAzT65722/7zJgREG95A7CPh+09olyxVuL3jccD 0BUWE0aXZgKw265hAPdFUg0/4bqvToL5hgehXG+XiETtlxcjuXRQBaSiZDzDV+t+ hBFwX1VDh5T7Trf/QSf30eUzYIXzXRhkR22ezx2ZkUFNRPcJ8cWTCpJ5HynymE3g DCwmXgAgqtBav4TXAtRW3kVrtQzmQrrrFlMMsgDAWSLSWJ+/Muv04M8GCI9F0XOf U/KIZiCdjBQ1QrIM6vKds/eXohbuMUqlsm18GUDRRzyosijE7OgsMbVn3pQRASMw eix7/JC92DqINNkCggEBAOoHpMwmRkIcQ4Caf7Gsdn2Lwylvhp7/JJ7wQlCCWJix XWxIciJRFjHCcRZgvUxcnJOLeWJimMX2ck+x9pWMd97YIcepH7gVjqTUK6XxskeH CKiGHaX98aTy65O0W2r+XTDPolI2LCkuAbDllwjWtNShW0lahcZEKXNepmF/AwYP iZ3nOnNjD6aYwIoSUGrTC3x3/OPF4akD747CyZZLA7Q1bjKL3h/UgVivX6+Yg5hd pYk56wCAKbBQlhTQfQhJ54xqwuRRZy4mnMuSjtNdzoE4l85CiQTdCRDo7VWJTw3d 3IqDo5YurXugnvhVrxc5F7jFcQRvlz3XHO+NWhMvF9kCggEBAL95XYdBtihxC6lt fNz2OPmO0vnAd5nil5Pvi8fspGqEQYGJMVDtooSTS/72ScAHb8prGu0t2RDa3iOq +JsAouAZEpV3g5KarNCdLm3rN+jFfieQENUNm3CHSraG9WaMc4VpJLZopuZtGiN2 9AAChgkBVXrWGHJ8dBJudwNMIrJQrndRSlHSSs1aBcCx1xPLypk/YiWuuVlIf8/1 GIj5SKJPFtc0zRF9iHSndSX0bfcw7OBpyQ0l+XEEZh1Hf8oaPZiQkZ1pVKbOnaAs wEwAODRuaQ5IdJpKQcreHzNdl+inANJNP9XegslXLZPxbo10/19Cf+2G3wDgILl0 J1Sp2jECggEBAJoazG7N6UfROrXthpZlnWTQaoPXd4stMV0jkldXbaWmbYFHNzjX skiz5Cm7LAujlEsn9ZdOm5EH1oAaDOivJaPtKFlESam7MEHjoJZWUHH/PjlSjyVl 0gAvIecSRXxv4MeqghWmrG+1ZtGobUsZrtuxIN5tqFdFPRJGSkM7Eq+j/Zen0np2 ybCHN4nzw1aEgDTHAhSukgjsmYulQn8gCGFbKaRJK8xD76SJXvXO9SCY0c9J/zBG NK1wc1NjcmHJ4Jo7Fvinjcz7ChaW/Eu8oqW+sV/Vukokjrq+1sGTeCYGaRog0tCr DfuxadzW90PQiYlXIjOsk6faBajMqHqncQkCggEAEqck850nvidKF5JE0DIxAKqj 0Vh2QAxYJ4fh2TMpGNlI9g+sC/wEy2h280+ZPGCjy+1y0cwU1AacPBwWk5BDis5d yRNYb0hlYRdfvrW/X7y9kSTOfKqPqX0BTBZv5aP2WEh5yWIs7PkzhWL+cljmW1nV W2UR47CzHR/B17kU+k8PtH5Cw4x5FzSpFIovRpadWMhN8R4S/9syMKIlEku7Qhk0 nsthRRJIMkD0BdIPJyzJa1ROhCPZs3bmGiqwBCHnAbG83RGFQSXDGKw14i4/7QNP AEgwV+fOePGkB+HY9C8iL91EhYX8oJlyKgRKabMCZ68X3BCSGP8W7pgcKWgBPQ== -----END RSA PRIVATE KEY----- libinfinity-0.7.1/test/certs/PaxHeaders.26529/test-good-crt.pem0000644000000000000000000000013213034342512021075 xustar0030 mtime=1483851082.049718536 30 atime=1483851082.049718536 30 ctime=1488261589.928137036 libinfinity-0.7.1/test/certs/test-good-crt.pem0000644000175000017500000000371413034342512021634 0ustar00arminarmin00000000000000-----BEGIN CERTIFICATE----- MIIFlTCCA30CAQIwDQYJKoZIhvcNAQELBQAwgYAxCzAJBgNVBAYTAlVTMRYwFAYD VQQIDA1NYXNzYWNodXNldHRzMRAwDgYDVQQHDAdCZWxtb250MQ4wDAYDVQQKDAUw eDUzOTEXMBUGA1UEAwwOZ29iYnkuMHg1MzkuZGUxHjAcBgkqhkiG9w0BCQEWD2Fy bWluQGFyYnVyLm5ldDAgFw0xNTA1MTcyMzQxMDJaGA8zMDE0MDkxNzIzNDEwMlow gZ0xCzAJBgNVBAYTAlVTMRYwFAYDVQQIDA1NYXNzYWNodXNldHRzMRAwDgYDVQQH DAdCZWxtb250MSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxITAf BgNVBAMMGHRlc3QtZ29vZC5nb2JieS4weDUzOS5kZTEeMBwGCSqGSIb3DQEJARYP YXJtaW5AYXJidXIubmV0MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA 5ZJghSodeZLfSqSaFoV8LlWK2mDXERzW+uSr38bn0LkCwMmbPq7ThLzm+Glq5Arn bCByZo6BVHB4MjhdUS0o8fiKXkMjJ/HlrC4WPmvrnA1bEOeGt9EjXDcfAAAWUjma 2BtDv9N7ZKI0LMaqTFg05vmItyCMGNILdFHkZO7fgy1OXw20g4xPILLuvIIe4ciN eMpQyCTYl+eZ7EAhXjDNZp62EOohZPj04jZllbZwUsDVbFdm38RM+TXNXcs6gZKH YlQVXFZXfQKvof2hGT2sNl8h/ZKOiCCKtSdQK7j4i+QiKsu7oWh/uSyU8d/c3ddS e23Zxro7pqKeJLIu1a9qC1QzcV2K7sKXUR3+7P2DEDQKupgvw3esAsjXfvqutiNK Gax2yY0WzQ5UrwTuwqxnCM25j3oPrKd8jheUJWsBCjfT/+VcMcLylQXrZm4AKtuS j3H6GhNCOSZakZghNwmYFB3jwF9egkb6qpy8yat1Q9ZS6MYTQPQQrL4363LFEc/U LOz65ZXSwifdvD3jp/BSH+I3jGThYPHriZOzfnEuEVw2qqbzMjX7M9iG0k5GBLDb o/j/21Yje5PS/Gq9PMiMezQOZAvBC4PAZ/dRRqGEiqvApdx4pRtKl44OaLOfQPk0 OoE5Wd0SUEuaVZ9UMZbxsEuQzbK2xG3lql9Nw6kLSvECAwEAATANBgkqhkiG9w0B AQsFAAOCAgEAF0d4g3ZSkyCbEq41iyB0Lv/AZI7TXLeADZ7RoDBcgM5WwuE/9Q0y mZLTXAbmX08SjuZS36Kb3OU7ZHNSI12rsttnFE/8lu8Pjy4nai/C74aedbhdXhIQ eesA0WN8mLcwNj/9S7gY9uf709Zxi7V5NIuXttUQ/NgDN77Wmrl3JYX5BFncX6AA f16LA88Bw1nMAyJCZbrYFIqNqbde7hJFL4EjuS5JdpYTRHF7KsUUopZBwae8P+4h Kg8ngmpDHkOuJtYv3UYhwwFggcofRJAGlEz3GquwujO+HC1hYjzrTRlbxPR2Uhff oKswsSV6brMgSdY2tHfpY5x3rreqaaaCkAAmJwYcBKR+EaC+K6/IgzniHlpQ58yP /KJde0HhfM6SDuEDc1CNA4P7lqF9nduVycs1bluNrf5x2G2WA5IVfACqOpsILb1+ XXQZtvMAIU/pl+B4fc1HW53GhY7V4bxijSq+klH2LpJD31TjdKSaOFKAb+Yv1Ya2 IdbIAwVSNSVbAoHaT4OPxX69H2dkdozcwC9r/Ir70fgHZFw/KLVvhPwZwmmtmx5t Td5fXdLNd3x+SQlmtt1LDzv/Q4MFm9toYhzI6bHG4utBwxxRJQOWtxzy5Hp07Vz+ ecfldMPYzBeY09oZaYdsLtypBXWakAMsy6t3h61S6zQJB6c0OxdmKjE= -----END CERTIFICATE----- libinfinity-0.7.1/test/PaxHeaders.26529/inf-test-mass-join.c0000644000000000000000000000013213034342512020352 xustar0030 mtime=1483851082.053718557 30 atime=1483851082.053718557 30 ctime=1488261589.724137482 libinfinity-0.7.1/test/inf-test-mass-join.c0000644000175000017500000003004513034342512021106 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include typedef struct _InfTestMassJoiner InfTestMassJoiner; struct _InfTestMassJoiner { InfCommunicationManager* communication_manager; InfcBrowser* browser; InfcSessionProxy* session; gchar* document; gchar* username; }; typedef struct _InfTestMassJoin InfTestMassJoin; struct _InfTestMassJoin { InfIo* io; GSList* joiners; }; static InfSession* inf_test_mass_join_session_new(InfIo* io, InfCommunicationManager* manager, InfSessionStatus status, InfCommunicationGroup* sync_group, InfXmlConnection* sync_connection, const gchar* path, gpointer user_data) { InfTextDefaultBuffer* buffer; InfTextSession* session; buffer = inf_text_default_buffer_new("UTF-8"); session = inf_text_session_new( manager, INF_TEXT_BUFFER(buffer), io, status, sync_group, sync_connection ); g_object_unref(buffer); return INF_SESSION(session); } static const InfcNotePlugin INF_TEST_MASS_JOIN_TEXT_PLUGIN = { NULL, "InfText", inf_test_mass_join_session_new }; static void inf_test_mass_join_user_join_finished_cb(InfRequest* request, const InfRequestResult* result, const GError* error, gpointer user_data) { InfTestMassJoiner* joiner; joiner = (InfTestMassJoiner*)user_data; if(error == NULL) { fprintf(stdout, "Joiner %s: User joined!\n", joiner->username); } else { fprintf( stderr, "Joiner %s: User join failed: %s\n", joiner->username, error->message ); inf_xml_connection_close(infc_browser_get_connection(joiner->browser)); } } static void inf_test_mass_join_join_user(InfTestMassJoiner* joiner) { InfSession* session; InfAdoptedStateVector* v; GParameter params[3] = { { "name", { 0 } }, { "vector", { 0 } }, { "caret-position", { 0 } } }; g_value_init(¶ms[0].value, G_TYPE_STRING); g_value_init(¶ms[1].value, INF_ADOPTED_TYPE_STATE_VECTOR); g_value_init(¶ms[2].value, G_TYPE_UINT); g_value_set_static_string(¶ms[0].value, joiner->username); g_object_get(G_OBJECT(joiner->session), "session", &session, NULL); v = inf_adopted_algorithm_get_current( inf_adopted_session_get_algorithm(INF_ADOPTED_SESSION(session)) ); g_object_unref(session); g_value_set_boxed(¶ms[1].value, v); g_value_set_uint(¶ms[2].value, 0u); inf_session_proxy_join_user( INF_SESSION_PROXY(joiner->session), 3, params, inf_test_mass_join_user_join_finished_cb, joiner ); g_value_unset(¶ms[2].value); g_value_unset(¶ms[1].value); g_value_unset(¶ms[0].value); } static void inf_test_mass_join_session_synchronization_failed_cb(InfSession* session, InfXmlConnection* connection, const GError* error, gpointer user_data) { InfTestMassJoiner* joiner; joiner = (InfTestMassJoiner*)user_data; fprintf( stderr, "Joiner %s: Session synchronization failed: %s\n", joiner->username, error->message ); inf_xml_connection_close(infc_browser_get_connection(joiner->browser)); } static void inf_test_mass_join_session_synchronization_complete_cb(InfSession* session, InfXmlConnection* connection, gpointer user_data) { InfTestMassJoiner* joiner; joiner = (InfTestMassJoiner*)user_data; inf_test_mass_join_join_user(joiner); } static void inf_test_mass_join_subscribe_finished_cb(InfRequest* request, const InfRequestResult* result, const GError* error, gpointer user_data) { InfTestMassJoiner* joiner; const InfBrowserIter* iter; InfSession* session; joiner = (InfTestMassJoiner*)user_data; inf_request_result_get_subscribe_session(result, NULL, &iter, NULL); joiner->session = INFC_SESSION_PROXY( inf_browser_get_session( INF_BROWSER(joiner->browser), iter ) ); g_assert(joiner->session != NULL); g_object_get(G_OBJECT(joiner->session), "session", &session, NULL); switch(inf_session_get_status(session)) { case INF_SESSION_PRESYNC: case INF_SESSION_SYNCHRONIZING: g_signal_connect_after( G_OBJECT(session), "synchronization-failed", G_CALLBACK(inf_test_mass_join_session_synchronization_failed_cb), joiner ); g_signal_connect_after( G_OBJECT(session), "synchronization-complete", G_CALLBACK(inf_test_mass_join_session_synchronization_complete_cb), joiner ); break; case INF_SESSION_RUNNING: inf_test_mass_join_join_user(joiner); break; case INF_SESSION_CLOSED: fprintf( stderr, "Joiner %s: Session closed after subscription\n", joiner->username ); inf_xml_connection_close(infc_browser_get_connection(joiner->browser)); break; } g_object_unref(session); } static void inf_test_mass_join_explore_finished_cb(InfRequest* request, const InfRequestResult* result, const GError* error, gpointer user_data) { InfTestMassJoiner* joiner; InfBrowser* browser; InfBrowserIter iter; const char* name; gboolean document_exists; joiner = (InfTestMassJoiner*)user_data; browser = INF_BROWSER(joiner->browser); inf_browser_get_root(browser, &iter); if(inf_browser_get_child(browser, &iter) == FALSE) { fprintf( stderr, "Joiner %s: Document %s does not exist\n", joiner->username, joiner->document ); inf_xml_connection_close(infc_browser_get_connection(joiner->browser)); } document_exists = FALSE; do { name = inf_browser_get_node_name(browser, &iter); if(strcmp(name, joiner->document) == 0) { document_exists = TRUE; inf_browser_subscribe( browser, &iter, inf_test_mass_join_subscribe_finished_cb, joiner ); break; } } while(inf_browser_get_next(browser, &iter) == TRUE); if(!document_exists) { fprintf( stderr, "Joiner %s: Document %s does not exist\n", joiner->username, joiner->document ); inf_xml_connection_close(infc_browser_get_connection(joiner->browser)); } } static void inf_test_mass_join_browser_notify_status_cb(GObject* object, const GParamSpec* pspec, gpointer user_data) { InfBrowser* browser; InfBrowserStatus status; InfBrowserIter iter; InfTestMassJoin* massjoin; InfTestMassJoiner* joiner; GSList* item; browser = INF_BROWSER(object); massjoin = (InfTestMassJoin*)user_data; joiner = NULL; for(item = massjoin->joiners; item != NULL; item = item->next) { joiner = (InfTestMassJoiner*)item->data; if(INF_BROWSER(joiner->browser) == browser) break; } g_assert(joiner != NULL); g_object_get(G_OBJECT(browser), "status", &status, NULL); switch(status) { case INF_BROWSER_OPENING: /* nothing to do */ break; case INF_BROWSER_OPEN: fprintf(stdout, "Joiner %s: Connected\n", joiner->username); inf_browser_get_root(browser, &iter); inf_browser_explore( browser, &iter, inf_test_mass_join_explore_finished_cb, joiner ); break; case INF_BROWSER_CLOSED: fprintf(stdout, "Joiner %s: Disconnected\n", joiner->username); massjoin->joiners = g_slist_remove(massjoin->joiners, joiner); if(massjoin->joiners == NULL) inf_standalone_io_loop_quit(INF_STANDALONE_IO(massjoin->io)); break; default: g_assert_not_reached(); break; } } static void inf_test_mass_join_connect(InfTestMassJoin* massjoin, const char* hostname, guint port, const char* document, const char* username) { InfIpAddress* addr; InfTcpConnection* tcp; InfXmppConnection* xmpp; InfTestMassJoiner* joiner; InfXmlConnection* xml; GError* error; addr = inf_ip_address_new_from_string(hostname); tcp = inf_tcp_connection_new(massjoin->io, addr, port); xmpp = inf_xmpp_connection_new( tcp, INF_XMPP_CONNECTION_CLIENT, g_get_host_name(), hostname, INF_XMPP_CONNECTION_SECURITY_BOTH_PREFER_TLS, NULL, NULL, NULL ); joiner = g_slice_new(InfTestMassJoiner); joiner->communication_manager = inf_communication_manager_new(); joiner->browser = infc_browser_new( massjoin->io, joiner->communication_manager, INF_XML_CONNECTION(xmpp) ); joiner->session = NULL; joiner->document = g_strdup(document); joiner->username = g_strdup(username); g_object_unref(xmpp); g_object_unref(tcp); inf_ip_address_free(addr); massjoin->joiners = g_slist_prepend(massjoin->joiners, joiner); infc_browser_add_plugin(joiner->browser, &INF_TEST_MASS_JOIN_TEXT_PLUGIN); g_signal_connect( G_OBJECT(joiner->browser), "notify::status", G_CALLBACK(inf_test_mass_join_browser_notify_status_cb), massjoin ); error = NULL; xml = infc_browser_get_connection(joiner->browser); if(inf_xml_connection_open(xml, &error) == FALSE) { fprintf( stderr, "Joiner %s: Failed to connect to %s: %s\n", joiner->username, hostname, error->message ); g_error_free(error); massjoin->joiners = g_slist_remove(massjoin->joiners, joiner); if(massjoin->joiners == NULL) inf_standalone_io_loop_quit(INF_STANDALONE_IO(massjoin->io)); } } int main(int argc, char* argv[]) { InfTestMassJoin massjoin; GError* error; int i; gchar* name; error = NULL; if(!inf_init(&error)) { fprintf(stderr, "%s\n", error->message); return -1; } massjoin.io = INF_IO(inf_standalone_io_new()); massjoin.joiners = NULL; for(i = 0; i < 128; ++i) { name = g_strdup_printf("MassJoin%03d", i); inf_test_mass_join_connect( &massjoin, "127.0.0.1", inf_protocol_get_default_port(), "Test", name ); g_free(name); //g_usleep(100000); } inf_standalone_io_loop(INF_STANDALONE_IO(massjoin.io)); return 0; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/test/PaxHeaders.26529/inf-test-text-quick-write.c0000644000000000000000000000013213034342512021700 xustar0030 mtime=1483851082.053718557 30 atime=1483851082.053718557 30 ctime=1488261589.736137456 libinfinity-0.7.1/test/inf-test-text-quick-write.c0000644000175000017500000003600013034342512022431 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include typedef struct _InfTestTextQuickWrite InfTestTextQuickWrite; struct _InfTestTextQuickWrite { InfCertificateCredentials* credentials; gchar* content; gsize content_pos; gsize content_length; InfStandaloneIo* io; InfXmppConnection* conn; InfBrowser* browser; InfSessionProxy* proxy; InfSession* session; InfUser* user; InfTextBuffer* buffer; }; static InfSession* inf_test_text_quick_write_session_new(InfIo* io, InfCommunicationManager* manager, InfSessionStatus status, InfCommunicationGroup* sync_group, InfXmlConnection* sync_connection, const gchar* path, gpointer user_data) { InfTextDefaultBuffer* buffer; InfTextSession* session; buffer = inf_text_default_buffer_new("UTF-8"); session = inf_text_session_new( manager, INF_TEXT_BUFFER(buffer), io, status, sync_group, sync_connection ); g_object_unref(buffer); return INF_SESSION(session); } static const InfcNotePlugin INF_TEST_TEXT_QUICK_WRITE_PLUGIN = { NULL, "InfText", inf_test_text_quick_write_session_new }; static void inf_test_text_quick_write_reconnect(InfTestTextQuickWrite* test); static void inf_test_text_quick_write_schedule_next(InfTestTextQuickWrite* test); static void inf_test_text_quick_write_next_cb(gpointer user_data) { InfTestTextQuickWrite* test; int action; test = (InfTestTextQuickWrite*)user_data; /* Decide what to do */ action = g_random_int_range(0, 100000); if(action < 50) { /* Start from scratch */ inf_test_text_quick_write_reconnect(test); } else if(action < 90000) { /* Write next character. */ /* TODO: Make this UTF-8 aware */ inf_text_buffer_insert_text( test->buffer, MIN(test->content_pos, inf_text_buffer_get_length(test->buffer)), &test->content[test->content_pos], 1, 1, test->user ); /* Move content pointer */ ++test->content_pos; if(test->content[test->content_pos] == '\0') test->content_pos = 0; /* Schedule next operation */ inf_test_text_quick_write_schedule_next(test); } else { /* Remove last character */ if(inf_text_buffer_get_length(test->buffer) > 0 && test->content_pos > 0) { inf_text_buffer_erase_text( test->buffer, test->content_pos - 1, 1, test->user ); /* Move content pointer */ g_assert(test->content_length > 0); if(test->content_pos == 0) test->content_pos = test->content_length - 1; else --test->content_pos; } /* Schedule next operation */ inf_test_text_quick_write_schedule_next(test); } } static void inf_test_text_quick_write_schedule_next(InfTestTextQuickWrite* test) { int secs; secs = g_random_int_range(10, 50); inf_io_add_timeout( INF_IO(test->io), secs, inf_test_text_quick_write_next_cb, test, NULL ); } static void inf_test_text_quick_write_user_join_cb(InfRequest* request, const InfRequestResult* result, const GError* error, gpointer user_data) { InfTestTextQuickWrite* test; test = (InfTestTextQuickWrite*)user_data; if(error != NULL) { fprintf(stderr, "%s\n", error->message); inf_standalone_io_loop_quit(test->io); } else { inf_request_result_get_join_user(result, NULL, &test->user); g_object_ref(test->user); /* We are ready to rumble now. First, delete all * text that is in the buffer already. */ test->buffer = INF_TEXT_BUFFER(inf_session_get_buffer(test->session)); g_object_ref(test->buffer); if(inf_text_buffer_get_length(test->buffer) > 0) { inf_text_buffer_erase_text( test->buffer, 0, inf_text_buffer_get_length(test->buffer), test->user ); } inf_test_text_quick_write_schedule_next(test); } } static void inf_test_text_quick_write_join_user(InfTestTextQuickWrite* test) { inf_text_session_join_user( test->proxy, "TestUser", INF_USER_ACTIVE, 0.0, 0, 0, inf_test_text_quick_write_user_join_cb, test ); } static void inf_test_text_quick_write_session_notify_status_cb(GObject* object, GParamSpec* pspec, gpointer user_data) { InfTestTextQuickWrite* test; test = (InfTestTextQuickWrite*)user_data; if(inf_session_get_status(test->session) == INF_SESSION_RUNNING) inf_test_text_quick_write_join_user(test); if(inf_session_get_status(test->session) == INF_SESSION_CLOSED) { fprintf(stderr, "Session closed remotely\n"); inf_standalone_io_loop_quit(test->io); } } static void inf_test_text_quick_write_subscribe_cb(InfRequest* request, const InfRequestResult* result, const GError* error, gpointer user_data) { InfTestTextQuickWrite* test; test = (InfTestTextQuickWrite*)user_data; if(error != NULL) { fprintf(stderr, "%s\n", error->message); inf_standalone_io_loop_quit(test->io); } else { inf_request_result_get_subscribe_session( result, NULL, NULL, &test->proxy ); g_object_ref(test->proxy); g_object_get(test->proxy, "session", &test->session, NULL); g_signal_connect( G_OBJECT(test->session), "notify::status", G_CALLBACK(inf_test_text_quick_write_session_notify_status_cb), test ); if(inf_session_get_status(test->session) == INF_SESSION_RUNNING) inf_test_text_quick_write_join_user(test); } } static void inf_test_text_quick_write_explore_cb(InfRequest* request, const InfRequestResult* result, const GError* error, gpointer user_data) { InfTestTextQuickWrite* test; InfBrowserIter iter; gboolean have_iter; test = (InfTestTextQuickWrite*)user_data; /* The root node has been explored. Subscribe to the "/test" document. */ if(error != NULL) { fprintf(stderr, "%s\n", error->message); inf_standalone_io_loop_quit(test->io); } else { inf_browser_get_root(test->browser, &iter); for(have_iter = inf_browser_get_child(test->browser, &iter); have_iter == TRUE; have_iter = inf_browser_get_next(test->browser, &iter)) { if(strcmp(inf_browser_get_node_name(test->browser, &iter), "test") == 0) { inf_browser_subscribe( test->browser, &iter, inf_test_text_quick_write_subscribe_cb, test ); break; } } if(have_iter == FALSE) { fprintf(stderr, "No document named /test\n"); inf_standalone_io_loop_quit(test->io); } } } static void inf_test_text_quick_write_error_cb(InfcBrowser* browser, GError* error, gpointer user_data) { fprintf(stderr, "Connection error: %s\n", error->message); } static void inf_test_text_quick_write_notify_status_cb(GObject* object, GParamSpec* pspec, gpointer user_data) { InfTestTextQuickWrite* test; InfBrowserStatus status; InfBrowserIter iter; test = (InfTestTextQuickWrite*)user_data; g_object_get(G_OBJECT(test->browser), "status", &status, NULL); if(status == INF_BROWSER_OPEN) { printf("Connection established\n"); /* Explore root node */ inf_browser_get_root(test->browser, &iter); inf_browser_explore( test->browser, &iter, inf_test_text_quick_write_explore_cb, test ); } if(status == INF_BROWSER_CLOSED) { if(inf_standalone_io_loop_running(test->io)) inf_standalone_io_loop_quit(test->io); } } static void inf_test_text_quick_write_disconnect(InfTestTextQuickWrite* test) { if(test->buffer != NULL) { g_object_unref(test->buffer); test->buffer = NULL; } if(test->user != NULL) { g_object_unref(test->user); test->user = NULL; } if(test->session != NULL) { inf_signal_handlers_disconnect_by_func( G_OBJECT(test->session), G_CALLBACK(inf_test_text_quick_write_session_notify_status_cb), test ); g_object_unref(test->session); test->session = NULL; } if(test->proxy != NULL) { g_object_unref(test->proxy); test->proxy = NULL; } if(test->browser != NULL) { inf_signal_handlers_disconnect_by_func( G_OBJECT(test->browser), G_CALLBACK(inf_test_text_quick_write_notify_status_cb), test ); inf_signal_handlers_disconnect_by_func( G_OBJECT(test->browser), G_CALLBACK(inf_test_text_quick_write_error_cb), test ); g_object_unref(test->browser); test->browser = NULL; } if(test->conn != NULL) { g_object_unref(test->conn); test->conn = NULL; } } static void inf_test_text_quick_write_reconnect(InfTestTextQuickWrite* test) { const char* hostname; InfNameResolver* resolver; InfTcpConnection* tcp_conn; InfCommunicationManager* manager; GError* error; test->content_pos = 0; error = NULL; inf_test_text_quick_write_disconnect(test); hostname = "londeroth.org"; resolver = inf_name_resolver_new( INF_IO(test->io), hostname, "6523", "_infinote._tcp" ); tcp_conn = inf_tcp_connection_new_resolve(INF_IO(test->io), resolver); g_object_unref(resolver); if(inf_tcp_connection_open(tcp_conn, &error) == FALSE) { fprintf(stderr, "Could not open TCP connection: %s\n", error->message); g_error_free(error); g_object_unref(tcp_conn); inf_standalone_io_loop_quit(test->io); } else { test->conn = inf_xmpp_connection_new( tcp_conn, INF_XMPP_CONNECTION_CLIENT, NULL, "localhost", INF_XMPP_CONNECTION_SECURITY_BOTH_PREFER_TLS, test->credentials, NULL, NULL ); g_object_unref(tcp_conn); manager = inf_communication_manager_new(); test->browser = INF_BROWSER( infc_browser_new( INF_IO(test->io), manager, INF_XML_CONNECTION(test->conn) ) ); g_object_unref(manager); infc_browser_add_plugin( INFC_BROWSER(test->browser), &INF_TEST_TEXT_QUICK_WRITE_PLUGIN ); g_signal_connect_after( G_OBJECT(test->browser), "notify::status", G_CALLBACK(inf_test_text_quick_write_notify_status_cb), test ); g_signal_connect( G_OBJECT(test->browser), "error", G_CALLBACK(inf_test_text_quick_write_error_cb), test ); } } static void inf_test_text_quick_write_start_cb(gpointer user_data) { inf_test_text_quick_write_reconnect((InfTestTextQuickWrite*)user_data); } static InfCertificateCredentials* inf_test_text_quick_write_load_credentials(const char* filename, GError** error) { InfCertificateCredentials* creds; GPtrArray* certs; gnutls_x509_privkey_t key; guint i; key = inf_cert_util_read_private_key(filename, error); if(key == NULL) return NULL; certs = inf_cert_util_read_certificate(filename, NULL, error); if(certs == NULL) { gnutls_x509_privkey_deinit(key); return NULL; } creds = inf_certificate_credentials_new(); gnutls_certificate_set_x509_key( inf_certificate_credentials_get(creds), (gnutls_x509_crt_t*)certs->pdata, certs->len, key ); gnutls_certificate_set_x509_trust( inf_certificate_credentials_get(creds), (gnutls_x509_crt_t*)&certs->pdata[certs->len - 1], certs->len ); gnutls_x509_privkey_deinit(key); for(i = 0; i < certs->len; ++i) gnutls_x509_crt_deinit(certs->pdata[i]); g_ptr_array_free(certs, TRUE); return creds; } int main(int argc, char* argv[]) { guint32 seed; const gchar* filename; const gchar* credentials; InfTestTextQuickWrite test; GError* error; error = NULL; if(!inf_init(&error)) { fprintf(stderr, "%s\n", error->message); return 1; } seed = time(NULL); printf("Random seed: %u\n", seed); g_random_set_seed(seed); if(argc < 2) filename = "inf-test-quick-write.c"; else filename = argv[1]; credentials = NULL; g_file_get_contents(filename, &test.content, &test.content_length, &error); if(error != NULL) { fprintf(stderr, "%s: %s\n", filename, error->message); g_error_free(error); return 1; } if(test.content_length == 0) { fprintf(stderr, "%s: File is empty\n", filename); return 1; } test.credentials = NULL; test.io = NULL; test.conn = NULL; test.browser = NULL; test.proxy = NULL; test.session = NULL; test.user = NULL; test.buffer = NULL; if(credentials != NULL) { test.credentials = inf_test_text_quick_write_load_credentials( credentials, &error ); if(test.credentials == NULL) { fprintf(stderr, "%s\n", error->message); g_error_free(error); return 1; } } test.io = inf_standalone_io_new(); inf_io_add_dispatch( INF_IO(test.io), inf_test_text_quick_write_start_cb, &test, NULL ); inf_standalone_io_loop(test.io); g_object_unref(test.io); inf_certificate_credentials_unref(test.credentials); g_free(test.content); return 0; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/test/PaxHeaders.26529/inf-test-certificate-request.c0000644000000000000000000000013013034342512022420 xustar0030 mtime=1483851082.049718536 30 atime=1483851082.049718536 28 ctime=1488261589.7161375 libinfinity-0.7.1/test/inf-test-certificate-request.c0000644000175000017500000001660713034342512023166 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include #include #include typedef struct _InfTestCertificateRequest InfTestCertificateRequest; struct _InfTestCertificateRequest { InfStandaloneIo* io; InfXmppConnection* conn; InfBrowser* browser; gnutls_x509_privkey_t key; }; static void inf_test_certificate_request_finished_cb(InfRequest* request, const InfRequestResult* result, const GError* error, gpointer user_data) { InfTestCertificateRequest* test; InfCertificateChain* chain; guint n_certs; guint i; gnutls_datum_t datum; gnutls_x509_crt_t cert; size_t cert_size; gchar* cert_pem; test = (InfTestCertificateRequest*)user_data; if(error != NULL) { fprintf(stderr, "Error: %s\n", error->message); } else { fprintf(stderr, "Certificate generated!\n\n"); inf_request_result_get_create_acl_account(result, NULL, NULL, &chain); n_certs = inf_certificate_chain_get_n_certificates(chain); for(i = 0; i < n_certs; ++i) { fprintf(stderr, "Certificate %d", i); if(i == 0) fprintf(stderr, " (own)"); if(i == 1) fprintf(stderr, " (issuer)"); if(i == n_certs - 1) fprintf(stderr, " (CA)"); fprintf(stderr, ":\n\n"); cert = inf_certificate_chain_get_nth_certificate(chain, i); gnutls_x509_crt_print(cert, GNUTLS_CRT_PRINT_FULL, &datum); fprintf(stderr, "%s\n", datum.data); gnutls_free(datum.data); } for(i = 0; i < n_certs; ++i) { cert = inf_certificate_chain_get_nth_certificate(chain, i); cert_size = 0; gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_PEM, NULL, &cert_size); cert_pem = g_malloc(cert_size); gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_PEM, cert_pem, &cert_size); printf("%s\n\n", cert_pem); g_free(cert_pem); } cert_size = 0; gnutls_x509_privkey_export( test->key, GNUTLS_X509_FMT_PEM, NULL, &cert_size ); cert_pem = g_malloc(cert_size); gnutls_x509_privkey_export( test->key, GNUTLS_X509_FMT_PEM, cert_pem, &cert_size ); printf("%s\n", cert_pem); g_free(cert_pem); } if(inf_standalone_io_loop_running(test->io)) inf_standalone_io_loop_quit(test->io); } static void inf_test_certificate_request_error_cb(InfcBrowser* browser, GError* error, gpointer user_data) { fprintf(stderr, "Connection error: %s\n", error->message); } static void inf_test_certificate_request_notify_status_cb(GObject* object, GParamSpec* pspec, gpointer user_data) { InfTestCertificateRequest* test; InfBrowserStatus status; gnutls_x509_crq_t crq; InfRequest* request; GError* error; int res; test = (InfTestCertificateRequest*)user_data; g_object_get(G_OBJECT(test->browser), "status", &status, NULL); if(status == INF_BROWSER_OPEN) { fprintf(stderr, "Connection established, creating key... (4096 bit)\n"); /* TODO: Some error checking here */ gnutls_x509_privkey_init(&test->key); gnutls_x509_privkey_generate(test->key, GNUTLS_PK_RSA, 4096, 0); fprintf(stderr, "Done, sending the certificate request\n"); gnutls_x509_crq_init(&crq); gnutls_x509_crq_set_key(crq, test->key); gnutls_x509_crq_set_key_usage(crq, GNUTLS_KEY_DIGITAL_SIGNATURE); gnutls_x509_crq_set_version(crq, 3); gnutls_x509_crq_set_dn_by_oid( crq, GNUTLS_OID_X520_COMMON_NAME, 0, "Armin Burgmeier", strlen("Armin Burgmeier") ); /* TODO: gnutls_x509_crq_sign2 is deprecated in favour of * gnutls_x509_crq_privkey_sign, but the latter returns the error code * GNUTLS_E_UNIMPLEMENTED_FEATURE, so we keep using the deprecated * version here. */ /*gnutls_x509_crq_privkey_sign(crq, key, GNUTLS_DIG_SHA1, 0);*/ gnutls_x509_crq_sign2(crq, test->key, GNUTLS_DIG_SHA1, 0); error = NULL; request = inf_browser_create_acl_account( INF_BROWSER(object), crq, inf_test_certificate_request_finished_cb, test ); gnutls_x509_crq_deinit(crq); } if(status == INF_BROWSER_CLOSED) { if(inf_standalone_io_loop_running(test->io)) inf_standalone_io_loop_quit(test->io); } } int main(int argc, char* argv[]) { InfTestCertificateRequest test; InfIpAddress* address; InfCommunicationManager* manager; InfTcpConnection* tcp_conn; GError* error; error = NULL; inf_init(NULL); /* gnutls_global_init(); g_type_init();*/ test.key = NULL; test.io = inf_standalone_io_new(); address = inf_ip_address_new_loopback4(); tcp_conn = inf_tcp_connection_new_and_open(INF_IO(test.io), address, inf_protocol_get_default_port(), &error); inf_ip_address_free(address); if(tcp_conn == NULL) { fprintf(stderr, "Could not open TCP connection: %s\n", error->message); g_error_free(error); } else { test.conn = inf_xmpp_connection_new( tcp_conn, INF_XMPP_CONNECTION_CLIENT, NULL, "localhost", INF_XMPP_CONNECTION_SECURITY_BOTH_PREFER_TLS, NULL, NULL, NULL ); g_object_unref(G_OBJECT(tcp_conn)); manager = inf_communication_manager_new(); test.browser = INF_BROWSER( infc_browser_new( INF_IO(test.io), manager, INF_XML_CONNECTION(test.conn) ) ); g_signal_connect_after( G_OBJECT(test.browser), "notify::status", G_CALLBACK(inf_test_certificate_request_notify_status_cb), &test ); g_signal_connect( G_OBJECT(test.browser), "error", G_CALLBACK(inf_test_certificate_request_error_cb), &test ); inf_standalone_io_loop(test.io); g_object_unref(G_OBJECT(manager)); g_object_unref(G_OBJECT(test.browser)); /* TODO: Wait until the XMPP connection is in status closed */ g_object_unref(G_OBJECT(test.conn)); } g_object_unref(G_OBJECT(test.io)); if(test.key != NULL) gnutls_x509_privkey_deinit(test.key); return 0; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/test/PaxHeaders.26529/inf-test-browser.c0000644000000000000000000000013213034342512020135 xustar0030 mtime=1483851082.049718536 30 atime=1483851082.049718536 30 ctime=1488261589.712137508 libinfinity-0.7.1/test/inf-test-browser.c0000644000175000017500000002221013034342512020664 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include #include typedef struct _InfTestBrowser InfTestBrowser; struct _InfTestBrowser { InfStandaloneIo* io; InfXmppConnection* conn; InfBrowser* browser; #ifndef G_OS_WIN32 int input_fd; #endif InfBrowserIter cwd; }; typedef void(*InfTestBrowserCmdFunc)(InfTestBrowser*, const gchar*); typedef struct _InfTestBrowserCmd InfTestBrowserCmd; struct _InfTestBrowserCmd { const gchar* name; InfTestBrowserCmdFunc func; }; static gboolean inf_test_browser_find_node(InfTestBrowser* test, const gchar* name, InfBrowserIter* result_iter) { InfBrowserIter iter; gboolean result; if(inf_browser_get_explored(test->browser, &test->cwd) == FALSE) { fprintf( stderr, "Directory '%s' not yet explored\n", inf_browser_get_node_name(test->browser, &test->cwd) ); } else { iter = test->cwd; for(result = inf_browser_get_child(test->browser, &iter); result == TRUE; result = inf_browser_get_next(test->browser, &iter)) { if(strcmp(inf_browser_get_node_name(test->browser, &iter), name) == 0) { *result_iter = iter; return TRUE; } } } return FALSE; } static void inf_test_browser_cmd_ls(InfTestBrowser* test, const gchar* param) { InfBrowserIter iter; gboolean result; if(inf_browser_get_explored(test->browser, &test->cwd) == FALSE) { fprintf( stderr, "Directory '%s' not yet explored\n", inf_browser_get_node_name(test->browser, &test->cwd) ); } else { iter = test->cwd; for(result = inf_browser_get_child(test->browser, &iter); result == TRUE; result = inf_browser_get_next(test->browser, &iter)) { printf("%s\n", inf_browser_get_node_name(test->browser, &iter)); } } } static void inf_test_browser_cmd_cd(InfTestBrowser* test, const gchar* param) { InfBrowserIter iter; if(strcmp(param, "..") == 0) { iter = test->cwd; if(inf_browser_get_parent(test->browser, &iter) == FALSE) { fprintf(stderr, "Already at the root directory\n"); } else { test->cwd = iter; } } else if(inf_test_browser_find_node(test, param, &iter) == FALSE) { fprintf( stderr, "Directory '%s' does not exist\n", param ); } else if(inf_browser_get_explored(test->browser, &iter) == FALSE) { fprintf( stderr, "Directory '%s' not yet explored\n", inf_browser_get_node_name(test->browser, &iter) ); } else { test->cwd = iter; } } static void inf_test_browser_cmd_explore(InfTestBrowser* test, const gchar* param) { InfBrowserIter iter; if(inf_test_browser_find_node(test, param, &iter) == FALSE) { fprintf( stderr, "Directory '%s' does not exist\n", param ); } else if(inf_browser_get_explored(test->browser, &iter) == TRUE) { fprintf( stderr, "Directory '%s' is already explored", inf_browser_get_node_name(test->browser, &iter) ); } else { inf_browser_explore(test->browser, &iter, NULL, NULL); } } static void inf_test_browser_cmd_create(InfTestBrowser* test, const gchar* param) { inf_browser_add_subdirectory( test->browser, &test->cwd, param, NULL, NULL, NULL ); } static void inf_test_browser_cmd_remove(InfTestBrowser* test, const gchar* param) { InfBrowserIter iter; if(inf_test_browser_find_node(test, param, &iter) == FALSE) { fprintf( stderr, "Directory '%s' does not exist\n", param ); } else { inf_browser_remove_node(test->browser, &iter, NULL, NULL); } } static const InfTestBrowserCmd inf_test_browser_commands[] = { { "ls", inf_test_browser_cmd_ls }, { "cd", inf_test_browser_cmd_cd }, { "explore", inf_test_browser_cmd_explore }, { "create", inf_test_browser_cmd_create }, { "remove", inf_test_browser_cmd_remove } }; static void inf_test_browser_input_cb(InfNativeSocket* fd, InfIoEvent io, gpointer user_data) { InfTestBrowser* test; char buffer[1024]; char* occ; guint i; test = (InfTestBrowser*)user_data; if(io & INF_IO_ERROR) { } if(io & INF_IO_INCOMING) { if(fgets(buffer, sizeof(buffer), stdin) == NULL) { inf_standalone_io_loop_quit(test->io); } else if(strlen(buffer) != sizeof(buffer) || buffer[sizeof(buffer)-2] == '\n') { buffer[strlen(buffer)-1] = '\0'; /* Read entire line */ occ = strchr(buffer, ' '); if(occ != NULL) { *occ = '\0'; ++ occ; } for(i = 0; i < G_N_ELEMENTS(inf_test_browser_commands); ++ i) { if(strcmp(inf_test_browser_commands[i].name, buffer) == 0) { inf_test_browser_commands[i].func(test, occ); break; } } if(i == G_N_ELEMENTS(inf_test_browser_commands)) { fprintf(stderr, "'%s': Command not found\n", buffer); } } } } static void inf_test_browser_error_cb(InfcBrowser* browser, GError* error, gpointer user_data) { fprintf(stderr, "Connection error: %s\n", error->message); } static void inf_test_browser_notify_status_cb(GObject* object, GParamSpec* pspec, gpointer user_data) { InfTestBrowser* test; InfBrowserStatus status; test = (InfTestBrowser*)user_data; g_object_get(G_OBJECT(test->browser), "status", &status, NULL); if(status == INF_BROWSER_OPEN) { printf("Connection established\n"); #ifndef G_OS_WIN32 inf_io_add_watch( INF_IO(test->io), &test->input_fd, INF_IO_INCOMING | INF_IO_ERROR, inf_test_browser_input_cb, test, NULL ); #endif /* Explore root node */ inf_browser_get_root(test->browser, &test->cwd); inf_browser_explore(test->browser, &test->cwd, NULL, NULL); } if(status == INF_BROWSER_CLOSED) { if(inf_standalone_io_loop_running(test->io)) inf_standalone_io_loop_quit(test->io); } } int main(int argc, char* argv[]) { InfTestBrowser test; InfIpAddress* address; InfCommunicationManager* manager; InfTcpConnection* tcp_conn; GError* error; error = NULL; if(!inf_init(&error)) { fprintf(stderr, "%s\n", error->message); return 1; } test.io = inf_standalone_io_new(); #ifndef G_OS_WIN32 test.input_fd = STDIN_FILENO; #endif address = inf_ip_address_new_loopback4(); tcp_conn = inf_tcp_connection_new_and_open(INF_IO(test.io), address, inf_protocol_get_default_port(), &error); inf_ip_address_free(address); if(tcp_conn == NULL) { fprintf(stderr, "Could not open TCP connection: %s\n", error->message); g_error_free(error); } else { test.conn = inf_xmpp_connection_new( tcp_conn, INF_XMPP_CONNECTION_CLIENT, NULL, "localhost", INF_XMPP_CONNECTION_SECURITY_BOTH_PREFER_TLS, NULL, NULL, NULL ); g_object_unref(G_OBJECT(tcp_conn)); manager = inf_communication_manager_new(); test.browser = INF_BROWSER( infc_browser_new( INF_IO(test.io), manager, INF_XML_CONNECTION(test.conn) ) ); g_signal_connect_after( G_OBJECT(test.browser), "notify::status", G_CALLBACK(inf_test_browser_notify_status_cb), &test ); g_signal_connect( G_OBJECT(test.browser), "error", G_CALLBACK(inf_test_browser_error_cb), &test ); inf_standalone_io_loop(test.io); g_object_unref(G_OBJECT(manager)); g_object_unref(G_OBJECT(test.browser)); /* TODO: Wait until the XMPP connection is in status closed */ g_object_unref(G_OBJECT(test.conn)); } g_object_unref(G_OBJECT(test.io)); return 0; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/test/PaxHeaders.26529/inf-test-xmpp-server.c0000644000000000000000000000013213034342512020742 xustar0030 mtime=1483851082.053718557 30 atime=1483851082.053718557 30 ctime=1488261589.740137447 libinfinity-0.7.1/test/inf-test-xmpp-server.c0000644000175000017500000001057213034342512021501 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include static void conn_notify_status_cb(InfXmlConnection* connection, GParamSpec* spec, gpointer user_data) { InfXmlConnectionStatus status; g_object_get( G_OBJECT(connection), "status", &status, NULL ); switch(status) { case INF_XML_CONNECTION_CLOSED: fprintf(stderr, "Connection closed\n"); break; case INF_XML_CONNECTION_CLOSING: fprintf(stderr, "Connection closing\n"); break; case INF_XML_CONNECTION_OPENING: fprintf(stderr, "Connection opening\n"); break; case INF_XML_CONNECTION_OPEN: fprintf(stderr, "Connection open\n"); break; } } static void conn_error_cb(InfXmlConnection* connection, GError* error, gpointer user_data) { fprintf(stderr, "Connection error occured: %s\n", error->message); } static void new_connection_cb(InfdXmlServer* server, InfXmlConnection* connection, gpointer user_data) { fprintf(stderr, "New connection\n"); g_signal_connect( G_OBJECT(connection), "error", G_CALLBACK(conn_error_cb), NULL ); g_signal_connect( G_OBJECT(connection), "notify::status", G_CALLBACK(conn_notify_status_cb), NULL ); g_object_ref(G_OBJECT(connection)); } static void error_cb(InfdXmppServer* server, GError* error, gpointer user_data) { fprintf(stderr, "Server Error occured: %s\n", error->message); } static void notify_status_cb(InfdXmlServer* server, GParamSpec* pspec, gpointer user_data) { InfdXmlServerStatus status; g_object_get( G_OBJECT(server), "status", &status, NULL ); switch(status) { case INFD_XML_SERVER_CLOSED: printf("Server closed\n"); inf_standalone_io_loop_quit(INF_STANDALONE_IO(user_data)); break; case INFD_XML_SERVER_CLOSING: printf("Server closing\n"); break; case INFD_XML_SERVER_OPENING: printf("Server opening\n"); break; case INFD_XML_SERVER_OPEN: printf("Server open\n"); break; default: g_assert_not_reached(); break; } } int main(int argc, char* argv[]) { InfStandaloneIo* io; InfdTcpServer* server; InfdXmppServer* xmpp; GError* error; error = NULL; if(!inf_init(&error)) { fprintf(stderr, "%s\n", error->message); return 1; } io = inf_standalone_io_new(); server = g_object_new( INFD_TYPE_TCP_SERVER, "io", io, "local-port", 5223, NULL ); if(infd_tcp_server_open(server, &error) == FALSE) { fprintf(stderr, "Could not open server: %s\n", error->message); g_error_free(error); } else { xmpp = infd_xmpp_server_new( server, INF_XMPP_CONNECTION_SECURITY_ONLY_UNSECURED, NULL, NULL, NULL ); g_signal_connect( G_OBJECT(xmpp), "error", G_CALLBACK(error_cb), io ); g_signal_connect( G_OBJECT(xmpp), "new-connection", G_CALLBACK(new_connection_cb), io ); g_signal_connect( G_OBJECT(xmpp), "notify::status", G_CALLBACK(notify_status_cb), io ); inf_standalone_io_loop(io); } g_object_unref(G_OBJECT(io)); g_object_unref(G_OBJECT(server)); return 0; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/test/PaxHeaders.26529/util0000644000000000000000000000013213055210725015462 xustar0030 mtime=1488261589.772137377 30 atime=1488261589.744137438 30 ctime=1488261589.772137377 libinfinity-0.7.1/test/util/0000755000175000017500000000000013055210725016271 5ustar00arminarmin00000000000000libinfinity-0.7.1/test/util/PaxHeaders.26529/inf-test-util.h0000644000000000000000000000013213034342512020411 xustar0030 mtime=1483851082.053718557 30 atime=1483851082.053718557 30 ctime=1488261589.768137386 libinfinity-0.7.1/test/util/inf-test-util.h0000644000175000017500000000367513034342512021156 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_TEST_UTIL_H__ #define __INF_TEST_UTIL_H__ #include #include #include #include G_BEGIN_DECLS typedef enum { INF_TEST_UTIL_PARSE_ERROR_UNEXPECTED_NODE, INF_TEST_UTIL_PARSE_ERROR_USER_ALREADY_EXISTS } InfTestUtilParseError; GQuark inf_test_util_parse_error_quark(void); void inf_test_util_print_operation(InfAdoptedOperation* op); void inf_test_util_print_request(InfAdoptedRequest* request); void inf_test_util_print_buffer(InfTextBuffer* buffer); gboolean inf_test_util_dir_foreach(const char* dirname, void(*callback)(const char*, gpointer), gpointer user_data, GError** error); InfTextChunk* inf_test_util_parse_buffer(xmlNodePtr xml, GError** error); gboolean inf_test_util_parse_user(xmlNodePtr xml, GSList** users, GError** error); G_END_DECLS #endif /* __INF_TEST_UTIL_H__ */ libinfinity-0.7.1/test/util/PaxHeaders.26529/Makefile.in0000644000000000000000000000013213051241010017567 xustar0030 mtime=1487225352.709151614 30 atime=1487225352.709151614 30 ctime=1488261589.768137386 libinfinity-0.7.1/test/util/Makefile.in0000644000175000017500000005371313051241010020332 0ustar00arminarmin00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 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__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) 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@ subdir = test/util ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/gtk-doc.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(noinst_HEADERS) \ $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/libinfinity/inf-config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LIBRARIES = $(noinst_LIBRARIES) ARFLAGS = cru AM_V_AR = $(am__v_AR_@AM_V@) am__v_AR_ = $(am__v_AR_@AM_DEFAULT_V@) am__v_AR_0 = @echo " AR " $@; am__v_AR_1 = libinftestutil_a_AR = $(AR) $(ARFLAGS) libinftestutil_a_DEPENDENCIES = ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la am_libinftestutil_a_OBJECTS = \ libinftestutil_a-inf-test-util.$(OBJEXT) libinftestutil_a_OBJECTS = $(am_libinftestutil_a_OBJECTS) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) -I$(top_builddir)/libinfinity depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles am__mv = mv -f AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = 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_CC_1 = 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_CCLD_1 = SOURCES = $(libinftestutil_a_SOURCES) DIST_SOURCES = $(libinftestutil_a_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac HEADERS = $(noinst_HEADERS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ 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@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIRNAME = @DATADIRNAME@ 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@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ GTKDOC_CHECK = @GTKDOC_CHECK@ GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ GTKDOC_MKPDF = @GTKDOC_MKPDF@ GTKDOC_REBASE = @GTKDOC_REBASE@ HTML_DIR = @HTML_DIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INSTOBJEXT = @INSTOBJEXT@ INTLLIBS = @INTLLIBS@ INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBINFINITY_API_VERSION = @LIBINFINITY_API_VERSION@ LIBINFINITY_LIBTOOL_VERSION = @LIBINFINITY_LIBTOOL_VERSION@ LIBINFINITY_VERSION = @LIBINFINITY_VERSION@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGFMT_OPTS = @MSGFMT_OPTS@ 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@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ 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@ avahi_CFLAGS = @avahi_CFLAGS@ avahi_LIBS = @avahi_LIBS@ 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@ gio_CFLAGS = @gio_CFLAGS@ gio_LIBS = @gio_LIBS@ gtk_requirement = @gtk_requirement@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infgtk_CFLAGS = @infgtk_CFLAGS@ infgtk_LIBS = @infgtk_LIBS@ infinity_CFLAGS = @infinity_CFLAGS@ infinity_LIBS = @infinity_LIBS@ infinoted_CFLAGS = @infinoted_CFLAGS@ infinoted_LIBS = @infinoted_LIBS@ infodir = @infodir@ inftext_CFLAGS = @inftext_CFLAGS@ inftext_LIBS = @inftext_LIBS@ inftextgtk_CFLAGS = @inftextgtk_CFLAGS@ inftextgtk_LIBS = @inftextgtk_LIBS@ install_sh = @install_sh@ libdaemon_CFLAGS = @libdaemon_CFLAGS@ libdaemon_LIBS = @libdaemon_LIBS@ 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@ runstatedir = @runstatedir@ 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@ noinst_LIBRARIES = libinftestutil.a libinftestutil_a_CPPFLAGS = \ -I${top_srcdir} \ -I${top_builddir} \ ${infinity_CFLAGS} \ ${inftext_CFLAGS} libinftestutil_a_SOURCES = \ inf-test-util.c noinst_HEADERS = \ inf-test-util.h libinftestutil_a_LIBADD = \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(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) --foreign test/util/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign test/util/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: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): clean-noinstLIBRARIES: -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) libinftestutil.a: $(libinftestutil_a_OBJECTS) $(libinftestutil_a_DEPENDENCIES) $(EXTRA_libinftestutil_a_DEPENDENCIES) $(AM_V_at)-rm -f libinftestutil.a $(AM_V_AR)$(libinftestutil_a_AR) libinftestutil.a $(libinftestutil_a_OBJECTS) $(libinftestutil_a_LIBADD) $(AM_V_at)$(RANLIB) libinftestutil.a mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libinftestutil_a-inf-test-util.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.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 -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.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 -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.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 $@ $< libinftestutil_a-inf-test-util.o: inf-test-util.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinftestutil_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libinftestutil_a-inf-test-util.o -MD -MP -MF $(DEPDIR)/libinftestutil_a-inf-test-util.Tpo -c -o libinftestutil_a-inf-test-util.o `test -f 'inf-test-util.c' || echo '$(srcdir)/'`inf-test-util.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libinftestutil_a-inf-test-util.Tpo $(DEPDIR)/libinftestutil_a-inf-test-util.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='inf-test-util.c' object='libinftestutil_a-inf-test-util.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) $(libinftestutil_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libinftestutil_a-inf-test-util.o `test -f 'inf-test-util.c' || echo '$(srcdir)/'`inf-test-util.c libinftestutil_a-inf-test-util.obj: inf-test-util.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinftestutil_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libinftestutil_a-inf-test-util.obj -MD -MP -MF $(DEPDIR)/libinftestutil_a-inf-test-util.Tpo -c -o libinftestutil_a-inf-test-util.obj `if test -f 'inf-test-util.c'; then $(CYGPATH_W) 'inf-test-util.c'; else $(CYGPATH_W) '$(srcdir)/inf-test-util.c'; fi` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libinftestutil_a-inf-test-util.Tpo $(DEPDIR)/libinftestutil_a-inf-test-util.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='inf-test-util.c' object='libinftestutil_a-inf-test-util.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) $(libinftestutil_a_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libinftestutil_a-inf-test-util.obj `if test -f 'inf-test-util.c'; then $(CYGPATH_W) 'inf-test-util.c'; else $(CYGPATH_W) '$(srcdir)/inf-test-util.c'; fi` mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ 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-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ 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" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files 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: check-am all-am: Makefile $(LIBRARIES) $(HEADERS) installdirs: install: 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: 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." clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLIBRARIES \ 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-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: .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libtool clean-noinstLIBRARIES cscopelist-am ctags \ ctags-am 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-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 tags-am uninstall uninstall-am .PRECIOUS: Makefile # 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: libinfinity-0.7.1/test/util/PaxHeaders.26529/Makefile.am0000644000000000000000000000013212400102201017551 xustar0030 mtime=1409320065.147131494 30 atime=1409320065.147131494 30 ctime=1488261589.768137386 libinfinity-0.7.1/test/util/Makefile.am0000644000175000017500000000062312400102201020304 0ustar00arminarmin00000000000000noinst_LIBRARIES = libinftestutil.a libinftestutil_a_CPPFLAGS = \ -I${top_srcdir} \ -I${top_builddir} \ ${infinity_CFLAGS} \ ${inftext_CFLAGS} libinftestutil_a_SOURCES = \ inf-test-util.c noinst_HEADERS = \ inf-test-util.h libinftestutil_a_LIBADD = \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la libinfinity-0.7.1/test/util/PaxHeaders.26529/inf-test-util.c0000644000000000000000000000013213034342512020404 xustar0030 mtime=1483851082.053718557 30 atime=1483851082.053718557 30 ctime=1488261589.772137377 libinfinity-0.7.1/test/util/inf-test-util.c0000644000175000017500000001472413034342512021146 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include "inf-test-util.h" #include #include #include #include #include static int inf_test_util_dir_foreach_sort_func(gconstpointer first, gconstpointer second) { return strcmp(first, second); } GQuark inf_test_util_parse_error_quark(void) { return g_quark_from_static_string("INF_TEST_UTIL_PARSE_ERROR"); } void inf_test_util_print_operation(InfAdoptedOperation* op) { InfAdoptedOperation* first; InfAdoptedOperation* second; gchar* chunk_text; gsize chunk_bytes; if(INF_TEXT_IS_DEFAULT_INSERT_OPERATION(op)) { chunk_text = inf_text_chunk_get_text( inf_text_default_insert_operation_get_chunk( INF_TEXT_DEFAULT_INSERT_OPERATION(op) ), &chunk_bytes ); printf( "insert(%u, %.*s)\n", inf_text_insert_operation_get_position(INF_TEXT_INSERT_OPERATION(op)), (int)chunk_bytes, chunk_text ); g_free(chunk_text); } else if(INF_TEXT_IS_DELETE_OPERATION(op)) { printf( "delete(%u/%u)\n", inf_text_delete_operation_get_position(INF_TEXT_DELETE_OPERATION(op)), inf_text_delete_operation_get_length(INF_TEXT_DELETE_OPERATION(op)) ); } else if(INF_ADOPTED_IS_SPLIT_OPERATION(op)) { g_object_get(G_OBJECT(op), "first", &first, "second", &second, NULL); printf("split(\n "); inf_test_util_print_operation(first); printf(" "); inf_test_util_print_operation(second); printf(")\n"); } else { printf("unknown: %s\n", g_type_name(G_TYPE_FROM_INSTANCE(op))); } } void inf_test_util_print_request(InfAdoptedRequest* request) { gchar* time; time = inf_adopted_state_vector_to_string( inf_adopted_request_get_vector(request) ); printf("%u [%s] ", inf_adopted_request_get_user_id(request), time); g_free(time); switch(inf_adopted_request_get_request_type(request)) { case INF_ADOPTED_REQUEST_DO: printf("DO {\n "); inf_test_util_print_operation(inf_adopted_request_get_operation(request)); printf("}\n"); break; case INF_ADOPTED_REQUEST_UNDO: printf("UNDO\n"); break; case INF_ADOPTED_REQUEST_REDO: printf("REDO\n"); break; } } void inf_test_util_print_buffer(InfTextBuffer* buffer) { InfTextChunk* chunk; gchar* text; gsize bytes; chunk = inf_text_buffer_get_slice( buffer, 0, inf_text_buffer_get_length(buffer) ); text = inf_text_chunk_get_text(chunk, &bytes); inf_text_chunk_free(chunk); printf("%.*s\n", (int)bytes, text); g_free(text); } gboolean inf_test_util_dir_foreach(const char* dirname, void(*callback)(const char*, gpointer), gpointer user_data, GError** error) { GDir* dir; const gchar* entry; gchar* path; GSList* items; GSList* item; gboolean result; dir = g_dir_open(dirname, 0, error); if(dir == NULL) return FALSE; items = NULL; for(entry = g_dir_read_name(dir); entry != NULL; entry = g_dir_read_name(dir)) { /* Ignore hidden files */ if(entry[0] == '.') continue; path = g_build_filename(dirname, entry, NULL); items = g_slist_prepend(items, path); } g_dir_close(dir); items = g_slist_sort(items, inf_test_util_dir_foreach_sort_func); result = TRUE; for(item = items; item != NULL; item = g_slist_next(item)) { path = (gchar*)item->data; if(g_file_test(path, G_FILE_TEST_IS_DIR)) { if(inf_test_util_dir_foreach(path, callback, user_data, error) == FALSE) { result = FALSE; } } else if(g_file_test(path, G_FILE_TEST_IS_REGULAR)) { callback(path, user_data); } g_free(path); } g_slist_free(items); return result; } InfTextChunk* inf_test_util_parse_buffer(xmlNodePtr xml, GError** error) { InfTextChunk* chunk; xmlNodePtr child; guint author; gchar* content; gsize bytes; guint chars; chunk = inf_text_chunk_new("UTF-8"); for(child = xml->children; child != NULL; child = child->next) { if(child->type != XML_ELEMENT_NODE) continue; if(strcmp((const char*)child->name, "segment") == 0) { if(!inf_xml_util_get_attribute_uint(child, "author", &author, error)) { inf_text_chunk_free(chunk); return NULL; } content = inf_xml_util_get_child_text(child, &bytes, &chars, error); if(!content) { inf_text_chunk_free(chunk); return NULL; } inf_text_chunk_insert_text( chunk, inf_text_chunk_get_length(chunk), content, bytes, chars, author ); g_free(content); } else { g_set_error( error, inf_test_util_parse_error_quark(), INF_TEST_UTIL_PARSE_ERROR_UNEXPECTED_NODE, "Node '%s' unexpected", (const gchar*)child->name ); inf_text_chunk_free(chunk); return NULL; } } return chunk; } gboolean inf_test_util_parse_user(xmlNodePtr xml, GSList** users, GError** error) { guint id; if(!inf_xml_util_get_attribute_uint_required(xml, "id", &id, error)) return FALSE; if(g_slist_find(*users, GUINT_TO_POINTER(id)) != NULL) { g_set_error( error, inf_test_util_parse_error_quark(), INF_TEST_UTIL_PARSE_ERROR_USER_ALREADY_EXISTS, "User with ID %u exists already", id ); return FALSE; } *users = g_slist_prepend(*users, GUINT_TO_POINTER(id)); return TRUE; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/test/PaxHeaders.26529/inf-test-chat.c0000644000000000000000000000013013034342512017367 xustar0030 mtime=1483851082.053718557 30 atime=1483851082.053718557 28 ctime=1488261589.7161375 libinfinity-0.7.1/test/inf-test-chat.c0000644000175000017500000002352413034342512020131 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include typedef struct _InfTestChat InfTestChat; struct _InfTestChat { InfStandaloneIo* io; InfXmppConnection* conn; InfBrowser* browser; #ifndef G_OS_WIN32 int input_fd; #endif InfChatBuffer* buffer; InfUser* self; }; static void inf_test_chat_input_cb(InfNativeSocket* fd, InfIoEvent io, gpointer user_data) { InfTestChat* test; char buffer[1024]; test = (InfTestChat*)user_data; if(io & INF_IO_ERROR) { } if(io & INF_IO_INCOMING) { if(fgets(buffer, sizeof(buffer), stdin) == NULL) { inf_standalone_io_loop_quit(test->io); } else if(strlen(buffer) != sizeof(buffer) || buffer[sizeof(buffer)-2] == '\n') { buffer[strlen(buffer)-1] = '\0'; if(test->buffer != NULL && test->self != NULL) { inf_chat_buffer_add_message( test->buffer, test->self, buffer, strlen(buffer), time(NULL), 0 ); } } } } static void inf_chat_test_buffer_receive_message_cb(InfChatSession* session, InfChatBufferMessage* message, gpointer user_data) { switch(message->type) { case INF_CHAT_BUFFER_MESSAGE_NORMAL: printf("<%s> %s\n", inf_user_get_name(message->user), message->text); break; case INF_CHAT_BUFFER_MESSAGE_EMOTE: printf(" * %s %s\n", inf_user_get_name(message->user), message->text); break; case INF_CHAT_BUFFER_MESSAGE_USERJOIN: printf(" --> %s has joined\n", inf_user_get_name(message->user)); break; case INF_CHAT_BUFFER_MESSAGE_USERPART: printf(" <-- %s has left\n", inf_user_get_name(message->user)); break; } } static void inf_test_chat_userjoin_finished_cb(InfRequest* request, const InfRequestResult* result, const GError* error, gpointer user_data) { InfTestChat* test; InfUser* user; test = (InfTestChat*)user_data; if(error == NULL) { printf("User join complete. Start chatting!\n"); #ifndef G_OS_WIN32 inf_io_add_watch( INF_IO(test->io), &test->input_fd, INF_IO_INCOMING | INF_IO_ERROR, inf_test_chat_input_cb, test, NULL ); #endif inf_request_result_get_join_user(result, NULL, &user); test->self = user; } else { fprintf(stderr, "User join failed: %s\n", error->message); fprintf(stderr, "Chat will be read-only\n"); } } static void inf_chat_test_session_synchronization_complete_cb(InfSession* session, InfXmlConnection* connection, gpointer user_data) { InfTestChat* test; InfcSessionProxy* proxy; InfRequest* request; GParameter params[1] = { { "name", { 0 } } }; printf("Synchronization complete, joining user...\n"); test = (InfTestChat*)user_data; proxy = infc_browser_get_chat_session(INFC_BROWSER(test->browser)); g_value_init(¶ms[0].value, G_TYPE_STRING); g_value_set_string(¶ms[0].value, g_get_user_name()); inf_session_proxy_join_user( INF_SESSION_PROXY(proxy), G_N_ELEMENTS(params), params, inf_test_chat_userjoin_finished_cb, test ); g_value_unset(¶ms[0].value); } static void inf_chat_test_session_synchronization_failed_cb(InfSession* session, InfXmlConnection* connection, const GError* error, gpointer user_data) { InfTestChat* test; test = (InfTestChat*)user_data; fprintf(stderr, "Synchronization failed: %s\n", error->message); inf_standalone_io_loop_quit(test->io); } static void inf_chat_test_session_close_cb(InfSession* session, gpointer user_data) { InfTestChat* test; test = (InfTestChat*)user_data; printf("The server closed the chat session\n"); if(inf_standalone_io_loop_running(test->io)) inf_standalone_io_loop_quit(test->io); } static void inf_chat_test_subscribe_finished_cb(InfRequest* request, const InfRequestResult* result, const GError* error, gpointer user_data) { InfTestChat* test; InfcSessionProxy* proxy; InfSession* session; test = (InfTestChat*)user_data; if(error == NULL) { printf("Subscription successful, waiting for synchronization...\n"); proxy = infc_browser_get_chat_session(INFC_BROWSER(test->browser)); g_object_get(G_OBJECT(proxy), "session", &session, NULL); test->buffer = INF_CHAT_BUFFER(inf_session_get_buffer(session)); /* TODO: Show backlog after during/after synchronization */ g_signal_connect_after( G_OBJECT(session), "receive-message", G_CALLBACK(inf_chat_test_buffer_receive_message_cb), test ); g_signal_connect_after( G_OBJECT(session), "synchronization-complete", G_CALLBACK(inf_chat_test_session_synchronization_complete_cb), test ); g_signal_connect_after( G_OBJECT(session), "synchronization-failed", G_CALLBACK(inf_chat_test_session_synchronization_failed_cb), test ); /* This can happen when the server disables the chat without being * shutdown. */ g_signal_connect_after( G_OBJECT(session), "close", G_CALLBACK(inf_chat_test_session_close_cb), test ); g_object_unref(session); } else { fprintf(stderr, "Subscription failed: %s\n", error->message); inf_standalone_io_loop_quit(test->io); } } static void inf_test_chat_notify_status_cb(GObject* object, GParamSpec* pspec, gpointer user_data) { InfTestChat* test; InfBrowserStatus status; test = (InfTestChat*)user_data; g_object_get(G_OBJECT(object), "status", &status, NULL); if(status == INF_BROWSER_OPEN) { printf("Connection established, subscribing to chat...\n"); /* Subscribe to chat */ infc_browser_subscribe_chat( INFC_BROWSER(test->browser), inf_chat_test_subscribe_finished_cb, test ); } if(status == INF_BROWSER_CLOSED) { printf("Connection closed\n"); if(inf_standalone_io_loop_running(test->io)) inf_standalone_io_loop_quit(test->io); } } static void inf_test_chat_error_cb(InfXmppConnection* xmpp, GError* error, gpointer user_data) { /* status notify will close conn: */ fprintf(stderr, "Connection error: %s\n", error->message); } int main(int argc, char* argv[]) { InfTestChat test; InfIpAddress* address; InfCommunicationManager* manager; InfTcpConnection* tcp_conn; GError* error; error = NULL; if(!inf_init(&error)) { fprintf(stderr, "%s\n", error->message); return 1; } test.io = inf_standalone_io_new(); #ifndef G_OS_WIN32 test.input_fd = STDIN_FILENO; #endif test.buffer = NULL; address = inf_ip_address_new_loopback4(); tcp_conn = inf_tcp_connection_new_and_open(INF_IO(test.io), address, inf_protocol_get_default_port(), &error); inf_ip_address_free(address); if(tcp_conn == NULL) { fprintf(stderr, "Could not open TCP connection: %s\n", error->message); g_error_free(error); } else { test.conn = inf_xmpp_connection_new( tcp_conn, INF_XMPP_CONNECTION_CLIENT, NULL, "localhost", INF_XMPP_CONNECTION_SECURITY_BOTH_PREFER_TLS, NULL, NULL, NULL ); g_object_unref(G_OBJECT(tcp_conn)); manager = inf_communication_manager_new(); test.browser = INF_BROWSER( infc_browser_new( INF_IO(test.io), manager, INF_XML_CONNECTION(test.conn) ) ); g_signal_connect_after( G_OBJECT(test.browser), "notify::status", G_CALLBACK(inf_test_chat_notify_status_cb), &test ); g_signal_connect( G_OBJECT(test.browser), "error", G_CALLBACK(inf_test_chat_error_cb), &test ); inf_standalone_io_loop(test.io); g_object_unref(G_OBJECT(manager)); g_object_unref(G_OBJECT(test.browser)); /* TODO: Wait until the XMPP connection is in status closed */ g_object_unref(G_OBJECT(test.conn)); } g_object_unref(G_OBJECT(test.io)); return 0; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/test/PaxHeaders.26529/session0000644000000000000000000000013213055210725016170 xustar0030 mtime=1488261589.860137185 30 atime=1488261589.772137377 30 ctime=1488261589.860137185 libinfinity-0.7.1/test/session/0000755000175000017500000000000013055210725016777 5ustar00arminarmin00000000000000libinfinity-0.7.1/test/session/PaxHeaders.26529/test-26.xml0000644000000000000000000000013212400102201020151 xustar0030 mtime=1409320065.147131494 30 atime=1409320065.147131494 30 ctime=1488261589.828137254 libinfinity-0.7.1/test/session/test-26.xml0000644000175000017500000000171312400102201020705 0ustar00arminarmin00000000000000 a b c a c b libinfinity-0.7.1/test/session/PaxHeaders.26529/test-34.xml0000644000000000000000000000013212400102201020150 xustar0030 mtime=1409320065.147131494 30 atime=1409320065.147131494 30 ctime=1488261589.840137228 libinfinity-0.7.1/test/session/test-34.xml0000644000175000017500000000105112400102201020677 0ustar00arminarmin00000000000000 ab ab libinfinity-0.7.1/test/session/PaxHeaders.26529/test-46.xml0000644000000000000000000000013212400102201020153 xustar0030 mtime=1409320065.147131494 30 atime=1409320065.147131494 30 ctime=1488261589.852137202 libinfinity-0.7.1/test/session/test-46.xml0000644000175000017500000000111412400102201020702 0ustar00arminarmin00000000000000 abcdefg foo foo libinfinity-0.7.1/test/session/PaxHeaders.26529/test-45.xml0000644000000000000000000000013212400102201020152 xustar0030 mtime=1409320065.147131494 30 atime=1409320065.147131494 30 ctime=1488261589.852137202 libinfinity-0.7.1/test/session/test-45.xml0000644000175000017500000000120612400102201020703 0ustar00arminarmin00000000000000 a b c d d c b a libinfinity-0.7.1/test/session/PaxHeaders.26529/test-27.xml0000644000000000000000000000013212400102201020152 xustar0030 mtime=1409320065.147131494 30 atime=1409320065.147131494 30 ctime=1488261589.828137254 libinfinity-0.7.1/test/session/test-27.xml0000644000175000017500000000111712400102201020704 0ustar00arminarmin00000000000000 a b c c libinfinity-0.7.1/test/session/PaxHeaders.26529/test-42.xml0000644000000000000000000000013212400102201020147 xustar0030 mtime=1409320065.147131494 30 atime=1409320065.147131494 30 ctime=1488261589.848137211 libinfinity-0.7.1/test/session/test-42.xml0000644000175000017500000000074412400102201020706 0ustar00arminarmin00000000000000 ABCDE libinfinity-0.7.1/test/session/PaxHeaders.26529/test-41.xml0000644000000000000000000000013112400102201020145 xustar0030 mtime=1409320065.147131494 30 atime=1409320065.147131494 29 ctime=1488261589.84413722 libinfinity-0.7.1/test/session/test-41.xml0000644000175000017500000000123612400102201020702 0ustar00arminarmin00000000000000 A B A libinfinity-0.7.1/test/session/PaxHeaders.26529/test-19.xml0000644000000000000000000000013212400102201020153 xustar0030 mtime=1409320065.147131494 30 atime=1409320065.147131494 30 ctime=1488261589.820137272 libinfinity-0.7.1/test/session/test-19.xml0000644000175000017500000000111012400102201020676 0ustar00arminarmin00000000000000 x a a libinfinity-0.7.1/test/session/PaxHeaders.26529/test-01.xml0000644000000000000000000000013212400102201020142 xustar0030 mtime=1409320065.147131494 30 atime=1409320065.147131494 30 ctime=1488261589.800137316 libinfinity-0.7.1/test/session/test-01.xml0000644000175000017500000000111712400102201020674 0ustar00arminarmin00000000000000 abcdefghi ac bc ac bc fghi libinfinity-0.7.1/test/session/PaxHeaders.26529/test-48.xml0000644000000000000000000000013212400102201020155 xustar0030 mtime=1409320065.147131494 30 atime=1409320065.147131494 30 ctime=1488261589.852137202 libinfinity-0.7.1/test/session/test-48.xml0000644000175000017500000000153212400102201020710 0ustar00arminarmin00000000000000 abcd z y abc y libinfinity-0.7.1/test/session/PaxHeaders.26529/test-51.xml0000644000000000000000000000013212400102201020147 xustar0030 mtime=1409320065.147131494 30 atime=1409320065.147131494 30 ctime=1488261589.860137185 libinfinity-0.7.1/test/session/test-51.xml0000644000175000017500000000640212400102201020703 0ustar00arminarmin00000000000000 abcd x x z a y g tez tar tez a z c tary x libinfinity-0.7.1/test/session/PaxHeaders.26529/test-12.xml0000644000000000000000000000013112400102201020143 xustar0030 mtime=1409320065.147131494 30 atime=1409320065.147131494 29 ctime=1488261589.81213729 libinfinity-0.7.1/test/session/test-12.xml0000644000175000017500000000132212400102201020674 0ustar00arminarmin00000000000000 2 3 4 h h h hhh 432 libinfinity-0.7.1/test/session/PaxHeaders.26529/test-07.xml0000644000000000000000000000013212400102201020150 xustar0030 mtime=1409320065.147131494 30 atime=1409320065.147131494 30 ctime=1488261589.808137298 libinfinity-0.7.1/test/session/test-07.xml0000644000175000017500000000124512400102201020704 0ustar00arminarmin00000000000000 a b c a c libinfinity-0.7.1/test/session/PaxHeaders.26529/test-10.xml0000644000000000000000000000013112400102201020141 xustar0030 mtime=1409320065.147131494 30 atime=1409320065.147131494 29 ctime=1488261589.81213729 libinfinity-0.7.1/test/session/test-10.xml0000644000175000017500000000132212400102201020672 0ustar00arminarmin00000000000000 2 3 4 h h h hhh 234 libinfinity-0.7.1/test/session/PaxHeaders.26529/test-31.xml0000644000000000000000000000013212400102201020145 xustar0030 mtime=1409320065.147131494 30 atime=1409320065.147131494 30 ctime=1488261589.836137237 libinfinity-0.7.1/test/session/test-31.xml0000644000175000017500000000073212400102201020701 0ustar00arminarmin00000000000000 a b libinfinity-0.7.1/test/session/PaxHeaders.26529/test-47.xml0000644000000000000000000000013212400102201020154 xustar0030 mtime=1409320065.147131494 30 atime=1409320065.147131494 30 ctime=1488261589.852137202 libinfinity-0.7.1/test/session/test-47.xml0000644000175000017500000000121212400102201020702 0ustar00arminarmin00000000000000 abcd x x ac x x libinfinity-0.7.1/test/session/PaxHeaders.26529/test-04.xml0000644000000000000000000000013212400102201020145 xustar0030 mtime=1409320065.147131494 30 atime=1409320065.147131494 30 ctime=1488261589.804137307 libinfinity-0.7.1/test/session/test-04.xml0000644000175000017500000000127412400102201020703 0ustar00arminarmin00000000000000 1 b c d d b libinfinity-0.7.1/test/session/PaxHeaders.26529/test-50.xml0000644000000000000000000000013212400102201020146 xustar0030 mtime=1409320065.147131494 30 atime=1409320065.147131494 30 ctime=1488261589.856137193 libinfinity-0.7.1/test/session/test-50.xml0000644000175000017500000000424312400102201020703 0ustar00arminarmin00000000000000 a b c d e f g h i j a b c d e f g h i j abcdefghij libinfinity-0.7.1/test/session/PaxHeaders.26529/Makefile.in0000644000000000000000000000012613051241010020300 xustar0028 mtime=1487225352.6731515 28 atime=1487225352.6731515 30 ctime=1488261589.800137316 libinfinity-0.7.1/test/session/Makefile.in0000644000175000017500000003464513051241010021043 0ustar00arminarmin00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 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__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) 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@ subdir = test/session ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/gtk-doc.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/libinfinity/inf-config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ 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@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIRNAME = @DATADIRNAME@ 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@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ GTKDOC_CHECK = @GTKDOC_CHECK@ GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ GTKDOC_MKPDF = @GTKDOC_MKPDF@ GTKDOC_REBASE = @GTKDOC_REBASE@ HTML_DIR = @HTML_DIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INSTOBJEXT = @INSTOBJEXT@ INTLLIBS = @INTLLIBS@ INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBINFINITY_API_VERSION = @LIBINFINITY_API_VERSION@ LIBINFINITY_LIBTOOL_VERSION = @LIBINFINITY_LIBTOOL_VERSION@ LIBINFINITY_VERSION = @LIBINFINITY_VERSION@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGFMT_OPTS = @MSGFMT_OPTS@ 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@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ 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@ avahi_CFLAGS = @avahi_CFLAGS@ avahi_LIBS = @avahi_LIBS@ 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@ gio_CFLAGS = @gio_CFLAGS@ gio_LIBS = @gio_LIBS@ gtk_requirement = @gtk_requirement@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infgtk_CFLAGS = @infgtk_CFLAGS@ infgtk_LIBS = @infgtk_LIBS@ infinity_CFLAGS = @infinity_CFLAGS@ infinity_LIBS = @infinity_LIBS@ infinoted_CFLAGS = @infinoted_CFLAGS@ infinoted_LIBS = @infinoted_LIBS@ infodir = @infodir@ inftext_CFLAGS = @inftext_CFLAGS@ inftext_LIBS = @inftext_LIBS@ inftextgtk_CFLAGS = @inftextgtk_CFLAGS@ inftextgtk_LIBS = @inftextgtk_LIBS@ install_sh = @install_sh@ libdaemon_CFLAGS = @libdaemon_CFLAGS@ libdaemon_LIBS = @libdaemon_LIBS@ 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@ runstatedir = @runstatedir@ 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 = \ test-01.xml \ test-02.xml \ test-03.xml \ test-04.xml \ test-05.xml \ test-06.xml \ test-07.xml \ test-08.xml \ test-09.xml \ test-10.xml \ test-11.xml \ test-12.xml \ test-13.xml \ test-14.xml \ test-15.xml \ test-16.xml \ test-17.xml \ test-18.xml \ test-19.xml \ test-20.xml \ test-21.xml \ test-22.xml \ test-23.xml \ test-24.xml \ test-25.xml \ test-26.xml \ test-27.xml \ test-28.xml \ test-29.xml \ test-30.xml \ test-31.xml \ test-32.xml \ test-33.xml \ test-34.xml \ test-35.xml \ test-36.xml \ test-37.xml \ test-38.xml \ test-39.xml \ test-40.xml \ test-41.xml \ test-42.xml \ test-43.xml \ test-44.xml \ test-45.xml \ test-46.xml \ test-47.xml \ test-48.xml \ test-49.xml \ test-50.xml \ test-51.xml \ test-52.xml all: all-am .SUFFIXES: $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(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) --foreign test/session/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign test/session/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: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs tags TAGS: ctags CTAGS: cscope cscopelist: 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: check-am all-am: Makefile installdirs: install: 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: 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." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic 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-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 -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool 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-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags-am uninstall uninstall-am .PRECIOUS: Makefile # 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: libinfinity-0.7.1/test/session/PaxHeaders.26529/test-03.xml0000644000000000000000000000013212400102201020144 xustar0030 mtime=1409320065.147131494 30 atime=1409320065.147131494 30 ctime=1488261589.804137307 libinfinity-0.7.1/test/session/test-03.xml0000644000175000017500000000066612400102201020706 0ustar00arminarmin00000000000000 1 c c 1 libinfinity-0.7.1/test/session/PaxHeaders.26529/Makefile.am0000644000000000000000000000013212400102201020257 xustar0030 mtime=1409320065.147131494 30 atime=1409320065.147131494 30 ctime=1488261589.800137316 libinfinity-0.7.1/test/session/Makefile.am0000644000175000017500000000143112400102201021010 0ustar00arminarmin00000000000000EXTRA_DIST = \ test-01.xml \ test-02.xml \ test-03.xml \ test-04.xml \ test-05.xml \ test-06.xml \ test-07.xml \ test-08.xml \ test-09.xml \ test-10.xml \ test-11.xml \ test-12.xml \ test-13.xml \ test-14.xml \ test-15.xml \ test-16.xml \ test-17.xml \ test-18.xml \ test-19.xml \ test-20.xml \ test-21.xml \ test-22.xml \ test-23.xml \ test-24.xml \ test-25.xml \ test-26.xml \ test-27.xml \ test-28.xml \ test-29.xml \ test-30.xml \ test-31.xml \ test-32.xml \ test-33.xml \ test-34.xml \ test-35.xml \ test-36.xml \ test-37.xml \ test-38.xml \ test-39.xml \ test-40.xml \ test-41.xml \ test-42.xml \ test-43.xml \ test-44.xml \ test-45.xml \ test-46.xml \ test-47.xml \ test-48.xml \ test-49.xml \ test-50.xml \ test-51.xml \ test-52.xml libinfinity-0.7.1/test/session/PaxHeaders.26529/test-20.xml0000644000000000000000000000013212400102201020143 xustar0030 mtime=1409320065.147131494 30 atime=1409320065.147131494 30 ctime=1488261589.824137264 libinfinity-0.7.1/test/session/test-20.xml0000644000175000017500000000135212400102201020676 0ustar00arminarmin00000000000000 ABCDE Y Z ABC libinfinity-0.7.1/test/session/PaxHeaders.26529/test-49.xml0000644000000000000000000000013212400102201020156 xustar0030 mtime=1409320065.147131494 30 atime=1409320065.147131494 30 ctime=1488261589.856137193 libinfinity-0.7.1/test/session/test-49.xml0000644000175000017500000000121512400102201020707 0ustar00arminarmin00000000000000 c a c d c d a libinfinity-0.7.1/test/session/PaxHeaders.26529/test-37.xml0000644000000000000000000000013212400102201020153 xustar0030 mtime=1409320065.147131494 30 atime=1409320065.147131494 30 ctime=1488261589.840137228 libinfinity-0.7.1/test/session/test-37.xml0000644000175000017500000000103612400102201020705 0ustar00arminarmin00000000000000 b b libinfinity-0.7.1/test/session/PaxHeaders.26529/test-35.xml0000644000000000000000000000013212400102201020151 xustar0030 mtime=1409320065.147131494 30 atime=1409320065.147131494 30 ctime=1488261589.840137228 libinfinity-0.7.1/test/session/test-35.xml0000644000175000017500000000104612400102201020704 0ustar00arminarmin00000000000000 ab 1 ab libinfinity-0.7.1/test/session/PaxHeaders.26529/test-17.xml0000644000000000000000000000013212400102201020151 xustar0030 mtime=1409320065.147131494 30 atime=1409320065.147131494 30 ctime=1488261589.820137272 libinfinity-0.7.1/test/session/test-17.xml0000644000175000017500000000160712400102201020707 0ustar00arminarmin00000000000000 a b c a libinfinity-0.7.1/test/session/PaxHeaders.26529/test-30.xml0000644000000000000000000000013212400102201020144 xustar0030 mtime=1409320065.147131494 30 atime=1409320065.147131494 30 ctime=1488261589.832137246 libinfinity-0.7.1/test/session/test-30.xml0000644000175000017500000000170112400102201020675 0ustar00arminarmin00000000000000 a b b a libinfinity-0.7.1/test/session/PaxHeaders.26529/test-32.xml0000644000000000000000000000013212400102201020146 xustar0030 mtime=1409320065.147131494 30 atime=1409320065.147131494 30 ctime=1488261589.836137237 libinfinity-0.7.1/test/session/test-32.xml0000644000175000017500000000104012400102201020673 0ustar00arminarmin00000000000000 ab ab libinfinity-0.7.1/test/session/PaxHeaders.26529/test-24.xml0000644000000000000000000000013212400102201020147 xustar0030 mtime=1409320065.147131494 30 atime=1409320065.147131494 30 ctime=1488261589.828137254 libinfinity-0.7.1/test/session/test-24.xml0000644000175000017500000000177712400102201020715 0ustar00arminarmin00000000000000 a x z a y y z libinfinity-0.7.1/test/session/PaxHeaders.26529/test-21.xml0000644000000000000000000000013212400102201020144 xustar0030 mtime=1409320065.147131494 30 atime=1409320065.147131494 30 ctime=1488261589.824137264 libinfinity-0.7.1/test/session/test-21.xml0000644000175000017500000000164212400102201020701 0ustar00arminarmin00000000000000 ABCDE Y Z DEG ABCDE libinfinity-0.7.1/test/session/PaxHeaders.26529/test-29.xml0000644000000000000000000000013212400102201020154 xustar0030 mtime=1409320065.147131494 30 atime=1409320065.147131494 30 ctime=1488261589.832137246 libinfinity-0.7.1/test/session/test-29.xml0000644000175000017500000000106612400102201020711 0ustar00arminarmin00000000000000 a b b libinfinity-0.7.1/test/session/PaxHeaders.26529/test-25.xml0000644000000000000000000000013212400102201020150 xustar0030 mtime=1409320065.147131494 30 atime=1409320065.147131494 30 ctime=1488261589.828137254 libinfinity-0.7.1/test/session/test-25.xml0000644000175000017500000000173512400102201020710 0ustar00arminarmin00000000000000 abcd x x y acd libinfinity-0.7.1/test/session/PaxHeaders.26529/test-11.xml0000644000000000000000000000013112400102201020142 xustar0030 mtime=1409320065.147131494 30 atime=1409320065.147131494 29 ctime=1488261589.81213729 libinfinity-0.7.1/test/session/test-11.xml0000644000175000017500000000132212400102201020673 0ustar00arminarmin00000000000000 2 3 4 h h h 234 hhh libinfinity-0.7.1/test/session/PaxHeaders.26529/test-39.xml0000644000000000000000000000013112400102201020154 xustar0030 mtime=1409320065.147131494 30 atime=1409320065.147131494 29 ctime=1488261589.84413722 libinfinity-0.7.1/test/session/test-39.xml0000644000175000017500000000100412400102201020702 0ustar00arminarmin00000000000000 a b libinfinity-0.7.1/test/session/PaxHeaders.26529/test-18.xml0000644000000000000000000000013212400102201020152 xustar0030 mtime=1409320065.147131494 30 atime=1409320065.147131494 30 ctime=1488261589.820137272 libinfinity-0.7.1/test/session/test-18.xml0000644000175000017500000000161212400102201020704 0ustar00arminarmin00000000000000 a b c a libinfinity-0.7.1/test/session/PaxHeaders.26529/test-28.xml0000644000000000000000000000013212400102201020153 xustar0030 mtime=1409320065.147131494 30 atime=1409320065.147131494 30 ctime=1488261589.832137246 libinfinity-0.7.1/test/session/test-28.xml0000644000175000017500000000127212400102201020707 0ustar00arminarmin00000000000000 a b c c a libinfinity-0.7.1/test/session/PaxHeaders.26529/test-23.xml0000644000000000000000000000013212400102201020146 xustar0030 mtime=1409320065.147131494 30 atime=1409320065.147131494 30 ctime=1488261589.824137264 libinfinity-0.7.1/test/session/test-23.xml0000644000175000017500000000126012400102201020677 0ustar00arminarmin00000000000000 x a a libinfinity-0.7.1/test/session/PaxHeaders.26529/test-38.xml0000644000000000000000000000013112400102201020153 xustar0030 mtime=1409320065.147131494 30 atime=1409320065.147131494 29 ctime=1488261589.84413722 libinfinity-0.7.1/test/session/test-38.xml0000644000175000017500000000104612400102201020707 0ustar00arminarmin00000000000000 ab ab libinfinity-0.7.1/test/session/PaxHeaders.26529/test-05.xml0000644000000000000000000000013212400102201020146 xustar0030 mtime=1409320065.147131494 30 atime=1409320065.147131494 30 ctime=1488261589.804137307 libinfinity-0.7.1/test/session/test-05.xml0000644000175000017500000000127412400102201020704 0ustar00arminarmin00000000000000 1 b c d b d libinfinity-0.7.1/test/session/PaxHeaders.26529/test-22.xml0000644000000000000000000000013212400102201020145 xustar0030 mtime=1409320065.147131494 30 atime=1409320065.147131494 30 ctime=1488261589.824137264 libinfinity-0.7.1/test/session/test-22.xml0000644000175000017500000000132412400102201020677 0ustar00arminarmin00000000000000 x a a a libinfinity-0.7.1/test/session/PaxHeaders.26529/test-02.xml0000644000000000000000000000013212400102201020143 xustar0030 mtime=1409320065.147131494 30 atime=1409320065.147131494 30 ctime=1488261589.804137307 libinfinity-0.7.1/test/session/test-02.xml0000644000175000017500000000066612400102201020705 0ustar00arminarmin00000000000000 1 c 1 c libinfinity-0.7.1/test/session/PaxHeaders.26529/test-13.xml0000644000000000000000000000013112400102201020144 xustar0030 mtime=1409320065.147131494 30 atime=1409320065.147131494 29 ctime=1488261589.81213729 libinfinity-0.7.1/test/session/test-13.xml0000644000175000017500000000132212400102201020675 0ustar00arminarmin00000000000000 2 3 4 h h h 432 hhh libinfinity-0.7.1/test/session/PaxHeaders.26529/test-36.xml0000644000000000000000000000013212400102201020152 xustar0030 mtime=1409320065.147131494 30 atime=1409320065.147131494 30 ctime=1488261589.840137228 libinfinity-0.7.1/test/session/test-36.xml0000644000175000017500000000112412400102201020702 0ustar00arminarmin00000000000000 a b libinfinity-0.7.1/test/session/PaxHeaders.26529/test-52.xml0000644000000000000000000000013212400102201020150 xustar0030 mtime=1409320065.147131494 30 atime=1409320065.147131494 30 ctime=1488261589.860137185 libinfinity-0.7.1/test/session/test-52.xml0000644000175000017500000000071012400102201020700 0ustar00arminarmin00000000000000 b libinfinity-0.7.1/test/session/PaxHeaders.26529/test-08.xml0000644000000000000000000000013212400102201020151 xustar0030 mtime=1409320065.147131494 30 atime=1409320065.147131494 30 ctime=1488261589.808137298 libinfinity-0.7.1/test/session/test-08.xml0000644000175000017500000000141112400102201020700 0ustar00arminarmin00000000000000 a c d a c libinfinity-0.7.1/test/session/PaxHeaders.26529/test-09.xml0000644000000000000000000000013212400102201020152 xustar0030 mtime=1409320065.147131494 30 atime=1409320065.147131494 30 ctime=1488261589.808137298 libinfinity-0.7.1/test/session/test-09.xml0000644000175000017500000000204312400102201020703 0ustar00arminarmin00000000000000 a b cd b c b d a libinfinity-0.7.1/test/session/PaxHeaders.26529/test-44.xml0000644000000000000000000000013212400102201020151 xustar0030 mtime=1409320065.147131494 30 atime=1409320065.147131494 30 ctime=1488261589.848137211 libinfinity-0.7.1/test/session/test-44.xml0000644000175000017500000000103612400102201020703 0ustar00arminarmin00000000000000 a b c c b a libinfinity-0.7.1/test/session/PaxHeaders.26529/test-43.xml0000644000000000000000000000013212400102201020150 xustar0030 mtime=1409320065.147131494 30 atime=1409320065.147131494 30 ctime=1488261589.848137211 libinfinity-0.7.1/test/session/test-43.xml0000644000175000017500000000066612400102201020712 0ustar00arminarmin00000000000000 a b b a libinfinity-0.7.1/test/session/PaxHeaders.26529/test-14.xml0000644000000000000000000000013212400102201020146 xustar0030 mtime=1409320065.147131494 30 atime=1409320065.147131494 30 ctime=1488261589.816137281 libinfinity-0.7.1/test/session/test-14.xml0000644000175000017500000000106012400102201020675 0ustar00arminarmin00000000000000 a b c b a libinfinity-0.7.1/test/session/PaxHeaders.26529/test-16.xml0000644000000000000000000000013212400102201020150 xustar0030 mtime=1409320065.147131494 30 atime=1409320065.147131494 30 ctime=1488261589.816137281 libinfinity-0.7.1/test/session/test-16.xml0000644000175000017500000000125212400102201020702 0ustar00arminarmin00000000000000 x a a libinfinity-0.7.1/test/session/PaxHeaders.26529/test-15.xml0000644000000000000000000000013212400102201020147 xustar0030 mtime=1409320065.147131494 30 atime=1409320065.147131494 30 ctime=1488261589.816137281 libinfinity-0.7.1/test/session/test-15.xml0000644000175000017500000000106012400102201020676 0ustar00arminarmin00000000000000 a b c a b libinfinity-0.7.1/test/session/PaxHeaders.26529/test-33.xml0000644000000000000000000000013212400102201020147 xustar0030 mtime=1409320065.147131494 30 atime=1409320065.147131494 30 ctime=1488261589.836137237 libinfinity-0.7.1/test/session/test-33.xml0000644000175000017500000000102212400102201020674 0ustar00arminarmin00000000000000 M S A M A libinfinity-0.7.1/test/session/PaxHeaders.26529/test-40.xml0000644000000000000000000000013112400102201020144 xustar0030 mtime=1409320065.147131494 30 atime=1409320065.147131494 29 ctime=1488261589.84413722 libinfinity-0.7.1/test/session/test-40.xml0000644000175000017500000000105712400102201020702 0ustar00arminarmin00000000000000 AC B A B C libinfinity-0.7.1/test/session/PaxHeaders.26529/test-06.xml0000644000000000000000000000013212400102201020147 xustar0030 mtime=1409320065.147131494 30 atime=1409320065.147131494 30 ctime=1488261589.808137298 libinfinity-0.7.1/test/session/test-06.xml0000644000175000017500000000124512400102201020703 0ustar00arminarmin00000000000000 a b c c a libinfinity-0.7.1/test/PaxHeaders.26529/cleanup0000644000000000000000000000013213055210725016134 xustar0030 mtime=1488261589.884137132 30 atime=1488261589.860137185 30 ctime=1488261589.884137132 libinfinity-0.7.1/test/cleanup/0000755000175000017500000000000013055210725016743 5ustar00arminarmin00000000000000libinfinity-0.7.1/test/cleanup/PaxHeaders.26529/cleanup-01.xml0000644000000000000000000000013012400102201020554 xustar0029 mtime=1409320065.13113192 29 atime=1409320065.13113192 30 ctime=1488261589.884137132 libinfinity-0.7.1/test/cleanup/cleanup-01.xml0000644000175000017500000000041712400102201021312 0ustar00arminarmin00000000000000 c libinfinity-0.7.1/test/cleanup/PaxHeaders.26529/Makefile.in0000644000000000000000000000013013051241010020237 xustar0029 mtime=1487225352.64515141 29 atime=1487225352.64515141 30 ctime=1488261589.884137132 libinfinity-0.7.1/test/cleanup/Makefile.in0000644000175000017500000003325313051241010021001 0ustar00arminarmin00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 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__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) 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@ subdir = test/cleanup ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/gtk-doc.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/libinfinity/inf-config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ 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@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIRNAME = @DATADIRNAME@ 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@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ GTKDOC_CHECK = @GTKDOC_CHECK@ GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ GTKDOC_MKPDF = @GTKDOC_MKPDF@ GTKDOC_REBASE = @GTKDOC_REBASE@ HTML_DIR = @HTML_DIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INSTOBJEXT = @INSTOBJEXT@ INTLLIBS = @INTLLIBS@ INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBINFINITY_API_VERSION = @LIBINFINITY_API_VERSION@ LIBINFINITY_LIBTOOL_VERSION = @LIBINFINITY_LIBTOOL_VERSION@ LIBINFINITY_VERSION = @LIBINFINITY_VERSION@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGFMT_OPTS = @MSGFMT_OPTS@ 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@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ 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@ avahi_CFLAGS = @avahi_CFLAGS@ avahi_LIBS = @avahi_LIBS@ 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@ gio_CFLAGS = @gio_CFLAGS@ gio_LIBS = @gio_LIBS@ gtk_requirement = @gtk_requirement@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infgtk_CFLAGS = @infgtk_CFLAGS@ infgtk_LIBS = @infgtk_LIBS@ infinity_CFLAGS = @infinity_CFLAGS@ infinity_LIBS = @infinity_LIBS@ infinoted_CFLAGS = @infinoted_CFLAGS@ infinoted_LIBS = @infinoted_LIBS@ infodir = @infodir@ inftext_CFLAGS = @inftext_CFLAGS@ inftext_LIBS = @inftext_LIBS@ inftextgtk_CFLAGS = @inftextgtk_CFLAGS@ inftextgtk_LIBS = @inftextgtk_LIBS@ install_sh = @install_sh@ libdaemon_CFLAGS = @libdaemon_CFLAGS@ libdaemon_LIBS = @libdaemon_LIBS@ 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@ runstatedir = @runstatedir@ 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 = \ cleanup-01.xml all: all-am .SUFFIXES: $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(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) --foreign test/cleanup/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign test/cleanup/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: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs tags TAGS: ctags CTAGS: cscope cscopelist: 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: check-am all-am: Makefile installdirs: install: 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: 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." clean: clean-am clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic 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-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 -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: .MAKE: install-am install-strip .PHONY: all all-am check check-am clean clean-generic clean-libtool \ cscopelist-am ctags-am distclean distclean-generic \ distclean-libtool 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-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ tags-am uninstall uninstall-am .PRECIOUS: Makefile # 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: libinfinity-0.7.1/test/cleanup/PaxHeaders.26529/Makefile.am0000644000000000000000000000013012400102201020221 xustar0029 mtime=1409320065.13113192 29 atime=1409320065.13113192 30 ctime=1488261589.880137141 libinfinity-0.7.1/test/cleanup/Makefile.am0000644000175000017500000000003712400102201020755 0ustar00arminarmin00000000000000EXTRA_DIST = \ cleanup-01.xml libinfinity-0.7.1/test/PaxHeaders.26529/inf-test-gtk-browser.c0000644000000000000000000000013213034342512020720 xustar0030 mtime=1483851082.053718557 30 atime=1483851082.053718557 30 ctime=1488261589.720137491 libinfinity-0.7.1/test/inf-test-gtk-browser.c0000644000175000017500000006226713034342512021467 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include typedef struct _InfTestGtkBrowserWindow InfTestGtkBrowserWindow; struct _InfTestGtkBrowserWindow { GtkWidget* textview; GtkWidget* undo_button; GtkWidget* redo_button; InfTextGtkBuffer* buffer; InfTextGtkView* view; InfTextGtkViewport* viewport; InfSessionProxy* proxy; InfUser* user; InfRequest* request; }; typedef struct _InfTestGtkBrowserChatWindow InfTestGtkBrowserChatWindow; struct _InfTestGtkBrowserChatWindow { GtkWidget* chat; GtkWidget* status; InfChatBuffer* buffer; InfSessionProxy* proxy; InfUser* user; InfRequest* request; }; static InfSession* inf_test_gtk_browser_session_new(InfIo* io, InfCommunicationManager* manager, InfSessionStatus status, InfCommunicationGroup* sync_group, InfXmlConnection* sync_connection, const gchar* path, gpointer user_data) { InfTextGtkBuffer* buffer; InfUserTable* user_table; GtkTextBuffer* textbuffer; InfTextSession* session; textbuffer = gtk_text_buffer_new(NULL); user_table = inf_user_table_new(); buffer = inf_text_gtk_buffer_new(textbuffer, user_table); session = inf_text_session_new_with_user_table( manager, INF_TEXT_BUFFER(buffer), io, user_table, status, sync_group, sync_connection ); return INF_SESSION(session); } static const InfcNotePlugin INF_TEST_GTK_BROWSER_TEXT_PLUGIN = { NULL, "InfText", inf_test_gtk_browser_session_new }; static void set_error(InfTestGtkBrowserWindow* test, const gchar* prefix, const gchar* error_message) { GtkTextBuffer* new_buffer; GtkTextIter iter; /* Note we cannot just write in the current buffer of the textview because * it is coupled with the InfTextGtkBuffer which would then try to send * the text insertion to the subscription group (and fail doing so, * probably). */ new_buffer = gtk_text_buffer_new(NULL); gtk_text_buffer_get_start_iter(new_buffer, &iter); gtk_text_buffer_insert(new_buffer, &iter, prefix, -1); gtk_text_buffer_insert(new_buffer, &iter, ": ", 2); gtk_text_buffer_insert(new_buffer, &iter, error_message, -1); gtk_text_view_set_buffer(GTK_TEXT_VIEW(test->textview), new_buffer); g_object_unref(G_OBJECT(new_buffer)); } static void on_undo_button_clicked(GtkButton* button, gpointer user_data) { InfTestGtkBrowserWindow* test; InfSession* session; test = (InfTestGtkBrowserWindow*)user_data; g_object_get(G_OBJECT(test->proxy), "session", &session, NULL); inf_adopted_session_undo( INF_ADOPTED_SESSION(session), INF_ADOPTED_USER(test->user), 1 ); g_object_unref(session); } static void on_redo_button_clicked(GtkButton* button, gpointer user_data) { InfTestGtkBrowserWindow* test; InfSession* session; test = (InfTestGtkBrowserWindow*)user_data; g_object_get(G_OBJECT(test->proxy), "session", &session, NULL); inf_adopted_session_redo( INF_ADOPTED_SESSION(session), INF_ADOPTED_USER(test->user), 1 ); g_object_unref(session); } static void on_can_undo_changed(InfAdoptedAlgorithm* algorithm, InfAdoptedUser* user, gboolean can_undo, gpointer user_data) { InfTestGtkBrowserWindow* test; test = (InfTestGtkBrowserWindow*)user_data; gtk_widget_set_sensitive(test->undo_button, can_undo); } static void on_can_redo_changed(InfAdoptedAlgorithm* algorithm, InfAdoptedUser* user, gboolean can_redo, gpointer user_data) { InfTestGtkBrowserWindow* test; test = (InfTestGtkBrowserWindow*)user_data; gtk_widget_set_sensitive(test->redo_button, can_redo); } static void request_chat_join(InfTestGtkBrowserChatWindow* test, const gchar* user_name); static void on_chat_join_finished(InfRequest* request, const InfRequestResult* result, const GError* error, gpointer user_data) { InfTestGtkBrowserChatWindow* test; InfUser* user; gchar* new_name; gchar* text; test = (InfTestGtkBrowserChatWindow*)user_data; if(test->request != NULL) { g_object_unref(test->request); test->request = NULL; } if(error == NULL) { inf_request_result_get_join_user(result, NULL, &user); inf_gtk_chat_set_active_user(INF_GTK_CHAT(test->chat), user); text = g_strdup_printf("Joined as %s", inf_user_get_name(user)); gtk_label_set_text(GTK_LABEL(test->status), text); g_free(text); test->user = user; g_object_ref(user); /* Unfortunately, gtk_widget_grab_focus(test->chat) + * gtk_container_set_focus_child() in inf_gtk_chat_set_active_user() does * not do the job which is why I added this crappy API. */ gtk_widget_grab_focus(inf_gtk_chat_get_entry(INF_GTK_CHAT(test->chat))); } else { if(error->domain == inf_user_error_quark() && error->code == INF_USER_ERROR_NAME_IN_USE) { new_name = g_strdup_printf("%s%d", g_get_user_name(), rand()); request_chat_join(test, new_name); g_free(new_name); } else { text = g_strdup_printf("User join failed: %s", error->message); gtk_label_set_text(GTK_LABEL(test->status), text); g_free(text); } } } static void request_join(InfTestGtkBrowserWindow* test, const gchar* user_name); static void on_join_finished(InfRequest* request, const InfRequestResult* result, const GError* error, gpointer user_data) { InfTestGtkBrowserWindow* test; InfUser* user; InfSession* session; InfAdoptedAlgorithm* algorithm; gboolean undo; gboolean redo; gchar* new_name; test = (InfTestGtkBrowserWindow*)user_data; if(test->request != NULL) { g_object_unref(test->request); test->request = NULL; } if(error == NULL) { inf_request_result_get_join_user(result, NULL, &user); inf_text_gtk_buffer_set_active_user(test->buffer, INF_TEXT_USER(user)); inf_text_gtk_view_set_active_user(test->view, INF_TEXT_USER(user)); inf_text_gtk_viewport_set_active_user( test->viewport, INF_TEXT_USER(user) ); gtk_text_view_set_editable(GTK_TEXT_VIEW(test->textview), TRUE); test->user = user; g_object_ref(user); g_object_get(G_OBJECT(test->proxy), "session", &session, NULL); algorithm = inf_adopted_session_get_algorithm(INF_ADOPTED_SESSION(session)); g_object_unref(session); undo = inf_adopted_algorithm_can_undo(algorithm, INF_ADOPTED_USER(user)); redo = inf_adopted_algorithm_can_redo(algorithm, INF_ADOPTED_USER(user)); gtk_widget_set_sensitive(test->undo_button, undo); gtk_widget_set_sensitive(test->redo_button, redo); } else { if(error->domain == inf_user_error_quark() && error->code == INF_USER_ERROR_NAME_IN_USE) { new_name = g_strdup_printf("%s%d", g_get_user_name(), rand()); request_join(test, new_name); g_free(new_name); } else { set_error(test, "User join failed", error->message); } } } static void request_chat_join(InfTestGtkBrowserChatWindow* test, const gchar* user_name) { InfRequest* request; gchar* text; GParameter params[1] = { { "name", { 0 } } }; g_value_init(¶ms[0].value, G_TYPE_STRING); g_value_set_static_string(¶ms[0].value, user_name); text = g_strdup_printf("Requesting user join for %s", user_name); gtk_label_set_text(GTK_LABEL(test->status), text); g_free(text); request = inf_session_proxy_join_user( test->proxy, 1, params, on_chat_join_finished, test ); g_value_unset(¶ms[0].value); if(request != NULL) { g_assert(test->request == NULL); test->request = request; g_object_ref(test->request); } } static void request_join(InfTestGtkBrowserWindow* test, const gchar* user_name) { InfRequest* request; InfSession* session; InfAdoptedStateVector* v; GtkTextBuffer* buffer; GtkTextMark* mark; GtkTextIter iter; GParameter params[3] = { { "name", { 0 } }, { "vector", { 0 } }, { "caret-position", { 0 } } }; g_value_init(¶ms[0].value, G_TYPE_STRING); g_value_init(¶ms[1].value, INF_ADOPTED_TYPE_STATE_VECTOR); g_value_init(¶ms[2].value, G_TYPE_UINT); g_value_set_static_string(¶ms[0].value, user_name); g_object_get(G_OBJECT(test->proxy), "session", &session, NULL); /* Use current state vector. Infinote should already do this. */ v = inf_adopted_state_vector_copy( inf_adopted_algorithm_get_current( inf_adopted_session_get_algorithm(INF_ADOPTED_SESSION(session)) ) ); g_value_take_boxed(¶ms[1].value, v); buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(test->textview)); mark = gtk_text_buffer_get_insert(buffer); gtk_text_buffer_get_iter_at_mark(buffer, &iter, mark); g_value_set_uint(¶ms[2].value, gtk_text_iter_get_offset(&iter)); request = inf_session_proxy_join_user( test->proxy, 3, params, on_join_finished, test ); g_object_unref(session); if(request != NULL) { g_assert(test->request == NULL); test->request = request; g_object_ref(request); } } static void on_chat_synchronization_failed(InfSession* session, InfXmlConnection* connection, const GError* error, gpointer user_data) { InfTestGtkBrowserChatWindow* test; gchar* text; test = (InfTestGtkBrowserChatWindow*)user_data; text = g_strdup_printf("Synchronization failed: %s\n", error->message); gtk_label_set_text(GTK_LABEL(test->status), text); g_free(text); } static void on_chat_synchronization_complete(InfSession* session, InfXmlConnection* connection, gpointer user_data) { InfTestGtkBrowserChatWindow* test; test = (InfTestGtkBrowserChatWindow*)user_data; request_chat_join(test, g_get_user_name()); } static void on_synchronization_failed(InfSession* session, InfXmlConnection* connection, const GError* error, gpointer user_data) { InfTestGtkBrowserWindow* test; test = (InfTestGtkBrowserWindow*)user_data; set_error(test, "Synchronization failed", error->message); } static void on_synchronization_complete(InfSession* session, InfXmlConnection* connection, gpointer user_data) { InfTestGtkBrowserWindow* test; InfAdoptedAlgorithm* algorithm; test = (InfTestGtkBrowserWindow*)user_data; algorithm = inf_adopted_session_get_algorithm(INF_ADOPTED_SESSION(session)); g_signal_connect( G_OBJECT(algorithm), "can-undo-changed", G_CALLBACK(on_can_undo_changed), test ); g_signal_connect( G_OBJECT(algorithm), "can-redo-changed", G_CALLBACK(on_can_redo_changed), test ); request_join(test, g_get_user_name()); } static void on_chat_window_destroy(GtkWindow* window, gpointer user_data) { InfTestGtkBrowserChatWindow* test; InfSession* session; test = (InfTestGtkBrowserChatWindow*)user_data; g_object_get(G_OBJECT(test->proxy), "session", &session, NULL); inf_signal_handlers_disconnect_by_func( session, G_CALLBACK(on_chat_synchronization_complete), test ); inf_signal_handlers_disconnect_by_func( session, G_CALLBACK(on_chat_synchronization_failed), test ); g_object_unref(session); if(test->request != NULL) { inf_signal_handlers_disconnect_by_func( test->request, G_CALLBACK(on_chat_join_finished), test ); g_object_unref(test->request); } if(test->proxy != NULL) g_object_unref(test->proxy); if(test->user != NULL) g_object_unref(test->user); g_slice_free(InfTestGtkBrowserChatWindow, test); } static void on_text_window_destroy(GtkWindow* window, gpointer user_data) { InfTestGtkBrowserWindow* test; InfSession* session; test = (InfTestGtkBrowserWindow*)user_data; g_object_get(G_OBJECT(test->proxy), "session", &session, NULL); inf_signal_handlers_disconnect_by_func( session, G_CALLBACK(on_synchronization_complete), test ); inf_signal_handlers_disconnect_by_func( session, G_CALLBACK(on_synchronization_failed), test ); g_object_unref(session); if(test->request != NULL) { inf_signal_handlers_disconnect_by_func( test->request, G_CALLBACK(on_join_finished), test ); g_object_unref(test->request); } if(test->proxy != NULL) g_object_unref(test->proxy); /* TODO: Do we ever ref buffer? */ if(test->buffer != NULL) g_object_unref(test->buffer); if(test->user !=NULL) g_object_unref(test->user); g_slice_free(InfTestGtkBrowserWindow, test); } static void on_subscribe_chat_session(InfcBrowser* browser, InfcSessionProxy* proxy, gpointer user_data) { InfSession* session; InfChatBuffer* buffer; GtkWidget* chat; GtkWidget* status; GtkWidget* vbox; GtkWidget* window; InfTestGtkBrowserChatWindow* test; g_object_get(G_OBJECT(proxy), "session", &session, NULL); buffer = INF_CHAT_BUFFER(inf_session_get_buffer(session)); chat = inf_gtk_chat_new(); inf_gtk_chat_set_session(INF_GTK_CHAT(chat), INF_CHAT_SESSION(session)); gtk_widget_show(chat); status = gtk_label_new("Synchronizing chat..."); gtk_widget_show(status); vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6); gtk_box_pack_start(GTK_BOX(vbox), chat, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(vbox), status, FALSE, TRUE, 0); gtk_widget_show(vbox); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(window), "Chat"); gtk_window_set_default_size(GTK_WINDOW(window), 400, 400); gtk_window_set_icon_name(GTK_WINDOW(window), "infinote"); gtk_container_set_border_width(GTK_CONTAINER(window), 6); gtk_container_add(GTK_CONTAINER(window), vbox); gtk_widget_show(window); test = g_slice_new(InfTestGtkBrowserChatWindow); test->chat = chat; test->status = status; test->buffer = buffer; test->proxy = INF_SESSION_PROXY(proxy); test->user = NULL; test->request = NULL; g_object_ref(test->proxy); g_signal_connect_after( G_OBJECT(session), "synchronization-failed", G_CALLBACK(on_chat_synchronization_failed), test ); g_signal_connect_after( G_OBJECT(session), "synchronization-complete", G_CALLBACK(on_chat_synchronization_complete), test ); g_signal_connect( G_OBJECT(window), "destroy", G_CALLBACK(on_chat_window_destroy), test ); g_object_unref(session); } static void on_subscribe_session(InfcBrowser* browser, const InfBrowserIter* iter, InfcSessionProxy* proxy, InfRequest* request, gpointer user_data) { GtkWidget* window; GtkWidget* scroll; GtkWidget* textview; GtkWidget* vbox; GtkWidget* hbox; GtkWidget* undo_button; GtkWidget* redo_button; InfSession* session; InfIo* io; InfUserTable* user_table; InfTextGtkBuffer* buffer; InfTextGtkView* view; InfTextGtkViewport* viewport; GtkTextBuffer* textbuffer; InfTestGtkBrowserWindow* test; if(iter == NULL) { on_subscribe_chat_session(browser, proxy, user_data); return; } g_object_get(G_OBJECT(proxy), "session", &session, NULL); io = inf_adopted_session_get_io(INF_ADOPTED_SESSION(session)); user_table = inf_session_get_user_table(session); buffer = INF_TEXT_GTK_BUFFER(inf_session_get_buffer(session)); textbuffer = inf_text_gtk_buffer_get_text_buffer(buffer); textview = gtk_text_view_new_with_buffer(textbuffer); view = inf_text_gtk_view_new(io, GTK_TEXT_VIEW(textview), user_table); gtk_text_view_set_editable(GTK_TEXT_VIEW(textview), FALSE); gtk_widget_show(textview); scroll = gtk_scrolled_window_new(NULL, NULL); viewport = inf_text_gtk_viewport_new(GTK_SCROLLED_WINDOW(scroll), user_table); gtk_scrolled_window_set_shadow_type( GTK_SCROLLED_WINDOW(scroll), GTK_SHADOW_IN ); gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC ); gtk_container_add(GTK_CONTAINER(scroll), textview); gtk_widget_show(scroll); undo_button = gtk_button_new_with_label("Undo"); redo_button = gtk_button_new_with_label("Redo"); gtk_widget_set_sensitive(undo_button, FALSE); gtk_widget_set_sensitive(redo_button, FALSE); gtk_widget_show(undo_button); gtk_widget_show(redo_button); hbox = gtk_button_box_new(GTK_ORIENTATION_HORIZONTAL); gtk_box_pack_start(GTK_BOX(hbox), undo_button, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(hbox), redo_button, FALSE, FALSE, 0); gtk_widget_show(hbox); vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 6); gtk_box_pack_start(GTK_BOX(vbox), scroll, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); gtk_widget_show(vbox); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title( GTK_WINDOW(window), inf_browser_get_node_name(INF_BROWSER(browser), iter) ); gtk_window_set_default_size(GTK_WINDOW(window), 400, 400); gtk_window_set_icon_name(GTK_WINDOW(window), "infinote"); gtk_container_set_border_width(GTK_CONTAINER(window), 6); gtk_container_add(GTK_CONTAINER(window), vbox); gtk_widget_show(window); test = g_slice_new(InfTestGtkBrowserWindow); test->textview = textview; test->undo_button = undo_button; test->redo_button = redo_button; test->buffer = buffer; test->view = view; test->viewport = viewport; test->proxy = INF_SESSION_PROXY(proxy); test->user = NULL; test->request = NULL; g_object_ref(proxy); g_signal_connect_after( G_OBJECT(session), "synchronization-failed", G_CALLBACK(on_synchronization_failed), test ); g_signal_connect_after( G_OBJECT(session), "synchronization-complete", G_CALLBACK(on_synchronization_complete), test ); g_signal_connect( G_OBJECT(window), "destroy", G_CALLBACK(on_text_window_destroy), test ); g_signal_connect( G_OBJECT(undo_button), "clicked", G_CALLBACK(on_undo_button_clicked), test ); g_signal_connect( G_OBJECT(redo_button), "clicked", G_CALLBACK(on_redo_button_clicked), test ); g_object_unref(session); } static void on_activate(InfGtkBrowserView* view, GtkTreeIter* iter, gpointer user_data) { InfBrowser* browser; InfBrowserIter* browser_iter; const char* note_type; const InfcNotePlugin* plugin; InfRequest* request; printf("activate\n"); gtk_tree_model_get( GTK_TREE_MODEL(gtk_tree_view_get_model(GTK_TREE_VIEW(view))), iter, INF_GTK_BROWSER_MODEL_COL_BROWSER, &browser, INF_GTK_BROWSER_MODEL_COL_NODE, &browser_iter, -1 ); note_type = inf_browser_get_node_type(browser, browser_iter); plugin = infc_browser_lookup_plugin(INFC_BROWSER(browser), note_type); /* Subscribe, if possible and not already */ request = inf_browser_get_pending_request( browser, browser_iter, "subscribe-session" ); if(!inf_browser_get_session(browser, browser_iter) && !request && plugin != NULL) { inf_browser_subscribe(browser, browser_iter, NULL, NULL); } inf_browser_iter_free(browser_iter); g_object_unref(browser); } static void on_browser_notify_status(GObject* object, const GParamSpec* pspec, gpointer user_data) { InfcBrowser* browser; InfBrowserStatus status; browser = INFC_BROWSER(object); g_object_get(G_OBJECT(browser), "status", &status, NULL); if(status == INF_BROWSER_OPEN) infc_browser_subscribe_chat(browser, NULL, NULL); } static void on_set_browser(InfGtkBrowserModel* model, GtkTreePath* path, GtkTreeIter* iter, InfBrowser* old_browser, InfBrowser* browser, gpointer user_data) { InfBrowserStatus status; if(browser != NULL) { infc_browser_add_plugin( INFC_BROWSER(browser), &INF_TEST_GTK_BROWSER_TEXT_PLUGIN ); g_signal_connect_after( G_OBJECT(browser), "subscribe-session", G_CALLBACK(on_subscribe_session), NULL ); g_object_get(G_OBJECT(browser), "status", &status, NULL); if(status == INF_BROWSER_OPEN) { infc_browser_subscribe_chat(INFC_BROWSER(browser), NULL, NULL); } else { g_signal_connect( G_OBJECT(browser), "notify::status", G_CALLBACK(on_browser_notify_status), browser ); } } } static void on_destroy(GtkWindow* window, gpointer user_data) { /* TODO: Destroy open text windows */ gtk_main_quit(); } int main(int argc, char* argv[]) { InfGtkIo* io; InfCommunicationManager* communication_manager; #ifdef LIBINFINITY_HAVE_AVAHI InfXmppManager* xmpp_manager; InfDiscoveryAvahi* avahi; #endif InfGtkBrowserStore* store; GtkWidget* view; GtkWidget* scroll; GtkWidget* window; GError* error; int i; InfTcpConnection* tcp; InfXmppConnection* xmpp; InfIpAddress* addr; gtk_init(&argc, &argv); error = NULL; if(!inf_init(&error)) { fprintf(stderr, "%s\n", error->message); return -1; } io = inf_gtk_io_new(); #ifdef LIBINFINITY_HAVE_AVAHI xmpp_manager = inf_xmpp_manager_new(); avahi = inf_discovery_avahi_new(INF_IO(io), xmpp_manager, NULL, NULL, NULL); g_object_unref(G_OBJECT(xmpp_manager)); #endif communication_manager = inf_communication_manager_new(); store = inf_gtk_browser_store_new(INF_IO(io), communication_manager); g_object_unref(communication_manager); g_signal_connect_after( G_OBJECT(store), "set-browser", G_CALLBACK(on_set_browser), NULL ); for(i = 1; i < argc; ++i) { addr = inf_ip_address_new_from_string(argv[i]); tcp = inf_tcp_connection_new( INF_IO(io), addr, inf_protocol_get_default_port() ); xmpp = inf_xmpp_connection_new( tcp, INF_XMPP_CONNECTION_CLIENT, g_get_host_name(), argv[i], INF_XMPP_CONNECTION_SECURITY_BOTH_PREFER_TLS, NULL, NULL, NULL ); inf_ip_address_free(addr); g_object_unref(tcp); #ifdef LIBINFINITY_HAVE_AVAHI inf_xmpp_manager_add_connection(xmpp_manager, xmpp); #endif inf_gtk_browser_store_add_connection( INF_GTK_BROWSER_STORE(store), INF_XML_CONNECTION(xmpp), argv[i] ); } g_object_unref(G_OBJECT(io)); #ifdef LIBINFINITY_HAVE_AVAHI inf_gtk_browser_store_add_discovery(store, INF_DISCOVERY(avahi)); g_object_unref(G_OBJECT(avahi)); #endif view = inf_gtk_browser_view_new_with_model(INF_GTK_BROWSER_MODEL(store)); g_object_unref(G_OBJECT(store)); gtk_widget_show(view); g_signal_connect( G_OBJECT(view), "activate", G_CALLBACK(on_activate), NULL ); scroll = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy( GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC ); gtk_scrolled_window_set_shadow_type( GTK_SCROLLED_WINDOW(scroll), GTK_SHADOW_IN ); gtk_container_add(GTK_CONTAINER(scroll), view); gtk_widget_show(scroll); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(window),"Infinote Browser"); gtk_window_set_default_size(GTK_WINDOW(window), 400, 400); gtk_window_set_icon_name(GTK_WINDOW(window), "infinote"); gtk_container_set_border_width(GTK_CONTAINER(window), 6); gtk_container_add(GTK_CONTAINER(window), scroll); gtk_widget_show(window); g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(on_destroy), NULL); gtk_main(); return 0; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/test/PaxHeaders.26529/inf-test-tcp-connection.c0000644000000000000000000000013213034342512021375 xustar0030 mtime=1483851082.053718557 30 atime=1483851082.053718557 30 ctime=1488261589.728137474 libinfinity-0.7.1/test/inf-test-tcp-connection.c0000644000175000017500000001330613034342512022132 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include static void received_cb(InfTcpConnection* connection, gconstpointer buffer, guint len, gpointer user_data) { printf("Received: \033[00;32m%.*s\033[00;00m", (int)len, (const char*)buffer); fflush(stdout); } static void sent_cb(InfTcpConnection* connection, gconstpointer buffer, guint len, gpointer user_data) { printf("Sent: \033[00;34m%.*s\033[00;00m", (int)len, (const char*)buffer); fflush(stdout); } static void error_cb(InfTcpConnection* connection, GError* error, gpointer user_data) { fprintf(stderr, "Connection Error occured: %s\n", error->message); if(inf_standalone_io_loop_running(INF_STANDALONE_IO(user_data))) inf_standalone_io_loop_quit(INF_STANDALONE_IO(user_data)); } static void resolved_cb(InfNameResolver* resolver, const GError* error, gpointer user_data) { gchar* hostname; gchar* service; gchar* srv; guint i; gchar* str; if(error != NULL) { fprintf(stderr, "Resolver error: %s\n", error->message); } else { g_object_get( G_OBJECT(resolver), "hostname", &hostname, "service", &service, "srv", &srv, NULL ); printf( "Resolved hostname %s (SRV %s):\n", hostname, srv ? srv : "(nul)" ); g_free(hostname); g_free(service); g_free(srv); for(i = 0; i < inf_name_resolver_get_n_addresses(resolver); ++i) { str = inf_ip_address_to_string( inf_name_resolver_get_address(resolver, i) ); printf( " %u: %s (port %u)\n", i, str, inf_name_resolver_get_port(resolver, i) ); g_free(str); } } } static void notify_status_cb(InfTcpConnection* connection, GParamSpec* pspec, gpointer user_data) { InfTcpConnectionStatus status; InfIpAddress* addr; guint port; InfNameResolver* resolver; gchar* addr_str_tmp; gchar* addr_str; g_object_get( G_OBJECT(connection), "status", &status, "remote-address", &addr, "remote-port", &port, "resolver", &resolver, NULL ); if(addr != NULL) { addr_str_tmp = inf_ip_address_to_string(addr); addr_str = g_strdup_printf("%s:%u", addr_str_tmp, port); g_free(addr_str_tmp); } else { g_object_get(G_OBJECT(resolver), "hostname", &addr_str, NULL); } if(addr != NULL) inf_ip_address_free(addr); if(resolver != NULL) g_object_unref(resolver); switch(status) { case INF_TCP_CONNECTION_CONNECTING: printf("Connecting to %s\n", addr_str); break; case INF_TCP_CONNECTION_CONNECTED: printf("Connected to %s\n", addr_str); g_object_get( G_OBJECT(connection), "local-address", &addr, "local-port", &port, NULL ); g_free(addr_str); addr_str = inf_ip_address_to_string(addr); inf_ip_address_free(addr); printf("Connected from %s:%u\n", addr_str, port); inf_tcp_connection_send(connection, "Hello, World!\n", 14); break; case INF_TCP_CONNECTION_CLOSED: printf("Connection to %s closed\n", addr_str); if(inf_standalone_io_loop_running(INF_STANDALONE_IO(user_data))) inf_standalone_io_loop_quit(INF_STANDALONE_IO(user_data)); break; default: g_assert_not_reached(); break; } g_free(addr_str); } int main(int argc, char* argv[]) { InfStandaloneIo* io; InfNameResolver* resolver; InfTcpConnection* connection; GError* error; error = NULL; if(inf_init(&error) == FALSE) { fprintf(stderr, "%s", error->message); g_error_free(error); return 1; } io = inf_standalone_io_new(); resolver = inf_name_resolver_new(INF_IO(io), "0x539.de", "5223", "_jabber._tcp"); g_signal_connect( G_OBJECT(resolver), "resolved", G_CALLBACK(resolved_cb), io ); connection = inf_tcp_connection_new_resolve(INF_IO(io), resolver); g_object_unref(resolver); g_signal_connect( G_OBJECT(connection), "received", G_CALLBACK(received_cb), io ); g_signal_connect( G_OBJECT(connection), "sent", G_CALLBACK(sent_cb), io ); g_signal_connect( G_OBJECT(connection), "error", G_CALLBACK(error_cb), io ); g_signal_connect( G_OBJECT(connection), "notify::status", G_CALLBACK(notify_status_cb), io ); if(inf_tcp_connection_open(connection, &error) == FALSE) { fprintf(stderr, "Could not open connection: %s\n", error->message); g_error_free(error); } else { inf_standalone_io_loop(io); } g_object_unref(G_OBJECT(io)); g_object_unref(G_OBJECT(connection)); return 0; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/test/PaxHeaders.26529/inf-test-text-cleanup.c0000644000000000000000000000013213034342512021063 xustar0030 mtime=1483851082.053718557 30 atime=1483851082.053718557 30 ctime=1488261589.728137474 libinfinity-0.7.1/test/inf-test-text-cleanup.c0000644000175000017500000002473313034342512021626 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include "util/inf-test-util.h" #include #include #include #include #include #include #include #include #include #include #include typedef struct { guint total; guint passed; } test_result; typedef enum { INF_TEST_TEXT_CLEANUP_USER_UNAVAILABLE, INF_TEST_TEXT_CLEANUP_UNSUPPORTED, INF_TEST_TEXT_CLEANUP_VERIFY_FAILED } InfTestTextCleanupError; static GQuark inf_test_text_cleanup_error_quark() { return g_quark_from_static_string("INF_TEST_TEXT_CLEANUP_ERROR"); } static void error_cb(InfSession* session, InfXmlConnection* connection, xmlNodePtr xml, const GError* error, gpointer user_data) { GError** error_loc = (GError**)user_data; *error_loc = g_error_copy(error); } static gboolean perform_test(guint max_total_log_size, InfTextChunk* initial, GSList* users, GSList* requests, GError** error) { InfTextBuffer* buffer; InfCommunicationManager* manager; InfIo* io; InfTextSession* session; InfAdoptedAlgorithm* algorithm; InfUserTable* user_table; InfTextUser* user; gchar* user_name; GSList* item; xmlNodePtr request; gboolean result; GError* local_error; guint verify_user_id; InfAdoptedUser* verify_user; guint verify_log_size; gint verify_can_undo; gint verify_can_redo; InfAdoptedRequestLog* log; guint log_size; buffer = INF_TEXT_BUFFER(inf_text_default_buffer_new("UTF-8")); inf_text_buffer_insert_chunk(buffer, 0, initial, NULL); manager = inf_communication_manager_new(); io = INF_IO(inf_standalone_io_new()); user_table = inf_user_table_new(); local_error = NULL; for(item = users; item != NULL; item = g_slist_next(item)) { user_name = g_strdup_printf("User_%u", GPOINTER_TO_UINT(item->data)); user = INF_TEXT_USER( g_object_new( INF_TEXT_TYPE_USER, "id", GPOINTER_TO_UINT(item->data), "name", user_name, "status", INF_USER_ACTIVE, "flags", 0, NULL ) ); g_free(user_name); inf_user_table_add_user(user_table, INF_USER(user)); g_object_unref(user); } session = INF_TEXT_SESSION( g_object_new( INF_TEXT_TYPE_SESSION, "communication-manager", manager, "buffer", buffer, "io", io, "user_table", user_table, "max-total-log-size", max_total_log_size, NULL ) ); g_signal_connect( G_OBJECT(session), "error", G_CALLBACK(error_cb), &local_error ); algorithm = inf_adopted_session_get_algorithm(INF_ADOPTED_SESSION(session)); g_object_unref(io); g_object_unref(manager); g_object_unref(user_table); g_object_unref(buffer); for(item = requests; item != NULL; item = item->next) { request = (xmlNodePtr)item->data; if(strcmp((const char*)request->name, "request") == 0) { /* Request */ result = inf_communication_object_received( INF_COMMUNICATION_OBJECT(session), NULL, request ); if(local_error != NULL) { g_prefix_error(&local_error, "[%d] ", request->line); goto fail; } } else { /* TODO: Make an extra function out of this: */ /* Verify */ result = inf_xml_util_get_attribute_uint_required( request, "user", &verify_user_id, &local_error ); if(result == FALSE) goto fail; verify_user = INF_ADOPTED_USER( inf_user_table_lookup_user_by_id(user_table, verify_user_id) ); if(verify_user == NULL) { g_set_error( error, inf_test_text_cleanup_error_quark(), INF_TEST_TEXT_CLEANUP_USER_UNAVAILABLE, "[%d] User ID '%u' not available", request->line, verify_user_id ); goto fail; } result = inf_xml_util_get_attribute_uint( request, "log-size", &verify_log_size, &local_error ); if(local_error) goto fail; if(result) { log = inf_adopted_user_get_request_log(INF_ADOPTED_USER(verify_user)); log_size = inf_adopted_request_log_get_end(log) - inf_adopted_request_log_get_begin(log); if(verify_log_size != log_size) { g_set_error( error, inf_test_text_cleanup_error_quark(), INF_TEST_TEXT_CLEANUP_VERIFY_FAILED, "[%d] Log size does not match; got %u, but expected %u", request->line, log_size, verify_log_size ); goto fail; } } result = inf_xml_util_get_attribute_int( request, "can-undo", &verify_can_undo, &local_error ); if(local_error) goto fail; if(result) { result = inf_adopted_algorithm_can_undo(algorithm, verify_user); if(result != verify_can_undo) { g_set_error( error, inf_test_text_cleanup_error_quark(), INF_TEST_TEXT_CLEANUP_VERIFY_FAILED, "[%d] can-undo does not match; got %d, but expected %d", request->line, (guint)result, verify_can_undo ); goto fail; } } result = inf_xml_util_get_attribute_int( request, "can-redo", &verify_can_redo, &local_error ); if(local_error) goto fail; if(result) { result = inf_adopted_algorithm_can_redo(algorithm, verify_user); if(result != verify_can_redo) { g_set_error( error, inf_test_text_cleanup_error_quark(), INF_TEST_TEXT_CLEANUP_VERIFY_FAILED, "[%d] can-redo does not match; got %d, but expected %d", request->line, (guint)result, verify_can_redo ); goto fail; } } } } g_object_unref(session); return TRUE; fail: g_object_unref(session); if(local_error) g_propagate_error(error, local_error); return FALSE; } static void foreach_test_func(const gchar* testfile, gpointer user_data) { test_result* result; xmlDocPtr doc; xmlNodePtr root; xmlNodePtr child; GSList* requests; InfTextChunk* initial; GSList* users; guint max_total_log_size; GError* error; gboolean res; /* Only process XML files, not the Makefiles or other stuff */ if(!g_str_has_suffix(testfile, ".xml")) return; result = (test_result*)user_data; doc = xmlParseFile(testfile); requests = NULL; initial = NULL; users = NULL; max_total_log_size = 0; error = NULL; printf("%s... ", testfile); fflush(stdout); ++ result->total; if(doc != NULL) { root = xmlDocGetRootElement(doc); for(child = root->children; child != NULL; child = child->next) { if(child->type != XML_ELEMENT_NODE) continue; if(strcmp((const char*)child->name, "log") == 0) { res = inf_xml_util_get_attribute_uint_required( child, "size", &max_total_log_size, &error ); if(!res) break; } else if(strcmp((const char*)child->name, "initial-buffer") == 0) { if(initial != NULL) inf_text_chunk_free(initial); initial = inf_test_util_parse_buffer(child, &error); if(initial == NULL) break; } else if(strcmp((const char*)child->name, "user") == 0) { if(inf_test_util_parse_user(child, &users, &error) == FALSE) break; } else if(strcmp((const char*)child->name, "request") == 0 || strcmp((const char*)child->name, "verify") == 0) { requests = g_slist_prepend(requests, child); } else { g_set_error( &error, inf_test_util_parse_error_quark(), INF_TEST_UTIL_PARSE_ERROR_UNEXPECTED_NODE, "Node '%s' unexpected", (const gchar*)child->name ); break; } } if(error != NULL) { printf("Failed to parse: %s\n", error->message); g_error_free(error); xmlFreeDoc(doc); g_slist_free(requests); if(initial != NULL) inf_text_chunk_free(initial); g_slist_free(users); } else { g_assert(initial != NULL); requests = g_slist_reverse(requests); if(perform_test(max_total_log_size, initial, users, requests, &error) == TRUE) { ++ result->passed; printf("OK\n"); } else { printf("FAILED (%s)\n", error->message); g_error_free(error); } xmlFreeDoc(doc); g_slist_free(requests); inf_text_chunk_free(initial); g_slist_free(users); } } } int main(int argc, char* argv[]) { const char* dir; GError* error; test_result result; if(argc > 1) dir = argv[1]; else dir = "cleanup"; error = NULL; if(!inf_init(&error)) { fprintf(stderr, "%s\n", error->message); return 1; } result.total = 0; result.passed = 0; if(inf_test_util_dir_foreach(dir, foreach_test_func, &result, &error) == FALSE) { fprintf(stderr, "%s\n", error->message); g_error_free(error); return -1; } printf("%u out of %u tests passed\n", result.passed, result.total); if(result.passed < result.total) return -1; return 0; } libinfinity-0.7.1/test/PaxHeaders.26529/inf-test-set-acl.c0000644000000000000000000000013213034342512020002 xustar0030 mtime=1483851082.053718557 30 atime=1483851082.053718557 30 ctime=1488261589.724137482 libinfinity-0.7.1/test/inf-test-set-acl.c0000644000175000017500000002227713034342512020546 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include #include #include #include typedef struct _InfTestSetAcl InfTestSetAcl; struct _InfTestSetAcl { InfStandaloneIo* io; InfXmppConnection* conn; InfBrowser* browser; }; static void inf_test_set_acl_set_acl_finished_cb(InfRequest* request, const InfRequestResult* result, const GError* error, gpointer user_data) { InfTestSetAcl* test; const InfAclSheetSet* sheet_set; const InfBrowserIter* iter; guint i; test = (InfTestSetAcl*)user_data; if(error != NULL) { fprintf(stderr, "Failed to change root node ACL: %s\n", error->message); } else { inf_request_result_get_set_acl(result, NULL, &iter); sheet_set = inf_browser_get_acl(test->browser, iter); fprintf(stderr, "New root node ACL:\n"); for(i = 0; i < sheet_set->n_sheets; ++i) { fprintf( stderr, " %s: mask=%llx, perms=%llx\n", inf_acl_account_id_to_string(sheet_set->sheets[i].account), (unsigned long long)sheet_set->sheets[i].mask.mask[0], (unsigned long long)sheet_set->sheets[i].perms.mask[0] ); } } inf_xml_connection_close(INF_XML_CONNECTION(test->conn)); } static void inf_test_set_acl_query_acl_finished_cb(InfRequest* request, const InfRequestResult* result, const GError* error, gpointer user_data) { InfTestSetAcl* test; InfAclSheetSet* sheet_set; const InfAclAccount* account; InfAclSheet* sheet; const InfBrowserIter* iter; guint i; test = (InfTestSetAcl*)user_data; if(error != NULL) { fprintf(stderr, "ACL query failed: %s\n", error->message); inf_xml_connection_close(INF_XML_CONNECTION(test->conn)); } else { inf_request_result_get_query_acl(result, NULL, &iter, NULL); sheet_set = inf_acl_sheet_set_copy(inf_browser_get_acl(test->browser, iter)); fprintf(stderr, "Root node ACL:\n"); for(i = 0; i < sheet_set->n_sheets; ++i) { fprintf( stderr, " %s: mask=%llx, perms=%llx\n", inf_acl_account_id_to_string(sheet_set->sheets[i].account), (unsigned long long)sheet_set->sheets[i].mask.mask[0], (unsigned long long)sheet_set->sheets[i].perms.mask[0] ); } account = inf_browser_get_acl_default_account(test->browser); sheet = inf_acl_sheet_set_add_sheet(sheet_set, account->id); fprintf(stderr, "Requesting CAN_SET_ACL permission for the root node\n"); inf_acl_mask_or1(&sheet->mask, INF_ACL_CAN_SET_ACL); inf_acl_mask_or1(&sheet->perms, INF_ACL_CAN_SET_ACL); inf_browser_set_acl( test->browser, iter, sheet_set, inf_test_set_acl_set_acl_finished_cb, test ); inf_acl_sheet_set_free(sheet_set); } } static void inf_test_set_acl_query_account_list_finished_cb(InfRequest* request, const InfRequestResult* res, const GError* error, gpointer user_data) { InfTestSetAcl* test; const InfAclAccount* accounts; guint n_accounts; guint i; InfBrowserIter iter; test = (InfTestSetAcl*)user_data; if(error != NULL) { fprintf(stderr, "Account List query failed: %s\n", error->message); } else { inf_request_result_get_query_acl_account_list( res, NULL, &accounts, &n_accounts, NULL ); printf("Account List:\n"); for(i = 0; i < n_accounts; ++i) { printf( " * %s (%s)\n", inf_acl_account_id_to_string(accounts[i].id), accounts[i].name ? accounts[i].name : "" ); } } fprintf(stderr, "Querying root node ACL...\n"); inf_browser_get_root(test->browser, &iter); inf_browser_query_acl( test->browser, &iter, inf_test_set_acl_query_acl_finished_cb, test ); } static void inf_test_set_acl_error_cb(InfcBrowser* browser, GError* error, gpointer user_data) { fprintf(stderr, "Connection error: %s\n", error->message); } static void inf_test_set_acl_notify_status_cb(GObject* object, GParamSpec* pspec, gpointer user_data) { InfTestSetAcl* test; InfBrowserStatus status; const InfAclAccount* account; test = (InfTestSetAcl*)user_data; g_object_get(G_OBJECT(test->browser), "status", &status, NULL); if(status == INF_BROWSER_OPEN) { account = inf_browser_get_acl_local_account(test->browser); fprintf(stderr, "Connection established, querying account list...\n"); fprintf( stderr, "Local account: %s (%s)\n", inf_acl_account_id_to_string(account->id), account->name ); inf_browser_query_acl_account_list( test->browser, inf_test_set_acl_query_account_list_finished_cb, test ); } else if(status == INF_BROWSER_CLOSED) { if(inf_standalone_io_loop_running(test->io)) inf_standalone_io_loop_quit(test->io); } } int main(int argc, char* argv[]) { InfTestSetAcl test; InfIpAddress* address; InfCommunicationManager* manager; InfTcpConnection* tcp_conn; GPtrArray* array; gnutls_x509_privkey_t key; gnutls_x509_crt_t* certs; guint n_certs; guint i; InfCertificateCredentials* creds; GError* error; key = NULL; certs = NULL; n_certs = 0; creds = NULL; error = NULL; inf_init(NULL); test.io = inf_standalone_io_new(); address = inf_ip_address_new_loopback4(); tcp_conn = inf_tcp_connection_new_and_open( INF_IO(test.io), address, inf_protocol_get_default_port(), &error ); inf_ip_address_free(address); if(tcp_conn == NULL) { fprintf(stderr, "Could not open TCP connection: %s\n", error->message); g_error_free(error); return EXIT_FAILURE; } if(argc >= 2) { array = inf_cert_util_read_certificate(argv[1], NULL, &error); if(error != NULL) { fprintf(stderr, "Failed to read certificate: %s\n", error->message); g_error_free(error); return EXIT_FAILURE; } n_certs = array->len; certs = (gnutls_x509_crt_t*)g_ptr_array_free(array, FALSE); if(n_certs == 0) { fprintf(stderr, "File does not contain a certificate\n"); return EXIT_FAILURE; } key = inf_cert_util_read_private_key(argv[1], &error); if(error != NULL) { fprintf(stderr, "Failed to read key: %s\n", error->message); g_error_free(error); return EXIT_FAILURE; } creds = inf_certificate_credentials_new(); gnutls_certificate_set_x509_key( inf_certificate_credentials_get(creds), certs, n_certs, key ); } test.conn = inf_xmpp_connection_new( tcp_conn, INF_XMPP_CONNECTION_CLIENT, NULL, "localhost", INF_XMPP_CONNECTION_SECURITY_BOTH_PREFER_TLS, creds, NULL, NULL ); g_object_unref(tcp_conn); manager = inf_communication_manager_new(); test.browser = INF_BROWSER( infc_browser_new( INF_IO(test.io), manager, INF_XML_CONNECTION(test.conn) ) ); g_signal_connect_after( G_OBJECT(test.browser), "notify::status", G_CALLBACK(inf_test_set_acl_notify_status_cb), &test ); g_signal_connect( G_OBJECT(test.browser), "error", G_CALLBACK(inf_test_set_acl_error_cb), &test ); inf_standalone_io_loop(test.io); g_object_unref(manager); g_object_unref(test.browser); /* TODO: Wait until the XMPP connection is in status closed */ g_object_unref(test.conn); if(creds != NULL) inf_certificate_credentials_unref(creds); for(i = 0; i < n_certs; ++i) gnutls_x509_crt_deinit(certs[i]); g_free(certs); if(key != NULL) gnutls_x509_privkey_deinit(key); g_object_unref(test.io); return 0; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/test/PaxHeaders.26529/inf-test-text-session.c0000644000000000000000000000013213034342512021117 xustar0030 mtime=1483851082.053718557 30 atime=1483851082.053718557 30 ctime=1488261589.740137447 libinfinity-0.7.1/test/inf-test-text-session.c0000644000175000017500000002532013034342512021653 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include "util/inf-test-util.h" #include #include #include #include #include #include #include #include #include #include #include #define NUM_PERMUTATIONS 100 typedef struct { GRand* rand; guint total; guint passed; gdouble time; } test_result; static gboolean perform_single_test(InfTextChunk* initial, InfTextChunk* final, GSList* users, GSList* requests, gdouble* time) { InfTextBuffer* buffer; InfCommunicationManager* manager; InfIo* io; InfTextSession* session; InfUserTable* user_table; InfTextUser* user; gchar* user_name; GSList* item; xmlNodePtr request; gboolean result; InfTextChunk* test_chunk; gchar* first; gchar* second; gsize first_bytes; gsize second_bytes; GTimer* timer; buffer = INF_TEXT_BUFFER(inf_text_default_buffer_new("UTF-8")); inf_text_buffer_insert_chunk(buffer, 0, initial, NULL); manager = inf_communication_manager_new(); io = INF_IO(inf_standalone_io_new()); user_table = inf_user_table_new(); for(item = users; item != NULL; item = g_slist_next(item)) { user_name = g_strdup_printf("User_%u", GPOINTER_TO_UINT(item->data)); user = INF_TEXT_USER( g_object_new( INF_TEXT_TYPE_USER, "id", GPOINTER_TO_UINT(item->data), "name", user_name, "status", INF_USER_ACTIVE, "flags", 0, NULL ) ); g_free(user_name); inf_user_table_add_user(user_table, INF_USER(user)); g_object_unref(user); } session = inf_text_session_new_with_user_table( manager, buffer, io, user_table, INF_SESSION_RUNNING, NULL, NULL ); g_object_unref(G_OBJECT(io)); g_object_unref(G_OBJECT(manager)); g_object_unref(G_OBJECT(user_table)); timer = g_timer_new(); for(item = requests; item != NULL; item = item->next) { request = (xmlNodePtr)item->data; inf_communication_object_received( INF_COMMUNICATION_OBJECT(session), NULL, request ); } *time = g_timer_elapsed(timer, NULL); g_timer_destroy(timer); test_chunk = inf_text_buffer_get_slice( buffer, 0, inf_text_buffer_get_length(buffer) ); g_object_unref(G_OBJECT(session)); result = inf_text_chunk_equal(test_chunk, final); if(result == FALSE) { first = inf_text_chunk_get_text(final, &first_bytes); second = inf_text_chunk_get_text(test_chunk, &second_bytes); printf("(%.*s vs. %.*s) ", (int)second_bytes, second, (int)first_bytes, first); g_free(second); g_free(first); } inf_text_chunk_free(test_chunk); g_object_unref(G_OBJECT(buffer)); return result; } static gboolean perform_test(InfTextChunk* initial, InfTextChunk* final, GSList* users, GSList* requests, GRand* rand, gdouble* time) { GSList* permutation; GSList* item; GSList* item2; GSList* dist_item; unsigned int i; unsigned int dist; unsigned int rval; gpointer temp; gboolean retval; gdouble local_time; guint user; guint user2; InfAdoptedStateVector* v; GError* error; g_assert(requests != NULL); permutation = g_slist_copy(requests); /* Mark per-user request order which must be kept when applying for the * state vector diffs to work. */ v = inf_adopted_state_vector_new(); error = NULL; for(item = permutation; item != NULL; item = g_slist_next(item)) { if(!inf_xml_util_get_attribute_uint(item->data, "user", &user, &error)) { printf("%s\n", error->message); inf_adopted_state_vector_free(v); g_slist_free(permutation); return FALSE; } ((xmlNodePtr)item->data)->_private = GUINT_TO_POINTER( inf_adopted_state_vector_get(v, user) ); inf_adopted_state_vector_add(v, user, 1); } inf_adopted_state_vector_free(v); *time = 0.0; for(i = 0; i < NUM_PERMUTATIONS; ++ i) { dist = 0; /* TODO: This can be optimized */ /* shuffle random */ for(item = permutation->next; item != NULL; item = g_slist_next(item)) { ++ dist; dist_item = g_slist_nth(permutation, g_rand_int(rand) % (dist + 1)); rval = g_rand_int(rand) % (dist + 1); temp = item->data; item->data = dist_item->data; dist_item->data = temp; } /* Resort according to per-user request order */ /* We could probably use g_slist_sort if it was stable, but the * documentation says nothing about it. So just do a primitive bubblesort * for now. */ for(item = permutation; item != NULL; item = g_slist_next(item)) { for(item2 = item->next; item2 != NULL; item2 = g_slist_next(item2)) { /* This can't fail anymore, otherwise it * would already have failed above. */ inf_xml_util_get_attribute_uint(item->data, "user", &user, NULL); inf_xml_util_get_attribute_uint(item2->data, "user", &user2, NULL); if(user == user2) { if(GPOINTER_TO_UINT( ((xmlNodePtr)item->data)->_private) > GPOINTER_TO_UINT( ((xmlNodePtr)item2->data)->_private) ) { temp = item->data; item->data = item2->data; item2->data = temp; } } } } if(i % (MAX(NUM_PERMUTATIONS/30, 1)) == 0) { printf("."); fflush(stdout); } retval = perform_single_test( initial, final, users, permutation, &local_time ); if(!retval) break; *time += local_time; } g_slist_free(permutation); return retval; } static void foreach_test_func(const gchar* testfile, gpointer user_data) { test_result* result; xmlDocPtr doc; xmlNodePtr root; xmlNodePtr child; GSList* requests; InfTextChunk* initial; InfTextChunk* final; GSList* users; GError* error; gboolean retval; gdouble local_time; /* Only process XML files, not the Makefiles or other stuff */ if(!g_str_has_suffix(testfile, ".xml")) return; result = (test_result*)user_data; doc = xmlParseFile(testfile); requests = NULL; initial = NULL; final = NULL; error = NULL; users = NULL; printf("%s... ", testfile); fflush(stdout); ++ result->total; if(doc != NULL) { root = xmlDocGetRootElement(doc); for(child = root->children; child != NULL; child = child->next) { if(child->type != XML_ELEMENT_NODE) continue; if(strcmp((const char*)child->name, "initial-buffer") == 0) { if(initial != NULL) inf_text_chunk_free(initial); initial = inf_test_util_parse_buffer(child, &error); if(initial == NULL) break; } else if(strcmp((const char*)child->name, "final-buffer") == 0) { if(final != NULL) inf_text_chunk_free(final); final = inf_test_util_parse_buffer(child, &error); if(final == NULL) break; } else if(strcmp((const char*)child->name, "user") == 0) { if(inf_test_util_parse_user(child, &users, &error) == FALSE) break; } else if(strcmp((const char*)child->name, "request") == 0) { requests = g_slist_prepend(requests, child); } else { g_set_error( &error, inf_test_util_parse_error_quark(), INF_TEST_UTIL_PARSE_ERROR_UNEXPECTED_NODE, "Node '%s' unexpected", (const gchar*)child->name ); break; } } if(error != NULL) { printf("Failed to parse: %s\n", error->message); g_error_free(error); xmlFreeDoc(doc); g_slist_free(requests); if(initial != NULL) inf_text_chunk_free(initial); if(final != NULL) inf_text_chunk_free(final); g_slist_free(users); } else { g_assert(initial != NULL); g_assert(final != NULL); requests = g_slist_reverse(requests); retval = perform_test( initial, final, users, requests, result->rand, &local_time ); if(retval == TRUE) { ++ result->passed; printf("OK (%g secs)\n", local_time); result->time += local_time; } else { printf("FAILED\n"); } xmlFreeDoc(doc); g_slist_free(requests); inf_text_chunk_free(initial); inf_text_chunk_free(final); g_slist_free(users); } } } int main(int argc, char* argv[]) { const char* dir; GError* error; test_result result; unsigned int rseed; int dirarg; gboolean retval; GTimer* timer; gdouble elapsed; dirarg = 1; if(argc > 1) { rseed = atoi(argv[1]); if(rseed > 0) dirarg = 2; else rseed = time(NULL); } else { rseed = time(NULL); } printf("Using random seed %u\n", rseed); error = NULL; if(!inf_init(&error)) { fprintf(stderr, "%s\n", error->message); return 1; } if(argc > dirarg) dir = argv[dirarg]; else dir = "session"; result.rand = g_rand_new_with_seed(rseed); result.total = 0; result.passed = 0; result.time = 0.0; timer = g_timer_new(); retval = inf_test_util_dir_foreach( dir, foreach_test_func, &result, &error ); g_timer_stop(timer); elapsed = g_timer_elapsed(timer, NULL); g_rand_free(result.rand); g_timer_destroy(timer); if(retval == FALSE) { fprintf(stderr, "%s\n", error->message); g_error_free(error); return -1; } printf( "%u out of %u tests passed (real %g secs, algo %g secs)\n", result.passed, result.total, elapsed, result.time ); if(result.passed < result.total) return -1; return 0; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/test/PaxHeaders.26529/inf-test-text-recover.c0000644000000000000000000000013213034342512021101 xustar0030 mtime=1483851082.053718557 30 atime=1483851082.053718557 30 ctime=1488261589.736137456 libinfinity-0.7.1/test/inf-test-text-recover.c0000644000175000017500000001207213034342512021635 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include #include #include #include #include #include static void inf_test_util_print_buffer(InfTextBuffer* buffer) { InfTextChunk* chunk; gchar* text; gsize bytes; chunk = inf_text_buffer_get_slice( buffer, 0, inf_text_buffer_get_length(buffer) ); text = inf_text_chunk_get_text(chunk, &bytes); inf_text_chunk_free(chunk); printf("%.*s\n", (int)bytes, text); g_free(text); } static InfSession* inf_test_text_recover_session_new(InfIo* io, InfCommunicationManager* manager, InfSessionStatus status, InfCommunicationGroup* sync_group, InfXmlConnection* sync_connection, const gchar* path, gpointer user_data) { InfTextDefaultBuffer* buffer; InfTextSession* session; buffer = inf_text_default_buffer_new("UTF-8"); session = inf_text_session_new( manager, INF_TEXT_BUFFER(buffer), io, status, sync_group, sync_connection ); g_object_unref(buffer); return INF_SESSION(session); } static const InfcNotePlugin INF_TEST_TEXT_RECOVER_TEXT_PLUGIN = { NULL, "InfText", inf_test_text_recover_session_new }; static void inf_test_text_recover_text_erased_cb(InfTextBuffer* buffer, guint pos, InfTextChunk* chunk, InfUser* user, gpointer user_data) { InfAdoptedOperation* operation; guint len; InfTextChunk* print_chunk; gsize print_bytes; gpointer print_text; /* If the document has substantial content and this deletes most of it, * then print out the document here. */ len = inf_text_chunk_get_length(chunk); if(inf_text_buffer_get_length(buffer) + len >= 50) { if(len >= (inf_text_buffer_get_length(buffer) + len)*75/100) { if(*(int*)user_data == 0) { print_chunk = inf_text_buffer_get_slice( buffer, 0, inf_text_buffer_get_length(buffer) ); inf_text_chunk_insert_chunk(print_chunk, pos, chunk); print_text = inf_text_chunk_get_text(print_chunk, &print_bytes); inf_text_chunk_free(print_chunk); printf("%.*s\n", (int)print_bytes, (gchar*)print_text); g_free(print_text); } --*(int*)user_data; } } g_object_unref(buffer); } /* * Entry point */ int main(int argc, char* argv[]) { InfAdoptedSessionReplay* replay; InfAdoptedSession* session; GError* error; int i; int ret; InfBuffer* buffer; GSList* item; gint counter; if(argc < 2) { fprintf(stderr, "Usage: %s [index]\n", argv[0]); return -1; } counter = 0; if(argc > 2) counter = atoi(argv[2]); error = NULL; if(!inf_init(&error)) { fprintf(stderr, "%s\n", error->message); g_error_free(error); return -1; } ret = 0; for(i = 1; i < 2; ++ i) { replay = inf_adopted_session_replay_new(); inf_adopted_session_replay_set_record( replay, argv[i], &INF_TEST_TEXT_RECOVER_TEXT_PLUGIN, &error ); if(error != NULL) { fprintf(stderr, "%s\n", error->message); g_error_free(error); error = NULL; ret = -1; } else { session = inf_adopted_session_replay_get_session(replay); buffer = inf_session_get_buffer(INF_SESSION(session)); g_signal_connect( buffer, "text-erased", G_CALLBACK(inf_test_text_recover_text_erased_cb), &counter ); if(!inf_adopted_session_replay_play_to_end(replay, &error)) { fprintf(stderr, "%s\n", error->message); g_error_free(error); error = NULL; ret = -1; } else if(counter == 0) { inf_test_util_print_buffer(INF_TEXT_BUFFER(buffer)); } } g_object_unref(replay); } return ret; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/test/PaxHeaders.26529/inf-test-text-operations.c0000644000000000000000000000013213034342512021617 xustar0030 mtime=1483851082.053718557 30 atime=1483851082.053718557 30 ctime=1488261589.732137464 libinfinity-0.7.1/test/inf-test-text-operations.c0000644000175000017500000003501313034342512022353 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include #include #include #include typedef struct { guint total; guint passed; } test_result; typedef enum { OP_INS, OP_DEL, OP_SPLIT } operation_type; typedef struct _operation_def operation_def; struct _operation_def { operation_type type; guint offset; const gchar* text; const operation_def* split_1; const operation_def* split_2; }; static const operation_def SPLIT_OPS[] = { { OP_DEL, 0, GUINT_TO_POINTER(1) }, { OP_DEL, 1, GUINT_TO_POINTER(1) }, { OP_DEL, 2, GUINT_TO_POINTER(1) }, { OP_INS, 0, "a" }, { OP_INS, 1, "b" } }; static const operation_def OPERATIONS[] = { { OP_INS, 4, "a" }, { OP_INS, 4, "b" }, { OP_INS, 4, "c" }, { OP_INS, 4, "a" }, { OP_INS, 2, "ac" }, { OP_INS, 3, "bc" }, { OP_INS, 2, "gro" }, { OP_DEL, 0, GUINT_TO_POINTER(1) }, { OP_DEL, 0, GUINT_TO_POINTER(5) }, { OP_DEL, 2, GUINT_TO_POINTER(7) }, { OP_DEL, 1, GUINT_TO_POINTER(9) }, /* del vs. del */ { OP_SPLIT, 0, NULL, &SPLIT_OPS[0], &SPLIT_OPS[2] }, { OP_SPLIT, 0, NULL, &SPLIT_OPS[2], &SPLIT_OPS[0] }, { OP_SPLIT, 0, NULL, &SPLIT_OPS[0], &SPLIT_OPS[1] }, { OP_SPLIT, 0, NULL, &SPLIT_OPS[1], &SPLIT_OPS[0] }, /* del vs. ins */ { OP_SPLIT, 0, NULL, &SPLIT_OPS[1], &SPLIT_OPS[3] }, { OP_SPLIT, 0, NULL, &SPLIT_OPS[1], &SPLIT_OPS[4] }, { OP_SPLIT, 0, NULL, &SPLIT_OPS[3], &SPLIT_OPS[1] }, { OP_SPLIT, 0, NULL, &SPLIT_OPS[4], &SPLIT_OPS[1] }, }; static const gchar EXAMPLE_DOCUMENT[] = "abcdefghijklmnopqrstuvwxyz"; static InfAdoptedOperation* def_to_operation(const operation_def* def, InfTextChunk* document, InfAdoptedUser* user) { InfTextChunk* chunk; InfAdoptedOperation* operation; InfAdoptedOperation* operation1; InfAdoptedOperation* operation2; InfTextDefaultBuffer* buf; InfTextChunk* new_document; gboolean result; switch(def->type) { case OP_INS: chunk = inf_text_chunk_new("UTF-8"); inf_text_chunk_insert_text( chunk, 0, def->text, strlen(def->text), strlen(def->text), inf_user_get_id(INF_USER(user)) ); operation = INF_ADOPTED_OPERATION( inf_text_default_insert_operation_new(def->offset, chunk) ); inf_text_chunk_free(chunk); break; case OP_DEL: chunk = inf_text_chunk_substring( document, def->offset, GPOINTER_TO_UINT(def->text) ); operation = INF_ADOPTED_OPERATION( inf_text_default_delete_operation_new(def->offset, chunk) ); inf_text_chunk_free(chunk); break; case OP_SPLIT: operation1 = def_to_operation(def->split_1, document, user); buf = inf_text_default_buffer_new("UTF-8"); inf_text_buffer_insert_chunk(INF_TEXT_BUFFER(buf), 0, document, NULL); result = inf_adopted_operation_apply( operation1, user, INF_BUFFER(buf), NULL ); g_assert(result == TRUE); new_document = inf_text_buffer_get_slice( INF_TEXT_BUFFER(buf), 0, inf_text_buffer_get_length(INF_TEXT_BUFFER(buf)) ); g_object_unref(buf); operation2 = def_to_operation(def->split_2, new_document, user); inf_text_chunk_free(new_document); operation = INF_ADOPTED_OPERATION( inf_adopted_split_operation_new(operation1, operation2) ); g_object_unref(operation1); g_object_unref(operation2); break; default: g_assert_not_reached(); break; } return operation; } static gboolean test_undo(InfAdoptedOperation* op, InfAdoptedUser* user, GError** error) { InfTextBuffer* first; InfTextBuffer* second; InfAdoptedOperation* reverted; InfTextChunk* first_chunk; InfTextChunk* second_chunk; int result; first = INF_TEXT_BUFFER(inf_text_default_buffer_new("UTF-8")); inf_text_buffer_insert_text( first, 0, EXAMPLE_DOCUMENT, strlen(EXAMPLE_DOCUMENT), strlen(EXAMPLE_DOCUMENT), NULL ); second = INF_TEXT_BUFFER(inf_text_default_buffer_new("UTF-8")); inf_text_buffer_insert_text( second, 0, EXAMPLE_DOCUMENT, strlen(EXAMPLE_DOCUMENT), strlen(EXAMPLE_DOCUMENT), NULL ); if(!inf_adopted_operation_apply(op, user, INF_BUFFER(first), error)) { g_object_unref(first); g_object_unref(second); return FALSE; } reverted = inf_adopted_operation_revert(op); if(!inf_adopted_operation_apply(reverted, user, INF_BUFFER(first), error)) { g_object_unref(first); g_object_unref(second); g_object_unref(reverted); return FALSE; } g_object_unref(reverted); first_chunk = inf_text_buffer_get_slice( INF_TEXT_BUFFER(first), 0, inf_text_buffer_get_length(INF_TEXT_BUFFER(first)) ); second_chunk = inf_text_buffer_get_slice( INF_TEXT_BUFFER(second), 0, inf_text_buffer_get_length(INF_TEXT_BUFFER(second)) ); result = inf_text_chunk_equal(first_chunk, second_chunk); inf_text_chunk_free(first_chunk); inf_text_chunk_free(second_chunk); g_object_unref(first); g_object_unref(second); return result; } static gboolean test_c1(InfAdoptedOperation* op1, InfAdoptedOperation* op2, InfAdoptedUser* user1, InfAdoptedUser* user2, InfAdoptedConcurrencyId cid12, GError** error) { InfBuffer* first; InfBuffer* second; InfTextChunk* first_chunk; InfTextChunk* second_chunk; InfAdoptedOperation* transformed; int result; first = INF_BUFFER(inf_text_default_buffer_new("UTF-8")); inf_text_buffer_insert_text( INF_TEXT_BUFFER(first), 0, EXAMPLE_DOCUMENT, strlen(EXAMPLE_DOCUMENT), strlen(EXAMPLE_DOCUMENT), NULL ); second = INF_BUFFER(inf_text_default_buffer_new("UTF-8")); inf_text_buffer_insert_text( INF_TEXT_BUFFER(second), 0, EXAMPLE_DOCUMENT, strlen(EXAMPLE_DOCUMENT), strlen(EXAMPLE_DOCUMENT), NULL ); if(!inf_adopted_operation_apply(op1, user1, first, error)) { g_object_unref(first); g_object_unref(second); return FALSE; } transformed = inf_adopted_operation_transform(op2, op1, op2, op1, -cid12); if(!inf_adopted_operation_apply(transformed, user2, first, error)) { g_object_unref(first); g_object_unref(second); g_object_unref(transformed); return FALSE; } g_object_unref(G_OBJECT(transformed)); if(!inf_adopted_operation_apply(op2, user2, second, error)) { g_object_unref(first); g_object_unref(second); return FALSE; } transformed = inf_adopted_operation_transform(op1, op2, op1, op2, cid12); if(!inf_adopted_operation_apply(transformed, user1, second, error)) { g_object_unref(first); g_object_unref(second); g_object_unref(transformed); return FALSE; } g_object_unref(transformed); first_chunk = inf_text_buffer_get_slice( INF_TEXT_BUFFER(first), 0, inf_text_buffer_get_length(INF_TEXT_BUFFER(first)) ); second_chunk = inf_text_buffer_get_slice( INF_TEXT_BUFFER(second), 0, inf_text_buffer_get_length(INF_TEXT_BUFFER(second)) ); result = inf_text_chunk_equal(first_chunk, second_chunk); inf_text_chunk_free(first_chunk); inf_text_chunk_free(second_chunk); g_object_unref(first); g_object_unref(second); return result; } static gboolean test_c2(InfAdoptedOperation* op1, InfAdoptedOperation* op2, InfAdoptedOperation* op3, InfAdoptedConcurrencyId cid12, InfAdoptedConcurrencyId cid13, InfAdoptedConcurrencyId cid23, InfAdoptedUser* user3, GError** error) { InfAdoptedOperation* temp1; InfAdoptedOperation* temp2; InfAdoptedOperation* result1; InfAdoptedOperation* result2; InfTextDefaultBuffer* first; InfTextDefaultBuffer* second; InfTextChunk* first_chunk; InfTextChunk* second_chunk; gboolean retval; first = inf_text_default_buffer_new("UTF-8"); inf_text_buffer_insert_text( INF_TEXT_BUFFER(first), 0, EXAMPLE_DOCUMENT, strlen(EXAMPLE_DOCUMENT), strlen(EXAMPLE_DOCUMENT), NULL ); second = inf_text_default_buffer_new("UTF-8"); inf_text_buffer_insert_text( INF_TEXT_BUFFER(second), 0, EXAMPLE_DOCUMENT, strlen(EXAMPLE_DOCUMENT), strlen(EXAMPLE_DOCUMENT), NULL ); temp1 = inf_adopted_operation_transform(op2, op1, op2, op1, -cid12); temp2 = inf_adopted_operation_transform(op3, op1, op3, op1, -cid13); result1 = inf_adopted_operation_transform(temp2, temp1, op3, op2, -cid23); g_object_unref(G_OBJECT(temp1)); g_object_unref(G_OBJECT(temp2)); temp1 = inf_adopted_operation_transform(op1, op2, op1, op2, cid12); temp2 = inf_adopted_operation_transform(op3, op2, op3, op2, -cid23); result2 = inf_adopted_operation_transform(temp2, temp1, op3, op1, -cid13); g_object_unref(G_OBJECT(temp1)); g_object_unref(G_OBJECT(temp2)); if(!inf_adopted_operation_apply(result1, user3, INF_BUFFER(first), error)) { g_object_unref(result1); g_object_unref(result2); return FALSE; } if(!inf_adopted_operation_apply(result2, user3, INF_BUFFER(second), error)) { g_object_unref(result1); g_object_unref(result2); return FALSE; } first_chunk = inf_text_buffer_get_slice( INF_TEXT_BUFFER(first), 0, inf_text_buffer_get_length(INF_TEXT_BUFFER(first)) ); second_chunk = inf_text_buffer_get_slice( INF_TEXT_BUFFER(second), 0, inf_text_buffer_get_length(INF_TEXT_BUFFER(second)) ); retval = inf_text_chunk_equal(first_chunk, second_chunk); inf_text_chunk_free(first_chunk); inf_text_chunk_free(second_chunk); g_object_unref(G_OBJECT(result1)); g_object_unref(G_OBJECT(result2)); return retval; } static InfAdoptedConcurrencyId cid(InfAdoptedOperation** first, InfAdoptedOperation** second) { if(first > second) return INF_ADOPTED_CONCURRENCY_SELF; else if(first < second) return INF_ADOPTED_CONCURRENCY_OTHER; else g_assert_not_reached(); } static void perform_undo(InfAdoptedOperation** begin, InfAdoptedOperation** end, InfAdoptedUser** users, test_result* result) { InfAdoptedOperation** _1; for(_1 = begin; _1 != end; ++ _1) { ++ result->total; if(test_undo(*_1, users[_1 - begin], NULL)) ++ result->passed; } } static void perform_c1(InfAdoptedOperation** begin, InfAdoptedOperation** end, InfAdoptedUser** users, test_result* result) { InfAdoptedOperation** _1; InfAdoptedOperation** _2; InfAdoptedUser* user1; InfAdoptedUser* user2; for(_1 = begin; _1 != end; ++ _1) { for(_2 = begin; _2 != end; ++ _2) { if(_1 != _2) { user1 = users[_1 - begin]; user2 = users[_2 - begin]; ++ result->total; if(test_c1(*_1, *_2, user1, user2, cid(_1, _2), NULL)) ++ result->passed; } } } } static void perform_c2(InfAdoptedOperation** begin, InfAdoptedOperation** end, InfAdoptedUser** users, test_result* result) { InfAdoptedOperation** _1; InfAdoptedOperation** _2; InfAdoptedOperation** _3; InfAdoptedConcurrencyId cid12; InfAdoptedConcurrencyId cid13; InfAdoptedConcurrencyId cid23; InfAdoptedUser* user3; for(_1 = begin; _1 != end; ++ _1) { for(_2 = begin; _2 != end; ++ _2) { for(_3 = begin; _3 != end; ++ _3) { if(_1 != _2 && _1 != _3 && _2 != _3) { cid12 = cid(_1, _2); cid13 = cid(_1, _3); cid23 = cid(_2, _3); user3 = users[_3 - begin]; ++ result->total; if(test_c2(*_1, *_2, *_3, cid12, cid13, cid23, user3, NULL)) ++ result->passed; } } } } } int main() { InfAdoptedOperation** operations; InfAdoptedUser** users; InfTextChunk* document; test_result result; guint i; int retval; retval = 0; operations = g_malloc( sizeof(InfAdoptedOperation*) * G_N_ELEMENTS(OPERATIONS) ); users = g_malloc(sizeof(InfAdoptedUser*) * G_N_ELEMENTS(OPERATIONS)); document = inf_text_chunk_new("UTF-8"); inf_text_chunk_insert_text( document, 0, EXAMPLE_DOCUMENT, strlen(EXAMPLE_DOCUMENT), strlen(EXAMPLE_DOCUMENT), 0 ); for(i = 0; i < G_N_ELEMENTS(OPERATIONS); ++ i) { users[i] = INF_ADOPTED_USER( g_object_new(INF_TEXT_TYPE_USER, "id", i + 1, NULL) ); operations[i] = def_to_operation( &OPERATIONS[i], document, users[i] ); } inf_text_chunk_free(document); result.passed = 0; result.total = 0; perform_undo( operations, operations + G_N_ELEMENTS(OPERATIONS), users, &result ); printf("UNDO: %u out of %u passed\n", result.passed, result.total); if(result.passed < result.total) retval = -1; result.passed = 0; result.total = 0; perform_c1( operations, operations + G_N_ELEMENTS(OPERATIONS), users, &result ); printf("C1: %u out of %u passed\n", result.passed, result.total); if(result.passed < result.total) retval = -1; result.passed = 0; result.total = 0; perform_c2( operations, operations + G_N_ELEMENTS(OPERATIONS), users, &result ); printf("C2: %u out of %u passed\n", result.passed, result.total); if(result.passed < result.total) retval = -1; for(i = 0; i < G_N_ELEMENTS(OPERATIONS); ++ i) { g_object_unref(G_OBJECT(operations[i])); g_object_unref(G_OBJECT(users[i])); } g_free(operations); g_free(users); return retval; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/PaxHeaders.26529/INSTALL0000644000000000000000000000013212400102201014612 xustar0030 mtime=1409320065.087133093 30 atime=1409320065.087133093 30 ctime=1488261588.772139564 libinfinity-0.7.1/INSTALL0000644000175000017500000003661012400102201015352 0ustar00arminarmin00000000000000Installation Instructions ************************* Copyright (C) 1994-1996, 1999-2002, 2004-2013 Free Software Foundation, Inc. Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved. This file is offered as-is, without warranty of any kind. Basic Installation ================== Briefly, the shell command `./configure && make && make install' should configure, build, and install this package. The following more-detailed instructions are generic; see the `README' file for instructions specific to this package. Some packages provide this `INSTALL' file but do not implement all of the features documented below. The lack of an optional feature in a given package is not necessarily a bug. More recommendations for GNU packages can be found in *note Makefile Conventions: (standards)Makefile Conventions. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a `Makefile' in each directory of the package. It may also create one or more `.h' files containing system-dependent definitions. Finally, it creates a shell script `config.status' that you can run in the future to recreate the current configuration, and a file `config.log' containing compiler output (useful mainly for debugging `configure'). It can also use an optional file (typically called `config.cache' and enabled with `--cache-file=config.cache' or simply `-C') that saves the results of its tests to speed up reconfiguring. Caching is disabled by default to prevent problems with accidental use of stale cache files. If you need to do unusual things to compile the package, please try to figure out how `configure' could check whether to do them, and mail diffs or instructions to the address given in the `README' so they can be considered for the next release. If you are using the cache, and at some point `config.cache' contains results you don't want to keep, you may remove or edit it. The file `configure.ac' (or `configure.in') is used to create `configure' by a program called `autoconf'. You need `configure.ac' if you want to change it or regenerate `configure' using a newer version of `autoconf'. The simplest way to compile this package is: 1. `cd' to the directory containing the package's source code and type `./configure' to configure the package for your system. Running `configure' might take a while. While running, it prints some messages telling which features it is checking for. 2. Type `make' to compile the package. 3. Optionally, type `make check' to run any self-tests that come with the package, generally using the just-built uninstalled binaries. 4. Type `make install' to install the programs and any data files and documentation. When installing into a prefix owned by root, it is recommended that the package be configured and built as a regular user, and only the `make install' phase executed with root privileges. 5. Optionally, type `make installcheck' to repeat any self-tests, but this time using the binaries in their final installed location. This target does not install anything. Running this target as a regular user, particularly if the prior `make install' required root privileges, verifies that the installation completed correctly. 6. You can remove the program binaries and object files from the source code directory by typing `make clean'. To also remove the files that `configure' created (so you can compile the package for a different kind of computer), type `make distclean'. There is also a `make maintainer-clean' target, but that is intended mainly for the package's developers. If you use it, you may have to get all sorts of other programs in order to regenerate files that came with the distribution. 7. Often, you can also type `make uninstall' to remove the installed files again. In practice, not all packages have tested that uninstallation works correctly, even though it is required by the GNU Coding Standards. 8. Some packages, particularly those that use Automake, provide `make distcheck', which can by used by developers to test that all other targets like `make install' and `make uninstall' work correctly. This target is generally not run by end users. Compilers and Options ===================== Some systems require unusual options for compilation or linking that the `configure' script does not know about. Run `./configure --help' for details on some of the pertinent environment variables. You can give `configure' initial values for configuration parameters by setting variables in the command line or in the environment. Here is an example: ./configure CC=c99 CFLAGS=-g LIBS=-lposix *Note Defining Variables::, for more details. Compiling For Multiple Architectures ==================================== You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their own directory. To do this, you can use GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the source code in the directory that `configure' is in and in `..'. This is known as a "VPATH" build. With a non-GNU `make', it is safer to compile the package for one architecture at a time in the source code directory. After you have installed the package for one architecture, use `make distclean' before reconfiguring for another architecture. On MacOS X 10.5 and later systems, you can create libraries and executables that work on multiple system types--known as "fat" or "universal" binaries--by specifying multiple `-arch' options to the compiler but only a single `-arch' option to the preprocessor. Like this: ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ CPP="gcc -E" CXXCPP="g++ -E" This is not guaranteed to produce working output in all cases, you may have to build one architecture at a time and combine the results using the `lipo' tool if you have problems. Installation Names ================== By default, `make install' installs the package's commands under `/usr/local/bin', include files under `/usr/local/include', etc. You can specify an installation prefix other than `/usr/local' by giving `configure' the option `--prefix=PREFIX', where PREFIX must be an absolute file name. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you pass the option `--exec-prefix=PREFIX' to `configure', the package uses PREFIX as the prefix for installing programs and libraries. Documentation and other data files still use the regular prefix. In addition, if you use an unusual directory layout you can give options like `--bindir=DIR' to specify different values for particular kinds of files. Run `configure --help' for a list of the directories you can set and what kinds of files go in them. In general, the default for these options is expressed in terms of `${prefix}', so that specifying just `--prefix' will affect all of the other directory specifications that were not explicitly provided. The most portable way to affect installation locations is to pass the correct locations to `configure'; however, many packages provide one or both of the following shortcuts of passing variable assignments to the `make install' command line to change installation locations without having to reconfigure or recompile. The first method involves providing an override variable for each affected directory. For example, `make install prefix=/alternate/directory' will choose an alternate location for all directory configuration variables that were expressed in terms of `${prefix}'. Any directories that were specified during `configure', but not in terms of `${prefix}', must each be overridden at install time for the entire installation to be relocated. The approach of makefile variable overrides for each directory variable is required by the GNU Coding Standards, and ideally causes no recompilation. However, some platforms have known limitations with the semantics of shared libraries that end up requiring recompilation when using this method, particularly noticeable in packages that use GNU Libtool. The second method involves providing the `DESTDIR' variable. For example, `make install DESTDIR=/alternate/directory' will prepend `/alternate/directory' before all installation names. The approach of `DESTDIR' overrides is not required by the GNU Coding Standards, and does not work on platforms that have drive letters. On the other hand, it does better at avoiding recompilation issues, and works well even when some directory options were not specified in terms of `${prefix}' at `configure' time. Optional Features ================= If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving `configure' the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. Some packages pay attention to `--enable-FEATURE' options to `configure', where FEATURE indicates an optional part of the package. They may also pay attention to `--with-PACKAGE' options, where PACKAGE is something like `gnu-as' or `x' (for the X Window System). The `README' should mention any `--enable-' and `--with-' options that the package recognizes. For packages that use the X Window System, `configure' can usually find the X include and library files automatically, but if it doesn't, you can use the `configure' options `--x-includes=DIR' and `--x-libraries=DIR' to specify their locations. Some packages offer the ability to configure how verbose the execution of `make' will be. For these packages, running `./configure --enable-silent-rules' sets the default to minimal output, which can be overridden with `make V=1'; while running `./configure --disable-silent-rules' sets the default to verbose, which can be overridden with `make V=0'. Particular systems ================== On HP-UX, the default C compiler is not ANSI C compatible. If GNU CC is not installed, it is recommended to use the following options in order to use an ANSI C compiler: ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" and if that doesn't work, install pre-built binaries of GCC for HP-UX. HP-UX `make' updates targets which have the same time stamps as their prerequisites, which makes it generally unusable when shipped generated files such as `configure' are involved. Use GNU `make' instead. On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot parse its `' header file. The option `-nodtk' can be used as a workaround. If GNU CC is not installed, it is therefore recommended to try ./configure CC="cc" and if that doesn't work, try ./configure CC="cc -nodtk" On Solaris, don't put `/usr/ucb' early in your `PATH'. This directory contains several dysfunctional programs; working variants of these programs are available in `/usr/bin'. So, if you need `/usr/ucb' in your `PATH', put it _after_ `/usr/bin'. On Haiku, software installed for all users goes in `/boot/common', not `/usr/local'. It is recommended to use the following options: ./configure --prefix=/boot/common Specifying the System Type ========================== There may be some features `configure' cannot figure out automatically, but needs to determine by the type of machine the package will run on. Usually, assuming the package is built to be run on the _same_ architectures, `configure' can figure that out, but if it prints a message saying it cannot guess the machine type, give it the `--build=TYPE' option. TYPE can either be a short name for the system type, such as `sun4', or a canonical name which has the form: CPU-COMPANY-SYSTEM where SYSTEM can have one of these forms: OS KERNEL-OS See the file `config.sub' for the possible values of each field. If `config.sub' isn't included in this package, then this package doesn't need to know the machine type. If you are _building_ compiler tools for cross-compiling, you should use the option `--target=TYPE' to select the type of system they will produce code for. If you want to _use_ a cross compiler, that generates code for a platform different from the build platform, you should specify the "host" platform (i.e., that on which the generated programs will eventually be run) with `--host=TYPE'. Sharing Defaults ================ If you want to set default values for `configure' scripts to share, you can create a site shell script called `config.site' that gives default values for variables like `CC', `cache_file', and `prefix'. `configure' looks for `PREFIX/share/config.site' if it exists, then `PREFIX/etc/config.site' if it exists. Or, you can set the `CONFIG_SITE' environment variable to the location of the site script. A warning: not all `configure' scripts look for a site script. Defining Variables ================== Variables not defined in a site shell script can be set in the environment passed to `configure'. However, some packages may run configure again during the build, and the customized values of these variables may be lost. In order to avoid this problem, you should set them in the `configure' command line, using `VAR=value'. For example: ./configure CC=/usr/local2/bin/gcc causes the specified `gcc' to be used as the C compiler (unless it is overridden in the site shell script). Unfortunately, this technique does not work for `CONFIG_SHELL' due to an Autoconf limitation. Until the limitation is lifted, you can use this workaround: CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash `configure' Invocation ====================== `configure' recognizes the following options to control how it operates. `--help' `-h' Print a summary of all of the options to `configure', and exit. `--help=short' `--help=recursive' Print a summary of the options unique to this package's `configure', and exit. The `short' variant lists options used only in the top level, while the `recursive' variant lists options also present in any nested packages. `--version' `-V' Print the version of Autoconf used to generate the `configure' script, and exit. `--cache-file=FILE' Enable the cache: use and save the results of the tests in FILE, traditionally `config.cache'. FILE defaults to `/dev/null' to disable caching. `--config-cache' `-C' Alias for `--cache-file=config.cache'. `--quiet' `--silent' `-q' Do not print messages saying which checks are being made. To suppress all normal output, redirect it to `/dev/null' (any error messages will still be shown). `--srcdir=DIR' Look for the package's source code in directory DIR. Usually `configure' can determine that directory automatically. `--prefix=DIR' Use DIR as the installation prefix. *note Installation Names:: for more details, including other options available for fine-tuning the installation locations. `--no-create' `-n' Run the configure checks, but stop before creating any output files. `configure' also accepts some other, not widely useful, options. Run `configure --help' for more details. libinfinity-0.7.1/PaxHeaders.26529/libinftext0000644000000000000000000000013213055210725015676 xustar0030 mtime=1488261589.224138575 30 atime=1488261589.140138759 30 ctime=1488261589.224138575 libinfinity-0.7.1/libinftext/0000755000175000017500000000000013055210725016505 5ustar00arminarmin00000000000000libinfinity-0.7.1/libinftext/PaxHeaders.26529/inf-text-insert-operation.c0000644000000000000000000000013213034342512023152 xustar0030 mtime=1483851082.045718513 30 atime=1483851082.045718513 30 ctime=1488261589.216138593 libinfinity-0.7.1/libinftext/inf-text-insert-operation.c0000644000175000017500000001611313034342512023706 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include G_DEFINE_INTERFACE(InfTextInsertOperation, inf_text_insert_operation, INF_ADOPTED_TYPE_OPERATION) static void inf_text_insert_operation_default_init(InfTextInsertOperationInterface* iface) { } /** * inf_text_insert_operation_get_position: * @operation: A #InfTextInsertOperation. * * Returns the position at which @operation inserts text. * * Returns: The position to insert text. **/ guint inf_text_insert_operation_get_position(InfTextInsertOperation* operation) { InfTextInsertOperationInterface* iface; g_return_val_if_fail(INF_TEXT_IS_INSERT_OPERATION(operation), 0); iface = INF_TEXT_INSERT_OPERATION_GET_IFACE(operation); g_return_val_if_fail(iface->get_position != NULL, 0); return iface->get_position(operation); } /** * inf_text_insert_operation_get_length: * @operation: A #InfTextInsertOperation. * * Returns the length of the text inserted by @operation. * * Returns: The length of @operation. **/ guint inf_text_insert_operation_get_length(InfTextInsertOperation* operation) { InfTextInsertOperationInterface* iface; g_return_val_if_fail(INF_TEXT_IS_INSERT_OPERATION(operation), 0); iface = INF_TEXT_INSERT_OPERATION_GET_IFACE(operation); g_return_val_if_fail(iface->get_length != NULL, 0); return iface->get_length(operation); } /** * inf_text_insert_operation_need_concurrency_id: * @op: A #InfTextInsertOperation. * @against: Another #InfAdoptedOperation. * * Returns whether transforming @op against @against requires a concurrency ID * (see inf_adopted_operation_need_concurrency_id() for further information). * * Returns: Whether transforming @op against @against requires a concurrency * ID. */ gboolean inf_text_insert_operation_need_concurrency_id(InfTextInsertOperation* op, InfAdoptedOperation* against) { InfTextInsertOperation* insert_against; g_return_val_if_fail(INF_TEXT_IS_INSERT_OPERATION(op), FALSE); g_return_val_if_fail(INF_ADOPTED_IS_OPERATION(against), FALSE); if(INF_TEXT_IS_INSERT_OPERATION(against)) { insert_against = INF_TEXT_INSERT_OPERATION(against); if(inf_text_insert_operation_get_position(op) == inf_text_insert_operation_get_position(insert_against)) { return TRUE; } } return FALSE; } /** * inf_text_insert_operation_transform_insert: * @operation: A #InfTextInsertOperation. * @against: Another #InfTextInsertOperation. * @op_lcs: The given operation in a previous state, or %NULL. * @ag_lcs: The @against operation in a previous state, or %NULL. * @cid: The concurrency ID for the transformation. * * Returns a new operation that includes the effect of @against into * @operation. * * Returns: (transfer full): A new #InfAdoptedOperation. **/ InfAdoptedOperation* inf_text_insert_operation_transform_insert(InfTextInsertOperation* operation, InfTextInsertOperation* against, InfTextInsertOperation* op_lcs, InfTextInsertOperation* ag_lcs, InfAdoptedConcurrencyId cid) { InfTextInsertOperationInterface* iface; guint op_pos; guint against_pos; guint op_lcs_pos; guint against_lcs_pos; guint against_length; g_return_val_if_fail(INF_TEXT_IS_INSERT_OPERATION(operation), NULL); g_return_val_if_fail(INF_TEXT_IS_INSERT_OPERATION(against), NULL); iface = INF_TEXT_INSERT_OPERATION_GET_IFACE(operation); g_return_val_if_fail(iface->transform_position != NULL, NULL); op_pos = inf_text_insert_operation_get_position(operation); against_pos = inf_text_insert_operation_get_position(against); if(op_pos < against_pos) { return inf_adopted_operation_copy(INF_ADOPTED_OPERATION(operation)); } else if(op_pos > against_pos) { against_length = inf_text_insert_operation_get_length(against); return INF_ADOPTED_OPERATION( iface->transform_position(operation, op_pos + against_length) ); } else { g_assert(op_lcs != NULL); g_assert(ag_lcs != NULL); op_lcs_pos = inf_text_insert_operation_get_position(op_lcs); against_lcs_pos = inf_text_insert_operation_get_position(ag_lcs); if(op_lcs_pos < against_lcs_pos || (op_lcs_pos == against_lcs_pos && cid == INF_ADOPTED_CONCURRENCY_OTHER)) { return inf_adopted_operation_copy(INF_ADOPTED_OPERATION(operation)); } else if(op_lcs_pos > against_lcs_pos || (op_lcs_pos == against_lcs_pos && cid == INF_ADOPTED_CONCURRENCY_SELF)) { against_length = inf_text_insert_operation_get_length(against); return INF_ADOPTED_OPERATION( iface->transform_position(operation, op_pos + against_length) ); } else { g_assert_not_reached(); return NULL; } } } /** * inf_text_insert_operation_transform_delete: * @operation: A #InfTextInsertOperation. * @against: A #InfTextDeleteOperation. * * Returns a new operation that includes the effect of @against into * @operation. * * Returns: (transfer full): A new #InfAdoptedOperation. **/ InfAdoptedOperation* inf_text_insert_operation_transform_delete(InfTextInsertOperation* operation, InfTextDeleteOperation* against) { InfTextInsertOperationInterface* iface; guint own_pos; guint other_pos; guint other_len; g_return_val_if_fail(INF_TEXT_IS_INSERT_OPERATION(operation), NULL); g_return_val_if_fail(INF_TEXT_IS_DELETE_OPERATION(against), NULL); iface = INF_TEXT_INSERT_OPERATION_GET_IFACE(operation); g_return_val_if_fail(iface->transform_position != NULL, NULL); own_pos = inf_text_insert_operation_get_position(operation); other_pos = inf_text_delete_operation_get_position(against); other_len = inf_text_delete_operation_get_length(against); if(own_pos >= other_pos + other_len) { return INF_ADOPTED_OPERATION( iface->transform_position(operation, own_pos - other_len) ); } else if(own_pos < other_pos) { return inf_adopted_operation_copy(INF_ADOPTED_OPERATION(operation)); } else { return INF_ADOPTED_OPERATION( iface->transform_position(operation, other_pos) ); } } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinftext/PaxHeaders.26529/inf-text-delete-operation.h0000644000000000000000000000013213034342512023115 xustar0030 mtime=1483851082.045718513 30 atime=1483851082.045718513 30 ctime=1488261589.188138654 libinfinity-0.7.1/libinftext/inf-text-delete-operation.h0000644000175000017500000001035013034342512023646 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_TEXT_DELETE_OPERATION_H__ #define __INF_TEXT_DELETE_OPERATION_H__ #include #include #include #include G_BEGIN_DECLS #define INF_TEXT_TYPE_DELETE_OPERATION (inf_text_delete_operation_get_type()) #define INF_TEXT_DELETE_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_TEXT_TYPE_DELETE_OPERATION, InfTextDeleteOperation)) #define INF_TEXT_IS_DELETE_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_TEXT_TYPE_DELETE_OPERATION)) #define INF_TEXT_DELETE_OPERATION_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), INF_TEXT_TYPE_DELETE_OPERATION, InfTextDeleteOperationInterface)) typedef struct _InfTextDeleteOperationInterface InfTextDeleteOperationInterface; /** * InfTextDeleteOperationInterface: * @get_position: Virtual function to retrieve the start position of the * delete operation. * @get_length: Virtual function to retrieve the end position of the number * of characters removed by the delete operation. * @transform_position: Virtual function to transform the operation such that * the start position of the operation changes. * @transform_overlap: Virtual function to transform the operation against * another delete operation with overlapping regions. * @transform_split: Virtual function to transform the operation against an * insert operation such that this operation needs to be split in two. * * This structure contains virtual methods of the #InfTextDeleteOperation * interface. */ struct _InfTextDeleteOperationInterface { /*< private >*/ GTypeInterface parent; /*< public >*/ /* Virtual table */ guint(*get_position)(InfTextDeleteOperation* operation); guint(*get_length)(InfTextDeleteOperation* operation); InfTextDeleteOperation*(*transform_position)(InfTextDeleteOperation* op, guint position); InfTextDeleteOperation*(*transform_overlap)(InfTextDeleteOperation* op, InfTextDeleteOperation* other, guint position, guint begin, guint other_begin, guint length); InfAdoptedSplitOperation*(*transform_split)(InfTextDeleteOperation* op, guint split_pos, guint split_length); }; GType inf_text_delete_operation_get_type(void) G_GNUC_CONST; guint inf_text_delete_operation_get_position(InfTextDeleteOperation* operation); guint inf_text_delete_operation_get_length(InfTextDeleteOperation* operation); gboolean inf_text_delete_operation_need_concurrency_id(InfTextDeleteOperation* op, InfAdoptedOperation* against); InfAdoptedOperation* inf_text_delete_operation_transform_insert(InfTextDeleteOperation* operation, InfTextInsertOperation* against); InfAdoptedOperation* inf_text_delete_operation_transform_delete(InfTextDeleteOperation* operation, InfTextDeleteOperation* against); G_END_DECLS #endif /* __INF_TEXT_DELETE_OPERATION_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinftext/PaxHeaders.26529/inf-text-fixline-buffer.h0000644000000000000000000000013213034342512022562 xustar0030 mtime=1483851082.045718513 30 atime=1483851082.045718513 30 ctime=1488261589.192138646 libinfinity-0.7.1/libinftext/inf-text-fixline-buffer.h0000644000175000017500000000506613034342512023323 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_TEXT_FIXLINE_BUFFER_H__ #define __INF_TEXT_FIXLINE_BUFFER_H__ #include #include #include G_BEGIN_DECLS #define INF_TEXT_TYPE_FIXLINE_BUFFER (inf_text_fixline_buffer_get_type()) #define INF_TEXT_FIXLINE_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_TEXT_TYPE_FIXLINE_BUFFER, InfTextFixlineBuffer)) #define INF_TEXT_FIXLINE_BUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INF_TEXT_TYPE_FIXLINE_BUFFER, InfTextFixlineBufferClass)) #define INF_TEXT_IS_FIXLINE_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_TEXT_TYPE_FIXLINE_BUFFER)) #define INF_TEXT_IS_FIXLINE_BUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INF_TEXT_TYPE_FIXLINE_BUFFER)) #define INF_TEXT_FIXLINE_BUFFER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INF_TEXT_TYPE_FIXLINE_BUFFER, InfTextFixlineBufferClass)) typedef struct _InfTextFixlineBuffer InfTextFixlineBuffer; typedef struct _InfTextFixlineBufferClass InfTextFixlineBufferClass; /** * InfTextFixlineBufferClass: * * This structure does not contain any public fields. */ struct _InfTextFixlineBufferClass { GObjectClass parent_class; }; /** * InfTextFixlineBuffer: * * #InfTextFixlineBuffer is an opaque data type. You should only access it * via the public API functions. */ struct _InfTextFixlineBuffer { GObject parent; }; GType inf_text_fixline_buffer_get_type(void) G_GNUC_CONST; InfTextFixlineBuffer* inf_text_fixline_buffer_new(InfIo* io, InfTextBuffer* buffer, guint n_lines); G_END_DECLS #endif /* __INF_TEXT_FIXLINE_BUFFER_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinftext/PaxHeaders.26529/inf-text-operations.h0000644000000000000000000000013213034342512022040 xustar0030 mtime=1483851082.045718513 30 atime=1483851082.045718513 30 ctime=1488261589.196138637 libinfinity-0.7.1/libinftext/inf-text-operations.h0000644000175000017500000000464613034342512022604 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_TEXT_OPERATIONS_H__ #define __INF_TEXT_OPERATIONS_H__ #include G_BEGIN_DECLS /* Forward declaration for inf-text-insert-operation.h and * inf-text-delete-operation.h each of which needs both. */ /** * InfTextOperationError: * @INF_TEXT_OPERATION_ERROR_INVALID_INSERT: A #InfTextInsertOperation * attempted to insert text after the end of the buffer. * @INF_TEXT_OPERATION_ERROR_INVALID_DELETE: A #InfTextDeleteOperation * attempted to delete text from after the end of the buffer. * @INF_TEXT_OPERATION_ERROR_INVALID_MOVE: A #InfTextMoveOperation attempted * to move the cursor of a user behind the end of the buffer. * @INF_TEXT_OPERATION_ERROR_FAILED: No further specified error code. * * Error codes that can occur when applying a #InfTextInsertOperation, * #InfTextDeleteOperation or #InfTextMoveOperation to the buffer. */ typedef enum _InfTextOperationError { INF_TEXT_OPERATION_ERROR_INVALID_INSERT, INF_TEXT_OPERATION_ERROR_INVALID_DELETE, INF_TEXT_OPERATION_ERROR_INVALID_MOVE, INF_TEXT_OPERATION_ERROR_FAILED } InfTextOperationError; /** * InfTextDeleteOperation: * * #InfTextDeleteOperation is an opaque data type. You should only access it * via the public API functions. */ typedef struct _InfTextDeleteOperation InfTextDeleteOperation; /** * InfTextInsertOperation: * * #InfTextInsertOperation is an opaque data type. You should only access it * via the public API functions. */ typedef struct _InfTextInsertOperation InfTextInsertOperation; G_END_DECLS #endif /* __INF_TEXT_OPERATIONS_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinftext/PaxHeaders.26529/inf-text-user.h0000644000000000000000000000013213034342512020633 xustar0030 mtime=1483851082.049718536 30 atime=1483851082.049718536 30 ctime=1488261589.200138628 libinfinity-0.7.1/libinftext/inf-text-user.h0000644000175000017500000000514413034342512021371 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_TEXT_USER_H__ #define __INF_TEXT_USER_H__ #include #include G_BEGIN_DECLS #define INF_TEXT_TYPE_USER (inf_text_user_get_type()) #define INF_TEXT_USER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_TEXT_TYPE_USER, InfTextUser)) #define INF_TEXT_USER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INF_TEXT_TYPE_USER, InfTextUserClass)) #define INF_TEXT_IS_USER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_TEXT_TYPE_USER)) #define INF_TEXT_IS_USER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INF_TEXT_TYPE_USER)) #define INF_TEXT_USER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INF_TEXT_TYPE_USER, InfTextUserClass)) typedef struct _InfTextUser InfTextUser; typedef struct _InfTextUserClass InfTextUserClass; struct _InfTextUserClass { InfAdoptedUserClass parent_class; void(*selection_changed)(InfTextUser* user, guint position, guint length, gboolean by_request); }; struct _InfTextUser { InfAdoptedUser parent; }; GType inf_text_user_get_type(void) G_GNUC_CONST; InfTextUser* inf_text_user_new(guint id, const gchar* name, InfAdoptedStateVector* vector, double hue); guint inf_text_user_get_caret_position(InfTextUser* user); gint inf_text_user_get_selection_length(InfTextUser* user); void inf_text_user_set_selection(InfTextUser* user, guint position, gint length, gboolean by_request); gdouble inf_text_user_get_hue(InfTextUser* user); G_END_DECLS #endif /* __INF_TEXT_USER_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinftext/PaxHeaders.26529/inf-text-default-buffer.h0000644000000000000000000000013213034342512022550 xustar0030 mtime=1483851082.045718513 30 atime=1483851082.045718513 30 ctime=1488261589.188138654 libinfinity-0.7.1/libinftext/inf-text-default-buffer.h0000644000175000017500000000424413034342512023306 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_TEXT_DEFAULT_BUFFER_H__ #define __INF_TEXT_DEFAULT_BUFFER_H__ #include G_BEGIN_DECLS #define INF_TEXT_TYPE_DEFAULT_BUFFER (inf_text_default_buffer_get_type()) #define INF_TEXT_DEFAULT_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_TEXT_TYPE_DEFAULT_BUFFER, InfTextDefaultBuffer)) #define INF_TEXT_DEFAULT_BUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INF_TEXT_TYPE_DEFAULT_BUFFER, InfTextDefaultBufferClass)) #define INF_TEXT_IS_DEFAULT_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_TEXT_TYPE_DEFAULT_BUFFER)) #define INF_TEXT_IS_DEFAULT_BUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INF_TEXT_TYPE_DEFAULT_BUFFER)) #define INF_TEXT_DEFAULT_BUFFER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INF_TEXT_TYPE_DEFAULT_BUFFER, InfTextDefaultBufferClass)) typedef struct _InfTextDefaultBuffer InfTextDefaultBuffer; typedef struct _InfTextDefaultBufferClass InfTextDefaultBufferClass; struct _InfTextDefaultBufferClass { GObjectClass parent_class; }; struct _InfTextDefaultBuffer { GObject parent; }; GType inf_text_default_buffer_get_type(void) G_GNUC_CONST; InfTextDefaultBuffer* inf_text_default_buffer_new(const gchar* encoding); G_END_DECLS #endif /* __INF_TEXT_DEFAULT_BUFFER_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinftext/PaxHeaders.26529/inf-text-move-operation.h0000644000000000000000000000013213034342512022621 xustar0030 mtime=1483851082.045718513 30 atime=1483851082.045718513 30 ctime=1488261589.196138637 libinfinity-0.7.1/libinftext/inf-text-move-operation.h0000644000175000017500000000564113034342512023361 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_TEXT_MOVE_OPERATION_H__ #define __INF_TEXT_MOVE_OPERATION_H__ #include G_BEGIN_DECLS #define INF_TEXT_TYPE_MOVE_OPERATION (inf_text_move_operation_get_type()) #define INF_TEXT_MOVE_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_TEXT_TYPE_MOVE_OPERATION, InfTextMoveOperation)) #define INF_TEXT_MOVE_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INF_TEXT_TYPE_MOVE_OPERATION, InfTextMoveOperationClass)) #define INF_TEXT_IS_MOVE_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_TEXT_TYPE_MOVE_OPERATION)) #define INF_TEXT_IS_MOVE_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INF_TEXT_TYPE_MOVE_OPERATION)) #define INF_TEXT_MOVE_OPERATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INF_TEXT_TYPE_MOVE_OPERATION, InfTextMoveOperationClass)) typedef struct _InfTextMoveOperation InfTextMoveOperation; typedef struct _InfTextMoveOperationClass InfTextMoveOperationClass; struct _InfTextMoveOperationClass { GObjectClass parent_class; }; struct _InfTextMoveOperation { GObject parent; }; GType inf_text_move_operation_get_type(void) G_GNUC_CONST; InfTextMoveOperation* inf_text_move_operation_new(guint position, gint length); guint inf_text_move_operation_get_position(InfTextMoveOperation* operation); gint inf_text_move_operation_get_length(InfTextMoveOperation* operation); void inf_text_move_operation_transform_insert(guint insert_position, guint insert_length, guint* move_position, gint* move_length, gboolean left_gravity); void inf_text_move_operation_transform_delete(guint delete_position, guint delete_length, guint* move_position, gint* move_length); G_END_DECLS #endif /* __INF_TEXT_MOVE_OPERATION_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinftext/PaxHeaders.26529/inf-text-default-insert-operation.h0000644000000000000000000000013213034342512024601 xustar0030 mtime=1483851082.045718513 30 atime=1483851082.045718513 30 ctime=1488261589.188138654 libinfinity-0.7.1/libinftext/inf-text-default-insert-operation.h0000644000175000017500000000515213034342512025336 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_TEXT_DEFAULT_INSERT_OPERATION_H__ #define __INF_TEXT_DEFAULT_INSERT_OPERATION_H__ #include #include G_BEGIN_DECLS #define INF_TEXT_TYPE_DEFAULT_INSERT_OPERATION (inf_text_default_insert_operation_get_type()) #define INF_TEXT_DEFAULT_INSERT_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_TEXT_TYPE_DEFAULT_INSERT_OPERATION, InfTextDefaultInsertOperation)) #define INF_TEXT_DEFAULT_INSERT_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INF_TEXT_TYPE_DEFAULT_INSERT_OPERATION, InfTextDefaultInsertOperationClass)) #define INF_TEXT_IS_DEFAULT_INSERT_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_TEXT_TYPE_DEFAULT_INSERT_OPERATION)) #define INF_TEXT_IS_DEFAULT_INSERT_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INF_TEXT_TYPE_DEFAULT_INSERT_OPERATION)) #define INF_TEXT_DEFAULT_INSERT_OPERATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INF_TEXT_TYPE_DEFAULT_INSERT_OPERATION, InfTextDefaultInsertOperationClass)) typedef struct _InfTextDefaultInsertOperation InfTextDefaultInsertOperation; typedef struct _InfTextDefaultInsertOperationClass InfTextDefaultInsertOperationClass; struct _InfTextDefaultInsertOperationClass { GObjectClass parent_class; }; struct _InfTextDefaultInsertOperation { GObject parent; }; GType inf_text_default_insert_operation_get_type(void) G_GNUC_CONST; InfTextDefaultInsertOperation* inf_text_default_insert_operation_new(guint pos, InfTextChunk* chunk); InfTextChunk* inf_text_default_insert_operation_get_chunk( InfTextDefaultInsertOperation* operation); G_END_DECLS #endif /* __INF_TEXT_DEFAULT_INSERT_OPERATION_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinftext/PaxHeaders.26529/inf-text-remote-delete-operation.c0000644000000000000000000000013213034342512024401 xustar0030 mtime=1483851082.045718513 30 atime=1483851082.045718513 30 ctime=1488261589.220138585 libinfinity-0.7.1/libinftext/inf-text-remote-delete-operation.c0000644000175000017500000005545613034342512025152 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include /* recon is helper information to reconstruct the original delete operation. * It stores the parts that have been erased from the remote delete operation * by transforming against other delete operations, including the deleted * text that is obtained from the operations transformed against. This * is necessary because that information is no longer available in the buffer * in the state the remote delete operation is made reversible. */ typedef struct _InfTextRemoteDeleteOperationRecon InfTextRemoteDeleteOperationRecon; struct _InfTextRemoteDeleteOperationRecon { guint position; InfTextChunk* chunk; }; typedef struct _InfTextRemoteDeleteOperationPrivate InfTextRemoteDeleteOperationPrivate; struct _InfTextRemoteDeleteOperationPrivate { guint position; guint length; /* TODO: Don't use GSList but link InfTextRemoteDeleteOperationRecon * directly? */ GSList* recon; /* TODO: We don't actually need recon_offset, it is just used in an * assertion. Perhaps keep in debug code. */ guint recon_offset; }; enum { PROP_0, PROP_POSITION, PROP_LENGTH }; #define INF_TEXT_REMOTE_DELETE_OPERATION_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INF_TEXT_TYPE_REMOTE_DELETE_OPERATION, InfTextRemoteDeleteOperationPrivate)) static void inf_text_remote_delete_operation_operation_iface_init(InfAdoptedOperationInterface* iface); static void inf_text_remote_delete_operation_delete_operation_iface_init(InfTextDeleteOperationInterface* iface); G_DEFINE_TYPE_WITH_CODE(InfTextRemoteDeleteOperation, inf_text_remote_delete_operation, G_TYPE_OBJECT, G_ADD_PRIVATE(InfTextRemoteDeleteOperation) G_IMPLEMENT_INTERFACE(INF_ADOPTED_TYPE_OPERATION, inf_text_remote_delete_operation_operation_iface_init) G_IMPLEMENT_INTERFACE(INF_TEXT_TYPE_DELETE_OPERATION, inf_text_remote_delete_operation_delete_operation_iface_init)) /* This appends an element to a GSList more efficiently than * g_slist_append() when the last item of the list in known. This updates * *last to point to the new last item. */ static GSList* g_slist_append_fast(GSList* list, GSList** last, gpointer item) { GSList* temp; g_assert(last != NULL); if(list == NULL) { list = g_slist_prepend(list, item); *last = list; } else { g_assert(*last != NULL); /* We don't actually need the return value, but glib warns if it * remains unused. We know that g_slist_append does not change the list * because the list has at least one element (otherwise it would be * NULL). */ temp = g_slist_append(*last, item); *last = (*last)->next; } return list; } static GSList* inf_text_remote_delete_operation_recon_copy(GSList* recon_list) { GSList* item; InfTextRemoteDeleteOperationRecon* recon; GSList* new_list; GSList* last; InfTextRemoteDeleteOperationRecon* new_recon; new_list = NULL; for(item = recon_list; item != NULL; item = g_slist_next(item)) { recon = (InfTextRemoteDeleteOperationRecon*)item->data; new_recon = g_slice_new(InfTextRemoteDeleteOperationRecon); new_recon->position = recon->position; new_recon->chunk = inf_text_chunk_copy(recon->chunk); new_list = g_slist_append_fast(new_list, &last, new_recon); } return new_list; } static void inf_text_remote_delete_operation_recon_free(GSList* recon_list) { GSList* item; InfTextRemoteDeleteOperationRecon* recon; for(item = recon_list; item != NULL; item = g_slist_next(item)) { recon = (InfTextRemoteDeleteOperationRecon*)item->data; inf_text_chunk_free(recon->chunk); g_slice_free(InfTextRemoteDeleteOperationRecon, recon); } g_slist_free(recon_list); } /* TODO: Make this work inline, adjust usages */ /* TODO: Merge adjacent text chunks */ static GSList* inf_text_remote_delete_operation_recon_feed(GSList* recon_list, guint position, InfTextChunk* chunk) { GSList* item; InfTextRemoteDeleteOperationRecon* recon; GSList* new_list; GSList* last; InfTextRemoteDeleteOperationRecon* new_recon; guint text_pos; guint cur_len; guint text_len; new_list = NULL; text_pos = 0; cur_len = 0; for(item = recon_list; item != NULL; item = g_slist_next(item)) { recon = (InfTextRemoteDeleteOperationRecon*)item->data; if(position + text_pos + cur_len < recon->position && text_pos < inf_text_chunk_get_length(chunk)) { text_len = recon->position - position - text_pos - cur_len; if(text_len > inf_text_chunk_get_length(chunk) - text_pos) text_len = inf_text_chunk_get_length(chunk) - text_pos; new_recon = g_slice_new(InfTextRemoteDeleteOperationRecon); new_recon->position = position + text_pos + cur_len; new_recon->chunk = inf_text_chunk_substring(chunk, text_pos, text_len); new_list = g_slist_append_fast(new_list, &last, new_recon); text_pos += text_len; } cur_len += inf_text_chunk_get_length(recon->chunk); new_recon = g_slice_new(InfTextRemoteDeleteOperationRecon); new_recon->position = recon->position; new_recon->chunk = inf_text_chunk_copy(recon->chunk); new_list = g_slist_append_fast(new_list, &last, new_recon); } if(text_pos < inf_text_chunk_get_length(chunk)) { new_recon = g_slice_new(InfTextRemoteDeleteOperationRecon); new_recon->position = position + text_pos + cur_len; new_recon->chunk = inf_text_chunk_substring( chunk, text_pos, inf_text_chunk_get_length(chunk) - text_pos ); new_list = g_slist_append_fast(new_list, &last, new_recon); } return new_list; } static void inf_text_remote_delete_operation_init(InfTextRemoteDeleteOperation* operation) { InfTextRemoteDeleteOperationPrivate* priv; priv = INF_TEXT_REMOTE_DELETE_OPERATION_PRIVATE(operation); priv->position = 0; priv->length = 0; priv->recon = NULL; priv->recon_offset = 0; } static void inf_text_remote_delete_operation_finalize(GObject* object) { InfTextRemoteDeleteOperation* operation; InfTextRemoteDeleteOperationPrivate* priv; operation = INF_TEXT_REMOTE_DELETE_OPERATION(object); priv = INF_TEXT_REMOTE_DELETE_OPERATION_PRIVATE(operation); inf_text_remote_delete_operation_recon_free(priv->recon); G_OBJECT_CLASS(inf_text_remote_delete_operation_parent_class)->finalize(object); } static void inf_text_remote_delete_operation_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfTextRemoteDeleteOperation* operation; InfTextRemoteDeleteOperationPrivate* priv; operation = INF_TEXT_REMOTE_DELETE_OPERATION(object); priv = INF_TEXT_REMOTE_DELETE_OPERATION_PRIVATE(operation); switch(prop_id) { case PROP_POSITION: priv->position = g_value_get_uint(value); break; case PROP_LENGTH: priv->length = g_value_get_uint(value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void inf_text_remote_delete_operation_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfTextRemoteDeleteOperation* operation; InfTextRemoteDeleteOperationPrivate* priv; operation = INF_TEXT_REMOTE_DELETE_OPERATION(object); priv = INF_TEXT_REMOTE_DELETE_OPERATION_PRIVATE(operation); switch(prop_id) { case PROP_POSITION: g_value_set_uint(value, priv->position); break; case PROP_LENGTH: g_value_set_uint(value, priv->length); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static gboolean inf_text_remote_delete_operation_need_concurrency_id( InfAdoptedOperation* operation, InfAdoptedOperation* against) { g_assert(INF_TEXT_IS_REMOTE_DELETE_OPERATION(operation)); return inf_text_delete_operation_need_concurrency_id( INF_TEXT_DELETE_OPERATION(operation), against ); } static InfAdoptedOperation* inf_text_remote_delete_operation_transform(InfAdoptedOperation* operation, InfAdoptedOperation* against, InfAdoptedOperation* operation_lcs, InfAdoptedOperation* against_lcs, InfAdoptedConcurrencyId cid) { g_assert(INF_TEXT_IS_REMOTE_DELETE_OPERATION(operation)); if(INF_TEXT_IS_INSERT_OPERATION(against)) { return inf_text_delete_operation_transform_insert( INF_TEXT_DELETE_OPERATION(operation), INF_TEXT_INSERT_OPERATION(against) ); } else if(INF_TEXT_IS_DELETE_OPERATION(against)) { return inf_text_delete_operation_transform_delete( INF_TEXT_DELETE_OPERATION(operation), INF_TEXT_DELETE_OPERATION(against) ); } else { g_assert_not_reached(); return NULL; } } static InfAdoptedOperation* inf_text_remote_delete_operation_copy(InfAdoptedOperation* operation) { InfTextRemoteDeleteOperationPrivate* priv; GObject* result; InfTextRemoteDeleteOperationPrivate* result_priv; priv = INF_TEXT_REMOTE_DELETE_OPERATION_PRIVATE(operation); result = g_object_new( INF_TEXT_TYPE_REMOTE_DELETE_OPERATION, "position", priv->position, "length", priv->length, NULL ); result_priv = INF_TEXT_REMOTE_DELETE_OPERATION_PRIVATE(result); result_priv->recon = inf_text_remote_delete_operation_recon_copy( priv->recon ); result_priv->recon_offset = priv->recon_offset; return INF_ADOPTED_OPERATION(result); } static InfAdoptedOperationFlags inf_text_remote_delete_operation_get_flags(InfAdoptedOperation* operation) { /* RemoteDeleteOperation is not reversible because it does not know * what text has been deleted */ return INF_ADOPTED_OPERATION_AFFECTS_BUFFER; } static gboolean inf_text_remote_delete_operation_apply(InfAdoptedOperation* operation, InfAdoptedUser* by, InfBuffer* buffer, GError** error) { InfTextRemoteDeleteOperationPrivate* priv; g_assert(INF_TEXT_IS_REMOTE_DELETE_OPERATION(operation)); g_assert(INF_TEXT_IS_BUFFER(buffer)); priv = INF_TEXT_REMOTE_DELETE_OPERATION_PRIVATE(operation); if(priv->position + priv->length > inf_text_buffer_get_length(INF_TEXT_BUFFER(buffer))) { g_set_error_literal( error, g_quark_from_static_string("INF_TEXT_OPERATION_ERROR"), INF_TEXT_OPERATION_ERROR_INVALID_DELETE, _("Attempt to remove text from after the end of the document") ); return FALSE; } else { inf_text_buffer_erase_text( INF_TEXT_BUFFER(buffer), priv->position, priv->length, INF_USER(by) ); return TRUE; } } static InfAdoptedOperation* inf_text_remote_delete_operation_apply_transformed(InfAdoptedOperation* op, InfAdoptedOperation* trans, InfAdoptedUser* by, InfBuffer* buffer, GError** error) { InfTextRemoteDeleteOperationPrivate* priv; InfTextChunk* chunk; InfTextChunk* temp_slice; GSList* list; GSList* item; InfAdoptedOperation* operation; GSList* recon_list; GSList* recon_item; InfTextRemoteDeleteOperationRecon* recon; InfTextDefaultDeleteOperation* result; g_assert(INF_TEXT_IS_REMOTE_DELETE_OPERATION(op)); g_assert(INF_TEXT_IS_BUFFER(buffer)); /* TODO: We can probably optimize this function, but then we should * a) profile it and b) in many cases input parameters to this function * are trivial anyway. */ if(INF_ADOPTED_IS_SPLIT_OPERATION(trans)) { list = inf_adopted_split_operation_unsplit( INF_ADOPTED_SPLIT_OPERATION(trans) ); } else { list = g_slist_prepend(NULL, trans); } chunk = inf_text_chunk_new( inf_text_buffer_get_encoding(INF_TEXT_BUFFER(buffer)) ); /* We assume the list of remote delete operations to be in order */ for(item = list; item != NULL; item = g_slist_next(item)) { g_assert(INF_TEXT_IS_REMOTE_DELETE_OPERATION(item->data)); priv = INF_TEXT_REMOTE_DELETE_OPERATION_PRIVATE(item->data); operation = INF_ADOPTED_OPERATION(item->data); if(priv->length > 0) { temp_slice = inf_text_buffer_get_slice( INF_TEXT_BUFFER(buffer), priv->position, priv->length ); recon_list = inf_text_remote_delete_operation_recon_feed( priv->recon, 0, temp_slice ); inf_text_chunk_free(temp_slice); } else { recon_list = priv->recon; } for(recon_item = recon_list; recon_item != NULL; recon_item = g_slist_next(recon_item)) { recon = (InfTextRemoteDeleteOperationRecon*)recon_item->data; g_assert(priv->recon_offset + recon->position == inf_text_chunk_get_length(chunk)); inf_text_chunk_insert_chunk( chunk, inf_text_chunk_get_length(chunk), recon->chunk ); } /* Free recon list if newly allocated */ if(priv->length > 0) inf_text_remote_delete_operation_recon_free(recon_list); if(!inf_adopted_operation_apply(operation, by, buffer, error)) { g_slist_free(list); inf_text_chunk_free(chunk); return NULL; } } g_slist_free(list); priv = INF_TEXT_REMOTE_DELETE_OPERATION_PRIVATE(op); result = inf_text_default_delete_operation_new(priv->position, chunk); inf_text_chunk_free(chunk); return INF_ADOPTED_OPERATION(result); } static guint inf_text_remote_delete_operation_get_position( InfTextDeleteOperation* operation) { return INF_TEXT_REMOTE_DELETE_OPERATION_PRIVATE(operation)->position; } static guint inf_text_remote_delete_operation_get_length(InfTextDeleteOperation* operation) { return INF_TEXT_REMOTE_DELETE_OPERATION_PRIVATE(operation)->length; } static InfTextDeleteOperation* inf_text_remote_delete_operation_transform_position( InfTextDeleteOperation* operation, guint position) { InfTextRemoteDeleteOperationPrivate* priv; GObject* result; InfTextRemoteDeleteOperationPrivate* result_priv; priv = INF_TEXT_REMOTE_DELETE_OPERATION_PRIVATE(operation); result = g_object_new( INF_TEXT_TYPE_REMOTE_DELETE_OPERATION, "position", position, "length", priv->length, NULL ); result_priv = INF_TEXT_REMOTE_DELETE_OPERATION_PRIVATE(result); result_priv->recon = inf_text_remote_delete_operation_recon_copy( priv->recon ); result_priv->recon_offset = priv->recon_offset; return INF_TEXT_DELETE_OPERATION(result); } static InfTextDeleteOperation* inf_text_remote_delete_operation_transform_overlap( InfTextDeleteOperation* operation, InfTextDeleteOperation* other, guint position, guint begin, guint other_begin, guint length) { InfTextRemoteDeleteOperationPrivate* priv; InfTextChunk* chunk; GObject* result; InfTextRemoteDeleteOperationPrivate* result_priv; /* It is actually possible that two remote delete operations are * transformed against each other (actually the parts of a splitted * remote delete operation). However, they must not overlap. */ g_assert(INF_TEXT_IS_DEFAULT_DELETE_OPERATION(other)); priv = INF_TEXT_REMOTE_DELETE_OPERATION_PRIVATE(operation); chunk = inf_text_chunk_substring( inf_text_default_delete_operation_get_chunk( INF_TEXT_DEFAULT_DELETE_OPERATION(other) ), other_begin, length ); result = g_object_new( INF_TEXT_TYPE_REMOTE_DELETE_OPERATION, "position", position, "length", priv->length - length, NULL ); result_priv = INF_TEXT_REMOTE_DELETE_OPERATION_PRIVATE(result); result_priv->recon = inf_text_remote_delete_operation_recon_feed( priv->recon, begin, chunk ); inf_text_chunk_free(chunk); result_priv->recon_offset = priv->recon_offset; return INF_TEXT_DELETE_OPERATION(result); } static InfAdoptedSplitOperation* inf_text_remote_delete_operation_transform_split( InfTextDeleteOperation* operation, guint split_pos, guint split_len) { /* Need to split the delete operation and the recon list */ InfTextRemoteDeleteOperationPrivate* priv; InfAdoptedSplitOperation* result; GObject* first_operation; GObject* second_operation; InfTextRemoteDeleteOperationPrivate* result_priv; InfTextRemoteDeleteOperationRecon* recon; InfTextRemoteDeleteOperationRecon* new_recon; GSList* first_recon; GSList* second_recon; guint recon_cur_len; GSList* item; priv = INF_TEXT_REMOTE_DELETE_OPERATION_PRIVATE(operation); first_recon = NULL; second_recon = NULL; recon_cur_len = 0; for(item = priv->recon; item != NULL; item = g_slist_next(item)) { recon = (InfTextRemoteDeleteOperationRecon*)item->data; g_assert(recon->position >= recon_cur_len); if(recon->position - recon_cur_len <= split_pos) { new_recon = g_slice_new(InfTextRemoteDeleteOperationRecon); new_recon->position = recon->position; new_recon->chunk = inf_text_chunk_copy(recon->chunk); first_recon = g_slist_prepend(first_recon, new_recon); recon_cur_len += inf_text_chunk_get_length(recon->chunk); } else { new_recon = g_slice_new(InfTextRemoteDeleteOperationRecon); new_recon->position = recon->position - (split_pos + recon_cur_len); new_recon->chunk = inf_text_chunk_copy(recon->chunk); second_recon = g_slist_prepend(second_recon, new_recon); } } first_operation = g_object_new( INF_TEXT_TYPE_REMOTE_DELETE_OPERATION, "position", priv->position, "length", split_pos, NULL ); second_operation = g_object_new( INF_TEXT_TYPE_REMOTE_DELETE_OPERATION, "position", priv->position + split_len, "length", priv->length - split_pos, NULL ); result_priv = INF_TEXT_REMOTE_DELETE_OPERATION_PRIVATE(first_operation); result_priv->recon = g_slist_reverse(first_recon); result_priv->recon_offset = priv->recon_offset; result_priv = INF_TEXT_REMOTE_DELETE_OPERATION_PRIVATE(second_operation); result_priv->recon = g_slist_reverse(second_recon); result_priv->recon_offset = priv->recon_offset + split_pos + recon_cur_len; result = inf_adopted_split_operation_new( INF_ADOPTED_OPERATION(first_operation), INF_ADOPTED_OPERATION(second_operation) ); g_object_unref(G_OBJECT(second_operation)); g_object_unref(G_OBJECT(first_operation)); return result; } static void inf_text_remote_delete_operation_class_init( InfTextRemoteDeleteOperationClass* remote_delete_operation_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(remote_delete_operation_class); object_class->finalize = inf_text_remote_delete_operation_finalize; object_class->set_property = inf_text_remote_delete_operation_set_property; object_class->get_property = inf_text_remote_delete_operation_get_property; g_object_class_install_property( object_class, PROP_POSITION, g_param_spec_uint( "position", "Position", "Position where to start deleting characters", 0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_LENGTH, g_param_spec_uint( "length", "Length", "The length of the deleted text", 0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); } static void inf_text_remote_delete_operation_operation_iface_init( InfAdoptedOperationInterface* iface) { iface->need_concurrency_id = inf_text_remote_delete_operation_need_concurrency_id; iface->transform = inf_text_remote_delete_operation_transform; iface->copy = inf_text_remote_delete_operation_copy; iface->get_flags = inf_text_remote_delete_operation_get_flags; iface->apply = inf_text_remote_delete_operation_apply; iface->apply_transformed = inf_text_remote_delete_operation_apply_transformed; /* RemoteDeleteOperation is not reversible */ iface->revert = NULL; } static void inf_text_remote_delete_operation_delete_operation_iface_init( InfTextDeleteOperationInterface* iface) { iface->get_position = inf_text_remote_delete_operation_get_position; iface->get_length = inf_text_remote_delete_operation_get_length; iface->transform_position = inf_text_remote_delete_operation_transform_position; iface->transform_overlap = inf_text_remote_delete_operation_transform_overlap; iface->transform_split = inf_text_remote_delete_operation_transform_split; } /** * inf_text_remote_delete_operation_new: (constructor) * @position: The position at which to delete text. * @length: The number of characters to delete. * * Creates a new delete operation that, when applied, deletes @length * characters starting from position @position. Note that this operation is * not reversible because it does not know the text to delete and is therefore * only used to transmit a delete operation through the network to reduce * bandwidth usage. The remote part can then reconstruct the deleted text * using inf_adopted_operation_apply_transformed(). * * However, it is easier to just use #InfTextDefaultDeleteOperation if you * want the operation to be reversible. * * Returns: (transfer full): A new #InfTextRemoteDeleteOperation. **/ InfTextRemoteDeleteOperation* inf_text_remote_delete_operation_new(guint position, guint length) { GObject* object; object = g_object_new( INF_TEXT_TYPE_REMOTE_DELETE_OPERATION, "position", position, "length", length, NULL ); return INF_TEXT_REMOTE_DELETE_OPERATION(object); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinftext/PaxHeaders.26529/inf-text-filesystem-format.h0000644000000000000000000000013213034342512023327 xustar0030 mtime=1483851082.045718513 30 atime=1483851082.045718513 30 ctime=1488261589.192138646 libinfinity-0.7.1/libinftext/inf-text-filesystem-format.h0000644000175000017500000000466613034342512024075 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_TEXT_FILESYSTEM_FORMAT_H__ #define __INF_TEXT_FILESYSTEM_FORMAT_H__ #include #include #include G_BEGIN_DECLS /** * InfTextFilesystemFormatError: * @INF_TEXT_FILESYSTEM_FORMAT_ERROR_NOT_A_TEXT_SESSION: The file to be read * is not a serialized text session. * @INF_TEXT_FILESYSTEM_FORMAT_ERROR_USER_EXISTS: The user table of the * session contains users with duplicate ID or duplicate name. * @INF_TEXT_FILESYSTEM_FORMAT_ERROR_NO_SUCH_USER: A segment of the text * document is written by a user which does not exist. * * Errors that can occur when reading a #InfTextSession from a * #InfdFilesystemStorage. */ typedef enum _InfTextFilesystemFormatError { INF_TEXT_FILESYSTEM_FORMAT_ERROR_NOT_A_TEXT_SESSION, INF_TEXT_FILESYSTEM_FORMAT_ERROR_USER_EXISTS, INF_TEXT_FILESYSTEM_FORMAT_ERROR_NO_SUCH_USER } InfTextFilesystemFormatError; gboolean inf_text_filesystem_format_read(InfdFilesystemStorage* storage, const gchar* path, InfUserTable* user_table, InfTextBuffer* buffer, GError** error); gboolean inf_text_filesystem_format_write(InfdFilesystemStorage* storage, const gchar* path, InfUserTable* user_table, InfTextBuffer* buffer, GError** error); G_END_DECLS #endif /* __INF_TEXT_FILESYSTEM_FORMAT_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinftext/PaxHeaders.26529/inf-text-filesystem-format.c0000644000000000000000000000013213034342512023322 xustar0030 mtime=1483851082.045718513 30 atime=1483851082.045718513 30 ctime=1488261589.212138602 libinfinity-0.7.1/libinftext/inf-text-filesystem-format.c0000644000175000017500000003727213034342512024067 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-text-filesystem-format * @title: Storage of text sessions on the file system * @short_description: Utility functions to deal with storing * InfTextSessions in filesystem storage * @include: libinftext/inf-text-filesystem-storage.h * @see_also: #InfTextSession, #InfdFilesystemStorage * @stability: Unstable * * The functions in this section are utility functions that can be used when * implementing a #InfdNotePlugin to handle #InfTextSessions. These * functions implement reading and writing the content of an #InfTextSession * to an XML file in the storage. */ #include #include #include #include typedef struct _InfTextFilesystemFormatWriteData { xmlNodePtr root; GHashTable* encountered_authors; } InfTextFilesystemFormatWriteData; static GQuark inf_text_filesystem_format_error_quark() { return g_quark_from_static_string("INF_TEXT_FILESYSTEM_FORMAT_ERROR"); } static int inf_text_filesystem_format_read_read_func(void* context, char* buffer, int len) { gsize res; res = infd_filesystem_storage_stream_read((FILE*)context, buffer, len); if(ferror((FILE*)context)) return -1; return (int)res; } static int inf_text_filesystem_format_read_close_func(void* context) { return infd_filesystem_storage_stream_close((FILE*)context); } static gboolean inf_text_filesystem_format_read_user(InfUserTable* user_table, xmlNodePtr node, GError** error) { guint id; gdouble hue; xmlChar* name; gboolean result; InfUser* user; if(!inf_xml_util_get_attribute_uint_required(node, "id", &id, error)) return FALSE; if(!inf_xml_util_get_attribute_double_required(node, "hue", &hue, error)) return FALSE; name = inf_xml_util_get_attribute_required(node, "name", error); if(name == NULL) return FALSE; if(inf_user_table_lookup_user_by_id(user_table, id) != NULL) { g_set_error( error, inf_text_filesystem_format_error_quark(), INF_TEXT_FILESYSTEM_FORMAT_ERROR_USER_EXISTS, _("User with ID %u exists already"), id ); result = FALSE; } else { if(inf_user_table_lookup_user_by_name(user_table, (const gchar*)name)) { g_set_error( error, inf_text_filesystem_format_error_quark(), INF_TEXT_FILESYSTEM_FORMAT_ERROR_USER_EXISTS, _("User with name \"%s\" exists already"), (const gchar*)name ); result = FALSE; } else { user = INF_USER( g_object_new( INF_TEXT_TYPE_USER, "id", id, "name", name, "hue", hue, NULL ) ); inf_user_table_add_user(user_table, user); g_object_unref(user); result = TRUE; } } xmlFree(name); return result; } static gboolean inf_text_filesystem_format_read_buffer(InfTextBuffer* buffer, InfUserTable* user_table, xmlNodePtr node, GError** error) { xmlNodePtr child; guint author; gchar* content; gboolean result; gboolean res; InfUser* user; gsize bytes; guint chars; gboolean is_utf8; gchar* converted; gsize converted_bytes; g_assert(inf_text_buffer_get_length(buffer) == 0); is_utf8 = TRUE; if(strcmp(inf_text_buffer_get_encoding(buffer), "UTF-8") != 0) is_utf8 = FALSE; for(child = node->children; child != NULL; child = child->next) { if(child->type != XML_ELEMENT_NODE) continue; if(strcmp((const gchar*)child->name, "segment") == 0) { res = inf_xml_util_get_attribute_uint_required( child, "author", &author, error ); if(res == FALSE) return FALSE; if(author != 0) { user = inf_user_table_lookup_user_by_id(user_table, author); if(user == NULL) { g_set_error( error, g_quark_from_static_string("INF_NOTE_PLUGIN_TEXT_ERROR"), INF_TEXT_FILESYSTEM_FORMAT_ERROR_NO_SUCH_USER, _("User with ID \"%u\" does not exist"), author ); return FALSE; } } else { user = NULL; } content = inf_xml_util_get_child_text(child, &bytes, &chars, error); if(!content) return FALSE; if(*content != '\0') { if(is_utf8) { inf_text_buffer_insert_text( buffer, inf_text_buffer_get_length(buffer), content, bytes, chars, user ); g_free(content); } else { /* Convert from UTF-8 to buffer encoding */ converted = g_convert( content, bytes, inf_text_buffer_get_encoding(buffer), "UTF-8", NULL, &converted_bytes, error ); g_free(content); if(converted == NULL) return FALSE; inf_text_buffer_insert_text( buffer, inf_text_buffer_get_length(buffer), converted, converted_bytes, chars, user ); g_free(converted); } } } } return TRUE; } static void inf_text_filesystem_format_write_foreach_user_func(InfUser* user, gpointer user_data) { InfTextFilesystemFormatWriteData* data; gpointer user_id; xmlNodePtr node; data = (InfTextFilesystemFormatWriteData*)user_data; user_id = GUINT_TO_POINTER(inf_user_get_id(user)); /* TODO: Use g_hash_table_contains when we can use glib 2.32 */ if(g_hash_table_lookup(data->encountered_authors, user_id) != NULL) { node = xmlNewChild(data->root, NULL, (const xmlChar*)"user", NULL); inf_xml_util_set_attribute_uint(node, "id", inf_user_get_id(user)); inf_xml_util_set_attribute(node, "name", inf_user_get_name(user)); inf_xml_util_set_attribute_double( node, "hue", inf_text_user_get_hue(INF_TEXT_USER(user)) ); } } /** * inf_text_filesystem_format_read: * @storage: A #InfdFilesystemStorage. * @path: Storage path to retrieve the session from. * @user_table: An empty #InfUserTable to use as the new session's user table. * @buffer: An empty #InfTextBuffer to use as the new session's buffer. * @error: Location to store error information, if any, or %NULL. * * Reads a text session from @path in @storage. The file is expected to have * been saved with inf_text_filesystem_format_write() before. The @user_table * parameter should be an empty user table that will be used for the session, * and the @buffer parameter should be an empty #InfTextBuffer, and the * document will be written into this buffer. If the function succeeds, the * user table and buffer can be used to create an #InfTextSession with * inf_text_session_new_with_user_table(). If the function fails, %FALSE is * returned and @error is set. * * Returns: %TRUE on success or %FALSE on error. */ gboolean inf_text_filesystem_format_read(InfdFilesystemStorage* storage, const gchar* path, InfUserTable* user_table, InfTextBuffer* buffer, GError** error) { FILE* stream; gchar* full_path; gchar* uri; xmlDocPtr doc; xmlErrorPtr xmlerror; xmlNodePtr root; xmlNodePtr child; gboolean result; g_return_val_if_fail(INFD_IS_FILESYSTEM_STORAGE(storage), FALSE); g_return_val_if_fail(path != NULL, FALSE); g_return_val_if_fail(INF_TEXT_IS_BUFFER(buffer), FALSE); g_return_val_if_fail(error == NULL || *error == NULL, FALSE); g_return_val_if_fail(inf_text_buffer_get_length(buffer) == 0, FALSE); /* TODO: Use a SAX parser for better performance */ full_path = NULL; stream = infd_filesystem_storage_open( INFD_FILESYSTEM_STORAGE(storage), "InfText", path, "r", &full_path, error ); if(stream == NULL) { g_free(full_path); return FALSE; } uri = g_filename_to_uri(full_path, NULL, error); g_free(full_path); if(uri == NULL) return FALSE; doc = xmlReadIO( inf_text_filesystem_format_read_read_func, inf_text_filesystem_format_read_close_func, stream, uri, "UTF-8", XML_PARSE_NOWARNING | XML_PARSE_NOERROR ); g_free(uri); if(doc == NULL) { xmlerror = xmlGetLastError(); g_set_error( error, g_quark_from_static_string("LIBXML2_PARSER_ERROR"), xmlerror->code, _("Error parsing XML in file \"%s\": [%d]: %s"), path, xmlerror->line, xmlerror->message ); result = FALSE; } else { root = xmlDocGetRootElement(doc); if(strcmp((const char*)root->name, "inf-text-session") != 0) { g_set_error( error, inf_text_filesystem_format_error_quark(), INF_TEXT_FILESYSTEM_FORMAT_ERROR_NOT_A_TEXT_SESSION, _("Error processing file \"%s\": %s"), path, _("The document is not a text session") ); result = FALSE; } else { for(child = root->children; child != NULL; child = child->next) { if(child->type != XML_ELEMENT_NODE) continue; if(strcmp((const char*)child->name, "user") == 0) { if(!inf_text_filesystem_format_read_user(user_table, child, error)) { g_prefix_error(error, _("Error processing file \"%s\": "), path); result = FALSE; break; } } else if(strcmp((const char*)child->name, "buffer") == 0) { if(!inf_text_filesystem_format_read_buffer(buffer, user_table, child, error)) { g_prefix_error(error, _("Error processing file \"%s\": "), path); result = FALSE; break; } } } if(child == NULL) result = TRUE; } xmlFreeDoc(doc); } return result; } /** * inf_text_filesystem_format_write: * @storage: A #InfdFilesystemStorage. * @path: Storage path where to write the session to. * @user_table: The #InfUserTable to write. * @buffer: The #InfTextBuffer to write. * @error: Location to store error information, if any, or %NULL. * * Writes the given user table and buffer into the filesystem storage at * @path. If successful, the session can then be read back with * inf_text_filesystem_format_read(). If the function fails, %FALSE is * returned and @error is set. * * Returns: %TRUE on success or %FALSE on error. */ gboolean inf_text_filesystem_format_write(InfdFilesystemStorage* storage, const gchar* path, InfUserTable* user_table, InfTextBuffer* buffer, GError** error) { InfTextBufferIter* iter; xmlNodePtr buffer_node; xmlNodePtr segment_node; guint author; gchar* content; gsize bytes; gchar* converted; gsize converted_bytes; FILE* stream; xmlDocPtr doc; xmlErrorPtr xmlerror; gboolean is_utf8; InfTextFilesystemFormatWriteData data; g_return_val_if_fail(INFD_IS_FILESYSTEM_STORAGE(storage), FALSE); g_return_val_if_fail(path != NULL, FALSE); g_return_val_if_fail(INF_IS_USER_TABLE(user_table), FALSE); g_return_val_if_fail(INF_TEXT_IS_BUFFER(buffer), FALSE); g_return_val_if_fail(error == NULL || *error == NULL, FALSE); is_utf8 = TRUE; if(strcmp(inf_text_buffer_get_encoding(buffer), "UTF-8") != 0) is_utf8 = FALSE; /* Open stream before exporting buffer to XML so possible errors are * catched earlier. */ stream = infd_filesystem_storage_open( INFD_FILESYSTEM_STORAGE(storage), "InfText", path, "w", NULL, error ); if(stream == NULL) return FALSE; data.root = xmlNewNode(NULL, (const xmlChar*)"inf-text-session"); data.encountered_authors = g_hash_table_new(NULL, NULL); buffer_node = xmlNewNode(NULL, (const xmlChar*)"buffer"); iter = inf_text_buffer_create_begin_iter(buffer); if(iter != NULL) { do { author = inf_text_buffer_iter_get_author(buffer, iter); content = inf_text_buffer_iter_get_text(buffer, iter); bytes = inf_text_buffer_iter_get_bytes(buffer, iter); /* TODO: Use g_hash_table_add with glib 2.32 */ g_hash_table_insert( data.encountered_authors, GUINT_TO_POINTER(author), GUINT_TO_POINTER(author) ); segment_node = xmlNewChild( buffer_node, NULL, (const xmlChar*)"segment", NULL ); inf_xml_util_set_attribute_uint(segment_node, "author", author); if(is_utf8) { /* Buffer is UTF-8, no conversion necessary */ inf_xml_util_add_child_text(segment_node, content, bytes); g_free(content); } else { /* Convert from buffer encoding to UTF-8 for storage */ converted = g_convert( content, bytes, "UTF-8", inf_text_buffer_get_encoding(buffer), NULL, &converted_bytes, error ); g_free(content); if(converted == NULL) { xmlFreeNode(buffer_node); xmlFreeNode(data.root); g_hash_table_destroy(data.encountered_authors); infd_filesystem_storage_stream_close(stream); return FALSE; } inf_xml_util_add_child_text(segment_node, converted, converted_bytes); g_free(converted); } } while(inf_text_buffer_iter_next(buffer, iter)); inf_text_buffer_destroy_iter(buffer, iter); } /* After we wrote the buffer, now write the user table, but only for those * users that have contributed to the document. The others we drop, to * avoid cluttering the user table too much. */ inf_user_table_foreach_user( user_table, inf_text_filesystem_format_write_foreach_user_func, &data ); g_hash_table_destroy(data.encountered_authors); /* Write the buffer after the users */ xmlAddChild(data.root, buffer_node); doc = xmlNewDoc((const xmlChar*)"1.0"); xmlDocSetRootElement(doc, data.root); /* TODO: At this point, we should tell libxml2 to use * infd_filesystem_storage_stream_write() instead of fwrite(), * to prevent C runtime mixups. */ if(xmlDocFormatDump(stream, doc, 1) == -1) { xmlerror = xmlGetLastError(); infd_filesystem_storage_stream_close(stream); xmlFreeDoc(doc); g_set_error_literal( error, g_quark_from_static_string("LIBXML2_OUTPUT_ERROR"), xmlerror->code, xmlerror->message ); return FALSE; } infd_filesystem_storage_stream_close(stream); xmlFreeDoc(doc); return TRUE; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinftext/PaxHeaders.26529/inf-text-default-buffer.c0000644000000000000000000000013213034342512022543 xustar0030 mtime=1483851082.045718513 30 atime=1483851082.045718513 30 ctime=1488261589.208138611 libinfinity-0.7.1/libinftext/inf-text-default-buffer.c0000644000175000017500000002734513034342512023310 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include #include #include struct _InfTextBufferIter { InfTextChunkIter chunk_iter; }; typedef struct _InfTextDefaultBufferPrivate InfTextDefaultBufferPrivate; struct _InfTextDefaultBufferPrivate { gchar* encoding; InfTextChunk* chunk; gboolean modified; }; enum { PROP_0, /* overwritten */ PROP_MODIFIED, PROP_ENCODING }; #define INF_TEXT_DEFAULT_BUFFER_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INF_TEXT_TYPE_DEFAULT_BUFFER, InfTextDefaultBufferPrivate)) static void inf_text_default_buffer_buffer_iface_init(InfBufferInterface* iface); static void inf_text_default_buffer_text_buffer_iface_init(InfTextBufferInterface* iface); G_DEFINE_TYPE_WITH_CODE(InfTextDefaultBuffer, inf_text_default_buffer, G_TYPE_OBJECT, G_ADD_PRIVATE(InfTextDefaultBuffer) G_IMPLEMENT_INTERFACE(INF_TYPE_BUFFER, inf_text_default_buffer_buffer_iface_init) G_IMPLEMENT_INTERFACE(INF_TEXT_TYPE_BUFFER, inf_text_default_buffer_text_buffer_iface_init)) static void inf_text_default_buffer_init(InfTextDefaultBuffer* buffer) { InfTextDefaultBufferPrivate* priv; priv = INF_TEXT_DEFAULT_BUFFER_PRIVATE(buffer); priv->encoding = NULL; priv->chunk = NULL; priv->modified = FALSE; } static void inf_text_default_buffer_finalize(GObject* object) { InfTextDefaultBuffer* default_buffer; InfTextDefaultBufferPrivate* priv; default_buffer = INF_TEXT_DEFAULT_BUFFER(object); priv = INF_TEXT_DEFAULT_BUFFER_PRIVATE(default_buffer); inf_text_chunk_free(priv->chunk); g_free(priv->encoding); G_OBJECT_CLASS(inf_text_default_buffer_parent_class)->finalize(object); } static void inf_text_default_buffer_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfTextDefaultBuffer* default_buffer; InfTextDefaultBufferPrivate* priv; default_buffer = INF_TEXT_DEFAULT_BUFFER(object); priv = INF_TEXT_DEFAULT_BUFFER_PRIVATE(default_buffer); switch(prop_id) { case PROP_ENCODING: /* construct only */ g_assert(priv->encoding == NULL); g_assert(priv->chunk == NULL); priv->encoding = g_value_dup_string(value); priv->chunk = inf_text_chunk_new(priv->encoding); break; case PROP_MODIFIED: priv->modified = g_value_get_boolean(value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void inf_text_default_buffer_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfTextDefaultBuffer* default_buffer; InfTextDefaultBufferPrivate* priv; default_buffer = INF_TEXT_DEFAULT_BUFFER(object); priv = INF_TEXT_DEFAULT_BUFFER_PRIVATE(default_buffer); switch(prop_id) { case PROP_ENCODING: g_value_set_string(value, priv->encoding); break; case PROP_MODIFIED: g_value_set_boolean(value, priv->modified); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static gboolean inf_text_default_buffer_buffer_get_modified(InfBuffer* buffer) { return INF_TEXT_DEFAULT_BUFFER_PRIVATE(buffer)->modified; } static void inf_text_default_buffer_buffer_set_modified(InfBuffer* buffer, gboolean modified) { InfTextDefaultBuffer* default_buffer; InfTextDefaultBufferPrivate* priv; default_buffer = INF_TEXT_DEFAULT_BUFFER(buffer); priv = INF_TEXT_DEFAULT_BUFFER_PRIVATE(default_buffer); if(priv->modified != modified) { priv->modified = modified; g_object_notify(G_OBJECT(buffer), "modified"); } } static const gchar* inf_text_default_buffer_buffer_get_encoding(InfTextBuffer* buffer) { return INF_TEXT_DEFAULT_BUFFER_PRIVATE(buffer)->encoding; } static guint inf_text_default_buffer_get_length(InfTextBuffer* buffer) { InfTextDefaultBufferPrivate* priv; priv = INF_TEXT_DEFAULT_BUFFER_PRIVATE(buffer); return inf_text_chunk_get_length(priv->chunk); } static InfTextChunk* inf_text_default_buffer_buffer_get_slice(InfTextBuffer* buffer, guint pos, guint len) { InfTextDefaultBufferPrivate* priv; priv = INF_TEXT_DEFAULT_BUFFER_PRIVATE(buffer); return inf_text_chunk_substring(priv->chunk, pos, len); } static void inf_text_default_buffer_buffer_insert_text(InfTextBuffer* buffer, guint pos, InfTextChunk* chunk, InfUser* user) { InfTextDefaultBufferPrivate* priv; priv = INF_TEXT_DEFAULT_BUFFER_PRIVATE(buffer); inf_text_chunk_insert_chunk(priv->chunk, pos, chunk); inf_text_buffer_text_inserted(buffer, pos, chunk, user); if(priv->modified == FALSE) { priv->modified = TRUE; g_object_notify(G_OBJECT(buffer), "modified"); } } static void inf_text_default_buffer_buffer_erase_text(InfTextBuffer* buffer, guint pos, guint len, InfUser* user) { InfTextDefaultBufferPrivate* priv; InfTextChunk* chunk; priv = INF_TEXT_DEFAULT_BUFFER_PRIVATE(buffer); chunk = inf_text_chunk_substring(priv->chunk, pos, len); inf_text_chunk_erase(priv->chunk, pos, len); inf_text_buffer_text_erased(buffer, pos, chunk, user); inf_text_chunk_free(chunk); if(priv->modified == FALSE) { priv->modified = TRUE; g_object_notify(G_OBJECT(buffer), "modified"); } } static InfTextBufferIter* inf_text_default_buffer_buffer_create_begin_iter(InfTextBuffer* buffer) { InfTextDefaultBufferPrivate* priv; InfTextChunkIter chunk_iter; InfTextBufferIter* iter; priv = INF_TEXT_DEFAULT_BUFFER_PRIVATE(buffer); if(inf_text_chunk_iter_init_begin(priv->chunk, &chunk_iter) == TRUE) { iter = g_slice_new(InfTextBufferIter); iter->chunk_iter = chunk_iter; return iter; } else { return NULL; } } static InfTextBufferIter* inf_text_default_buffer_buffer_create_end_iter(InfTextBuffer* buffer) { InfTextDefaultBufferPrivate* priv; InfTextChunkIter chunk_iter; InfTextBufferIter* iter; priv = INF_TEXT_DEFAULT_BUFFER_PRIVATE(buffer); if(inf_text_chunk_iter_init_end(priv->chunk, &chunk_iter) == TRUE) { iter = g_slice_new(InfTextBufferIter); iter->chunk_iter = chunk_iter; return iter; } else { return NULL; } } static void inf_text_default_buffer_buffer_destroy_iter(InfTextBuffer* buffer, InfTextBufferIter* iter) { g_slice_free(InfTextBufferIter, iter); } static gboolean inf_text_default_buffer_buffer_iter_next(InfTextBuffer* buffer, InfTextBufferIter* iter) { return inf_text_chunk_iter_next(&iter->chunk_iter); } static gboolean inf_text_default_buffer_buffer_iter_prev(InfTextBuffer* buffer, InfTextBufferIter* iter) { return inf_text_chunk_iter_prev(&iter->chunk_iter); } static gpointer inf_text_default_buffer_buffer_iter_get_text(InfTextBuffer* buffer, InfTextBufferIter* iter) { return g_memdup( inf_text_chunk_iter_get_text(&iter->chunk_iter), inf_text_chunk_iter_get_bytes(&iter->chunk_iter) ); } static guint inf_text_default_buffer_buffer_iter_get_offset(InfTextBuffer* buffer, InfTextBufferIter* iter) { return inf_text_chunk_iter_get_offset(&iter->chunk_iter); } static guint inf_text_default_buffer_buffer_iter_get_length(InfTextBuffer* buffer, InfTextBufferIter* iter) { return inf_text_chunk_iter_get_length(&iter->chunk_iter); } static gsize inf_text_default_buffer_buffer_iter_get_bytes(InfTextBuffer* buffer, InfTextBufferIter* iter) { return inf_text_chunk_iter_get_bytes(&iter->chunk_iter); } static guint inf_text_default_buffer_buffer_iter_get_author(InfTextBuffer* buffer, InfTextBufferIter* iter) { return inf_text_chunk_iter_get_author(&iter->chunk_iter); } static void inf_text_default_buffer_class_init( InfTextDefaultBufferClass* default_buffer_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(default_buffer_class); object_class->finalize = inf_text_default_buffer_finalize; object_class->set_property = inf_text_default_buffer_set_property; object_class->get_property = inf_text_default_buffer_get_property; g_object_class_override_property(object_class, PROP_MODIFIED, "modified"); g_object_class_install_property( object_class, PROP_ENCODING, g_param_spec_string( "encoding", "Encoding", "The character encoding of the text buffer", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); } static void inf_text_default_buffer_buffer_iface_init(InfBufferInterface* iface) { iface->get_modified = inf_text_default_buffer_buffer_get_modified; iface->set_modified = inf_text_default_buffer_buffer_set_modified; } static void inf_text_default_buffer_text_buffer_iface_init(InfTextBufferInterface* iface) { iface->get_encoding = inf_text_default_buffer_buffer_get_encoding; iface->get_length = inf_text_default_buffer_get_length; iface->get_slice = inf_text_default_buffer_buffer_get_slice; iface->insert_text = inf_text_default_buffer_buffer_insert_text; iface->erase_text = inf_text_default_buffer_buffer_erase_text; iface->create_begin_iter = inf_text_default_buffer_buffer_create_begin_iter; iface->create_end_iter = inf_text_default_buffer_buffer_create_end_iter; iface->destroy_iter = inf_text_default_buffer_buffer_destroy_iter; iface->iter_next = inf_text_default_buffer_buffer_iter_next; iface->iter_prev = inf_text_default_buffer_buffer_iter_prev; iface->iter_get_text = inf_text_default_buffer_buffer_iter_get_text; iface->iter_get_offset = inf_text_default_buffer_buffer_iter_get_offset; iface->iter_get_length = inf_text_default_buffer_buffer_iter_get_length; iface->iter_get_bytes = inf_text_default_buffer_buffer_iter_get_bytes; iface->iter_get_author = inf_text_default_buffer_buffer_iter_get_author; iface->text_inserted = NULL; iface->text_erased = NULL; } /** * inf_text_default_buffer_new: (constructor) * @encoding: The character encoding to use for the buffer. * * Creates a new, empty #InfTextDefaultBuffer. * * Returns: (transfer full): A #InfTextDefaultBuffer. **/ InfTextDefaultBuffer* inf_text_default_buffer_new(const gchar* encoding) { GObject* object; object = g_object_new( INF_TEXT_TYPE_DEFAULT_BUFFER, "encoding", encoding, NULL ); return INF_TEXT_DEFAULT_BUFFER(object); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinftext/PaxHeaders.26529/Makefile.in0000644000000000000000000000013213051241010020003 xustar0030 mtime=1487225352.353150482 30 atime=1487225352.353150482 30 ctime=1488261589.200138628 libinfinity-0.7.1/libinftext/Makefile.in0000644000175000017500000014036413051241010020545 0ustar00arminarmin00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 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__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) 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@ subdir = libinftext ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/gtk-doc.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(libinftext_0_7_la_HEADERS) \ $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/libinfinity/inf-config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(girdir)" \ "$(DESTDIR)$(typelibdir)" "$(DESTDIR)$(libinftext_0_7_ladir)" LTLIBRARIES = $(lib_LTLIBRARIES) am__DEPENDENCIES_1 = libinftext_0_7_la_DEPENDENCIES = ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) am_libinftext_0_7_la_OBJECTS = libinftext_0_7_la-inf-text-buffer.lo \ libinftext_0_7_la-inf-text-chunk.lo \ libinftext_0_7_la-inf-text-default-buffer.lo \ libinftext_0_7_la-inf-text-default-delete-operation.lo \ libinftext_0_7_la-inf-text-default-insert-operation.lo \ libinftext_0_7_la-inf-text-delete-operation.lo \ libinftext_0_7_la-inf-text-filesystem-format.lo \ libinftext_0_7_la-inf-text-fixline-buffer.lo \ libinftext_0_7_la-inf-text-insert-operation.lo \ libinftext_0_7_la-inf-text-move-operation.lo \ libinftext_0_7_la-inf-text-remote-delete-operation.lo \ libinftext_0_7_la-inf-text-session.lo \ libinftext_0_7_la-inf-text-undo-grouping.lo \ libinftext_0_7_la-inf-text-user.lo libinftext_0_7_la_OBJECTS = $(am_libinftext_0_7_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libinftext_0_7_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libinftext_0_7_la_LDFLAGS) $(LDFLAGS) \ -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) -I$(top_builddir)/libinfinity 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_CC_1 = 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_CCLD_1 = SOURCES = $(libinftext_0_7_la_SOURCES) DIST_SOURCES = $(libinftext_0_7_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(gir_DATA) $(typelib_DATA) HEADERS = $(libinftext_0_7_la_HEADERS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ 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@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIRNAME = @DATADIRNAME@ 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@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ GTKDOC_CHECK = @GTKDOC_CHECK@ GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ GTKDOC_MKPDF = @GTKDOC_MKPDF@ GTKDOC_REBASE = @GTKDOC_REBASE@ HTML_DIR = @HTML_DIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INSTOBJEXT = @INSTOBJEXT@ INTLLIBS = @INTLLIBS@ INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBINFINITY_API_VERSION = @LIBINFINITY_API_VERSION@ LIBINFINITY_LIBTOOL_VERSION = @LIBINFINITY_LIBTOOL_VERSION@ LIBINFINITY_VERSION = @LIBINFINITY_VERSION@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGFMT_OPTS = @MSGFMT_OPTS@ 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@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ 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@ avahi_CFLAGS = @avahi_CFLAGS@ avahi_LIBS = @avahi_LIBS@ 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@ gio_CFLAGS = @gio_CFLAGS@ gio_LIBS = @gio_LIBS@ gtk_requirement = @gtk_requirement@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infgtk_CFLAGS = @infgtk_CFLAGS@ infgtk_LIBS = @infgtk_LIBS@ infinity_CFLAGS = @infinity_CFLAGS@ infinity_LIBS = @infinity_LIBS@ infinoted_CFLAGS = @infinoted_CFLAGS@ infinoted_LIBS = @infinoted_LIBS@ infodir = @infodir@ inftext_CFLAGS = @inftext_CFLAGS@ inftext_LIBS = @inftext_LIBS@ inftextgtk_CFLAGS = @inftextgtk_CFLAGS@ inftextgtk_LIBS = @inftextgtk_LIBS@ install_sh = @install_sh@ libdaemon_CFLAGS = @libdaemon_CFLAGS@ libdaemon_LIBS = @libdaemon_LIBS@ 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@ runstatedir = @runstatedir@ 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@ # TODO: Find a way to have the version number set automatically. lib_LTLIBRARIES = libinftext-0.7.la libinftext_0_7_la_CPPFLAGS = \ -I$(top_srcdir) \ $(inftext_CFLAGS) \ $(infinity_CFLAGS) libinftext_0_7_la_LDFLAGS = \ -no-undefined \ -version-info $(LIBINFINITY_LIBTOOL_VERSION) libinftext_0_7_la_LIBADD = \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(inftext_LIBS) \ $(infinity_LIBS) libinftext_0_7_ladir = \ $(includedir)/libinftext-$(LIBINFINITY_API_VERSION)/libinftext libinftext_0_7_la_HEADERS = \ inf-text-buffer.h \ inf-text-chunk.h \ inf-text-default-buffer.h \ inf-text-default-delete-operation.h \ inf-text-default-insert-operation.h \ inf-text-delete-operation.h \ inf-text-filesystem-format.h \ inf-text-fixline-buffer.h \ inf-text-insert-operation.h \ inf-text-move-operation.h \ inf-text-operations.h \ inf-text-remote-delete-operation.h \ inf-text-session.h \ inf-text-undo-grouping.h \ inf-text-user.h libinftext_0_7_la_SOURCES = \ inf-text-buffer.c \ inf-text-chunk.c \ inf-text-default-buffer.c \ inf-text-default-delete-operation.c \ inf-text-default-insert-operation.c \ inf-text-delete-operation.c \ inf-text-filesystem-format.c \ inf-text-fixline-buffer.c \ inf-text-insert-operation.c \ inf-text-move-operation.c \ inf-text-remote-delete-operation.c \ inf-text-session.c \ inf-text-undo-grouping.c \ inf-text-user.c @HAVE_INTROSPECTION_TRUE@INTROSPECTION_GIRS = InfText-0.7.gir @HAVE_INTROSPECTION_TRUE@INTROSPECTION_SCANNER_ENV = CC="${CC}" @HAVE_INTROSPECTION_TRUE@INTROSPECTION_COMPILER_ARGS = \ @HAVE_INTROSPECTION_TRUE@ --includedir=${top_srcdir}/libinfinity \ @HAVE_INTROSPECTION_TRUE@ --includedir=${top_builddir}/libinfinity @HAVE_INTROSPECTION_TRUE@InfText_0_7_gir_SCANNERFLAGS = \ @HAVE_INTROSPECTION_TRUE@ -I${top_srcdir} \ @HAVE_INTROSPECTION_TRUE@ --add-include-path=$(top_srcdir)/libinfinity \ @HAVE_INTROSPECTION_TRUE@ --add-include-path=$(top_builddir)/libinfinity \ @HAVE_INTROSPECTION_TRUE@ -n InfText \ @HAVE_INTROSPECTION_TRUE@ --identifier-prefix=InfText @HAVE_INTROSPECTION_TRUE@InfText_0_7_gir_NAMESPACE = InfText @HAVE_INTROSPECTION_TRUE@InfText_0_7_gir_VERSION = 0.7 @HAVE_INTROSPECTION_TRUE@InfText_0_7_gir_CFLAGS = $(inftext_CFLAGS) $(infinity_CFLAGS) @HAVE_INTROSPECTION_TRUE@InfText_0_7_gir_LIBS = libinftext-0.7.la @HAVE_INTROSPECTION_TRUE@InfText_0_7_gir_FILES = \ @HAVE_INTROSPECTION_TRUE@ $(libinftext_0_7_la_SOURCES) \ @HAVE_INTROSPECTION_TRUE@ $(libinftext_0_7_la_HEADERS) @HAVE_INTROSPECTION_TRUE@InfText_0_7_gir_INCLUDES = Infinity-0.7 Infinityd-0.7 @HAVE_INTROSPECTION_TRUE@InfText_0_7_gir_PACKAGES = gobject-2.0 @HAVE_INTROSPECTION_TRUE@InfText_0_7_gir_EXPORT_PACKAGES = libinftext-0.7 @HAVE_INTROSPECTION_TRUE@girdir = $(datadir)/gir-1.0 @HAVE_INTROSPECTION_TRUE@gir_DATA = InfText-0.7.gir @HAVE_INTROSPECTION_TRUE@typelibdir = $(libdir)/girepository-1.0 @HAVE_INTROSPECTION_TRUE@typelib_DATA = InfText-0.7.typelib @HAVE_INTROSPECTION_TRUE@CLEANFILES = \ @HAVE_INTROSPECTION_TRUE@ $(gir_DATA) \ @HAVE_INTROSPECTION_TRUE@ $(typelib_DATA) all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(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) --foreign libinftext/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign libinftext/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: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libinftext-0.7.la: $(libinftext_0_7_la_OBJECTS) $(libinftext_0_7_la_DEPENDENCIES) $(EXTRA_libinftext_0_7_la_DEPENDENCIES) $(AM_V_CCLD)$(libinftext_0_7_la_LINK) -rpath $(libdir) $(libinftext_0_7_la_OBJECTS) $(libinftext_0_7_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libinftext_0_7_la-inf-text-buffer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libinftext_0_7_la-inf-text-chunk.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libinftext_0_7_la-inf-text-default-buffer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libinftext_0_7_la-inf-text-default-delete-operation.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libinftext_0_7_la-inf-text-default-insert-operation.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libinftext_0_7_la-inf-text-delete-operation.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libinftext_0_7_la-inf-text-filesystem-format.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libinftext_0_7_la-inf-text-fixline-buffer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libinftext_0_7_la-inf-text-insert-operation.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libinftext_0_7_la-inf-text-move-operation.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libinftext_0_7_la-inf-text-remote-delete-operation.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libinftext_0_7_la-inf-text-session.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libinftext_0_7_la-inf-text-undo-grouping.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libinftext_0_7_la-inf-text-user.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.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 -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.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 -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.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 $@ $< libinftext_0_7_la-inf-text-buffer.lo: inf-text-buffer.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinftext_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libinftext_0_7_la-inf-text-buffer.lo -MD -MP -MF $(DEPDIR)/libinftext_0_7_la-inf-text-buffer.Tpo -c -o libinftext_0_7_la-inf-text-buffer.lo `test -f 'inf-text-buffer.c' || echo '$(srcdir)/'`inf-text-buffer.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libinftext_0_7_la-inf-text-buffer.Tpo $(DEPDIR)/libinftext_0_7_la-inf-text-buffer.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='inf-text-buffer.c' object='libinftext_0_7_la-inf-text-buffer.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) $(libinftext_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libinftext_0_7_la-inf-text-buffer.lo `test -f 'inf-text-buffer.c' || echo '$(srcdir)/'`inf-text-buffer.c libinftext_0_7_la-inf-text-chunk.lo: inf-text-chunk.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinftext_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libinftext_0_7_la-inf-text-chunk.lo -MD -MP -MF $(DEPDIR)/libinftext_0_7_la-inf-text-chunk.Tpo -c -o libinftext_0_7_la-inf-text-chunk.lo `test -f 'inf-text-chunk.c' || echo '$(srcdir)/'`inf-text-chunk.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libinftext_0_7_la-inf-text-chunk.Tpo $(DEPDIR)/libinftext_0_7_la-inf-text-chunk.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='inf-text-chunk.c' object='libinftext_0_7_la-inf-text-chunk.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) $(libinftext_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libinftext_0_7_la-inf-text-chunk.lo `test -f 'inf-text-chunk.c' || echo '$(srcdir)/'`inf-text-chunk.c libinftext_0_7_la-inf-text-default-buffer.lo: inf-text-default-buffer.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinftext_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libinftext_0_7_la-inf-text-default-buffer.lo -MD -MP -MF $(DEPDIR)/libinftext_0_7_la-inf-text-default-buffer.Tpo -c -o libinftext_0_7_la-inf-text-default-buffer.lo `test -f 'inf-text-default-buffer.c' || echo '$(srcdir)/'`inf-text-default-buffer.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libinftext_0_7_la-inf-text-default-buffer.Tpo $(DEPDIR)/libinftext_0_7_la-inf-text-default-buffer.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='inf-text-default-buffer.c' object='libinftext_0_7_la-inf-text-default-buffer.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) $(libinftext_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libinftext_0_7_la-inf-text-default-buffer.lo `test -f 'inf-text-default-buffer.c' || echo '$(srcdir)/'`inf-text-default-buffer.c libinftext_0_7_la-inf-text-default-delete-operation.lo: inf-text-default-delete-operation.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinftext_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libinftext_0_7_la-inf-text-default-delete-operation.lo -MD -MP -MF $(DEPDIR)/libinftext_0_7_la-inf-text-default-delete-operation.Tpo -c -o libinftext_0_7_la-inf-text-default-delete-operation.lo `test -f 'inf-text-default-delete-operation.c' || echo '$(srcdir)/'`inf-text-default-delete-operation.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libinftext_0_7_la-inf-text-default-delete-operation.Tpo $(DEPDIR)/libinftext_0_7_la-inf-text-default-delete-operation.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='inf-text-default-delete-operation.c' object='libinftext_0_7_la-inf-text-default-delete-operation.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) $(libinftext_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libinftext_0_7_la-inf-text-default-delete-operation.lo `test -f 'inf-text-default-delete-operation.c' || echo '$(srcdir)/'`inf-text-default-delete-operation.c libinftext_0_7_la-inf-text-default-insert-operation.lo: inf-text-default-insert-operation.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinftext_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libinftext_0_7_la-inf-text-default-insert-operation.lo -MD -MP -MF $(DEPDIR)/libinftext_0_7_la-inf-text-default-insert-operation.Tpo -c -o libinftext_0_7_la-inf-text-default-insert-operation.lo `test -f 'inf-text-default-insert-operation.c' || echo '$(srcdir)/'`inf-text-default-insert-operation.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libinftext_0_7_la-inf-text-default-insert-operation.Tpo $(DEPDIR)/libinftext_0_7_la-inf-text-default-insert-operation.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='inf-text-default-insert-operation.c' object='libinftext_0_7_la-inf-text-default-insert-operation.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) $(libinftext_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libinftext_0_7_la-inf-text-default-insert-operation.lo `test -f 'inf-text-default-insert-operation.c' || echo '$(srcdir)/'`inf-text-default-insert-operation.c libinftext_0_7_la-inf-text-delete-operation.lo: inf-text-delete-operation.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinftext_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libinftext_0_7_la-inf-text-delete-operation.lo -MD -MP -MF $(DEPDIR)/libinftext_0_7_la-inf-text-delete-operation.Tpo -c -o libinftext_0_7_la-inf-text-delete-operation.lo `test -f 'inf-text-delete-operation.c' || echo '$(srcdir)/'`inf-text-delete-operation.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libinftext_0_7_la-inf-text-delete-operation.Tpo $(DEPDIR)/libinftext_0_7_la-inf-text-delete-operation.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='inf-text-delete-operation.c' object='libinftext_0_7_la-inf-text-delete-operation.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) $(libinftext_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libinftext_0_7_la-inf-text-delete-operation.lo `test -f 'inf-text-delete-operation.c' || echo '$(srcdir)/'`inf-text-delete-operation.c libinftext_0_7_la-inf-text-filesystem-format.lo: inf-text-filesystem-format.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinftext_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libinftext_0_7_la-inf-text-filesystem-format.lo -MD -MP -MF $(DEPDIR)/libinftext_0_7_la-inf-text-filesystem-format.Tpo -c -o libinftext_0_7_la-inf-text-filesystem-format.lo `test -f 'inf-text-filesystem-format.c' || echo '$(srcdir)/'`inf-text-filesystem-format.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libinftext_0_7_la-inf-text-filesystem-format.Tpo $(DEPDIR)/libinftext_0_7_la-inf-text-filesystem-format.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='inf-text-filesystem-format.c' object='libinftext_0_7_la-inf-text-filesystem-format.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) $(libinftext_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libinftext_0_7_la-inf-text-filesystem-format.lo `test -f 'inf-text-filesystem-format.c' || echo '$(srcdir)/'`inf-text-filesystem-format.c libinftext_0_7_la-inf-text-fixline-buffer.lo: inf-text-fixline-buffer.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinftext_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libinftext_0_7_la-inf-text-fixline-buffer.lo -MD -MP -MF $(DEPDIR)/libinftext_0_7_la-inf-text-fixline-buffer.Tpo -c -o libinftext_0_7_la-inf-text-fixline-buffer.lo `test -f 'inf-text-fixline-buffer.c' || echo '$(srcdir)/'`inf-text-fixline-buffer.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libinftext_0_7_la-inf-text-fixline-buffer.Tpo $(DEPDIR)/libinftext_0_7_la-inf-text-fixline-buffer.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='inf-text-fixline-buffer.c' object='libinftext_0_7_la-inf-text-fixline-buffer.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) $(libinftext_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libinftext_0_7_la-inf-text-fixline-buffer.lo `test -f 'inf-text-fixline-buffer.c' || echo '$(srcdir)/'`inf-text-fixline-buffer.c libinftext_0_7_la-inf-text-insert-operation.lo: inf-text-insert-operation.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinftext_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libinftext_0_7_la-inf-text-insert-operation.lo -MD -MP -MF $(DEPDIR)/libinftext_0_7_la-inf-text-insert-operation.Tpo -c -o libinftext_0_7_la-inf-text-insert-operation.lo `test -f 'inf-text-insert-operation.c' || echo '$(srcdir)/'`inf-text-insert-operation.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libinftext_0_7_la-inf-text-insert-operation.Tpo $(DEPDIR)/libinftext_0_7_la-inf-text-insert-operation.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='inf-text-insert-operation.c' object='libinftext_0_7_la-inf-text-insert-operation.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) $(libinftext_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libinftext_0_7_la-inf-text-insert-operation.lo `test -f 'inf-text-insert-operation.c' || echo '$(srcdir)/'`inf-text-insert-operation.c libinftext_0_7_la-inf-text-move-operation.lo: inf-text-move-operation.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinftext_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libinftext_0_7_la-inf-text-move-operation.lo -MD -MP -MF $(DEPDIR)/libinftext_0_7_la-inf-text-move-operation.Tpo -c -o libinftext_0_7_la-inf-text-move-operation.lo `test -f 'inf-text-move-operation.c' || echo '$(srcdir)/'`inf-text-move-operation.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libinftext_0_7_la-inf-text-move-operation.Tpo $(DEPDIR)/libinftext_0_7_la-inf-text-move-operation.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='inf-text-move-operation.c' object='libinftext_0_7_la-inf-text-move-operation.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) $(libinftext_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libinftext_0_7_la-inf-text-move-operation.lo `test -f 'inf-text-move-operation.c' || echo '$(srcdir)/'`inf-text-move-operation.c libinftext_0_7_la-inf-text-remote-delete-operation.lo: inf-text-remote-delete-operation.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinftext_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libinftext_0_7_la-inf-text-remote-delete-operation.lo -MD -MP -MF $(DEPDIR)/libinftext_0_7_la-inf-text-remote-delete-operation.Tpo -c -o libinftext_0_7_la-inf-text-remote-delete-operation.lo `test -f 'inf-text-remote-delete-operation.c' || echo '$(srcdir)/'`inf-text-remote-delete-operation.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libinftext_0_7_la-inf-text-remote-delete-operation.Tpo $(DEPDIR)/libinftext_0_7_la-inf-text-remote-delete-operation.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='inf-text-remote-delete-operation.c' object='libinftext_0_7_la-inf-text-remote-delete-operation.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) $(libinftext_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libinftext_0_7_la-inf-text-remote-delete-operation.lo `test -f 'inf-text-remote-delete-operation.c' || echo '$(srcdir)/'`inf-text-remote-delete-operation.c libinftext_0_7_la-inf-text-session.lo: inf-text-session.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinftext_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libinftext_0_7_la-inf-text-session.lo -MD -MP -MF $(DEPDIR)/libinftext_0_7_la-inf-text-session.Tpo -c -o libinftext_0_7_la-inf-text-session.lo `test -f 'inf-text-session.c' || echo '$(srcdir)/'`inf-text-session.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libinftext_0_7_la-inf-text-session.Tpo $(DEPDIR)/libinftext_0_7_la-inf-text-session.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='inf-text-session.c' object='libinftext_0_7_la-inf-text-session.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) $(libinftext_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libinftext_0_7_la-inf-text-session.lo `test -f 'inf-text-session.c' || echo '$(srcdir)/'`inf-text-session.c libinftext_0_7_la-inf-text-undo-grouping.lo: inf-text-undo-grouping.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinftext_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libinftext_0_7_la-inf-text-undo-grouping.lo -MD -MP -MF $(DEPDIR)/libinftext_0_7_la-inf-text-undo-grouping.Tpo -c -o libinftext_0_7_la-inf-text-undo-grouping.lo `test -f 'inf-text-undo-grouping.c' || echo '$(srcdir)/'`inf-text-undo-grouping.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libinftext_0_7_la-inf-text-undo-grouping.Tpo $(DEPDIR)/libinftext_0_7_la-inf-text-undo-grouping.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='inf-text-undo-grouping.c' object='libinftext_0_7_la-inf-text-undo-grouping.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) $(libinftext_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libinftext_0_7_la-inf-text-undo-grouping.lo `test -f 'inf-text-undo-grouping.c' || echo '$(srcdir)/'`inf-text-undo-grouping.c libinftext_0_7_la-inf-text-user.lo: inf-text-user.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinftext_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libinftext_0_7_la-inf-text-user.lo -MD -MP -MF $(DEPDIR)/libinftext_0_7_la-inf-text-user.Tpo -c -o libinftext_0_7_la-inf-text-user.lo `test -f 'inf-text-user.c' || echo '$(srcdir)/'`inf-text-user.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libinftext_0_7_la-inf-text-user.Tpo $(DEPDIR)/libinftext_0_7_la-inf-text-user.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='inf-text-user.c' object='libinftext_0_7_la-inf-text-user.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) $(libinftext_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libinftext_0_7_la-inf-text-user.lo `test -f 'inf-text-user.c' || echo '$(srcdir)/'`inf-text-user.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-girDATA: $(gir_DATA) @$(NORMAL_INSTALL) @list='$(gir_DATA)'; test -n "$(girdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(girdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(girdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(girdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(girdir)" || exit $$?; \ done uninstall-girDATA: @$(NORMAL_UNINSTALL) @list='$(gir_DATA)'; test -n "$(girdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(girdir)'; $(am__uninstall_files_from_dir) install-typelibDATA: $(typelib_DATA) @$(NORMAL_INSTALL) @list='$(typelib_DATA)'; test -n "$(typelibdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(typelibdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(typelibdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(typelibdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(typelibdir)" || exit $$?; \ done uninstall-typelibDATA: @$(NORMAL_UNINSTALL) @list='$(typelib_DATA)'; test -n "$(typelibdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(typelibdir)'; $(am__uninstall_files_from_dir) install-libinftext_0_7_laHEADERS: $(libinftext_0_7_la_HEADERS) @$(NORMAL_INSTALL) @list='$(libinftext_0_7_la_HEADERS)'; test -n "$(libinftext_0_7_ladir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libinftext_0_7_ladir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libinftext_0_7_ladir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libinftext_0_7_ladir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(libinftext_0_7_ladir)" || exit $$?; \ done uninstall-libinftext_0_7_laHEADERS: @$(NORMAL_UNINSTALL) @list='$(libinftext_0_7_la_HEADERS)'; test -n "$(libinftext_0_7_ladir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(libinftext_0_7_ladir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ 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-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ 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" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files 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: check-am all-am: Makefile $(LTLIBRARIES) $(DATA) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(girdir)" "$(DESTDIR)$(typelibdir)" "$(DESTDIR)$(libinftext_0_7_ladir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: 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." clean: clean-am clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ 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-girDATA install-libinftext_0_7_laHEADERS \ install-typelibDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-libLTLIBRARIES 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-girDATA uninstall-libLTLIBRARIES \ uninstall-libinftext_0_7_laHEADERS uninstall-typelibDATA .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libLTLIBRARIES clean-libtool cscopelist-am ctags \ ctags-am 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-girDATA install-html install-html-am \ install-info install-info-am install-libLTLIBRARIES \ install-libinftext_0_7_laHEADERS install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ install-typelibDATA installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \ uninstall-girDATA uninstall-libLTLIBRARIES \ uninstall-libinftext_0_7_laHEADERS uninstall-typelibDATA .PRECIOUS: Makefile @HAVE_INTROSPECTION_TRUE@-include $(INTROSPECTION_MAKEFILE) @HAVE_INTROSPECTION_TRUE@InfText-0.7.gir: libinftext-0.7.la # 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: libinfinity-0.7.1/libinftext/PaxHeaders.26529/inf-text-undo-grouping.h0000644000000000000000000000013213034342512022452 xustar0030 mtime=1483851082.049718536 30 atime=1483851082.049718536 30 ctime=1488261589.200138628 libinfinity-0.7.1/libinftext/inf-text-undo-grouping.h0000644000175000017500000000472613034342512023215 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_TEXT_UNDO_GROUPING_H__ #define __INF_TEXT_UNDO_GROUPING_H__ #include #include G_BEGIN_DECLS #define INF_TEXT_TYPE_UNDO_GROUPING (inf_text_undo_grouping_get_type()) #define INF_TEXT_UNDO_GROUPING(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_TEXT_TYPE_UNDO_GROUPING, InfTextUndoGrouping)) #define INF_TEXT_UNDO_GROUPING_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INF_TEXT_TYPE_UNDO_GROUPING, InfTextUndoGroupingClass)) #define INF_TEXT_IS_UNDO_GROUPING(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_TEXT_TYPE_UNDO_GROUPING)) #define INF_TEXT_IS_UNDO_GROUPING_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INF_TEXT_TYPE_UNDO_GROUPING)) #define INF_TEXT_UNDO_GROUPING_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INF_TEXT_TYPE_UNDO_GROUPING, InfTextUndoGroupingClass)) typedef struct _InfTextUndoGrouping InfTextUndoGrouping; typedef struct _InfTextUndoGroupingClass InfTextUndoGroupingClass; /** * InfATextUndoGroupingClass: * * This structure does not contain any public fields. */ struct _InfTextUndoGroupingClass { /*< private >*/ InfAdoptedUndoGroupingClass parent_class; }; /** * InfTextUndoGrouping: * * #InfTextUndoGrouping is an opaque data type. You should only access it via * the public API functions. */ struct _InfTextUndoGrouping { /*< private >*/ InfAdoptedUndoGrouping parent; }; GType inf_text_undo_grouping_get_type(void); InfTextUndoGrouping* inf_text_undo_grouping_new(void); G_END_DECLS #endif /* __INF_TEXT_UNDO_GROUPING_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinftext/PaxHeaders.26529/inf-text-fixline-buffer.c0000644000000000000000000000013213034342512022555 xustar0030 mtime=1483851082.045718513 30 atime=1483851082.045718513 30 ctime=1488261589.212138602 libinfinity-0.7.1/libinftext/inf-text-fixline-buffer.c0000644000175000017500000013752313034342512023322 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-text-fixline-buffer * @title: InfTextFixlineBuffer * @short_description: Keep a fixed number of trailing lines * @include: libinftext/inf-text-fixline-buffer.h * @see_also: #InfTextBuffer, #InfTextDefaultBuffer * @stability: Unstable * * This class is a wrapper around another #InfTextBuffer. It makes sure that * the number of trailing empty lines in the underlying buffer is always fixed * to a given number while it itself keeps track of the missing or additional * lines. This can be used for example to keep the number of empty lines * fixed on the client side even if lines are added and removed within a * text session. */ #include #include #include #include #include #include struct _InfTextBufferIter { InfTextBufferIter* base_iter; /* NULL base_iter means that keep_begin and keep_end are used */ guint keep_begin; guint keep_end; }; typedef struct _InfTextFixlineBufferPrivate InfTextFixlineBufferPrivate; struct _InfTextFixlineBufferPrivate { InfIo* io; InfTextBuffer* buffer; guint lines; /* base + n_keep == buffer */ guint* keep; gint n_keep; InfIoDispatch* dispatch; }; enum { PROP_0, /* overwritten */ PROP_MODIFIED, PROP_IO, PROP_BUFFER, PROP_LINES }; #define INF_TEXT_FIXLINE_BUFFER_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INF_TEXT_TYPE_FIXLINE_BUFFER, InfTextFixlineBufferPrivate)) static void inf_text_fixline_buffer_buffer_iface_init(InfBufferInterface* iface); static void inf_text_fixline_buffer_text_buffer_iface_init(InfTextBufferInterface* iface); G_DEFINE_TYPE_WITH_CODE(InfTextFixlineBuffer, inf_text_fixline_buffer, G_TYPE_OBJECT, G_ADD_PRIVATE(InfTextFixlineBuffer) G_IMPLEMENT_INTERFACE(INF_TYPE_BUFFER, inf_text_fixline_buffer_buffer_iface_init) G_IMPLEMENT_INTERFACE(INF_TEXT_TYPE_BUFFER, inf_text_fixline_buffer_text_buffer_iface_init)) /* Checks whether chunk consists only of newline characters */ static gboolean inf_text_fixline_buffer_chunk_only_newlines(InfTextChunk* chunk) { const gchar* text; gsize bytes; const gchar* end; gunichar c; /* TODO: Implement this properly with iconv */ g_assert(strcmp(inf_text_chunk_get_encoding(chunk), "UTF-8") == 0); text = inf_text_chunk_get_text(chunk, &bytes); end = text + bytes; while(text != end) { c = g_utf8_get_char(text); if(c != '\n') return FALSE; text = g_utf8_next_char(text); } return TRUE; } /* Adds len newlines into chunk at the given position */ static void inf_text_fixline_buffer_newlines_to_chunk(InfTextChunk* chunk, guint chunk_pos, guint len, guint user_id) { gchar stext[16]; gchar* text; guint i; if(len > sizeof(stext)) text = g_malloc(len * sizeof(gchar)); else text = stext; for(i = 0; i < len; ++i) text[i] = '\n'; /* TODO: Implement this properly with iconv */ g_assert(strcmp(inf_text_chunk_get_encoding(chunk), "UTF-8") == 0); inf_text_chunk_insert_text(chunk, chunk_pos, text, len, len, user_id); if(text != stext) g_free(text); } /* Count the number of trailing newlines in the buffer, but only check * up to the given position. Set min_check to 0 to check the whole buffer. */ static guint inf_text_fixline_buffer_buffer_count_trailing_newlines(InfTextBuffer* buffer, guint min_check) { InfTextBufferIter* iter; guint cur_pos; gchar* text; gchar* text_pos; gunichar c; /* TODO: Implement this properly with iconv */ g_assert(strcmp(inf_text_buffer_get_encoding(buffer), "UTF-8") == 0); iter = inf_text_buffer_create_end_iter(buffer); if(iter == NULL) return 0; cur_pos = inf_text_buffer_get_length(buffer); text = inf_text_buffer_iter_get_text(buffer, iter); text_pos = text + inf_text_buffer_iter_get_bytes(buffer, iter); for(cur_pos = inf_text_buffer_get_length(buffer); cur_pos > min_check; --cur_pos) { if(text_pos == text) { g_free(text); inf_text_buffer_iter_prev(buffer, iter); text = inf_text_buffer_iter_get_text(buffer, iter); text_pos = text + inf_text_buffer_iter_get_bytes(buffer, iter); } g_assert(text_pos > text); text_pos = g_utf8_prev_char(text_pos); c = g_utf8_get_char(text_pos); if(c != '\n') break; } g_free(text); inf_text_buffer_destroy_iter(buffer, iter); return inf_text_buffer_get_length(buffer) - cur_pos; } /* Checks whether the given buffer contains only newline characters * after the given position */ static gboolean inf_text_fixline_buffer_buffer_only_newlines_after(InfTextBuffer* buffer, guint pos) { guint new_lines; new_lines = inf_text_fixline_buffer_buffer_count_trailing_newlines( buffer, pos ); if(inf_text_buffer_get_length(buffer) - new_lines <= pos) return TRUE; return FALSE; } /* advance to next author in keep */ static guint inf_text_fixline_buffer_keep_next(const guint* keep, guint n_keep, guint pos) { guint new_author; g_assert(pos < n_keep); new_author = keep[pos++]; while(pos < n_keep && keep[pos] == new_author) ++pos; return pos; } /* advance to previous author in keep */ static guint inf_text_fixline_buffer_keep_prev(const guint* keep, guint n_keep, guint pos) { guint new_author; g_assert(pos > 0); new_author = keep[--pos]; while(pos > 0 && keep[pos-1] == new_author) --pos; return pos; } /* Fills a part of the keep from a chunk */ static void inf_text_fixline_buffer_chunk_to_keep(InfTextFixlineBuffer* fixline_buffer, InfTextChunk* chunk, guint chunk_pos, guint keep_pos, guint len) { InfTextFixlineBufferPrivate* priv; InfTextChunkIter iter; gboolean result; guint offset; guint i; priv = INF_TEXT_FIXLINE_BUFFER_PRIVATE(fixline_buffer); g_assert(priv->n_keep > 0); g_assert(keep_pos + len <= (guint)priv->n_keep); g_assert(chunk_pos + len <= inf_text_chunk_get_length(chunk)); g_assert(chunk_pos == 0); /* TODO: Lift this restriction */ offset = 0; result = inf_text_chunk_iter_init_begin(chunk, &iter); g_assert(result == TRUE || len == 0); for(i = 0; i < len; ++i) { g_assert(i - offset <= inf_text_chunk_iter_get_length(&iter)); if(i - offset == inf_text_chunk_iter_get_length(&iter)) { offset = i; result = inf_text_chunk_iter_next(&iter); g_assert(result == TRUE); } g_assert(inf_text_chunk_iter_get_length(&iter) > 0); priv->keep[keep_pos + i] = inf_text_chunk_iter_get_author(&iter); } } /* Insert into a chunk from the keep */ static void inf_text_fixline_buffer_keep_to_chunk(InfTextFixlineBuffer* fixline_buffer, InfTextChunk* chunk, guint chunk_pos, guint keep_pos, guint len) { InfTextFixlineBufferPrivate* priv; guint i; priv = INF_TEXT_FIXLINE_BUFFER_PRIVATE(fixline_buffer); g_assert(priv->n_keep > 0); g_assert(keep_pos + len <= (guint)priv->n_keep); g_assert(chunk_pos <= inf_text_chunk_get_length(chunk)); /* TODO: Implement this properly with iconv */ g_assert(strcmp(inf_text_chunk_get_encoding(chunk), "UTF-8") == 0); /* TODO: merge for adjacent users, so we * have fewer calls to inf_text_chunk_insert_text */ for(i = 0; i < len; ++i) { inf_text_chunk_insert_text( chunk, chunk_pos + i, "\n", 1, 1, priv->keep[keep_pos + i] ); } } static void inf_text_fixline_buffer_text_inserted_cb(InfTextBuffer* buffer, guint pos, InfTextChunk* chunk, InfUser* user, gpointer user_data); static void inf_text_fixline_buffer_text_erased_cb(InfTextBuffer* buffer, guint pos, InfTextChunk* chunk, InfUser* user, gpointer user_data); /* Move some newlines from the keep to the base buffer */ static void inf_text_fixline_buffer_keep_to_base(InfTextFixlineBuffer* fixline_buffer, guint len) { InfTextFixlineBufferPrivate* priv; InfTextChunk* chunk; guint keep_len; priv = INF_TEXT_FIXLINE_BUFFER_PRIVATE(fixline_buffer); chunk = inf_text_chunk_new(inf_text_buffer_get_encoding(priv->buffer)); if(priv->n_keep > 0) { keep_len = MIN( (guint)priv->n_keep, len); inf_text_fixline_buffer_keep_to_chunk( fixline_buffer, chunk, 0, 0, keep_len ); if(keep_len < priv->n_keep) { g_memmove( priv->keep, priv->keep + keep_len, (priv->n_keep - keep_len) * sizeof(guint) ); priv->keep = g_realloc( priv->keep, (priv->n_keep - keep_len) * sizeof(guint) ); } else { g_free(priv->keep); priv->keep = NULL; } priv->n_keep -= keep_len; len -= keep_len; } if(len > 0) { g_assert(priv->n_keep <= 0); inf_text_fixline_buffer_newlines_to_chunk( chunk, inf_text_chunk_get_length(chunk), len, 0 ); priv->n_keep -= (gint)len; } inf_signal_handlers_block_by_func( priv->buffer, G_CALLBACK(inf_text_fixline_buffer_text_inserted_cb), fixline_buffer ); inf_text_buffer_insert_chunk( priv->buffer, inf_text_buffer_get_length(priv->buffer), chunk, NULL ); inf_signal_handlers_unblock_by_func( priv->buffer, G_CALLBACK(inf_text_fixline_buffer_text_inserted_cb), fixline_buffer ); inf_text_chunk_free(chunk); } /* Move some newlines from the base buffer to the keep */ static void inf_text_fixline_buffer_base_to_keep(InfTextFixlineBuffer* fixline_buffer, guint len) { InfTextFixlineBufferPrivate* priv; guint use_keep; guint remaining_len; InfTextBufferIter* iter; guint iter_offset; guint iter_pos; gboolean iter_result; guint keep_len; guint keep_index; guint keep_author; guint i; priv = INF_TEXT_FIXLINE_BUFFER_PRIVATE(fixline_buffer); g_assert(inf_text_buffer_get_length(priv->buffer) >= len); if(priv->n_keep < 0) { use_keep = MIN( (guint)(-priv->n_keep), len); priv->n_keep = -(gint)((guint)(-priv->n_keep) - use_keep); remaining_len = len - use_keep; } else { remaining_len = len; } if(remaining_len > 0) { g_assert(priv->n_keep >= 0); iter = inf_text_buffer_create_end_iter(priv->buffer); g_assert(iter != NULL); iter_pos = 0; iter_offset = inf_text_buffer_iter_get_length(priv->buffer, iter); /* Go back len - remaining_len characters from the end of the buffer. * These characters are in the represented buffer already since we had * negative keeps for them */ while(iter_pos < len - remaining_len) { if(iter_offset <= len - remaining_len) { iter_pos = iter_offset; iter_result = inf_text_buffer_iter_prev(priv->buffer, iter); g_assert(iter_result == TRUE); iter_offset += inf_text_buffer_iter_get_length(priv->buffer, iter); } else { iter_pos = (len - remaining_len); } } /* Now, from here, move remaining_len characters into the keep */ priv->keep = g_realloc( priv->keep, (priv->n_keep + remaining_len) * sizeof(guint) ); g_memmove( priv->keep + remaining_len, priv->keep, priv->n_keep * sizeof(guint) ); while(iter_pos < len) { keep_author = inf_text_buffer_iter_get_author(priv->buffer, iter); keep_index = len - iter_pos; if(iter_offset <= len) { keep_len = iter_offset - iter_pos; iter_pos = iter_offset; iter_result = inf_text_buffer_iter_prev(priv->buffer, iter); g_assert(iter_result == TRUE); iter_offset += inf_text_buffer_iter_get_length(priv->buffer, iter); } else { keep_len = len - iter_pos; iter_pos = len; } for(i = 0; i < keep_len; ++i) priv->keep[keep_index - 1 - i] = keep_author; } inf_text_buffer_destroy_iter(priv->buffer, iter); priv->n_keep += remaining_len; } /* The keep is now updated, we can go ahead and make the change to the * base buffer now */ inf_signal_handlers_block_by_func( priv->buffer, G_CALLBACK(inf_text_fixline_buffer_text_erased_cb), fixline_buffer ); inf_text_buffer_erase_text( priv->buffer, inf_text_buffer_get_length(priv->buffer) - len, len, NULL ); inf_signal_handlers_unblock_by_func( priv->buffer, G_CALLBACK(inf_text_fixline_buffer_text_erased_cb), fixline_buffer ); } static void inf_text_fixline_buffer_fix_lines(InfTextFixlineBuffer* fixline_buffer) { InfTextFixlineBufferPrivate* priv; guint count; priv = INF_TEXT_FIXLINE_BUFFER_PRIVATE(fixline_buffer); count = inf_text_fixline_buffer_buffer_count_trailing_newlines( priv->buffer, 0 ); if(count < priv->lines) { inf_text_fixline_buffer_keep_to_base(fixline_buffer, priv->lines - count); } else if(count > priv->lines) { inf_text_fixline_buffer_base_to_keep(fixline_buffer, count - priv->lines); } } static void inf_text_fixline_buffer_dispatch_func(gpointer user_data) { InfTextFixlineBuffer* fixline_buffer; InfTextFixlineBufferPrivate* priv; fixline_buffer = INF_TEXT_FIXLINE_BUFFER(user_data); priv = INF_TEXT_FIXLINE_BUFFER_PRIVATE(fixline_buffer); g_assert(priv->dispatch != NULL); priv->dispatch = NULL; inf_text_fixline_buffer_fix_lines(fixline_buffer); } static void inf_text_fixline_buffer_text_inserted_cb(InfTextBuffer* buffer, guint pos, InfTextChunk* chunk, InfUser* user, gpointer user_data) { InfTextFixlineBufferPrivate* priv; guint chunk_length; guint buffer_length; guint end; guint user_pos; gint user_len; InfTextChunk* new_chunk; priv = INF_TEXT_FIXLINE_BUFFER_PRIVATE(user_data); chunk_length = inf_text_chunk_get_length(chunk); g_assert(inf_text_buffer_get_length(buffer) >= chunk_length); /* Note that this is the buffer length before the operation */ buffer_length = inf_text_buffer_get_length(buffer) - chunk_length; g_assert(priv->n_keep > 0 || buffer_length >= (guint)(-priv->n_keep)); /* This is now the end of the infinote buffer */ end = buffer_length + priv->n_keep; if(inf_text_fixline_buffer_chunk_only_newlines(chunk) && inf_text_fixline_buffer_buffer_only_newlines_after(buffer, pos + chunk_length)) { /* Newlines were inserted at the end of the buffer. Don't propagate. * Note that this step is optional, we could also propagate it to the * infinote buffer, but it might lead to a strange user experience */ /* TODO: In principle we have to re-brand some * of the newlines inside the buffer here: */ #if 0 for(i = 0; i < inf_text_buffer_get_length(buffer) - inf_text_chunk_get_length(chunk) - pos; ++i) author(i + pos) = author(i + pos + inf_text_chunk_get_length(chunk)) if(priv->n_keep > 0) for(i = 0; i < priv->n_keep && i < inf_text_chunk_get_length(chunk); ++i) author(i + pos + inf_text_chunk_get_length(chunk)) = priv->keep[i]; #endif /* remove the used keeps */ if(priv->n_keep > 0 && inf_text_chunk_get_length(chunk) > (guint)priv->n_keep) priv->n_keep = -(int)(inf_text_chunk_get_length(chunk) - priv->n_keep); else priv->n_keep = priv->n_keep - inf_text_chunk_get_length(chunk); if(priv->n_keep > 0) { g_memmove( priv->keep, priv->keep + inf_text_chunk_get_length(chunk), priv->n_keep * sizeof(guint) ); priv->keep = g_realloc(priv->keep, priv->n_keep * sizeof(guint)); } else { g_free(priv->keep); priv->keep = NULL; } /* TODO: We don't know whether this was an insert-caret or not, but * assume for now that it was. Advance the user's caret, which would * account for the added newlines that we swallowed above. */ /* TODO: A better way might be to just skip this special handling * altogether and just actually propagate this change. */ user_pos = inf_text_user_get_caret_position(INF_TEXT_USER(user)); user_len = inf_text_user_get_selection_length(INF_TEXT_USER(user)); inf_text_move_operation_transform_insert( pos, chunk_length, &user_pos, &user_len, FALSE ); inf_text_user_set_selection( INF_TEXT_USER(user), user_pos, user_len, TRUE ); } else { if(pos > end) { /* TODO: Should we handle caret updates here as well? */ g_assert(priv->n_keep < 0); g_assert((guint)(-priv->n_keep) >= pos - end); /* We remove the first pos - end keeps and prepend them to the text */ priv->n_keep += (pos - end); new_chunk = inf_text_chunk_copy(chunk); inf_text_fixline_buffer_newlines_to_chunk( new_chunk, 0, pos - end, user == NULL ? 0 : inf_user_get_id(user) ); inf_text_buffer_text_inserted( INF_TEXT_BUFFER(user_data), end, new_chunk, user ); inf_text_chunk_free(new_chunk); } else { /* Just propagate */ inf_text_buffer_text_inserted( INF_TEXT_BUFFER(user_data), pos, chunk, user ); } } /* Schedule a dispatch to correct the number of newlines in the underlying * buffer. */ if(priv->dispatch == NULL) { priv->dispatch = inf_io_add_dispatch( priv->io, inf_text_fixline_buffer_dispatch_func, user_data, NULL ); } } static void inf_text_fixline_buffer_text_erased_cb(InfTextBuffer* buffer, guint pos, InfTextChunk* chunk, InfUser* user, gpointer user_data) { InfTextFixlineBufferPrivate* priv; guint chunk_length; guint buffer_length; guint end; guint use_keep; InfTextChunk* new_chunk; guint user_pos; gint user_len; priv = INF_TEXT_FIXLINE_BUFFER_PRIVATE(user_data); chunk_length = inf_text_chunk_get_length(chunk); buffer_length = inf_text_buffer_get_length(buffer) + chunk_length; g_assert(priv->n_keep > 0 || buffer_length >= (guint)(-priv->n_keep)); end = buffer_length + priv->n_keep; /* buffer_length: length of base buffer before the operation * end: length of buffer before the operation */ if(inf_text_fixline_buffer_chunk_only_newlines(chunk) && inf_text_fixline_buffer_buffer_only_newlines_after(buffer, pos)) { /* Newlines were removed from the end of the buffer. Don't propagate. * Note that this step is optional, we could also propagate it to the * infinote buffer, but it might lead to a strange user experience */ /* TODO: In principle we have to re-brand some * of the newlines inside the buffer here: */ #if 0 for(i = pos; i < inf_text_buffer_get_length(buffer); ++i) rebrand(i); #endif if(priv->n_keep > 0) use_keep = inf_text_chunk_get_length(chunk); else if((guint)(-priv->n_keep) < inf_text_chunk_get_length(chunk)) use_keep = inf_text_chunk_get_length(chunk) - (guint)(-priv->n_keep); else use_keep = 0; priv->n_keep += inf_text_chunk_get_length(chunk); if(priv->n_keep > 0) { g_assert( priv->keep == NULL || (guint)priv->n_keep > inf_text_chunk_get_length(chunk) ); priv->keep = g_realloc(priv->keep, priv->n_keep * sizeof(guint)); if((guint)priv->n_keep > inf_text_chunk_get_length(chunk)) { g_memmove( priv->keep + inf_text_chunk_get_length(chunk), priv->keep, (priv->n_keep - inf_text_chunk_get_length(chunk)) * sizeof(guint) ); } inf_text_fixline_buffer_chunk_to_keep( INF_TEXT_FIXLINE_BUFFER(user_data), chunk, 0, 0, use_keep ); } /* TODO: We don't know whether this was an erase-caret or not, but * assume for now that it was. Advance the user's caret, which would * account for the removed newlines that we swallowed above. */ /* TODO: A better way might be to just skip this special handling * altogether and just actually propagate this change. */ user_pos = inf_text_user_get_caret_position(INF_TEXT_USER(user)); user_len = inf_text_user_get_selection_length(INF_TEXT_USER(user)); inf_text_move_operation_transform_delete( pos, chunk_length, &user_pos, &user_len ); inf_text_user_set_selection( INF_TEXT_USER(user), user_pos, user_len, TRUE ); } else { if(pos > end) { g_assert(priv->n_keep < 0); /* only keep modifications. We could handle it in principle, but it * should not happen, since the keep stores only newline characters, * in which case we would have ended up in the case above. */ g_assert_not_reached(); } else if(pos + chunk_length > end) { /* Propagate partly */ /* TODO: Should we handle caret updates here as well? */ g_assert(priv->n_keep < 0); g_assert(chunk_length - (end - pos) <= (guint)(-priv->n_keep)); priv->n_keep += (chunk_length - (end - pos)); new_chunk = inf_text_chunk_copy(chunk); inf_text_chunk_erase(new_chunk, end - pos, chunk_length - (end - pos)); inf_text_buffer_text_erased( INF_TEXT_BUFFER(user_data), pos, new_chunk, user ); inf_text_chunk_free(new_chunk); } else { /* Propagate fully */ inf_text_buffer_text_erased( INF_TEXT_BUFFER(user_data), pos, chunk, user ); } } /* sanity check */ g_assert( priv->n_keep > 0 || inf_text_buffer_get_length(buffer) >= (guint)(-priv->n_keep) ); /* Schedule a dispatch to correct the number of newlines in the underlying * buffer. */ if(priv->dispatch == NULL) { priv->dispatch = inf_io_add_dispatch( priv->io, inf_text_fixline_buffer_dispatch_func, user_data, NULL ); } } static void inf_text_fixline_buffer_init(InfTextFixlineBuffer* fixline_buffer) { InfTextFixlineBufferPrivate* priv; priv = INF_TEXT_FIXLINE_BUFFER_PRIVATE(fixline_buffer); priv->io = NULL; priv->buffer = NULL; priv->lines = 0; priv->keep = NULL; priv->n_keep = 0; priv->dispatch = NULL; } static void inf_text_fixline_buffer_constructed(GObject* object) { InfTextFixlineBuffer* fixline_buffer; InfTextFixlineBufferPrivate* priv; fixline_buffer = INF_TEXT_FIXLINE_BUFFER(object); priv = INF_TEXT_FIXLINE_BUFFER_PRIVATE(fixline_buffer); /* Keep the number of lines at the end fixed */ inf_text_fixline_buffer_fix_lines(fixline_buffer); } static void inf_text_fixline_buffer_dispose(GObject* object) { InfTextFixlineBuffer* fixline_buffer; InfTextFixlineBufferPrivate* priv; fixline_buffer = INF_TEXT_FIXLINE_BUFFER(object); priv = INF_TEXT_FIXLINE_BUFFER_PRIVATE(fixline_buffer); if(priv->buffer != NULL) { inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->buffer), G_CALLBACK(inf_text_fixline_buffer_text_inserted_cb), fixline_buffer ); inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->buffer), G_CALLBACK(inf_text_fixline_buffer_text_erased_cb), fixline_buffer ); g_object_unref(priv->buffer); priv->buffer = NULL; } if(priv->io != NULL) { if(priv->dispatch != NULL) { inf_io_remove_dispatch(priv->io, priv->dispatch); priv->dispatch = NULL; } g_object_unref(priv->io); priv->io = NULL; } G_OBJECT_CLASS(inf_text_fixline_buffer_parent_class)->dispose(object); } static void inf_text_fixline_buffer_finalize(GObject* object) { InfTextFixlineBuffer* fixline_buffer; InfTextFixlineBufferPrivate* priv; fixline_buffer = INF_TEXT_FIXLINE_BUFFER(object); priv = INF_TEXT_FIXLINE_BUFFER_PRIVATE(fixline_buffer); g_free(priv->keep); G_OBJECT_CLASS(inf_text_fixline_buffer_parent_class)->finalize(object); } static void inf_text_fixline_buffer_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfTextFixlineBuffer* fixline_buffer; InfTextFixlineBufferPrivate* priv; gboolean modified; fixline_buffer = INF_TEXT_FIXLINE_BUFFER(object); priv = INF_TEXT_FIXLINE_BUFFER_PRIVATE(fixline_buffer); switch(prop_id) { case PROP_IO: /* construct only */ g_assert(priv->io == NULL); priv->io = INF_IO(g_value_dup_object(value)); break; case PROP_BUFFER: /* construct only */ g_assert(priv->buffer == NULL); priv->buffer = INF_TEXT_BUFFER(g_value_dup_object(value)); g_signal_connect( G_OBJECT(priv->buffer), "text-inserted", G_CALLBACK(inf_text_fixline_buffer_text_inserted_cb), fixline_buffer ); g_signal_connect( G_OBJECT(priv->buffer), "text-erased", G_CALLBACK(inf_text_fixline_buffer_text_erased_cb), fixline_buffer ); break; case PROP_LINES: /* construct only */ g_assert(priv->lines == 0); priv->lines = g_value_get_uint(value); break; case PROP_MODIFIED: inf_buffer_set_modified( INF_BUFFER(priv->buffer), g_value_get_boolean(value) ); break; fixline: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void inf_text_fixline_buffer_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfTextFixlineBuffer* fixline_buffer; InfTextFixlineBufferPrivate* priv; gboolean modified; fixline_buffer = INF_TEXT_FIXLINE_BUFFER(object); priv = INF_TEXT_FIXLINE_BUFFER_PRIVATE(fixline_buffer); switch(prop_id) { case PROP_IO: g_value_set_object(value, priv->io); break; case PROP_BUFFER: g_value_set_object(value, priv->buffer); break; case PROP_LINES: g_value_set_uint(value, priv->lines); break; case PROP_MODIFIED: g_value_set_boolean( value, inf_buffer_get_modified(INF_BUFFER(priv->buffer)) ); break; fixline: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static gboolean inf_text_fixline_buffer_buffer_get_modified(InfBuffer* buffer) { InfTextFixlineBuffer* fixline_buffer; InfTextFixlineBufferPrivate* priv; fixline_buffer = INF_TEXT_FIXLINE_BUFFER(buffer); priv = INF_TEXT_FIXLINE_BUFFER_PRIVATE(fixline_buffer); return inf_buffer_get_modified(INF_BUFFER(priv->buffer)); } static void inf_text_fixline_buffer_buffer_set_modified(InfBuffer* buffer, gboolean modified) { InfTextFixlineBuffer* fixline_buffer; InfTextFixlineBufferPrivate* priv; fixline_buffer = INF_TEXT_FIXLINE_BUFFER(buffer); priv = INF_TEXT_FIXLINE_BUFFER_PRIVATE(fixline_buffer); inf_buffer_set_modified(INF_BUFFER(priv->buffer), modified); } static const gchar* inf_text_fixline_buffer_buffer_get_encoding(InfTextBuffer* buffer) { InfTextFixlineBuffer* fixline_buffer; InfTextFixlineBufferPrivate* priv; fixline_buffer = INF_TEXT_FIXLINE_BUFFER(buffer); priv = INF_TEXT_FIXLINE_BUFFER_PRIVATE(fixline_buffer); return inf_text_buffer_get_encoding(priv->buffer); } static guint inf_text_fixline_buffer_get_length(InfTextBuffer* buffer) { InfTextFixlineBuffer* fixline_buffer; InfTextFixlineBufferPrivate* priv; guint buf_len; fixline_buffer = INF_TEXT_FIXLINE_BUFFER(buffer); priv = INF_TEXT_FIXLINE_BUFFER_PRIVATE(fixline_buffer); buf_len = inf_text_buffer_get_length(priv->buffer); g_assert(priv->n_keep > 0 || buf_len >= (guint)(-priv->n_keep)); return buf_len + priv->n_keep; } static InfTextChunk* inf_text_fixline_buffer_buffer_get_slice(InfTextBuffer* buffer, guint pos, guint len) { InfTextFixlineBuffer* fixline_buffer; InfTextFixlineBufferPrivate* priv; guint buf_len; guint keep_begin; InfTextChunk* chunk; guint i; fixline_buffer = INF_TEXT_FIXLINE_BUFFER(buffer); priv = INF_TEXT_FIXLINE_BUFFER_PRIVATE(fixline_buffer); buf_len = inf_text_buffer_get_length(priv->buffer); if(pos + len > buf_len) { g_assert(priv->n_keep > 0); if(pos < buf_len) { chunk = inf_text_buffer_get_slice(priv->buffer, pos, buf_len - pos); inf_text_fixline_buffer_keep_to_chunk( fixline_buffer, chunk, inf_text_chunk_get_length(chunk), 0, pos + len - buf_len ); } else { chunk = inf_text_chunk_new(inf_text_buffer_get_encoding(priv->buffer)); inf_text_fixline_buffer_keep_to_chunk( fixline_buffer, chunk, 0, pos - buf_len, len ); } } else { chunk = inf_text_buffer_get_slice(priv->buffer, pos, len); } return chunk; } static void inf_text_fixline_buffer_buffer_insert_text(InfTextBuffer* buffer, guint pos, InfTextChunk* chunk, InfUser* user) { InfTextFixlineBuffer* fixline_buffer; InfTextFixlineBufferPrivate* priv; guint buf_len; InfTextChunk* new_chunk; fixline_buffer = INF_TEXT_FIXLINE_BUFFER(buffer); priv = INF_TEXT_FIXLINE_BUFFER_PRIVATE(fixline_buffer); buf_len = inf_text_buffer_get_length(priv->buffer); inf_signal_handlers_block_by_func( priv->buffer, G_CALLBACK(inf_text_fixline_buffer_text_inserted_cb), fixline_buffer ); if(pos >= buf_len && inf_text_fixline_buffer_chunk_only_newlines(chunk)) { /* Add the added newlines only to the keep */ g_assert(priv->n_keep >= 0); g_assert(pos - buf_len <= (guint)priv->n_keep); priv->keep = g_realloc( priv->keep, (priv->n_keep + inf_text_chunk_get_length(chunk)) * sizeof(guint) ); if(pos - buf_len < priv->n_keep) { g_memmove( priv->keep + (pos - buf_len + inf_text_chunk_get_length(chunk)), priv->keep + (pos - buf_len), priv->n_keep - (pos - buf_len) ); } priv->n_keep += inf_text_chunk_get_length(chunk); inf_text_fixline_buffer_chunk_to_keep( fixline_buffer, chunk, 0, pos - buf_len, inf_text_chunk_get_length(chunk) ); } else if(pos > buf_len) { g_assert(priv->n_keep > 0); g_assert((guint)priv->n_keep >= pos - buf_len); new_chunk = inf_text_chunk_copy(chunk); inf_text_fixline_buffer_keep_to_chunk( fixline_buffer, new_chunk, 0, 0, pos - buf_len ); g_memmove( priv->keep, priv->keep + (pos - buf_len), ((guint)priv->n_keep - (pos - buf_len)) * sizeof(guint) ); priv->keep = g_realloc( priv->keep, ((guint)priv->n_keep - (pos - buf_len)) * sizeof(guint) ); priv->n_keep -= (pos - buf_len); inf_text_buffer_insert_chunk(priv->buffer, buf_len, new_chunk, user); inf_text_chunk_free(new_chunk); } else { inf_text_buffer_insert_chunk(priv->buffer, pos, chunk, user); } inf_signal_handlers_unblock_by_func( priv->buffer, G_CALLBACK(inf_text_fixline_buffer_text_inserted_cb), fixline_buffer ); /* Notify */ inf_text_buffer_text_inserted(buffer, pos, chunk, user); /* Keep the number of lines at the end fixed */ inf_text_fixline_buffer_fix_lines(fixline_buffer); } static void inf_text_fixline_buffer_buffer_erase_text(InfTextBuffer* buffer, guint pos, guint len, InfUser* user) { InfTextFixlineBuffer* fixline_buffer; InfTextFixlineBufferPrivate* priv; InfTextChunk* erased_content; guint buf_len; fixline_buffer = INF_TEXT_FIXLINE_BUFFER(buffer); priv = INF_TEXT_FIXLINE_BUFFER_PRIVATE(fixline_buffer); buf_len = inf_text_buffer_get_length(priv->buffer); inf_signal_handlers_block_by_func( priv->buffer, G_CALLBACK(inf_text_fixline_buffer_text_erased_cb), fixline_buffer ); erased_content = inf_text_buffer_get_slice(buffer, pos, len); if(pos + len > buf_len) { if(pos > buf_len) { /* Only erase in the keep */ g_assert(priv->n_keep > 0); g_assert((guint)priv->n_keep >= len); g_assert(pos + len - buf_len <= (guint)priv->n_keep); if(pos + len - buf_len < (guint)priv->n_keep) { g_memmove( priv->keep + (pos - buf_len), priv->keep + (pos + len - buf_len), (priv->n_keep - (pos + len - buf_len)) * sizeof(guint) ); } priv->keep = g_realloc( priv->keep, (priv->n_keep - len) * sizeof(guint) ); priv->n_keep -= len; } else { g_assert(priv->n_keep > 0); g_assert(pos + len - buf_len <= (guint)priv->n_keep); if(pos + len - buf_len < (guint)priv->n_keep) { g_memmove( priv->keep, priv->keep + (pos + len - buf_len), (priv->n_keep - (pos + len - buf_len)) * sizeof(guint) ); } priv->keep = g_realloc( priv->keep, (priv->n_keep - (pos + len - buf_len)) * sizeof(guint) ); priv->n_keep -= (pos + len - buf_len); inf_text_buffer_erase_text(priv->buffer, pos, buf_len - pos, user); } } else { inf_text_buffer_erase_text(priv->buffer, pos, len, user); } inf_signal_handlers_unblock_by_func( priv->buffer, G_CALLBACK(inf_text_fixline_buffer_text_erased_cb), fixline_buffer ); /* Notify */ inf_text_buffer_text_erased(buffer, pos, erased_content, user); inf_text_chunk_free(erased_content); /* Keep the number of lines at the end fixed */ inf_text_fixline_buffer_fix_lines(fixline_buffer); } static InfTextBufferIter* inf_text_fixline_buffer_buffer_create_begin_iter(InfTextBuffer* buffer) { InfTextFixlineBuffer* fixline_buffer; InfTextFixlineBufferPrivate* priv; InfTextBufferIter* base_iter; InfTextBufferIter* iter; fixline_buffer = INF_TEXT_FIXLINE_BUFFER(buffer); priv = INF_TEXT_FIXLINE_BUFFER_PRIVATE(fixline_buffer); if(priv->n_keep <= 0 && inf_text_buffer_get_length(priv->buffer) == (guint)(-priv->n_keep)) { return NULL; } base_iter = inf_text_buffer_create_begin_iter(priv->buffer); if(base_iter == NULL) { g_assert(priv->n_keep > 0); iter = g_slice_new(InfTextBufferIter); iter->base_iter = NULL; iter->keep_begin = 0; iter->keep_end = inf_text_fixline_buffer_keep_next( priv->keep, priv->n_keep, 0 ); } else { iter = g_slice_new(InfTextBufferIter); iter->base_iter = base_iter; } return iter; } static InfTextBufferIter* inf_text_fixline_buffer_buffer_create_end_iter(InfTextBuffer* buffer) { InfTextFixlineBuffer* fixline_buffer; InfTextFixlineBufferPrivate* priv; InfTextBufferIter* iter; InfTextBufferIter* base_iter; guint buf_len; gboolean result; fixline_buffer = INF_TEXT_FIXLINE_BUFFER(buffer); priv = INF_TEXT_FIXLINE_BUFFER_PRIVATE(fixline_buffer); buf_len = inf_text_buffer_get_length(priv->buffer); if(priv->n_keep > 0) { iter = g_slice_new(InfTextBufferIter); iter->base_iter = NULL; iter->keep_end = priv->n_keep; iter->keep_begin = inf_text_fixline_buffer_keep_prev( priv->keep, priv->n_keep, priv->n_keep ); } else { if(buf_len == (guint)(-priv->n_keep)) return NULL; base_iter = inf_text_buffer_create_end_iter(priv->buffer); g_assert(base_iter != NULL); while(inf_text_buffer_iter_get_offset(priv->buffer, base_iter) >= buf_len - (guint)(-priv->n_keep)) { result = inf_text_buffer_iter_prev(priv->buffer, base_iter); g_assert(result == TRUE); } iter = g_slice_new(InfTextBufferIter); iter->base_iter = base_iter; } return iter; } static void inf_text_fixline_buffer_buffer_destroy_iter(InfTextBuffer* buffer, InfTextBufferIter* iter) { InfTextFixlineBuffer* fixline_buffer; InfTextFixlineBufferPrivate* priv; fixline_buffer = INF_TEXT_FIXLINE_BUFFER(buffer); priv = INF_TEXT_FIXLINE_BUFFER_PRIVATE(fixline_buffer); if(iter->base_iter != NULL) inf_text_buffer_destroy_iter(priv->buffer, iter->base_iter); g_slice_free(InfTextBufferIter, iter); } static gboolean inf_text_fixline_buffer_buffer_iter_next(InfTextBuffer* buffer, InfTextBufferIter* iter) { InfTextFixlineBuffer* fixline_buffer; InfTextFixlineBufferPrivate* priv; guint offset; guint length; guint buf_len; fixline_buffer = INF_TEXT_FIXLINE_BUFFER(buffer); priv = INF_TEXT_FIXLINE_BUFFER_PRIVATE(fixline_buffer); if(iter->base_iter == NULL) { g_assert(priv->n_keep > 0); /* Move inside keep */ if(iter->keep_end == priv->n_keep) return FALSE; iter->keep_begin = iter->keep_end; iter->keep_end = inf_text_fixline_buffer_keep_next( priv->keep, priv->n_keep, iter->keep_end ); return TRUE; } else if(priv->n_keep > 0) { /* Try to advance; if not possible: move to keep */ if(inf_text_buffer_iter_next(priv->buffer, iter->base_iter) == TRUE) return TRUE; inf_text_buffer_destroy_iter(priv->buffer, iter->base_iter); iter->base_iter = NULL; iter->keep_begin = 0; iter->keep_end = inf_text_fixline_buffer_keep_next( priv->keep, priv->n_keep, 0 ); return TRUE; } else { offset = inf_text_buffer_iter_get_offset(priv->buffer, iter->base_iter); length = inf_text_buffer_iter_get_length(priv->buffer, iter->base_iter); buf_len = inf_text_buffer_get_length(priv->buffer); if(offset + length >= buf_len - (guint)(-priv->n_keep)) return FALSE; return inf_text_buffer_iter_next(priv->buffer, iter->base_iter); } } static gboolean inf_text_fixline_buffer_buffer_iter_prev(InfTextBuffer* buffer, InfTextBufferIter* iter) { InfTextFixlineBuffer* fixline_buffer; InfTextFixlineBufferPrivate* priv; fixline_buffer = INF_TEXT_FIXLINE_BUFFER(buffer); priv = INF_TEXT_FIXLINE_BUFFER_PRIVATE(fixline_buffer); if(iter->base_iter == NULL) { g_assert(priv->n_keep > 0); if(iter->keep_begin == 0) { iter->base_iter = inf_text_buffer_create_end_iter(priv->buffer); if(iter->base_iter == NULL) return FALSE; return TRUE; } else { iter->keep_end = iter->keep_begin; iter->keep_begin = inf_text_fixline_buffer_keep_next( priv->keep, priv->n_keep, iter->keep_begin ); return TRUE; } } else { return inf_text_buffer_iter_prev(priv->buffer, iter->base_iter); } } static gpointer inf_text_fixline_buffer_buffer_iter_get_text(InfTextBuffer* buffer, InfTextBufferIter* iter) { InfTextFixlineBuffer* fixline_buffer; InfTextFixlineBufferPrivate* priv; gpointer text; guint i; fixline_buffer = INF_TEXT_FIXLINE_BUFFER(buffer); priv = INF_TEXT_FIXLINE_BUFFER_PRIVATE(fixline_buffer); if(iter->base_iter == NULL) { /* TODO: This only works for UTF-8 encoding: */ g_assert(iter->keep_end > iter->keep_begin); text = g_malloc(iter->keep_end - iter->keep_begin); for(i = 0; i < iter->keep_end - iter->keep_begin; ++i) ((gchar*)text)[i] = '\n'; return text; } else { text = inf_text_buffer_iter_get_text(priv->buffer, iter->base_iter); /* TODO: We could cut away the end here with a g_realloc, but it's not * really necessary. */ return text; } } static guint inf_text_fixline_buffer_buffer_iter_get_offset(InfTextBuffer* buffer, InfTextBufferIter* iter) { InfTextFixlineBuffer* fixline_buffer; InfTextFixlineBufferPrivate* priv; fixline_buffer = INF_TEXT_FIXLINE_BUFFER(buffer); priv = INF_TEXT_FIXLINE_BUFFER_PRIVATE(fixline_buffer); if(iter->base_iter == NULL) { return inf_text_buffer_get_length(priv->buffer) + iter->keep_begin; } else { return inf_text_buffer_iter_get_offset(priv->buffer, iter->base_iter); } } static guint inf_text_fixline_buffer_buffer_iter_get_length(InfTextBuffer* buffer, InfTextBufferIter* iter) { InfTextFixlineBuffer* fixline_buffer; InfTextFixlineBufferPrivate* priv; guint length; guint offset; guint buf_len; fixline_buffer = INF_TEXT_FIXLINE_BUFFER(buffer); priv = INF_TEXT_FIXLINE_BUFFER_PRIVATE(fixline_buffer); if(iter->base_iter == NULL) { return iter->keep_end - iter->keep_begin; } else { length = inf_text_buffer_iter_get_length(priv->buffer, iter->base_iter); if(priv->n_keep >= 0) return length; buf_len = inf_text_buffer_get_length(priv->buffer); offset = inf_text_buffer_iter_get_offset(priv->buffer, iter->base_iter); g_assert(offset + length <= buf_len); if(offset + length > buf_len - (guint)(-priv->n_keep)) { return length - (buf_len - (guint)(-priv->n_keep) - offset); } else { return length; } } } static gsize inf_text_fixline_buffer_buffer_iter_get_bytes(InfTextBuffer* buffer, InfTextBufferIter* iter) { InfTextFixlineBuffer* fixline_buffer; InfTextFixlineBufferPrivate* priv; gsize bytes; guint length; guint offset; guint buf_len; guint extra_chars; fixline_buffer = INF_TEXT_FIXLINE_BUFFER(buffer); priv = INF_TEXT_FIXLINE_BUFFER_PRIVATE(fixline_buffer); if(iter->base_iter == NULL) { /* TODO: This assumes encoding is UTF-8: */ return iter->keep_end - iter->keep_begin; } else { bytes = inf_text_buffer_iter_get_bytes(priv->buffer, iter->base_iter); if(priv->n_keep >= 0) return bytes; length = inf_text_buffer_iter_get_length(priv->buffer, iter->base_iter); offset = inf_text_buffer_iter_get_offset(priv->buffer, iter->base_iter); buf_len = inf_text_buffer_get_length(priv->buffer); g_assert(offset + length <= buf_len); if(offset + length > buf_len - (guint)(-priv->n_keep)) { extra_chars = (buf_len - (guint)(-priv->n_keep) - offset); /* TODO: This assumes encoding is UTF-8: */ return bytes - extra_chars; } else { return bytes; } } } static guint inf_text_fixline_buffer_buffer_iter_get_author(InfTextBuffer* buffer, InfTextBufferIter* iter) { InfTextFixlineBuffer* fixline_buffer; InfTextFixlineBufferPrivate* priv; gsize bytes; guint length; guint offset; guint buf_len; guint extra_chars; fixline_buffer = INF_TEXT_FIXLINE_BUFFER(buffer); priv = INF_TEXT_FIXLINE_BUFFER_PRIVATE(fixline_buffer); if(iter->base_iter == NULL) { g_assert(priv->n_keep > 0); g_assert(iter->keep_begin < (guint)priv->n_keep); return priv->keep[iter->keep_begin]; } else { return inf_text_buffer_iter_get_author(priv->buffer, iter->base_iter); } } static void inf_text_fixline_buffer_class_init( InfTextFixlineBufferClass* fixline_buffer_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(fixline_buffer_class); object_class->constructed = inf_text_fixline_buffer_constructed; object_class->dispose = inf_text_fixline_buffer_dispose; object_class->finalize = inf_text_fixline_buffer_finalize; object_class->set_property = inf_text_fixline_buffer_set_property; object_class->get_property = inf_text_fixline_buffer_get_property; g_object_class_override_property(object_class, PROP_MODIFIED, "modified"); g_object_class_install_property( object_class, PROP_IO, g_param_spec_object( "io", "IO", "The I/O object used to schedule line keeping", INF_TYPE_IO, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_BUFFER, g_param_spec_object( "buffer", "Buffer", "The buffer for which to keep a fixed line count", INF_TEXT_TYPE_BUFFER, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_LINES, g_param_spec_uint( "lines", "lines", "The number of lines to keep in the underlying buffer", 0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); } static void inf_text_fixline_buffer_buffer_iface_init(InfBufferInterface* iface) { iface->get_modified = inf_text_fixline_buffer_buffer_get_modified; iface->set_modified = inf_text_fixline_buffer_buffer_set_modified; } static void inf_text_fixline_buffer_text_buffer_iface_init(InfTextBufferInterface* iface) { iface->get_encoding = inf_text_fixline_buffer_buffer_get_encoding; iface->get_length = inf_text_fixline_buffer_get_length; iface->get_slice = inf_text_fixline_buffer_buffer_get_slice; iface->insert_text = inf_text_fixline_buffer_buffer_insert_text; iface->erase_text = inf_text_fixline_buffer_buffer_erase_text; iface->create_begin_iter = inf_text_fixline_buffer_buffer_create_begin_iter; iface->create_end_iter = inf_text_fixline_buffer_buffer_create_end_iter; iface->destroy_iter = inf_text_fixline_buffer_buffer_destroy_iter; iface->iter_next = inf_text_fixline_buffer_buffer_iter_next; iface->iter_prev = inf_text_fixline_buffer_buffer_iter_prev; iface->iter_get_text = inf_text_fixline_buffer_buffer_iter_get_text; iface->iter_get_offset = inf_text_fixline_buffer_buffer_iter_get_offset; iface->iter_get_length = inf_text_fixline_buffer_buffer_iter_get_length; iface->iter_get_bytes = inf_text_fixline_buffer_buffer_iter_get_bytes; iface->iter_get_author = inf_text_fixline_buffer_buffer_iter_get_author; iface->text_inserted = NULL; iface->text_erased = NULL; } /** * inf_text_fixline_buffer_new: (constructor) * @io: A #InfIo object to schedule timeouts. * @buffer: The underlying buffer for which to keep a fixed line count. * @n_lines: The number of lines to be kept fixed. * * Creates a new #InfTextFixlineBuffer which keeps the number of trailing * lines of the given underlying buffer fixed to @n_lines. * * Returns: (transfer full): A #InfTextFixlineBuffer. **/ InfTextFixlineBuffer* inf_text_fixline_buffer_new(InfIo* io, InfTextBuffer* buffer, guint n_lines) { GObject* object; object = g_object_new( INF_TEXT_TYPE_FIXLINE_BUFFER, "io", io, "buffer", buffer, "lines", n_lines, NULL ); return INF_TEXT_FIXLINE_BUFFER(object); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinftext/PaxHeaders.26529/inf-text-default-delete-operation.c0000644000000000000000000000013213034342512024532 xustar0030 mtime=1483851082.045718513 30 atime=1483851082.045718513 30 ctime=1488261589.208138611 libinfinity-0.7.1/libinftext/inf-text-default-delete-operation.c0000644000175000017500000003551613034342512025276 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include #include /* Don't check text match in stable releases */ /* #define DELETE_OPERATION_CHECK_TEXT_MATCH */ typedef struct _InfTextDefaultDeleteOperationPrivate InfTextDefaultDeleteOperationPrivate; struct _InfTextDefaultDeleteOperationPrivate { guint position; InfTextChunk* chunk; }; enum { PROP_0, PROP_POSITION, PROP_CHUNK }; #define INF_TEXT_DEFAULT_DELETE_OPERATION_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INF_TEXT_TYPE_DEFAULT_DELETE_OPERATION, InfTextDefaultDeleteOperationPrivate)) static void inf_text_default_delete_operation_operation_iface_init(InfAdoptedOperationInterface* iface); static void inf_text_default_delete_operation_delete_operation_iface_init(InfTextDeleteOperationInterface* iface); G_DEFINE_TYPE_WITH_CODE(InfTextDefaultDeleteOperation, inf_text_default_delete_operation, G_TYPE_OBJECT, G_ADD_PRIVATE(InfTextDefaultDeleteOperation) G_IMPLEMENT_INTERFACE(INF_ADOPTED_TYPE_OPERATION, inf_text_default_delete_operation_operation_iface_init) G_IMPLEMENT_INTERFACE(INF_TEXT_TYPE_DELETE_OPERATION, inf_text_default_delete_operation_delete_operation_iface_init)) #ifdef DELETE_OPERATION_CHECK_TEXT_MATCH static gboolean inf_text_default_delete_operation_text_match( InfTextDefaultDeleteOperation* operation, InfTextBuffer* buffer) { InfTextDefaultDeleteOperationPrivate* priv; InfTextChunk* chunk; gchar* first; gchar* second; gsize first_len; gsize second_len; int result; priv = INF_TEXT_DEFAULT_DELETE_OPERATION_PRIVATE(operation); /* TODO: inf_text_chunk_cmp_substring */ chunk = inf_text_buffer_get_slice( buffer, priv->position, inf_text_chunk_get_length(priv->chunk) ); first = inf_text_chunk_get_text(priv->chunk, &first_len); second = inf_text_chunk_get_text(chunk, &second_len); inf_text_chunk_free(chunk); /* TODO: Owners must match, too */ if(first_len == second_len) result = memcmp(first, second, first_len); else result = 1; /* != 0 */ g_free(second); g_free(first); return result == 0; } #endif /* DELETE_OPERATION_CHECK_TEXT_MATCH */ static void inf_text_default_delete_operation_init( InfTextDefaultDeleteOperation* operation) { InfTextDefaultDeleteOperationPrivate* priv; priv = INF_TEXT_DEFAULT_DELETE_OPERATION_PRIVATE(operation); priv->position = 0; priv->chunk = NULL; } static void inf_text_default_delete_operation_finalize(GObject* object) { InfTextDefaultDeleteOperation* operation; InfTextDefaultDeleteOperationPrivate* priv; operation = INF_TEXT_DEFAULT_DELETE_OPERATION(object); priv = INF_TEXT_DEFAULT_DELETE_OPERATION_PRIVATE(operation); inf_text_chunk_free(priv->chunk); G_OBJECT_CLASS(inf_text_default_delete_operation_parent_class)->finalize(object); } static void inf_text_default_delete_operation_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfTextDefaultDeleteOperation* operation; InfTextDefaultDeleteOperationPrivate* priv; operation = INF_TEXT_DEFAULT_DELETE_OPERATION(object); priv = INF_TEXT_DEFAULT_DELETE_OPERATION_PRIVATE(operation); switch(prop_id) { case PROP_POSITION: priv->position = g_value_get_uint(value); break; case PROP_CHUNK: g_assert(priv->chunk == NULL); /* construct only */ priv->chunk = (InfTextChunk*)g_value_dup_boxed(value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void inf_text_default_delete_operation_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfTextDefaultDeleteOperation* operation; InfTextDefaultDeleteOperationPrivate* priv; operation = INF_TEXT_DEFAULT_DELETE_OPERATION(object); priv = INF_TEXT_DEFAULT_DELETE_OPERATION_PRIVATE(operation); switch(prop_id) { case PROP_POSITION: g_value_set_uint(value, priv->position); break; case PROP_CHUNK: g_value_set_boxed(value, priv->chunk); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static gboolean inf_text_default_delete_operation_need_concurrency_id( InfAdoptedOperation* operation, InfAdoptedOperation* against) { g_assert(INF_TEXT_IS_DEFAULT_DELETE_OPERATION(operation)); return inf_text_delete_operation_need_concurrency_id( INF_TEXT_DELETE_OPERATION(operation), against ); } static InfAdoptedOperation* inf_text_default_delete_operation_transform(InfAdoptedOperation* operation, InfAdoptedOperation* against, InfAdoptedOperation* op_lcs, InfAdoptedOperation* against_lcs, InfAdoptedConcurrencyId cid) { g_assert(INF_TEXT_IS_DEFAULT_DELETE_OPERATION(operation)); if(INF_TEXT_IS_INSERT_OPERATION(against)) { return inf_text_delete_operation_transform_insert( INF_TEXT_DELETE_OPERATION(operation), INF_TEXT_INSERT_OPERATION(against) ); } else if(INF_TEXT_IS_DELETE_OPERATION(against)) { return inf_text_delete_operation_transform_delete( INF_TEXT_DELETE_OPERATION(operation), INF_TEXT_DELETE_OPERATION(against) ); } else { g_assert_not_reached(); return NULL; } } static InfAdoptedOperation* inf_text_default_delete_operation_copy(InfAdoptedOperation* operation) { InfTextDefaultDeleteOperationPrivate* priv; priv = INF_TEXT_DEFAULT_DELETE_OPERATION_PRIVATE(operation); return INF_ADOPTED_OPERATION( g_object_new( INF_TEXT_TYPE_DEFAULT_DELETE_OPERATION, "position", priv->position, "chunk", priv->chunk, NULL ) ); } static InfAdoptedOperationFlags inf_text_default_delete_operation_get_flags(InfAdoptedOperation* operation) { return INF_ADOPTED_OPERATION_AFFECTS_BUFFER | INF_ADOPTED_OPERATION_REVERSIBLE; } static gboolean inf_text_default_delete_operation_apply(InfAdoptedOperation* operation, InfAdoptedUser* by, InfBuffer* buffer, GError** error) { InfTextDefaultDeleteOperationPrivate* priv; g_assert(INF_TEXT_IS_DEFAULT_DELETE_OPERATION(operation)); g_assert(INF_TEXT_IS_BUFFER(buffer)); priv = INF_TEXT_DEFAULT_DELETE_OPERATION_PRIVATE(operation); #ifdef DELETE_OPERATION_CHECK_TEXT_MATCH g_assert( inf_text_default_delete_operation_text_match( INF_TEXT_DEFAULT_DELETE_OPERATION(operation), INF_TEXT_BUFFER(buffer) ) ); #endif /* DELETE_OPERATION_CHECK_TEXT_MATCH */ if(priv->position + inf_text_chunk_get_length(priv->chunk) > inf_text_buffer_get_length(INF_TEXT_BUFFER(buffer))) { g_set_error_literal( error, g_quark_from_static_string("INF_TEXT_OPERATION_ERROR"), INF_TEXT_OPERATION_ERROR_INVALID_DELETE, _("Attempt to remove text from after the end of the document") ); return FALSE; } else { inf_text_buffer_erase_text( INF_TEXT_BUFFER(buffer), priv->position, inf_text_chunk_get_length(priv->chunk), INF_USER(by) ); return TRUE; } } static InfAdoptedOperation* inf_text_default_delete_operation_revert(InfAdoptedOperation* operation) { InfTextDefaultDeleteOperationPrivate* priv; priv = INF_TEXT_DEFAULT_DELETE_OPERATION_PRIVATE(operation); return INF_ADOPTED_OPERATION( inf_text_default_insert_operation_new( priv->position, priv->chunk ) ); } static guint inf_text_default_delete_operation_get_position( InfTextDeleteOperation* operation) { return INF_TEXT_DEFAULT_DELETE_OPERATION_PRIVATE(operation)->position; } static guint inf_text_default_delete_operation_get_length( InfTextDeleteOperation* operation) { return inf_text_chunk_get_length( INF_TEXT_DEFAULT_DELETE_OPERATION_PRIVATE(operation)->chunk ); } static InfTextDeleteOperation* inf_text_default_delete_operation_transform_position( InfTextDeleteOperation* operation, guint position) { InfTextDefaultDeleteOperationPrivate* priv; priv = INF_TEXT_DEFAULT_DELETE_OPERATION_PRIVATE(operation); return INF_TEXT_DELETE_OPERATION( g_object_new( INF_TEXT_TYPE_DEFAULT_DELETE_OPERATION, "position", position, "chunk", priv->chunk, NULL ) ); } static InfTextDeleteOperation* inf_text_default_delete_operation_transform_overlap( InfTextDeleteOperation* operation, InfTextDeleteOperation* other, guint position, guint begin, guint other_begin, guint length) { InfTextDefaultDeleteOperationPrivate* priv; InfTextChunk* chunk; GObject* result; priv = INF_TEXT_DEFAULT_DELETE_OPERATION_PRIVATE(operation); chunk = inf_text_chunk_copy(priv->chunk); inf_text_chunk_erase(chunk, begin, length); result = g_object_new( INF_TEXT_TYPE_DEFAULT_DELETE_OPERATION, "position", position, "chunk", chunk, NULL ); inf_text_chunk_free(chunk); return INF_TEXT_DELETE_OPERATION(result); } static InfAdoptedSplitOperation* inf_text_default_delete_operation_transform_split( InfTextDeleteOperation* operation, guint split_pos, guint split_len) { InfTextDefaultDeleteOperationPrivate* priv; InfTextChunk* first_chunk; InfTextChunk* second_chunk; GObject* first; GObject* second; InfAdoptedSplitOperation* result; priv = INF_TEXT_DEFAULT_DELETE_OPERATION_PRIVATE(operation); first_chunk = inf_text_chunk_substring(priv->chunk, 0, split_pos); second_chunk = inf_text_chunk_substring( priv->chunk, split_pos, inf_text_chunk_get_length(priv->chunk) - split_pos ); first = g_object_new( INF_TEXT_TYPE_DEFAULT_DELETE_OPERATION, "position", priv->position, "chunk", first_chunk, NULL ); second = g_object_new( INF_TEXT_TYPE_DEFAULT_DELETE_OPERATION, "position", priv->position + split_len, "chunk", second_chunk, NULL ); inf_text_chunk_free(first_chunk); inf_text_chunk_free(second_chunk); result = inf_adopted_split_operation_new( INF_ADOPTED_OPERATION(first), INF_ADOPTED_OPERATION(second) ); g_object_unref(first); g_object_unref(second); return result; } static void inf_text_default_delete_operation_class_init( InfTextDefaultDeleteOperationClass* default_delete_operation_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(default_delete_operation_class); object_class->finalize = inf_text_default_delete_operation_finalize; object_class->set_property = inf_text_default_delete_operation_set_property; object_class->get_property = inf_text_default_delete_operation_get_property; g_object_class_install_property( object_class, PROP_POSITION, g_param_spec_uint( "position", "Position", "Position where to start deleting characters", 0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_CHUNK, g_param_spec_boxed( "chunk", "Chunk", "The deleted text", INF_TEXT_TYPE_CHUNK, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); } static void inf_text_default_delete_operation_operation_iface_init( InfAdoptedOperationInterface* iface) { iface->need_concurrency_id = inf_text_default_delete_operation_need_concurrency_id; iface->transform = inf_text_default_delete_operation_transform; iface->copy = inf_text_default_delete_operation_copy; iface->get_flags = inf_text_default_delete_operation_get_flags; iface->apply = inf_text_default_delete_operation_apply; iface->apply_transformed = NULL; iface->revert = inf_text_default_delete_operation_revert; } static void inf_text_default_delete_operation_delete_operation_iface_init( InfTextDeleteOperationInterface* iface) { iface->get_position = inf_text_default_delete_operation_get_position; iface->get_length = inf_text_default_delete_operation_get_length; iface->transform_position = inf_text_default_delete_operation_transform_position; iface->transform_overlap = inf_text_default_delete_operation_transform_overlap; iface->transform_split = inf_text_default_delete_operation_transform_split; } /** * inf_text_default_delete_operation_new: (constructor) * @position: The position at which to delete text. * @chunk: The text to delete. * * Creates a new delete operation that, when applied, deletes the text @chunk * that starts at character offset @position in the buffer. The operation * cannot be applied, if there is some other text at that position in the * buffer. * * Returns: (transfer full): A new #InfTextDefaultDeleteOperation. **/ InfTextDefaultDeleteOperation* inf_text_default_delete_operation_new(guint position, InfTextChunk* chunk) { GObject* object; g_return_val_if_fail(chunk != NULL, NULL); object = g_object_new( INF_TEXT_TYPE_DEFAULT_DELETE_OPERATION, "position", position, "chunk", chunk, NULL ); return INF_TEXT_DEFAULT_DELETE_OPERATION(object); } /** * inf_text_default_delete_operation_get_chunk: * @operation: A #InfTextDefaultDeleteOperation. * * Returns the text deleted by @operation. * * Returns: (transfer none): A #InfTextChunk, owned by the operation. **/ InfTextChunk* inf_text_default_delete_operation_get_chunk( InfTextDefaultDeleteOperation* operation) { g_return_val_if_fail(INF_TEXT_IS_DEFAULT_DELETE_OPERATION(operation), NULL); return INF_TEXT_DEFAULT_DELETE_OPERATION_PRIVATE(operation)->chunk; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinftext/PaxHeaders.26529/Makefile.am0000644000000000000000000000013213034544714020014 xustar0030 mtime=1483917772.686920573 30 atime=1483917772.686920573 30 ctime=1488261589.180138672 libinfinity-0.7.1/libinftext/Makefile.am0000644000175000017500000000466113034544714020555 0ustar00arminarmin00000000000000# TODO: Find a way to have the version number set automatically. lib_LTLIBRARIES = libinftext-0.7.la libinftext_0_7_la_CPPFLAGS = \ -I$(top_srcdir) \ $(inftext_CFLAGS) \ $(infinity_CFLAGS) libinftext_0_7_la_LDFLAGS = \ -no-undefined \ -version-info $(LIBINFINITY_LIBTOOL_VERSION) libinftext_0_7_la_LIBADD = \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(inftext_LIBS) \ $(infinity_LIBS) libinftext_0_7_ladir = \ $(includedir)/libinftext-$(LIBINFINITY_API_VERSION)/libinftext libinftext_0_7_la_HEADERS = \ inf-text-buffer.h \ inf-text-chunk.h \ inf-text-default-buffer.h \ inf-text-default-delete-operation.h \ inf-text-default-insert-operation.h \ inf-text-delete-operation.h \ inf-text-filesystem-format.h \ inf-text-fixline-buffer.h \ inf-text-insert-operation.h \ inf-text-move-operation.h \ inf-text-operations.h \ inf-text-remote-delete-operation.h \ inf-text-session.h \ inf-text-undo-grouping.h \ inf-text-user.h libinftext_0_7_la_SOURCES = \ inf-text-buffer.c \ inf-text-chunk.c \ inf-text-default-buffer.c \ inf-text-default-delete-operation.c \ inf-text-default-insert-operation.c \ inf-text-delete-operation.c \ inf-text-filesystem-format.c \ inf-text-fixline-buffer.c \ inf-text-insert-operation.c \ inf-text-move-operation.c \ inf-text-remote-delete-operation.c \ inf-text-session.c \ inf-text-undo-grouping.c \ inf-text-user.c if HAVE_INTROSPECTION -include $(INTROSPECTION_MAKEFILE) INTROSPECTION_GIRS = InfText-0.7.gir INTROSPECTION_SCANNER_ENV = CC="${CC}" INTROSPECTION_COMPILER_ARGS = \ --includedir=${top_srcdir}/libinfinity \ --includedir=${top_builddir}/libinfinity InfText-0.7.gir: libinftext-0.7.la InfText_0_7_gir_SCANNERFLAGS = \ -I${top_srcdir} \ --add-include-path=$(top_srcdir)/libinfinity \ --add-include-path=$(top_builddir)/libinfinity \ -n InfText \ --identifier-prefix=InfText InfText_0_7_gir_NAMESPACE = InfText InfText_0_7_gir_VERSION = 0.7 InfText_0_7_gir_CFLAGS = $(inftext_CFLAGS) $(infinity_CFLAGS) InfText_0_7_gir_LIBS = libinftext-0.7.la InfText_0_7_gir_FILES = \ $(libinftext_0_7_la_SOURCES) \ $(libinftext_0_7_la_HEADERS) InfText_0_7_gir_INCLUDES = Infinity-0.7 Infinityd-0.7 InfText_0_7_gir_PACKAGES = gobject-2.0 InfText_0_7_gir_EXPORT_PACKAGES = libinftext-0.7 girdir = $(datadir)/gir-1.0 gir_DATA = InfText-0.7.gir typelibdir = $(libdir)/girepository-1.0 typelib_DATA = InfText-0.7.typelib CLEANFILES = \ $(gir_DATA) \ $(typelib_DATA) endif libinfinity-0.7.1/libinftext/PaxHeaders.26529/inf-text-chunk.h0000644000000000000000000000013213034342512020765 xustar0030 mtime=1483851082.045718513 30 atime=1483851082.045718513 30 ctime=1488261589.184138663 libinfinity-0.7.1/libinftext/inf-text-chunk.h0000644000175000017500000000767313034342512021534 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_TEXT_CHUNK_H__ #define __INF_TEXT_CHUNK_H__ #include #include G_BEGIN_DECLS #define INF_TEXT_TYPE_CHUNK_ITER (inf_text_chunk_iter_get_type()) #define INF_TEXT_TYPE_CHUNK (inf_text_chunk_get_type()) /** * InfTextChunk: * * #InfTextChunk is an opaque data type. You should only access it * via the public API functions. */ typedef struct _InfTextChunk InfTextChunk; /** * InfTextChunkIter: * * #InfTextChunkIter is an opaque data type. You should only access it * via the public API functions. * * #InfTextChunkIter can be safely allocated on the stack and copied by value. * Use inf_text_chunk_iter_init_begin() or inf_text_chunk_iter_init_end() to * initialize a #InfTextChunkIter. There is no deinitialization required. A * #InfTextChunkIter is valid as long as the chunk is not modified. */ typedef struct _InfTextChunkIter InfTextChunkIter; struct _InfTextChunkIter { /*< private >*/ InfTextChunk* chunk; GSequenceIter* first; GSequenceIter* second; }; GType inf_text_chunk_iter_get_type(void) G_GNUC_CONST; GType inf_text_chunk_get_type(void) G_GNUC_CONST; InfTextChunkIter* inf_text_chunk_iter_copy(const InfTextChunkIter* iter); void inf_text_chunk_iter_free(InfTextChunkIter* iter); InfTextChunk* inf_text_chunk_new(const gchar* encoding); InfTextChunk* inf_text_chunk_copy(InfTextChunk* self); void inf_text_chunk_free(InfTextChunk* self); const gchar* inf_text_chunk_get_encoding(InfTextChunk* self); guint inf_text_chunk_get_length(InfTextChunk* self); InfTextChunk* inf_text_chunk_substring(InfTextChunk* self, guint begin, guint length); void inf_text_chunk_insert_text(InfTextChunk* self, guint offset, gconstpointer text, gsize bytes, guint length, guint author); void inf_text_chunk_insert_chunk(InfTextChunk* self, guint offset, InfTextChunk* text); void inf_text_chunk_erase(InfTextChunk* self, guint begin, guint length); gpointer inf_text_chunk_get_text(InfTextChunk* self, gsize* length); gboolean inf_text_chunk_equal(InfTextChunk* self, InfTextChunk* other); gboolean inf_text_chunk_iter_init_begin(InfTextChunk* self, InfTextChunkIter* iter); gboolean inf_text_chunk_iter_init_end(InfTextChunk* self, InfTextChunkIter* iter); gboolean inf_text_chunk_iter_next(InfTextChunkIter* iter); gboolean inf_text_chunk_iter_prev(InfTextChunkIter* iter); gconstpointer inf_text_chunk_iter_get_text(InfTextChunkIter* iter); guint inf_text_chunk_iter_get_offset(InfTextChunkIter* iter); guint inf_text_chunk_iter_get_length(InfTextChunkIter* iter); gsize inf_text_chunk_iter_get_bytes(InfTextChunkIter* iter); guint inf_text_chunk_iter_get_author(InfTextChunkIter* iter); G_END_DECLS #endif /* __INF_TEXT_CHUNK_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinftext/PaxHeaders.26529/inf-text-user.c0000644000000000000000000000013213034342512020626 xustar0030 mtime=1483851082.049718536 30 atime=1483851082.049718536 30 ctime=1488261589.224138575 libinfinity-0.7.1/libinftext/inf-text-user.c0000644000175000017500000002012513034342512021360 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include typedef struct _InfTextUserPrivate InfTextUserPrivate; struct _InfTextUserPrivate { guint caret; gint selection; gdouble hue; }; enum { PROP_0, PROP_CARET, PROP_SELECTION, PROP_HUE }; enum { SELECTION_CHANGED, LAST_SIGNAL }; #define INF_TEXT_USER_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INF_TEXT_TYPE_USER, InfTextUserPrivate)) static guint user_signals[LAST_SIGNAL] = { 0 }; G_DEFINE_TYPE_WITH_CODE(InfTextUser, inf_text_user, INF_ADOPTED_TYPE_USER, G_ADD_PRIVATE(InfTextUser)) static void inf_text_user_init(InfTextUser* user) { InfTextUserPrivate* priv; priv = INF_TEXT_USER_PRIVATE(user); priv->caret = 0; priv->selection = 0; priv->hue = 0.0; } static void inf_text_user_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfTextUser* user; InfTextUserPrivate* priv; user = INF_TEXT_USER(object); priv = INF_TEXT_USER_PRIVATE(user); switch(prop_id) { case PROP_CARET: priv->caret = g_value_get_uint(value); break; case PROP_SELECTION: priv->selection = g_value_get_int(value); break; case PROP_HUE: priv->hue = g_value_get_double(value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void inf_text_user_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfTextUser* user; InfTextUserPrivate* priv; user = INF_TEXT_USER(object); priv = INF_TEXT_USER_PRIVATE(user); switch(prop_id) { case PROP_CARET: g_value_set_uint(value, priv->caret); break; case PROP_SELECTION: g_value_set_int(value, priv->selection); break; case PROP_HUE: g_value_set_double(value, priv->hue); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void inf_text_user_selection_changed(InfTextUser* user, guint position, guint length, gboolean by_request) { InfTextUserPrivate* priv; priv = INF_TEXT_USER_PRIVATE(user); priv->caret = position; priv->selection = length; g_object_notify(G_OBJECT(user), "caret-position"); g_object_notify(G_OBJECT(user), "selection-length"); } static void inf_text_user_class_init(InfTextUserClass* user_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(user_class); object_class->set_property = inf_text_user_set_property; object_class->get_property = inf_text_user_get_property; user_class->selection_changed = inf_text_user_selection_changed; g_object_class_install_property( object_class, PROP_CARET, g_param_spec_uint( "caret-position", "Caret position", "The position of this user's caret", 0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT ) ); g_object_class_install_property( object_class, PROP_SELECTION, g_param_spec_int( "selection-length", "Selection length", "The number of characters of this user's selection", G_MININT, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT ) ); g_object_class_install_property( object_class, PROP_HUE, g_param_spec_double( "hue", "Hue", "The hue value of the user's color. saturation and lightness are set " "by each client individually.", 0.0, 1.0, 0.0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT ) ); user_signals[SELECTION_CHANGED] = g_signal_new( "selection-changed", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfTextUserClass, selection_changed), NULL, NULL, NULL, G_TYPE_NONE, 3, G_TYPE_UINT, G_TYPE_INT, G_TYPE_BOOLEAN ); } /** * inf_text_user_new: (constructor) * @id: The user ID for this user. * @name: The user's name. * @vector: (allow-none): The state at which the user is at, or %NULL. * @hue: The hue value of the user's color. * * Creates a new #InfTextUser. @id should be unique for all users working * together. #InfUserTable will refuse to add users with duplicate id. If * @vector is %NULL, then the vector with all components zero is used. * * Returns: (transfer full): A new #InfTextUser. Free with g_object_unref() * when no longer needed. */ InfTextUser* inf_text_user_new(guint id, const gchar* name, InfAdoptedStateVector* vector, double hue) { g_return_val_if_fail(name != NULL, NULL); return INF_TEXT_USER( g_object_new( INF_TEXT_TYPE_USER, "id", id, "name", name, "vector", vector, "hue", hue, NULL ) ); } /** * inf_text_user_get_caret_position: * @user: A #InfTextUser. * * Returns the position of @user's caret. * * Returns: @user's caret position. **/ guint inf_text_user_get_caret_position(InfTextUser* user) { g_return_val_if_fail(INF_TEXT_IS_USER(user), 0); return INF_TEXT_USER_PRIVATE(user)->caret; } /** * inf_text_user_get_selection_length: * @user: A #InfTextUser. * * Returns the number of characters this user has selected, starting from * the caret position. Negative number mean selection towards the beginning * of the buffer. * * Returns: @user's selection length in characters. **/ gint inf_text_user_get_selection_length(InfTextUser* user) { g_return_val_if_fail(INF_TEXT_IS_USER(user), 0); return INF_TEXT_USER_PRIVATE(user)->selection; } /** * inf_text_user_set_selection: * @user: A #InfTextUser. * @position: The new position for the user's caret. * @length: The number of characters to select. Negative numbers mean * selection towards the beginning. * @by_request: %TRUE if explicitly requested or %FALSE when just an effect * of another operation. * * Changes @user's selection (i.e. caret position and selection length). The * @by_request parameter should be set to %TRUE if the selection change was * requested explicitly, for example by the user actively moving the cursor * using the mouse or the keyboard. If the cursor position changes only * because another user inserted text at a position before the user's cursor * and this results in a change of the selection position, the @by_request * parameter should be set to %FALSE. **/ void inf_text_user_set_selection(InfTextUser* user, guint position, gint length, gboolean by_request) { g_return_if_fail(INF_TEXT_IS_USER(user)); g_signal_emit( G_OBJECT(user), user_signals[SELECTION_CHANGED], 0, position, length, by_request ); } /** * inf_text_user_get_hue: * @user: A #InfTextUser. * * Returns the hue of the user's color as a double ranging from 0 to 1. * The other components (saturation and lightness) are not specific to the * user and may be chosen indivudually to optimize the actual visual display. * * Returns: The hue of the @user's color. **/ gdouble inf_text_user_get_hue(InfTextUser* user) { g_return_val_if_fail(INF_TEXT_IS_USER(user), 0.0); return INF_TEXT_USER_PRIVATE(user)->hue; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinftext/PaxHeaders.26529/inf-text-session.h0000644000000000000000000000013213034342512021340 xustar0030 mtime=1483851082.049718536 30 atime=1483851082.049718536 30 ctime=1488261589.200138628 libinfinity-0.7.1/libinftext/inf-text-session.h0000644000175000017500000000742013034342512022075 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_TEXT_SESSION_H__ #define __INF_TEXT_SESSION_H__ #include #include #include #include #include #include #include G_BEGIN_DECLS #define INF_TEXT_TYPE_SESSION (inf_text_session_get_type()) #define INF_TEXT_SESSION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_TEXT_TYPE_SESSION, InfTextSession)) #define INF_TEXT_SESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INF_TEXT_TYPE_SESSION, InfTextSessionClass)) #define INF_TEXT_IS_SESSION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_TEXT_TYPE_SESSION)) #define INF_TEXT_IS_SESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INF_TEXT_TYPE_SESSION)) #define INF_TEXT_SESSION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INF_TEXT_TYPE_SESSION, InfTextSessionClass)) typedef struct _InfTextSession InfTextSession; typedef struct _InfTextSessionClass InfTextSessionClass; typedef enum _InfTextSessionError { INF_TEXT_SESSION_ERROR_INVALID_HUE, INF_TEXT_SESSION_ERROR_FAILED } InfTextSessionError; struct _InfTextSessionClass { InfAdoptedSessionClass parent_class; }; struct _InfTextSession { InfAdoptedSession parent; }; GType inf_text_session_get_type(void); InfTextSession* inf_text_session_new(InfCommunicationManager* manager, InfTextBuffer* buffer, InfIo* io, InfSessionStatus status, InfCommunicationGroup* sync_group, InfXmlConnection* sync_connection); InfTextSession* inf_text_session_new_with_user_table(InfCommunicationManager* manager, InfTextBuffer* buffer, InfIo* io, InfUserTable* user_table, InfSessionStatus status, InfCommunicationGroup* sync_group, InfXmlConnection* sync_connection); void inf_text_session_set_user_color(InfTextSession* session, InfTextUser* user, gdouble hue); void inf_text_session_flush_requests_for_user(InfTextSession* session, InfTextUser* user); InfRequest* inf_text_session_join_user(InfSessionProxy* proxy, const gchar* name, InfUserStatus status, gdouble hue, guint caret_position, int selection_length, InfRequestFunc func, gpointer user_data); G_END_DECLS #endif /* __INF_TEXT_SESSION_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinftext/PaxHeaders.26529/inf-text-undo-grouping.c0000644000000000000000000000013213034342512022445 xustar0030 mtime=1483851082.049718536 30 atime=1483851082.049718536 30 ctime=1488261589.220138585 libinfinity-0.7.1/libinftext/inf-text-undo-grouping.c0000644000175000017500000002427613034342512023212 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-text-undo-grouping * @title:InfTextUndoGrouping * @short_description: Undo grouping for text operations * @include: libinftext/inf-text-undo-grouping.h * @see_also: #InfAdoptedUndoGrouping * @stabilitiy: Unstable * * #InfTextUndoGrouping handles undo grouping for text operations. It makes * sure many insert or delete operations occuring in a row can be undone * simultaneousely, taking into account that other users might have issued * requests inbetween. * * Using this class you don't need to connect to * #InfAdoptedUndoGrouping::group-requests to perform the grouping. */ #include #include #include #include #include #include #include #define INF_TEXT_UNDO_GROUPING_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INF_TEXT_TYPE_UNDO_GROUPING, InfTextUndoGroupingPrivate)) G_DEFINE_TYPE(InfTextUndoGrouping, inf_text_undo_grouping, INF_ADOPTED_TYPE_UNDO_GROUPING) /* Returns the gunichar of the first character of a InfTextChunk */ static gunichar inf_text_undo_grouping_get_char_from_chunk(InfTextChunk* chunk) { GIConv cd; InfTextChunkIter iter; gchar* inbuf; size_t inlen; gchar* outbuf; size_t outlen; size_t result; gchar buffer[6]; cd = g_iconv_open("UTF-8", inf_text_chunk_get_encoding(chunk)); g_assert(cd != (GIConv)-1); inf_text_chunk_iter_init_begin(chunk, &iter); /* cast const away without warning */ /* more or less */ *(gconstpointer*) &inbuf = inf_text_chunk_iter_get_text(&iter); inlen = inf_text_chunk_iter_get_bytes(&iter); outbuf = buffer; outlen = 6; /* max length of a UTF-8 character */ result = g_iconv(cd, &inbuf, &inlen, &outbuf, &outlen); /* we expect exactly one char in chunk, so there should be enough space */ g_assert(result == 0);/* || (result == (size_t)(-1) && errno == E2BIG));*/ g_iconv_close(cd); return g_utf8_get_char(buffer); } static guint inf_text_undo_grouping_get_translated_position(InfAdoptedAlgorithm* algorithm, InfAdoptedRequest* from, InfAdoptedRequest* to, guint pos) { guint move_id; InfAdoptedOperation* move_op; InfAdoptedStateVector* move_vec; InfAdoptedRequest* move_req; InfAdoptedRequest* moved_req; InfAdoptedOperation* moved_op; guint move_pos; move_id = inf_adopted_request_get_user_id(from); move_op = INF_ADOPTED_OPERATION(inf_text_move_operation_new(pos, 0)); move_vec = inf_adopted_state_vector_copy(inf_adopted_request_get_vector(from)); inf_adopted_state_vector_set( move_vec, move_id, inf_adopted_request_get_index(to) ); move_req = inf_adopted_request_new_do( move_vec, move_id, move_op, inf_adopted_request_get_receive_time(from) ); inf_adopted_state_vector_free(move_vec); g_object_unref(move_op); /* This should always succeed because of the vdiff check in * inf_text_undo_grouping_group_requests(). */ moved_req = inf_adopted_algorithm_translate_request( algorithm, move_req, inf_adopted_request_get_vector(to) ); g_object_unref(move_req); moved_op = inf_adopted_request_get_operation(moved_req); move_pos = inf_text_move_operation_get_position(INF_TEXT_MOVE_OPERATION(moved_op)); g_object_unref(moved_req); return move_pos; } static gboolean inf_text_undo_grouping_group_requests(InfAdoptedUndoGrouping* grouping, InfAdoptedRequest* first, InfAdoptedRequest* second) { InfAdoptedOperation* first_op; InfAdoptedOperation* second_op; InfAdoptedStateVector* first_vector; InfAdoptedStateVector* second_vector; InfAdoptedAlgorithm* algorithm; guint max_total_log_size; guint vdiff; guint first_length; guint second_length; guint first_pos; guint second_pos; gunichar first_char; gunichar second_char; g_assert(inf_adopted_request_get_request_type(first) == INF_ADOPTED_REQUEST_DO); g_assert(inf_adopted_request_get_request_type(second) == INF_ADOPTED_REQUEST_DO); /* We want to avoid doing excessive transformations so that if someone * types a character, waits a long time with others writing a lot in the * meantime, and then writes another character. This also avoids the * problem that we might not have all the requests from other users * around anymore to do the transformation. */ first_vector = inf_adopted_request_get_vector(first); second_vector = inf_adopted_request_get_vector(second); vdiff = inf_adopted_state_vector_vdiff(first_vector, second_vector); algorithm = inf_adopted_undo_grouping_get_algorithm(grouping); g_object_get( G_OBJECT(algorithm), "max-total-log-size", &max_total_log_size, NULL ); if(vdiff > max_total_log_size) return FALSE; first_op = inf_adopted_request_get_operation(first); second_op = inf_adopted_request_get_operation(second); g_assert(INF_TEXT_IS_DEFAULT_INSERT_OPERATION(first_op) || INF_TEXT_IS_DEFAULT_DELETE_OPERATION(first_op)); g_assert(INF_TEXT_IS_DEFAULT_INSERT_OPERATION(second_op) || INF_TEXT_IS_DEFAULT_DELETE_OPERATION(second_op)); /* Never group insert and delete operations */ if(INF_TEXT_IS_DEFAULT_INSERT_OPERATION(first_op) && INF_TEXT_IS_DEFAULT_DELETE_OPERATION(second_op)) { return FALSE; } else if(INF_TEXT_IS_DEFAULT_DELETE_OPERATION(first_op) && INF_TEXT_IS_DEFAULT_INSERT_OPERATION(second_op)) { return FALSE; } else if(INF_TEXT_IS_INSERT_OPERATION(first_op)) { first_length = inf_text_insert_operation_get_length( INF_TEXT_INSERT_OPERATION(first_op) ); second_length = inf_text_insert_operation_get_length( INF_TEXT_INSERT_OPERATION(second_op) ); if(first_length > 1 || second_length > 1) { return FALSE; } else { first_pos = inf_text_insert_operation_get_position( INF_TEXT_INSERT_OPERATION(first_op) ); first_pos = inf_text_undo_grouping_get_translated_position( inf_adopted_undo_grouping_get_algorithm(grouping), first, second, first_pos + 1 ); second_pos = inf_text_insert_operation_get_position( INF_TEXT_INSERT_OPERATION(second_op) ); if(first_pos != second_pos) return FALSE; /* start new group when going from whitespace to non-whitespace */ first_char = inf_text_undo_grouping_get_char_from_chunk( inf_text_default_insert_operation_get_chunk( INF_TEXT_DEFAULT_INSERT_OPERATION(first_op) ) ); second_char = inf_text_undo_grouping_get_char_from_chunk( inf_text_default_insert_operation_get_chunk( INF_TEXT_DEFAULT_INSERT_OPERATION(second_op) ) ); if(g_unichar_isspace(first_char) && !g_unichar_isspace(second_char)) return FALSE; return TRUE; } } else if(INF_TEXT_IS_DELETE_OPERATION(first_op)) { first_length = inf_text_delete_operation_get_length( INF_TEXT_DELETE_OPERATION(first_op) ); second_length = inf_text_delete_operation_get_length( INF_TEXT_DELETE_OPERATION(second_op) ); if(first_length > 1 || second_length > 1) { return FALSE; } else { first_pos = inf_text_delete_operation_get_position( INF_TEXT_DELETE_OPERATION(first_op) ); first_pos = inf_text_undo_grouping_get_translated_position( inf_adopted_undo_grouping_get_algorithm(grouping), first, second, first_pos ); second_pos = inf_text_delete_operation_get_position( INF_TEXT_DELETE_OPERATION(second_op) ); if(first_pos != second_pos && first_pos != second_pos + 1) return FALSE; /* start new group when going from whitespace to non-whitespace */ first_char = inf_text_undo_grouping_get_char_from_chunk( inf_text_default_delete_operation_get_chunk( INF_TEXT_DEFAULT_DELETE_OPERATION(first_op) ) ); second_char = inf_text_undo_grouping_get_char_from_chunk( inf_text_default_delete_operation_get_chunk( INF_TEXT_DEFAULT_DELETE_OPERATION(second_op) ) ); if(g_unichar_isspace(first_char) && !g_unichar_isspace(second_char)) return FALSE; return TRUE; } } else { g_assert_not_reached(); return FALSE; } } static void inf_text_undo_grouping_init(InfTextUndoGrouping* grouping) { } static void inf_text_undo_grouping_class_init( InfTextUndoGroupingClass* text_undo_grouping_class) { InfAdoptedUndoGroupingClass* undo_grouping_class; undo_grouping_class = INF_ADOPTED_UNDO_GROUPING_CLASS(text_undo_grouping_class); undo_grouping_class->group_requests = inf_text_undo_grouping_group_requests; } /* * Public API. */ /** * inf_text_undo_grouping_new: (constructor) * * Creates a new #InfTextUndoGrouping. * * Returns: (transfer full): A new #InfTextUndoGrouping. To be freed with * g_object_unref(). **/ InfTextUndoGrouping* inf_text_undo_grouping_new(void) { GObject* object; object = g_object_new(INF_TEXT_TYPE_UNDO_GROUPING, NULL); return INF_TEXT_UNDO_GROUPING(object); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinftext/PaxHeaders.26529/inf-text-delete-operation.c0000644000000000000000000000013213034342512023110 xustar0030 mtime=1483851082.045718513 30 atime=1483851082.045718513 30 ctime=1488261589.212138602 libinfinity-0.7.1/libinftext/inf-text-delete-operation.c0000644000175000017500000001747613034342512023661 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-text-delete-operation * @title: InfTextDeleteOperation * @short_description: Interface for an operation erasing text * @include: libinftext/inf-text-delete-operation.h * @see_also: #InfTextInsertOperation * @stability: Unstable * * #InfTextDeleteOperation is an interface for an operation removing text * from the document. It implements the transformation logic for * transformation against other delete operations or insert operations. * * This interface does not make any assumption on what kind of text is * removed, it works only with character offsets and lengths. This information * is enough to perform transformation of this operation or other operations * against this operation. Whether the actual operation only knows about the * offsets, too, or actually knows the text that is being erased (and if so, * in what representation), is up to the implementation. */ #include #include G_DEFINE_INTERFACE(InfTextDeleteOperation, inf_text_delete_operation, INF_ADOPTED_TYPE_OPERATION) static void inf_text_delete_operation_default_init(InfTextDeleteOperationInterface* iface) { } /** * inf_text_delete_operation_get_position: * @operation: A #InfTextDeleteOperation. * * Returns the position at which @operation starts to delete dext. * * Returns: The position of @operation. **/ guint inf_text_delete_operation_get_position(InfTextDeleteOperation* operation) { InfTextDeleteOperationInterface* iface; g_return_val_if_fail(INF_TEXT_IS_DELETE_OPERATION(operation), 0); iface = INF_TEXT_DELETE_OPERATION_GET_IFACE(operation); g_return_val_if_fail(iface->get_position != NULL, 0); return iface->get_position(operation); } /** * inf_text_delete_operation_get_length: * @operation: A #InfTextDeleteOperation. * * Returns the number of characters deleted by @operation. * * Returns: The length of @operation. **/ guint inf_text_delete_operation_get_length(InfTextDeleteOperation* operation) { InfTextDeleteOperationInterface* iface; g_return_val_if_fail(INF_TEXT_IS_DELETE_OPERATION(operation), 0); iface = INF_TEXT_DELETE_OPERATION_GET_IFACE(operation); g_return_val_if_fail(iface->get_length != NULL, 0); return iface->get_length(operation); } /** * inf_text_delete_operation_need_concurrency_id: * @op: A #InfTextDeleteOperation. * @against: Another #InfAdoptedOperation. * * Returns whether transforming @op against @against requires a concurrency ID * (see inf_adopted_operation_need_concurrency_id() for further information). * * Returns: Whether transforming @op against @against requires a concurrency * ID. */ gboolean inf_text_delete_operation_need_concurrency_id(InfTextDeleteOperation* op, InfAdoptedOperation* against) { g_return_val_if_fail(INF_TEXT_IS_DELETE_OPERATION(op), FALSE); g_return_val_if_fail(INF_ADOPTED_IS_OPERATION(against), FALSE); return FALSE; } /** * inf_text_delete_operation_transform_insert: * @operation: A #InfTextDeleteOperation. * @against: A #InfTextInsertOperation. * * Returns a new operation that includes the effect of @against into * @operation. * * Returns: (transfer full): A new #InfAdoptedOperation. **/ InfAdoptedOperation* inf_text_delete_operation_transform_insert(InfTextDeleteOperation* operation, InfTextInsertOperation* against) { InfTextDeleteOperationInterface* iface; guint own_pos; guint own_len; guint other_pos; guint other_len; g_return_val_if_fail(INF_TEXT_IS_DELETE_OPERATION(operation), NULL); g_return_val_if_fail(INF_TEXT_IS_INSERT_OPERATION(against), NULL); iface = INF_TEXT_DELETE_OPERATION_GET_IFACE(operation); g_return_val_if_fail(iface->transform_position != NULL, NULL); g_return_val_if_fail(iface->transform_split != NULL, NULL); own_pos = inf_text_delete_operation_get_position(operation); own_len = inf_text_delete_operation_get_length(operation); other_pos = inf_text_insert_operation_get_position(against); other_len = inf_text_insert_operation_get_length(against); if(other_pos >= own_pos + own_len) { return inf_adopted_operation_copy(INF_ADOPTED_OPERATION(operation)); } else if(other_pos <= own_pos) { return INF_ADOPTED_OPERATION( iface->transform_position(operation, own_pos + other_len) ); } else { return INF_ADOPTED_OPERATION( iface->transform_split(operation, other_pos - own_pos, other_len) ); } } /** * inf_text_delete_operation_transform_delete: * @operation: A #InfTextDeleteOperation. * @against: Another #InfTextDeleteOperation. * * Returns a new operation that includes the effect of @against into * @operation. * * Returns: (transfer full): A new #InfAdoptedOperation. **/ InfAdoptedOperation* inf_text_delete_operation_transform_delete(InfTextDeleteOperation* operation, InfTextDeleteOperation* against) { InfTextDeleteOperationInterface* iface; guint own_pos; guint own_len; guint other_pos; guint other_len; g_return_val_if_fail(INF_TEXT_IS_DELETE_OPERATION(operation), NULL); g_return_val_if_fail(INF_TEXT_IS_DELETE_OPERATION(against), NULL); iface = INF_TEXT_DELETE_OPERATION_GET_IFACE(operation); g_return_val_if_fail(iface->transform_position != NULL, NULL); g_return_val_if_fail(iface->transform_overlap != NULL, NULL); own_pos = inf_text_delete_operation_get_position(operation); own_len = inf_text_delete_operation_get_length(operation); other_pos = inf_text_delete_operation_get_position(against); other_len = inf_text_delete_operation_get_length(against); if(own_pos + own_len <= other_pos) { return inf_adopted_operation_copy(INF_ADOPTED_OPERATION(operation)); } else if(own_pos >= other_pos + other_len) { return INF_ADOPTED_OPERATION( iface->transform_position(operation, own_pos - other_len) ); } /* Somehow overlapping now */ else if(other_pos <= own_pos && other_pos + other_len >= own_pos + own_len) { return INF_ADOPTED_OPERATION( iface->transform_overlap( operation, against, other_pos, 0, own_pos - other_pos, own_len ) ); } else if(other_pos <= own_pos && other_pos + other_len < own_pos + own_len) { return INF_ADOPTED_OPERATION( iface->transform_overlap( operation, against, other_pos, 0, own_pos - other_pos, other_pos + other_len - own_pos ) ); } else if(other_pos > own_pos && other_pos + other_len >= own_pos + own_len) { return INF_ADOPTED_OPERATION( iface->transform_overlap( operation, against, own_pos, other_pos - own_pos, 0, own_pos + own_len - other_pos ) ); } else { return INF_ADOPTED_OPERATION( iface->transform_overlap( operation, against, own_pos, other_pos - own_pos, 0, other_len ) ); } } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinftext/PaxHeaders.26529/inf-text-chunk.c0000644000000000000000000000013213034342512020760 xustar0030 mtime=1483851082.045718513 30 atime=1483851082.045718513 30 ctime=1488261589.204138619 libinfinity-0.7.1/libinftext/inf-text-chunk.c0000644000175000017500000012120313034342512021511 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-text-chunk * @title: InfTextChunk * @short_description: A chunk of text written by various authors * @include: libinftext/inf-text-chunk.h * @see_also: #InfTextBuffer * @stability: Unstable * * #InfTextChunk represents a chunk of text where different parts of it can * be written by different authors. The #InfTextChunk API can be used like a * normal string API, except that apart from the text itself it also stores * the author information. * * An #InfTextChunk is made up of segments, where each segment represents a * contiguous piece of text which is written by the same user. The * #InfTextChunkIter functionality can be used to iterate over the segments * of a chunk. * * The #InfTextChunk API works with characters, not bytes, i.e. all offsets * are given in number of characters. This ensures that unicode strings * cannot be torn apart in the middle of a multibyte sequence. The encoding * of an #InfTextChunk is not fixed, but it can be freely chosen. * #InfTextChunk then uses iconv to convert between bytes and character * offsets where necessary. For a small set of selected encodings which are * very popular, most notably UTF-8, there exist more optimized code paths to * do the conversion. */ #include #include #include G_DEFINE_BOXED_TYPE(InfTextChunkIter, inf_text_chunk_iter, inf_text_chunk_iter_copy, inf_text_chunk_iter_free) G_DEFINE_BOXED_TYPE(InfTextChunk, inf_text_chunk, inf_text_chunk_copy, inf_text_chunk_free) /* Don't check integrity in stable releases */ /*#define CHUNK_CHECK_INTEGRITY*/ typedef struct _InfTextChunkPath InfTextChunkPath; struct _InfTextChunkPath { gsize (*get_byte_index)(InfTextChunk* chunk, gchar* text, gsize bytes, guint offset); }; struct _InfTextChunk { GSequence* segments; guint length; /* in characters */ GQuark encoding; const InfTextChunkPath* path; }; typedef struct _InfTextChunkSegment InfTextChunkSegment; struct _InfTextChunkSegment { guint author; /* This is gchar so that we can do pointer arithmetic. It does not * necessarily store a full character in each byte. This depends on the * encoding specified in the InfTextChunk. */ gchar* text; gsize length; /* in bytes */ guint offset; /* absolute to chunk begin in characters, sort criteria */ }; /* * get_byte_index paths */ gsize inf_text_chunk_get_byte_index_utf8(InfTextChunk* self, gchar* text, gsize bytes, guint offset) { #ifdef CHUNK_CHECK_INTEGRITY g_assert(offset <= g_utf8_strlen(text, bytes)); #endif return g_utf8_offset_to_pointer(text, offset) - text; } gsize inf_text_chunk_get_byte_index_iconv(InfTextChunk* self, gchar* text, gsize bytes, guint offset) { /* We convert the segment's text into UCS-4, character by character. * This assumes every UCS-4 character is 4 bytes in length */ /* This is quite inefficient, but a general-purpose solution. It looks like * libicu has a function, UCharIteratorMove, which would allow us to move * directly N characters ahead and get the new byte index. * TODO: We could profile it, and if it brings a benefit, we could use it, * maybe with an option to fall back to iconv at configure time */ GIConv cd; gchar buffer[4]; gchar* inbuf; gchar* outbuf; gsize inlen; gsize outlen; guint count; gsize result; cd = g_iconv_open("UCS-4", g_quark_to_string(self->encoding)); g_assert(cd != (GIConv)-1); inbuf = text; inlen = bytes; for(count = 0; count < offset; ++count) { g_assert(inlen > 0); outbuf = buffer; outlen = 4; result = g_iconv(cd, &inbuf, &inlen, &outbuf, &outlen); g_assert(result == (size_t)(-1)); /* errno == E2BIG */ } g_iconv_close(cd); return bytes - inlen; } const InfTextChunkPath INF_TEXT_CHUNK_PATH_UTF8 = { inf_text_chunk_get_byte_index_utf8 }; const InfTextChunkPath INF_TEXT_CHUNK_PATH_ICONV = { inf_text_chunk_get_byte_index_iconv }; /* * Helper functions */ static void inf_text_chunk_segment_free(InfTextChunkSegment* segment) { g_free(segment->text); g_slice_free(InfTextChunkSegment, segment); } static int inf_text_chunk_segment_cmp(gconstpointer first, gconstpointer second, gpointer userdata) { const InfTextChunkSegment* first_segment; const InfTextChunkSegment* second_segment; first_segment = (const InfTextChunkSegment*)first; second_segment = (const InfTextChunkSegment*)second; g_return_val_if_fail(second != NULL && first != NULL, 0); if (first_segment->offset < second_segment->offset) return -1; else if (first_segment->offset == second_segment->offset) return 0; else return 1; } /* This is a special comparison function which is only used * in inf_text_chunk_get_segment. It makes sure that when two segments * have the same offset, the second one gets sorted behind. This ensures * that the first segment in the sequence is never returned, since it * always has offset 0, which is a precondition for the algorithm * in inf_text_chunk_get_segment. See also libinfinity github issue #10. */ static int inf_text_chunk_segment_cmp_for_get_segment(gconstpointer first, gconstpointer second, gpointer userdata) { const InfTextChunkSegment* first_segment; const InfTextChunkSegment* second_segment; first_segment = (const InfTextChunkSegment*)first; second_segment = (const InfTextChunkSegment*)second; g_return_val_if_fail(second != NULL && first != NULL, 0); if (first_segment->offset < second_segment->offset) return -1; else if (first_segment->offset == second_segment->offset) return -1; else return 1; } static guint inf_text_chunk_next_offset(InfTextChunk* self, GSequenceIter* iter) { GSequenceIter* next_iter; g_assert(iter != g_sequence_get_end_iter(self->segments)); next_iter = g_sequence_iter_next(iter); if(next_iter == g_sequence_get_end_iter(self->segments)) return self->length; else return ((InfTextChunkSegment*)g_sequence_get(next_iter))->offset; } #ifdef CHUNK_CHECK_INTEGRITY static gboolean inf_text_chunk_check_integrity(InfTextChunk* self) { GSequenceIter* iter; InfTextChunkSegment* segment; guint offset; guint new_offset; offset = 0; for(iter = g_sequence_get_begin_iter(self->segments); iter != g_sequence_get_end_iter(self->segments); iter = g_sequence_iter_next(iter)) { segment = (InfTextChunkSegment*)g_sequence_get(iter); if(offset != segment->offset) return FALSE; new_offset = inf_text_chunk_next_offset(self, iter); if(new_offset <= offset) return FALSE; if(new_offset - offset > segment->length) return FALSE; offset = new_offset; } return TRUE; } #endif static GSequenceIter* inf_text_chunk_get_segment(InfTextChunk* self, guint pos, gsize* index) { InfTextChunkSegment* found; InfTextChunkSegment key; GSequenceIter* iter; g_assert(pos <= self->length); /* only offset is relevant for lookup */ key.offset = pos; /* TODO: Verify this does binary search */ iter = g_sequence_search( self->segments, &key, inf_text_chunk_segment_cmp_for_get_segment, NULL ); if(self->length > 0) { g_assert(iter != g_sequence_get_begin_iter(self->segments)); iter = g_sequence_iter_prev(iter); found = g_sequence_get(iter); g_assert(pos >= found->offset); /* This is not "<=" because it should rather find position 0 on the * next segment in that case. */ g_assert(pos <= inf_text_chunk_next_offset(self, iter)); /* Find byte index in the segment where the specified character starts. * This is rather ugly, I wish iconv or glib or someone had some nice(r) * API for this. */ if(index != NULL) { if(pos == inf_text_chunk_next_offset(self, iter)) { *index = found->length; } else { *index = self->path->get_byte_index( self, found->text, found->length, pos - found->offset ); } } } else { if(index != NULL) *index = 0; } return iter; } /* * Public API */ /** * inf_text_chunk_iter_copy: * @iter: A #InfTextChunkIter. * * Makes a dynamically-allocated copy of @iter. This is typically not needed * because #InfTextChunkIter can be copied by value, however it might be * useful to language bindings. * * Returns: (transfer full): A copy of @iter. Free with * inf_text_chunk_iter_free(). */ InfTextChunkIter* inf_text_chunk_iter_copy(const InfTextChunkIter* iter) { InfTextChunkIter* new_iter; new_iter = g_slice_new(InfTextChunkIter); *new_iter = *iter; return new_iter; } /** * inf_text_chunk_iter_free: * @iter: The #InfTextChunkIter to free. * * Frees all resources allocated with inf_text_chunk_iter_copy(). Must not * be used with stack-allocated #InfTextChunkIters. */ void inf_text_chunk_iter_free(InfTextChunkIter* iter) { g_slice_free(InfTextChunkIter, iter); } /** * inf_text_chunk_new: (constructor) * @encoding: A content encoding, such as "UTF-8" or "LATIN1". * * Creates a new #InfTextChunk with no initial content that holds text * in the given encoding. TODO: Allow binary data with %NULL encoding. * * Returns: (transfer full): A new #InfTextChunk. **/ InfTextChunk* inf_text_chunk_new(const gchar* encoding) { InfTextChunk* chunk = g_slice_new(InfTextChunk); chunk->segments = g_sequence_new( (GDestroyNotify)inf_text_chunk_segment_free ); chunk->length = 0; chunk->encoding = g_quark_from_string(encoding); if(chunk->encoding == g_quark_from_static_string("UTF-8")) chunk->path = &INF_TEXT_CHUNK_PATH_UTF8; else chunk->path = &INF_TEXT_CHUNK_PATH_ICONV; return chunk; } /** * inf_text_chunk_copy: * @self: A #InfTextChunk. * * Returns a copy of @self. * * Returns: (transfer full): A new #InfTextChunk. **/ InfTextChunk* inf_text_chunk_copy(InfTextChunk* self) { InfTextChunk* new_chunk; GSequenceIter* iter; g_return_val_if_fail(self != NULL, NULL); new_chunk = g_slice_new(InfTextChunk); new_chunk->segments = g_sequence_new( (GDestroyNotify)inf_text_chunk_segment_free ); for(iter = g_sequence_get_begin_iter(self->segments); iter != g_sequence_get_end_iter(self->segments); iter = g_sequence_iter_next(iter)) { InfTextChunkSegment* segment = g_sequence_get(iter); InfTextChunkSegment* new_segment = g_slice_new(InfTextChunkSegment); new_segment->author = segment->author; new_segment->text = g_memdup(segment->text, segment->length); new_segment->length = segment->length; new_segment->offset = segment->offset; g_sequence_append(new_chunk->segments, new_segment); } new_chunk->length = self->length; new_chunk->encoding = self->encoding; new_chunk->path = self->path; return new_chunk; } /** * inf_text_chunk_free: * @self: A #InfTextChunk. * * Frees a #InfTextChunk allocated with inf_text_chunk_new(), * inf_text_chunk_copy() or inf_text_chunk_substring(). **/ void inf_text_chunk_free(InfTextChunk* self) { g_return_if_fail(self != NULL); g_sequence_free(self->segments); g_slice_free(InfTextChunk, self); } /** * inf_text_chunk_get_encoding: * @self: A #InfTextChunk. * * Returns the character encoding in which the content of @self is encoded. * * Returns: The encoding of @self. **/ const gchar* inf_text_chunk_get_encoding(InfTextChunk* self) { g_return_val_if_fail(self != NULL, NULL); return g_quark_to_string(self->encoding); } /** * inf_text_chunk_get_length: * @self: A #InfTextChunk. * * Returns the number of characters contained in @self. * * Returns: The number of characters of @self. **/ guint inf_text_chunk_get_length(InfTextChunk* self) { g_return_val_if_fail(self != NULL, 0); return self->length; } /** * inf_text_chunk_substring: * @self: A #InfTextChunk. * @begin: A character offset into @self. * @length: The length of the text to extract. * * Returns a new #InfTextChunk containing a substring of @self, beginning * at character offset @begin and @length characters long. * * Returns: (transfer full): A new #InfTextChunk. **/ InfTextChunk* inf_text_chunk_substring(InfTextChunk* self, guint begin, guint length) { GSequenceIter* begin_iter; GSequenceIter* end_iter; gsize begin_index; gsize end_index; InfTextChunk* result; InfTextChunkSegment* segment; InfTextChunkSegment* new_segment; guint current_length; g_return_val_if_fail(self != NULL, NULL); g_return_val_if_fail(begin + length <= self->length, NULL); if(self->length > 0 && length > 0) { begin_iter = inf_text_chunk_get_segment(self, begin, &begin_index); end_iter = inf_text_chunk_get_segment(self, begin + length, &end_index); if(end_index == 0) { g_assert(end_iter != g_sequence_get_end_iter(self->segments)); end_iter = g_sequence_iter_prev(end_iter); end_index = ((InfTextChunkSegment*)g_sequence_get(end_iter))->length; } result = inf_text_chunk_new(g_quark_to_string(self->encoding)); current_length = 0; segment = g_sequence_get(begin_iter); while(begin_iter != end_iter) { new_segment = g_slice_new(InfTextChunkSegment); new_segment->author = segment->author; new_segment->text = g_memdup( segment->text + begin_index, segment->length - begin_index ); new_segment->length = segment->length - begin_index; new_segment->offset = current_length; begin_iter = g_sequence_iter_next(begin_iter); segment = g_sequence_get(begin_iter); /* Add (remaining) length of this segment to current length */ current_length = segment->offset - begin; /* So we get the next segment from the beginning. This may only be * non-zero during the first iteration. */ begin_index = 0; /* begin = new_segment->offset;*/ g_sequence_append(result->segments, new_segment); } /* Don't forget last segment */ new_segment = g_slice_new(InfTextChunkSegment); new_segment->author = segment->author; new_segment->text = g_memdup( segment->text + begin_index, end_index - begin_index ); new_segment->length = end_index - begin_index; new_segment->offset = current_length; g_sequence_append(result->segments, new_segment); result->length = length; result->encoding = self->encoding; result->path = self->path; } else { g_assert(length == 0 || begin == 0); /* New, empty chunk */ result = inf_text_chunk_new(g_quark_to_string(self->encoding)); } #ifdef CHUNK_CHECK_INTEGRITY g_assert(inf_text_chunk_check_integrity(result) == TRUE); #endif return result; } /** * inf_text_chunk_insert_text: * @self: A #InfTextChunk. * @offset: Character offset at which to insert text * @text (type const guint8*) (array length=bytes) (transfer none): Text * to insert. * @length: Number of characters contained in @text. * @bytes: Number of bytes of @text. * @author: User that wrote @text. * * Inserts text written by @author into @self. @text is expected to be in * the chunk's encoding. **/ void inf_text_chunk_insert_text(InfTextChunk* self, guint offset, gconstpointer text, gsize bytes, guint length, guint author) { GSequenceIter* iter; gsize offset_index; InfTextChunkSegment* segment; InfTextChunkSegment* new_segment; g_return_if_fail(self != NULL); g_return_if_fail(offset <= self->length); if(self->length > 0) { iter = inf_text_chunk_get_segment(self, offset, &offset_index); segment = (InfTextChunkSegment*)g_sequence_get(iter); /* Have to split segment, unless it is between two segments in which * case we can perhaps append to the previous. */ if(segment->author != author && offset > 0 && offset_index == 0) { g_assert(iter != g_sequence_get_begin_iter(self->segments)); iter = g_sequence_iter_prev(iter); segment = (InfTextChunkSegment*)g_sequence_get(iter); offset_index = segment->length; } if(segment->author != author) { /* No luck, split if necessary */ if(offset_index > 0 && offset_index < segment->length) { new_segment = g_slice_new(InfTextChunkSegment); new_segment->author = segment->author; new_segment->text = g_memdup( segment->text + offset_index, segment->length - offset_index ); new_segment->length = segment->length - offset_index; new_segment->offset = offset; iter = g_sequence_iter_next(iter); iter = g_sequence_insert_before(iter, new_segment); /* Don't realloc to make smaller */ segment->length = offset_index; /* Note that we did not invalidate offsets so far */ } else if(offset_index == segment->length) { /* Insert behind segment */ iter = g_sequence_iter_next(iter); } new_segment = g_slice_new(InfTextChunkSegment); new_segment->author = author; new_segment->text = g_memdup(text, bytes); new_segment->length = bytes; new_segment->offset = offset; g_sequence_insert_before(iter, new_segment); } else { /* TODO: g_malloc + g_free + 2*memcpy? */ segment->text = g_realloc(segment->text, segment->length + bytes); if(offset_index < segment->length) { g_memmove( segment->text + offset_index + bytes, segment->text + offset_index, segment->length - offset_index ); } memcpy(segment->text + offset_index, text, bytes); segment->length += bytes; iter = g_sequence_iter_next(iter); } /* Adjust offsets */ while(iter != g_sequence_get_end_iter(self->segments)) { segment = (InfTextChunkSegment*)g_sequence_get(iter); segment->offset += length; iter = g_sequence_iter_next(iter); } self->length += length; } else { new_segment = g_slice_new(InfTextChunkSegment); new_segment->author = author; new_segment->text = g_memdup(text, bytes); new_segment->length = bytes; new_segment->offset = 0; g_sequence_append(self->segments, new_segment); self->length = length; } #ifdef CHUNK_CHECK_INTEGRITY g_assert(inf_text_chunk_check_integrity(self) == TRUE); #endif } /** * inf_text_chunk_insert_chunk: * @self: A #InfTextChunk. * @offset: Character offset at which to insert text. * @text: (transfer none): Chunk to insert into @self. * * Inserts @text into @self at position @offset. @text and @self must * have the same encoding. **/ void inf_text_chunk_insert_chunk(InfTextChunk* self, guint offset, InfTextChunk* text) { GSequenceIter* iter; GSequenceIter* text_iter; gsize offset_index; InfTextChunkSegment* segment; InfTextChunkSegment* new_segment; GSequenceIter* first_iter; GSequenceIter* last_iter; InfTextChunkSegment* first; InfTextChunkSegment* last; InfTextChunkSegment* first_merge; InfTextChunkSegment* last_merge; GSequenceIter* beyond; g_return_if_fail(self != NULL); g_return_if_fail(offset <= self->length); g_return_if_fail(text != NULL); g_return_if_fail(self->encoding == text->encoding); if(self->length > 0 && text->length > 0) { if(g_sequence_get_length(text->segments) == 1) { segment = g_sequence_get(g_sequence_get_begin_iter(text->segments)); inf_text_chunk_insert_text( self, offset, segment->text, segment->length, text->length, segment->author ); } else { iter = inf_text_chunk_get_segment(self, offset, &offset_index); segment = (InfTextChunkSegment*)g_sequence_get(iter); /* First, we insert the first and last segment of text into self, * possibly merging with adjacent segments. Then, the rest is * copied. */ first_iter = g_sequence_get_begin_iter(text->segments); last_iter = g_sequence_iter_prev( g_sequence_get_end_iter(text->segments) ); first = (InfTextChunkSegment*)g_sequence_get(first_iter); last = (InfTextChunkSegment*)g_sequence_get(last_iter); /* 0 and 1 segment special cases have been handled above */ g_assert(first != last); last_merge = segment; first_merge = segment; /* beyond points to the first segment that needs offset adjustment * after insertion */ beyond = iter; /* Try merge with end of previous segment if inserting inbetween two * segments. */ if(offset_index == 0 && offset > 0) { g_assert(iter != g_sequence_get_begin_iter(self->segments)); iter = g_sequence_iter_prev(iter); first_merge = (InfTextChunkSegment*)g_sequence_get(iter); offset_index = first_merge->length; } if(offset == 0 || offset == self->length || first_merge != last_merge) { /* Insert between two segments, or at beginning/end */ if(first_merge->author == first->author && offset > 0) { /* Can merge first segment */ first_merge->length += first->length; first_merge->text = g_realloc( first_merge->text, first_merge->length ); memcpy( first_merge->text + first_merge->length - first->length, first->text, first->length ); /* Already inserted */ first_iter = g_sequence_iter_next(first_iter); } if(last_merge->author == last->author && offset < self->length) { /* Can merge last segment */ last_merge->length += last->length; last_merge->text = g_realloc(last_merge->text, last_merge->length); g_memmove( last_merge->text + last->length, last_merge->text, last_merge->length - last->length ); memcpy(last_merge->text, last->text, last->length); last_merge->offset = offset + last->offset; /* Merged with last, so don't need to adjust last_merge->offset * anymore, continue behind with offset adjustment. */ beyond = g_sequence_iter_next(beyond); } else { /* Could not merge last segment, so we have to insert it. Therefore, * make last_iter point to the end of the sequence. */ last_iter = g_sequence_iter_next(last_iter); if(offset_index > 0) /* Note: This is only false for offset == 0 */ beyond = g_sequence_iter_next(iter); } if(offset_index > 0) /* Note: This is only false for offset == 0 */ { /* Pointing to the position before which to insert * the rest of text. */ iter = g_sequence_iter_next(iter); } } else { /* Insert within a segment, split segment */ new_segment = g_slice_new(InfTextChunkSegment); new_segment->author = last_merge->author; if(last_merge->author == last->author) { /* Merge last part into new segment */ new_segment->length = last_merge->length - offset_index + last->length; new_segment->text = g_malloc(new_segment->length); memcpy(new_segment->text, last->text, last->length); memcpy( new_segment->text + last->length, last_merge->text + offset_index, last_merge->length - offset_index ); new_segment->offset = offset + last->offset; } else { /* Split up last part */ new_segment->length = last_merge->length - offset_index; new_segment->text = g_malloc(new_segment->length); memcpy( new_segment->text, last_merge->text + offset_index, new_segment->length ); new_segment->offset = offset + text->length; /* We still have to insert last segment since we could not merge */ last_iter = g_sequence_iter_next(last_iter); } iter = g_sequence_iter_next(iter); iter = g_sequence_insert_before(iter, new_segment); /* The segment just inserted is the last one being inserted, so * we need to adjust beyond that */ beyond = g_sequence_iter_next(iter); /* Note first_merge == last_merge */ if(first_merge->author == first->author) { /* Merge into first */ if(first_merge->length < offset_index + first->length) { first_merge->text = g_realloc( first_merge->text, offset_index + first->length ); } first_merge->length = offset_index + first->length; memcpy( first_merge->text + offset_index, first->text, first->length ); /* Already inserted */ first_iter = g_sequence_iter_next(first_iter); } else { /* Cannot merge, just cut */ first_merge->length = offset_index; } } /* iter now points to the segment before which the rest of text has to * be inserted */ for(text_iter = first_iter; text_iter != last_iter; text_iter = g_sequence_iter_next(text_iter)) { segment = g_sequence_get(text_iter); new_segment = g_slice_new(InfTextChunkSegment); new_segment->author = segment->author; new_segment->text = g_memdup(segment->text, segment->length); new_segment->length = segment->length; new_segment->offset = offset + segment->offset; g_sequence_insert_before(iter, new_segment); } for(iter = beyond; iter != g_sequence_get_end_iter(self->segments); iter = g_sequence_iter_next(iter)) { segment = g_sequence_get(iter); segment->offset += inf_text_chunk_get_length(text); } self->length += text->length; } } else { for(text_iter = g_sequence_get_begin_iter(text->segments); text_iter != g_sequence_get_end_iter(text->segments); text_iter = g_sequence_iter_next(text_iter)) { segment = (InfTextChunkSegment*)g_sequence_get(text_iter); new_segment = g_slice_new(InfTextChunkSegment); new_segment->author = segment->author; new_segment->text = g_memdup(segment->text, segment->length); new_segment->length = segment->length; new_segment->offset = segment->offset; g_sequence_append(self->segments, new_segment); } self->length += text->length; } #ifdef CHUNK_CHECK_INTEGRITY g_assert(inf_text_chunk_check_integrity(self) == TRUE); #endif } /** * inf_text_chunk_erase: * @self: A #InfTextChunk. * @begin: A character offset into @self. * @length: Number of characters to erase. * * Removes @length characters of @self, starting from character offset @begin. **/ void inf_text_chunk_erase(InfTextChunk* self, guint begin, guint length) { GSequenceIter* first_iter; GSequenceIter* last_iter; GSequenceIter* beyond; gsize first_index; gsize last_index; InfTextChunkSegment* first; InfTextChunkSegment* last; g_return_if_fail(self != NULL); g_return_if_fail(begin + length <= self->length); if(self->length > 0 && length > 0) { first_iter = inf_text_chunk_get_segment(self, begin, &first_index); last_iter = inf_text_chunk_get_segment(self, begin + length, &last_index); first = (InfTextChunkSegment*)g_sequence_get(first_iter); last = (InfTextChunkSegment*)g_sequence_get(last_iter); if(begin > 0 && begin + length < self->length) { if(first_index == 0) { g_assert(first_iter != g_sequence_get_end_iter(self->segments)); first_iter = g_sequence_iter_prev(first_iter); first = (InfTextChunkSegment*)g_sequence_get(first_iter); first_index = first->length; } if(first->author == last->author) { /* Can merge */ if(first == last) { /* Remove within a segment */ g_memmove( first->text + first_index, first->text + last_index, first->length - last_index ); first->length -= (last_index - first_index); beyond = g_sequence_iter_next(last_iter); } else { if(first->length < first_index + last->length - last_index) { first->text = g_realloc( first->text, first_index + last->length - last_index ); } first->length = first_index + last->length - last_index; memcpy( first->text + first_index, last->text + last_index, last->length - last_index ); last_iter = g_sequence_iter_next(last_iter); beyond = last_iter; } } else { /* This could only happen if these are the first or last segment, * of the whole chunk, respectively, which they are not * (as checked above). */ g_assert(first_index > 0); g_assert(last_index < last->length); /* Erase from border segments */ first->length = first_index; if(last_index > 0) { g_memmove( last->text, last->text + last_index, last->length - last_index ); } last->length -= last_index; last->offset = begin; /* We already adjusted offset of last, so only adjust behind */ beyond = g_sequence_iter_next(last_iter); } /* Keep first alive, we merged stuff into it */ first_iter = g_sequence_iter_next(first_iter); } else { if(begin == 0 && length == self->length) { /* Erase everything */ last_iter = g_sequence_iter_next(last_iter); g_assert(last_iter == g_sequence_get_end_iter(self->segments)); beyond = last_iter; } else if(begin == 0) { g_assert(last_index < last->length); /* Erase from beginning */ if(last_index > 0) { g_memmove( last->text, last->text + last_index, last->length - last_index ); last->length -= last_index; last->offset = 0; beyond = g_sequence_iter_next(last_iter); } else { /* First segments are completely removed */ beyond = last_iter; } } else { /* Erase until end */ /* This could only be possible in the last segment, but then we * would erase 0-length, which is a special case we would have * catched elsewhere. */ g_assert(first_index < first->length); if(first_index > 0) { /* Cannot erase whole first chunk */ first->length = first_index; first_iter = g_sequence_iter_next(first_iter); } last_iter = g_sequence_iter_next(last_iter); g_assert(last_iter == g_sequence_get_end_iter(self->segments)); beyond = last_iter; } } /* first_iter and last_iter have been adjusted so that we have to * remove [first_iter, last_iter). */ /* segments are freed through the sequence's destroy function */ g_sequence_remove_range(first_iter, last_iter); /* adjust offsets */ for(first_iter = beyond; first_iter != g_sequence_get_end_iter(self->segments); first_iter = g_sequence_iter_next(first_iter)) { first = (InfTextChunkSegment*)g_sequence_get(first_iter); first->offset -= length; } } self->length -= length; #ifdef CHUNK_CHECK_INTEGRITY g_assert(inf_text_chunk_check_integrity(self) == TRUE); #endif } /** * inf_text_chunk_get_text: * @self: A #InfTextChunk. * @length: (out): Location to write the number of bytes to, or %NULL. * * Returns the content of @self as an array. The text is encoded in * @self's encoding. @length is set to the number of bytes in the returned * buffer, if non-%NULL. The result is _not_ zero-terminated. * * Returns: (type guint8*) (array length=length) (transfer full): Content of * @self. Free with g_free() if no longer in use. **/ gpointer inf_text_chunk_get_text(InfTextChunk* self, gsize* length) { GSequenceIter* iter; InfTextChunkSegment* segment; gsize bytes; gsize cur; gchar* result; g_return_val_if_fail(self != NULL, NULL); bytes = 0; /* First pass, determine size */ for(iter = g_sequence_get_begin_iter(self->segments); iter != g_sequence_get_end_iter(self->segments); iter = g_sequence_iter_next(iter)) { segment = (InfTextChunkSegment*)g_sequence_get(iter); bytes += segment->length; } /* Second pass, copy */ result = g_malloc(bytes); cur = 0; for(iter = g_sequence_get_begin_iter(self->segments); iter != g_sequence_get_end_iter(self->segments); iter = g_sequence_iter_next(iter)) { segment = (InfTextChunkSegment*)g_sequence_get(iter); memcpy(result + cur, segment->text, segment->length); cur += segment->length; } if(length != NULL) *length = bytes; return result; } /** * inf_text_chunk_equal: * @self: A #InfTextChunk. * @other: Another #InfTextChunk. * * Returns whether the two text chunks contain the same text and the same * segments were written by the same authors. * * Returns: Whether the two chunks are equal. **/ gboolean inf_text_chunk_equal(InfTextChunk* self, InfTextChunk* other) { GSequenceIter* iter1; GSequenceIter* iter2; InfTextChunkSegment* segment1; InfTextChunkSegment* segment2; g_return_val_if_fail(self != NULL, FALSE); g_return_val_if_fail(other != NULL, FALSE); g_return_val_if_fail(self->encoding == other->encoding, FALSE); iter1 = g_sequence_get_begin_iter(self->segments); iter2 = g_sequence_get_begin_iter(other->segments); while(iter1 != g_sequence_get_end_iter(self->segments) && iter2 != g_sequence_get_end_iter(other->segments)) { segment1 = (InfTextChunkSegment*)g_sequence_get(iter1); segment2 = (InfTextChunkSegment*)g_sequence_get(iter2); if(segment1->length != segment2->length) return FALSE; if(memcmp(segment1->text, segment2->text, segment1->length) != 0) return FALSE; iter1 = g_sequence_iter_next(iter1); iter2 = g_sequence_iter_next(iter2); } if(iter1 != g_sequence_get_end_iter(self->segments) || iter2 != g_sequence_get_end_iter(other->segments)) { return FALSE; } return TRUE; } /** * inf_text_chunk_iter_init_begin: * @self: A #InfTextChunk. * @iter: (out): A #InfTextChunkIter. * * Sets @iter to point to the first segment of @self. If there are no * segments (i.e. @self is empty), @iter is left untouched and the function * returns %FALSE. * * Returns: Whether @iter was set. **/ gboolean inf_text_chunk_iter_init_begin(InfTextChunk* self, InfTextChunkIter* iter) { g_return_val_if_fail(self != NULL, FALSE); g_return_val_if_fail(iter != NULL, FALSE); if(self->length > 0) { iter->chunk = self; iter->first = g_sequence_get_begin_iter(self->segments); iter->second = g_sequence_iter_next(iter->first); return TRUE; } else { return FALSE; } } /** * inf_text_chunk_iter_init_end: * @self: A #InfTextChunk. * @iter: (out): A #InfTextChunkIter. * * Sets @iter to point to the last segment of @self. If there are no * segments (i.e. @self is empty), @iter is left untouched and the function * returns %FALSE. * * Returns: Whether @iter was set. **/ gboolean inf_text_chunk_iter_init_end(InfTextChunk* self, InfTextChunkIter* iter) { g_return_val_if_fail(self != NULL, FALSE); g_return_val_if_fail(iter != NULL, FALSE); if(self->length > 0) { iter->chunk = self; iter->second = g_sequence_get_end_iter(self->segments); iter->first = g_sequence_iter_prev(iter->second); return TRUE; } else { return FALSE; } } /** * inf_text_chunk_iter_next: * @iter: An initialized #InfTextChunkIter. * * Sets @iter to point to the next segment. If @iter already points to the * last segment, the function returns %FALSE. * * Returns: Whether @iter was set. **/ gboolean inf_text_chunk_iter_next(InfTextChunkIter* iter) { g_return_val_if_fail(iter != NULL, FALSE); if(g_sequence_iter_is_end(iter->second) == FALSE) { iter->first = iter->second; iter->second = g_sequence_iter_next(iter->first); return TRUE; } else { return FALSE; } } /** * inf_text_chunk_iter_prev: * @iter: An initialized #InfTextChunkIter. * * Sets @iter to point to the previous segment. If @iter already points to * the first segment, the function returns %FALSE. * * Returns: Whether @iter has changed. **/ gboolean inf_text_chunk_iter_prev(InfTextChunkIter* iter) { g_return_val_if_fail(iter != NULL, FALSE); if(g_sequence_iter_is_begin(iter->first) == FALSE) { iter->second = iter->first; iter->first = g_sequence_iter_prev(iter->first); return TRUE; } else { return FALSE; } } /** * inf_text_chunk_iter_get_text: * @iter: An initialized #InfTextChunkIter. * * Returns the text of the segment @iter points to. The text is in the * underlaying #InfTextChunk's encoding. * * Returns: (transfer none): The text of the segment @iter points to. **/ gconstpointer inf_text_chunk_iter_get_text(InfTextChunkIter* iter) { g_return_val_if_fail(iter != NULL, NULL); return ((InfTextChunkSegment*)g_sequence_get(iter->first))->text; } /** * inf_text_chunk_iter_get_offset: * @iter: An initialized #InfTextChunkIter. * * Returns the offset of the first character in the segment @iter points to. * * Returns: The offset of the first characters in the segment @iter * points to. **/ guint inf_text_chunk_iter_get_offset(InfTextChunkIter* iter) { InfTextChunkSegment* first; g_return_val_if_fail(iter != NULL, 0); first = (InfTextChunkSegment*)g_sequence_get(iter->first); return first->offset; } /** * inf_text_chunk_iter_get_length: * @iter: An initialized #InfTextChunkIter. * * Returns the number of characters in the segment @iter points to. * * Returns: The number of characters in the segment @iter points to. **/ guint inf_text_chunk_iter_get_length(InfTextChunkIter* iter) { InfTextChunkSegment* first; InfTextChunkSegment* second; g_return_val_if_fail(iter != NULL, 0); if(g_sequence_iter_is_end(iter->second) == TRUE) { first = (InfTextChunkSegment*)g_sequence_get(iter->first); return iter->chunk->length - first->offset; } else { first = (InfTextChunkSegment*)g_sequence_get(iter->first); second = (InfTextChunkSegment*)g_sequence_get(iter->second); return second->offset - first->offset; } } /** * inf_text_chunk_iter_get_bytes: * @iter: An initialized #InfTextChunkIter. * * Returns the number of bytes in the segment @iter points to. * * Returns: The number of bytes in the segment @iter points to. **/ gsize inf_text_chunk_iter_get_bytes(InfTextChunkIter* iter) { g_return_val_if_fail(iter != NULL, 0); return ((InfTextChunkSegment*)g_sequence_get(iter->first))->length; } /** * inf_text_chunk_iter_get_author: * @iter: An initialized #InfTextChunkIter. * * Returns the user ID of the author of the segment @iter points to. * * Returns: The user ID of the author of the segment @iter points to. **/ guint inf_text_chunk_iter_get_author(InfTextChunkIter* iter) { g_return_val_if_fail(iter != NULL, 0); return ((InfTextChunkSegment*)g_sequence_get(iter->first))->author; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinftext/PaxHeaders.26529/inf-text-buffer.c0000644000000000000000000000013213034342512021121 xustar0030 mtime=1483851082.045718513 30 atime=1483851082.045718513 30 ctime=1488261589.204138619 libinfinity-0.7.1/libinftext/inf-text-buffer.c0000644000175000017500000004114313034342512021656 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-text-buffer * @title: InfTextBuffer * @short_description: Interface for the text storage of an #InfTextSession * @include: libinftext/inf-text-buffer.h * @see_also: #InfTextDefaultBuffer * @stability: Unstable * * #InfTextBuffer is an interface on top of #InfBuffer which represents a * text buffer in a similar way as #GtkTextBuffer. #InfTextBuffer can be used * as the buffer of an #InfTextSession, allowing the session to insert text * written by remote users and access text written by local users and send * it to everyone else. * * See #InfTextDefaultBuffer for a simple implementation based on * #InfTextChunk. However, in GUI collaborative editing clients this interface * should be implemented in a more sophisticated way, such that the text of * a document is not stored twice in memory. #InfTextGtkBuffer does this for * GTK+ based user interfaces. */ #include #include G_DEFINE_INTERFACE(InfTextBuffer, inf_text_buffer, INF_TYPE_BUFFER) enum { TEXT_INSERTED, TEXT_ERASED, LAST_SIGNAL }; static guint text_buffer_signals[LAST_SIGNAL]; static void inf_text_buffer_default_init(InfTextBufferInterface* iface) { text_buffer_signals[TEXT_INSERTED] = g_signal_new( "text-inserted", INF_TEXT_TYPE_BUFFER, G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET(InfTextBufferInterface, text_inserted), NULL, NULL, NULL, G_TYPE_NONE, 3, G_TYPE_UINT, INF_TEXT_TYPE_CHUNK | G_SIGNAL_TYPE_STATIC_SCOPE, INF_TYPE_USER ); text_buffer_signals[TEXT_ERASED] = g_signal_new( "text-erased", INF_TEXT_TYPE_BUFFER, G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET(InfTextBufferInterface, text_erased), NULL, NULL, NULL, G_TYPE_NONE, 3, G_TYPE_UINT, INF_TEXT_TYPE_CHUNK | G_SIGNAL_TYPE_STATIC_SCOPE, INF_TYPE_USER ); } /** * inf_text_buffer_get_encoding: * @buffer: A #InfTextBuffer. * * Returns the character encoding that the buffer uses. This means that all * #InfTextChunk return values are encoded in this encoding and all * #InfTextChunk parameters are expected to be encoded in that encoding. * * Returns: The character encoding for @buffer. **/ const gchar* inf_text_buffer_get_encoding(InfTextBuffer* buffer) { InfTextBufferInterface* iface; g_return_val_if_fail(INF_TEXT_IS_BUFFER(buffer), NULL); iface = INF_TEXT_BUFFER_GET_IFACE(buffer); g_return_val_if_fail(iface->get_encoding != NULL, NULL); return iface->get_encoding(buffer); } /** * inf_text_buffer_get_length: * @buffer: A #InfTextBuffer. * * Returns the number of characters in @buffer. * * Returns: The length of @buffer. **/ guint inf_text_buffer_get_length(InfTextBuffer* buffer) { InfTextBufferInterface* iface; g_return_val_if_fail(INF_TEXT_IS_BUFFER(buffer), 0); iface = INF_TEXT_BUFFER_GET_IFACE(buffer); g_return_val_if_fail(iface->get_length != NULL, 0); return iface->get_length(buffer); } /** * inf_text_buffer_get_slice: * @buffer: A #InfTextBuffer. * @pos: Character offset of where to start extracting. * @len: Number of characters to extract. * * Reads @len characters, starting at @pos, from the buffer, and returns them * as a #InfTextChunk. * * Returns: (transfer full): A #InfTextChunk. **/ InfTextChunk* inf_text_buffer_get_slice(InfTextBuffer* buffer, guint pos, guint len) { InfTextBufferInterface* iface; g_return_val_if_fail(INF_TEXT_IS_BUFFER(buffer), NULL); iface = INF_TEXT_BUFFER_GET_IFACE(buffer); g_return_val_if_fail(iface->get_slice != NULL, NULL); return iface->get_slice(buffer, pos, len); } /** * inf_text_buffer_insert_text: * @buffer: A #InfTextBuffer. * @pos: A character offset into @buffer. * @text (type=guint8*) (array length=bytes) (transfer none): A pointer to * the text to insert. * @len: The length (in characters) of @text. * @bytes: The length (in bytes) of @text. * @user: (allow-none): A #InfUser that has inserted the new text, or %NULL. * * Inserts @text into @buffer as written by @author. @text must be encoded in * the character encoding of the buffer, see inf_text_buffer_get_encoding(). **/ void inf_text_buffer_insert_text(InfTextBuffer* buffer, guint pos, gconstpointer text, gsize bytes, guint len, InfUser* user) { InfTextBufferInterface* iface; InfTextChunk* chunk; g_return_if_fail(INF_TEXT_IS_BUFFER(buffer)); g_return_if_fail(text != NULL); g_return_if_fail(user == NULL || INF_IS_USER(user)); iface = INF_TEXT_BUFFER_GET_IFACE(buffer); g_return_if_fail(iface->insert_text != NULL); chunk = inf_text_chunk_new(inf_text_buffer_get_encoding(buffer)); inf_text_chunk_insert_text( chunk, 0, text, bytes, len, user == NULL ? 0 : inf_user_get_id(user) ); iface->insert_text(buffer, pos, chunk, user); inf_text_chunk_free(chunk); } /** * inf_text_buffer_insert_chunk: * @buffer: A #InfTextBuffer. * @pos: A character offset into @buffer. * @chunk: (transfer none): A #InfTextChunk. * @user: (allow-none): A #InfUser inserting @chunk, or %NULL. * * Inserts a #InfTextChunk into @buffer. @user must not necessarily be the * author of @chunk (@chunk may even consist of multiple segments). This * happens when undoing a delete operation that erased another user's text. **/ void inf_text_buffer_insert_chunk(InfTextBuffer* buffer, guint pos, InfTextChunk* chunk, InfUser* user) { InfTextBufferInterface* iface; g_return_if_fail(INF_TEXT_IS_BUFFER(buffer)); g_return_if_fail(chunk != NULL); g_return_if_fail(user == NULL || INF_IS_USER(user)); iface = INF_TEXT_BUFFER_GET_IFACE(buffer); g_return_if_fail(iface->insert_text != NULL); iface->insert_text(buffer, pos, chunk, user); } /** * inf_text_buffer_erase_text: * @buffer: A #InfTextBuffer. * @pos: The position to begin deleting characters from. * @len: The amount of characters to delete. * @user: (allow-none): A #InfUser that erases the text, or %NULL. * * Erases characters from the text buffer. **/ void inf_text_buffer_erase_text(InfTextBuffer* buffer, guint pos, guint len, InfUser* user) { InfTextBufferInterface* iface; g_return_if_fail(INF_TEXT_IS_BUFFER(buffer)); g_return_if_fail(user == NULL || INF_IS_USER(user)); iface = INF_TEXT_BUFFER_GET_IFACE(buffer); g_return_if_fail(iface->erase_text != NULL); iface->erase_text(buffer, pos, len, user); } /** * inf_text_buffer_create_begin_iter: * @buffer: A #InfTextBuffer. * * Creates a #InfTextBufferIter pointing to the first segment of @buffer. * A #InfTextBufferIter is used to traverse the buffer contents in steps of * so-called segments each of which is written by the same user. The function * returns %NULL if there are no segments (i.e. the buffer is empty). * * The iterator stays valid as long as the buffer remains unmodified and * must be freed with inf_text_buffer_destroy_iter() before. * * Returns: (transfer full) (allow-none): A #InfTextBufferIter to be freed by * inf_text_buffer_destroy_iter() when done using it, or %NULL. **/ InfTextBufferIter* inf_text_buffer_create_begin_iter(InfTextBuffer* buffer) { InfTextBufferInterface* iface; g_return_val_if_fail(INF_TEXT_IS_BUFFER(buffer), NULL); iface = INF_TEXT_BUFFER_GET_IFACE(buffer); g_return_val_if_fail(iface->create_begin_iter != NULL, NULL); return iface->create_begin_iter(buffer); } /** * inf_text_buffer_create_end_iter: * @buffer: A #InfTextBuffer. * * Creates a #InfTextBufferIter pointing to the last segment of @buffer. * A #InfTextBufferIter is used to traverse the buffer contents in steps of * so-called segments each of which is written by the same user. The function * returns %NULL if there are no segments (i.e. the buffer is empty). * * The iterator stays valid as long as the buffer remains unmodified and * must be freed with inf_text_buffer_destroy_iter() before. * * Returns: (transfer full) (allow-none): A #InfTextBufferIter to be freed by * inf_text_buffer_destroy_iter() when done using it, or %NULL. **/ InfTextBufferIter* inf_text_buffer_create_end_iter(InfTextBuffer* buffer) { InfTextBufferInterface* iface; g_return_val_if_fail(INF_TEXT_IS_BUFFER(buffer), NULL); iface = INF_TEXT_BUFFER_GET_IFACE(buffer); g_return_val_if_fail(iface->create_end_iter != NULL, NULL); return iface->create_end_iter(buffer); } /** * inf_text_buffer_destroy_iter: * @buffer: A #InfTextBuffer. * @iter: (transfer full): A #InfTextBufferIter pointing into @buffer. * * Destroys a #InfTextBufferIter created by * inf_text_buffer_create_begin_iter() or inf_text_buffer_create_end_iter(). **/ void inf_text_buffer_destroy_iter(InfTextBuffer* buffer, InfTextBufferIter* iter) { InfTextBufferInterface* iface; g_return_if_fail(INF_TEXT_IS_BUFFER(buffer)); g_return_if_fail(iter != NULL); iface = INF_TEXT_BUFFER_GET_IFACE(buffer); g_return_if_fail(iface->destroy_iter != NULL); iface->destroy_iter(buffer, iter); } /** * inf_text_buffer_iter_next: * @buffer: A #InfTextBuffer. * @iter: A #InfTextBufferIter pointing into @buffer. * * Moves @iter to point to the next segment in the buffer. If @iter already * points to the last segment, @iter is left unmodified and the function * returns %FALSE. * * Returns: Whether @iter was moved. **/ gboolean inf_text_buffer_iter_next(InfTextBuffer* buffer, InfTextBufferIter* iter) { InfTextBufferInterface* iface; g_return_val_if_fail(INF_TEXT_IS_BUFFER(buffer), FALSE); g_return_val_if_fail(iter != NULL, FALSE); iface = INF_TEXT_BUFFER_GET_IFACE(buffer); g_return_val_if_fail(iface->iter_next != NULL, FALSE); return iface->iter_next(buffer, iter); } /** * inf_text_buffer_iter_prev: * @buffer: A #InfTextBuffer. * @iter: A #InfTextBufferIter pointing into @buffer. * * Moves @iter to point to the previous segment in the buffer. If @iter * already points to the first segment, @iter is left unmodified and the * function returns %FALSE. * * Returns: Whether @iter was moved. **/ gboolean inf_text_buffer_iter_prev(InfTextBuffer* buffer, InfTextBufferIter* iter) { InfTextBufferInterface* iface; g_return_val_if_fail(INF_TEXT_IS_BUFFER(buffer), FALSE); g_return_val_if_fail(iter != NULL, FALSE); iface = INF_TEXT_BUFFER_GET_IFACE(buffer); g_return_val_if_fail(iface->iter_prev != NULL, FALSE); return iface->iter_prev(buffer, iter); } /** * inf_text_buffer_iter_get_text: * @buffer: A #InfTextBuffer. * @iter: A #InfTextBufferIter pointing into @buffer. * * Returns the text of the segment @iter points to. It is encoded in * @buffer's encoding (see inf_text_buffer_get_encoding()). * * Returns: (transfer full): The text of the segment @iter points to. Free * with g_free() when done using it. **/ gpointer inf_text_buffer_iter_get_text(InfTextBuffer* buffer, InfTextBufferIter* iter) { InfTextBufferInterface* iface; g_return_val_if_fail(INF_TEXT_IS_BUFFER(buffer), NULL); g_return_val_if_fail(iter != NULL, NULL); iface = INF_TEXT_BUFFER_GET_IFACE(buffer); g_return_val_if_fail(iface->iter_get_text != NULL, NULL); return iface->iter_get_text(buffer, iter); } /** * inf_text_buffer_iter_get_offset: * @buffer: A #InfTextBuffer. * @iter: A #InfTextBufferIter pointing into @buffer. * * Returns the offset of the first character in the segment @iter points * to, in characters. * * Returns: The offset of the first character in the segment @iter * points to. **/ guint inf_text_buffer_iter_get_offset(InfTextBuffer* buffer, InfTextBufferIter* iter) { InfTextBufferInterface* iface; g_return_val_if_fail(INF_TEXT_IS_BUFFER(buffer), 0); g_return_val_if_fail(iter != NULL, 0); iface = INF_TEXT_BUFFER_GET_IFACE(buffer); g_return_val_if_fail(iface->iter_get_offset != NULL, 0); return iface->iter_get_offset(buffer, iter); } /** * inf_text_buffer_iter_get_length: * @buffer: A #InfTextBuffer. * @iter: A #InfTextBufferIter pointing into @buffer. * * Returns the length of the segment @iter points to, in characters. * * Returns: The number of characters of the segment @iter points to. **/ guint inf_text_buffer_iter_get_length(InfTextBuffer* buffer, InfTextBufferIter* iter) { InfTextBufferInterface* iface; g_return_val_if_fail(INF_TEXT_IS_BUFFER(buffer), 0); g_return_val_if_fail(iter != NULL, 0); iface = INF_TEXT_BUFFER_GET_IFACE(buffer); g_return_val_if_fail(iface->iter_get_length != NULL, 0); return iface->iter_get_length(buffer, iter); } /** * inf_text_buffer_iter_get_bytes: * @buffer: A #InfTextBuffer. * @iter: A #InfTextBufferIter pointing into @buffer. * * Returns the length of the segment @iter points to, in bytes. * * Returns: The number of bytes of the segment @iter points to. **/ gsize inf_text_buffer_iter_get_bytes(InfTextBuffer* buffer, InfTextBufferIter* iter) { InfTextBufferInterface* iface; g_return_val_if_fail(INF_TEXT_IS_BUFFER(buffer), 0); g_return_val_if_fail(iter != NULL, 0); iface = INF_TEXT_BUFFER_GET_IFACE(buffer); g_return_val_if_fail(iface->iter_get_bytes != NULL, 0); return iface->iter_get_bytes(buffer, iter); } /** * inf_text_buffer_iter_get_author: * @buffer: A #InfTextBuffer. * @iter: A #InfTextBufferIter pointing into @buffer. * * Returns the user ID of the user that has written the segment @iter points * to. * * Returns: The user ID of the user that wrote the segment @iter points * to. **/ guint inf_text_buffer_iter_get_author(InfTextBuffer* buffer, InfTextBufferIter* iter) { InfTextBufferInterface* iface; g_return_val_if_fail(INF_TEXT_IS_BUFFER(buffer), 0); g_return_val_if_fail(iter != NULL, 0); iface = INF_TEXT_BUFFER_GET_IFACE(buffer); g_return_val_if_fail(iface->iter_get_author != NULL, 0); return iface->iter_get_author(buffer, iter); } /** * inf_text_buffer_text_inserted: * @buffer: A #InfTextBuffer. * @pos: A character offset into @buffer. * @chunk: A #InfTextChunk. * @user: (allow-none): A #InfUser inserting @chunk, or %NULL. * * Emits the #InfTextBuffer::text-inserted signal. This is meant to be used * by interface implementations in their @insert_text function, or when text * was inserted by other means. **/ void inf_text_buffer_text_inserted(InfTextBuffer* buffer, guint pos, InfTextChunk* chunk, InfUser* user) { g_return_if_fail(INF_TEXT_IS_BUFFER(buffer)); g_return_if_fail(chunk != NULL); g_return_if_fail(user == NULL || INF_IS_USER(user)); g_signal_emit( G_OBJECT(buffer), text_buffer_signals[TEXT_INSERTED], 0, pos, chunk, user ); } /** * inf_text_buffer_text_erased: * @buffer: A #InfTextBuffer. * @pos: The position to begin deleting characters from. * @chunk: A #InfTextChunk containing the erased text. * @user: (allow-none): A #InfUser that erases the text, or %NULL. * * Emits the #InfTextBuffer::text-erased signal. This is meant to be used * by interface implementations in their @erase_text function, or when text * was erased by other means. **/ void inf_text_buffer_text_erased(InfTextBuffer* buffer, guint pos, InfTextChunk* chunk, InfUser* user) { g_return_if_fail(INF_TEXT_IS_BUFFER(buffer)); g_return_if_fail(chunk != NULL); g_return_if_fail(user == NULL || INF_IS_USER(user)); g_signal_emit( G_OBJECT(buffer), text_buffer_signals[TEXT_ERASED], 0, pos, chunk, user ); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinftext/PaxHeaders.26529/inf-text-buffer.h0000644000000000000000000000013213034342512021126 xustar0030 mtime=1483851082.045718513 30 atime=1483851082.045718513 30 ctime=1488261589.184138663 libinfinity-0.7.1/libinftext/inf-text-buffer.h0000644000175000017500000002010213034342512021653 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_TEXT_BUFFER_H__ #define __INF_TEXT_BUFFER_H__ #include #include #include #include G_BEGIN_DECLS #define INF_TEXT_TYPE_BUFFER (inf_text_buffer_get_type()) #define INF_TEXT_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_TEXT_TYPE_BUFFER, InfTextBuffer)) #define INF_TEXT_IS_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_TEXT_TYPE_BUFFER)) #define INF_TEXT_BUFFER_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), INF_TEXT_TYPE_BUFFER, InfTextBufferInterface)) /** * InfTextBuffer: * * #InfTextBuffer is an opaque data type. You should only access it * via the public API functions. */ typedef struct _InfTextBuffer InfTextBuffer; typedef struct _InfTextBufferInterface InfTextBufferInterface; /** * InfTextBufferIter: (foreign) * * #InfTextBufferIter is an opaque data type. You should only access it * via the public API functions. */ typedef struct _InfTextBufferIter InfTextBufferIter; /** * InfTextBufferInterface: * @get_encoding: Virtual function which returns the character coding of the * buffer. * @get_length: Virtual function to return the total length of the text in * the buffer, in characters. * @get_slice: Virtual function to extract a slice of text from the buffer. * @insert_text: Virtual function to insert text into the buffer. * @erase_text: Virtual function to remove text from the buffer. * @create_begin_iter: Virtual function to create a #InfTextBufferIter at the * beginning of the buffer, used for traversing through buffer segments. * @create_end_iter: Virtual function to create a #InfTextBufferIter at the * end of the buffer, used for traversing through buffer segments. * @destroy_iter: Virtual function to destroy an iterator created with * the @create_begin_iter and @create_end_iter functions. * @iter_next: Virtual function to advance a #InfTextBufferIter to the next * segment. * @iter_prev: Virtual function to retreat a #InfTextBufferIter to the * previous segment. * @iter_get_text: Virtual function to obtain the text of a segment a * #InfTextBufferIter points to. * @iter_get_offset: Virtual function to obtain the offset of the first * character in the segment a #InfTextBufferIter points to. * @iter_get_length: Virtual function to obtain the length of a segment a * #InfTextBufferIter points to. * @iter_get_bytes: Virtual function to obtain the number of bytes in a * segment a #InfTextBufferIter points to. * @iter_get_author: Virtual function to obtain the author of the segment a * #InfTextBufferIter points to. * @text_inserted: Default signal handler of the #InfTextBuffer::text-inserted * signal. * @text_erased: Default signal handler of the #InfTextBuffer::text-erased * signal. * * This structure contains virtual functions and signal handlers of the * #InfTextBuffer interface. */ struct _InfTextBufferInterface { /*< private >*/ GTypeInterface parent; /*< public >*/ /* Virtual table */ const gchar* (*get_encoding)(InfTextBuffer* buffer); guint(*get_length)(InfTextBuffer* buffer); InfTextChunk*(*get_slice)(InfTextBuffer* buffer, guint pos, guint len); void(*insert_text)(InfTextBuffer* buffer, guint pos, InfTextChunk* chunk, InfUser* user); void(*erase_text)(InfTextBuffer* buffer, guint pos, guint len, InfUser* user); InfTextBufferIter*(*create_begin_iter)(InfTextBuffer* buffer); InfTextBufferIter*(*create_end_iter)(InfTextBuffer* buffer); void(*destroy_iter)(InfTextBuffer* buffer, InfTextBufferIter* iter); gboolean(*iter_next)(InfTextBuffer* buffer, InfTextBufferIter* iter); gboolean(*iter_prev)(InfTextBuffer* buffer, InfTextBufferIter* iter); gpointer(*iter_get_text)(InfTextBuffer* buffer, InfTextBufferIter* iter); guint(*iter_get_offset)(InfTextBuffer* buffer, InfTextBufferIter* iter); guint(*iter_get_length)(InfTextBuffer* buffer, InfTextBufferIter* iter); gsize(*iter_get_bytes)(InfTextBuffer* buffer, InfTextBufferIter* iter); guint(*iter_get_author)(InfTextBuffer* buffer, InfTextBufferIter* iter); /* Signals */ void(*text_inserted)(InfTextBuffer* buffer, guint pos, InfTextChunk* chunk, InfUser* user); void(*text_erased)(InfTextBuffer* buffer, guint pos, InfTextChunk* chunk, InfUser* user); }; GType inf_text_buffer_get_type(void) G_GNUC_CONST; const gchar* inf_text_buffer_get_encoding(InfTextBuffer* buffer); guint inf_text_buffer_get_length(InfTextBuffer* buffer); InfTextChunk* inf_text_buffer_get_slice(InfTextBuffer* buffer, guint pos, guint len); void inf_text_buffer_insert_text(InfTextBuffer* buffer, guint pos, gconstpointer text, gsize bytes, guint len, InfUser* user); void inf_text_buffer_insert_chunk(InfTextBuffer* buffer, guint pos, InfTextChunk* chunk, InfUser* user); void inf_text_buffer_erase_text(InfTextBuffer* buffer, guint pos, guint len, InfUser* user); InfTextBufferIter* inf_text_buffer_create_begin_iter(InfTextBuffer* buffer); InfTextBufferIter* inf_text_buffer_create_end_iter(InfTextBuffer* buffer); void inf_text_buffer_destroy_iter(InfTextBuffer* buffer, InfTextBufferIter* iter); gboolean inf_text_buffer_iter_next(InfTextBuffer* buffer, InfTextBufferIter* iter); gboolean inf_text_buffer_iter_prev(InfTextBuffer* buffer, InfTextBufferIter* iter); gpointer inf_text_buffer_iter_get_text(InfTextBuffer* buffer, InfTextBufferIter* iter); guint inf_text_buffer_iter_get_offset(InfTextBuffer* buffer, InfTextBufferIter* iter); guint inf_text_buffer_iter_get_length(InfTextBuffer* buffer, InfTextBufferIter* iter); gsize inf_text_buffer_iter_get_bytes(InfTextBuffer* buffer, InfTextBufferIter* iter); guint inf_text_buffer_iter_get_author(InfTextBuffer* buffer, InfTextBufferIter* iter); void inf_text_buffer_text_inserted(InfTextBuffer* buffer, guint pos, InfTextChunk* chunk, InfUser* user); void inf_text_buffer_text_erased(InfTextBuffer* buffer, guint pos, InfTextChunk* chunk, InfUser* user); G_END_DECLS #endif /* __INF_TEXT_BUFFER_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinftext/PaxHeaders.26529/inf-text-session.c0000644000000000000000000000013213034342512021333 xustar0030 mtime=1483851082.049718536 30 atime=1483851082.045718513 30 ctime=1488261589.220138585 libinfinity-0.7.1/libinftext/inf-text-session.c0000644000175000017500000015727213034342512022103 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* TODO: Optionally broadcast operations delayed to merge adjacent operations * and send as a single request. */ typedef struct _InfTextSessionLocalUser InfTextSessionLocalUser; struct _InfTextSessionLocalUser { InfTextSession* session; InfTextUser* user; GTimeVal last_caret_update; InfIoTimeout* caret_timeout; }; typedef struct _InfTextSessionPrivate InfTextSessionPrivate; struct _InfTextSessionPrivate { guint caret_update_interval; GSList* local_users; }; enum { PROP_0, PROP_CARET_UPDATE_INTERVAL }; typedef struct _InfTextSessionInsertForeachData InfTextSessionInsertForeachData; typedef struct _InfTextSessionEraseForeachData InfTextSessionEraseForeachData; struct _InfTextSessionInsertForeachData { guint position; InfTextChunk* chunk; InfUser* user; }; struct _InfTextSessionEraseForeachData { guint position; guint length; InfUser* user; }; #define INF_TEXT_SESSION_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INF_TEXT_TYPE_SESSION, InfTextSessionPrivate)) static GQuark inf_text_session_error_quark; G_DEFINE_TYPE_WITH_CODE(InfTextSession, inf_text_session, INF_ADOPTED_TYPE_SESSION, G_ADD_PRIVATE(InfTextSession)) /* * Utility functions */ /* Returns the difference between two GTimeVal, in milliseconds */ static guint inf_text_session_timeval_diff(GTimeVal* first, GTimeVal* second) { g_assert(first->tv_sec > second->tv_sec || (first->tv_sec == second->tv_sec && first->tv_usec >= second->tv_usec)); /* Don't risk overflow, don't need to convert to signed int */ return (first->tv_sec - second->tv_sec) * 1000 + (first->tv_usec+500)/1000 - (second->tv_usec+500)/1000; } /* Converts at most *bytes bytes with cd and writes the result, which are * at most 1024 bytes, into xml, setting the given author. *bytes will be * set to the number of bytes not yet processed. */ static void inf_text_session_segment_to_xml(GIConv* cd, xmlNodePtr xml, gconstpointer text, gsize* bytes, /* in/out */ guint author) { gchar utf8_text[1024]; gsize result; gsize bytes_left; gchar* inbuf; gchar* outbuf; bytes_left = 1024; inbuf = *(gchar**)(gpointer)&text; /* cast const away without warning */ outbuf = utf8_text; result = g_iconv( *cd, &inbuf, bytes, &outbuf, &bytes_left ); /* Conversion into UTF-8 should always succeed */ g_assert(result == 0 || errno == E2BIG); inf_xml_util_add_child_text(xml, utf8_text, 1024 - bytes_left); inf_xml_util_set_attribute_uint(xml, "author", author); } static gpointer inf_text_session_segment_from_xml(GIConv* cd, xmlNodePtr xml, guint* length, gsize* bytes, guint* author, GError** error) { gsize bytes_read; gchar* utf8_text; gpointer text; if(!inf_xml_util_get_attribute_uint_required(xml, "author", author, error)) return NULL; utf8_text = inf_xml_util_get_child_text(xml, &bytes_read, length, error); if(!utf8_text) return NULL; text = g_convert_with_iconv( utf8_text, bytes_read, *cd, NULL, bytes, error ); g_free(utf8_text); return text; } /* * Caret/Selection handling */ static InfTextSessionLocalUser* inf_text_session_find_local_user(InfTextSession* session, InfTextUser* user) { InfTextSessionPrivate* priv; GSList* item; InfTextSessionLocalUser* local; priv = INF_TEXT_SESSION_PRIVATE(session); for(item = priv->local_users; item != NULL; item = g_slist_next(item)) { local = (InfTextSessionLocalUser*)item->data; if(local->user == user) return local; } return NULL; } static void inf_text_session_broadcast_caret_selection(InfTextSession* session, InfTextSessionLocalUser* local) { InfAdoptedOperation* operation; InfAdoptedAlgorithm* algorithm; InfAdoptedRequest* request; guint buf_len; guint position; int sel; guint end; algorithm = inf_adopted_session_get_algorithm(INF_ADOPTED_SESSION(session)); position = inf_text_user_get_caret_position(local->user); sel = inf_text_user_get_selection_length(local->user); end = position + sel; /* Clamp position and selection to buffer length. The only case when this is * needed is when a local user's position is beyond the end of the document * since there are some local document modifications. This can happen with * for example InfTextFixlineBuffer. */ /* TODO: This should be handled more cleverly, by propagating the user * position and selection through the buffer, to make sure that at this * point it is always consistent with the infinote view of the buffer. */ buf_len = inf_text_buffer_get_length( INF_TEXT_BUFFER(inf_session_get_buffer(INF_SESSION(session))) ); if(position > buf_len) position = buf_len; if(end > buf_len) end = buf_len; if(end >= position) sel = (int)(end - position); else sel = -(int)(position - end); operation = INF_ADOPTED_OPERATION( inf_text_move_operation_new(position, sel) ); request = inf_adopted_algorithm_generate_request( algorithm, INF_ADOPTED_REQUEST_DO, INF_ADOPTED_USER(local->user), operation ); /* This cannot fail since operation is not applied */ inf_adopted_algorithm_execute_request(algorithm, request, FALSE, NULL); g_object_unref(operation); inf_adopted_session_broadcast_request( INF_ADOPTED_SESSION(session), request ); g_object_unref(request); g_get_current_time(&local->last_caret_update); if(local->caret_timeout != NULL) { inf_io_remove_timeout( inf_adopted_session_get_io(INF_ADOPTED_SESSION(session)), local->caret_timeout ); local->caret_timeout = NULL; } } static void inf_text_session_caret_update_timeout_func(gpointer user_data) { InfTextSessionLocalUser* local; local = (InfTextSessionLocalUser*)user_data; local->caret_timeout = NULL; inf_text_session_broadcast_caret_selection(local->session, local); } static void inf_text_session_selection_changed_cb(InfTextUser* user, guint position, gint sel, gboolean by_request, gpointer user_data) { InfTextSession* session; InfTextSessionPrivate* priv; InfAdoptedAlgorithm* algorithm; InfAdoptedRequest* execute_request; InfTextSessionLocalUser* local; GTimeVal current; guint diff; session = INF_TEXT_SESSION(user_data); priv = INF_TEXT_SESSION_PRIVATE(session); algorithm = inf_adopted_session_get_algorithm(INF_ADOPTED_SESSION(session)); execute_request = inf_adopted_algorithm_get_execute_request(algorithm); /* We should block all changes that have by_request set to FALSE... breaks * if someone else does that... should maybe emit a warning instead. */ g_assert( (execute_request != NULL && by_request == FALSE) || (execute_request == NULL && by_request == TRUE)); if(execute_request == NULL) { local = inf_text_session_find_local_user(session, user); g_assert(local != NULL); g_get_current_time(¤t); diff = inf_text_session_timeval_diff(¤t, &local->last_caret_update); if(diff < priv->caret_update_interval) { if(local->caret_timeout == NULL) { /* TODO: Interrupt timeout if a -caret request is sent from that * local user. */ local->caret_timeout = inf_io_add_timeout( inf_adopted_session_get_io(INF_ADOPTED_SESSION(local->session)), priv->caret_update_interval - diff, inf_text_session_caret_update_timeout_func, local, NULL ); } } else { inf_text_session_broadcast_caret_selection(session, local); } } } static void inf_text_session_add_local_user(InfTextSession* session, InfTextUser* user) { InfTextSessionPrivate* priv; InfTextSessionLocalUser* local; priv = INF_TEXT_SESSION_PRIVATE(session); local = g_slice_new(InfTextSessionLocalUser); local->session = session; local->user = user; g_get_current_time(&local->last_caret_update); local->caret_timeout = NULL; priv->local_users = g_slist_prepend(priv->local_users, local); g_signal_connect_after( G_OBJECT(user), "selection-changed", G_CALLBACK(inf_text_session_selection_changed_cb), session ); } static void inf_text_session_remove_local_user(InfTextSession* session, InfTextSessionLocalUser* local) { InfTextSessionPrivate* priv; priv = INF_TEXT_SESSION_PRIVATE(session); if(local->caret_timeout != NULL) { inf_io_remove_timeout( inf_adopted_session_get_io(INF_ADOPTED_SESSION(session)), local->caret_timeout ); } inf_signal_handlers_disconnect_by_func( G_OBJECT(local->user), G_CALLBACK(inf_text_session_selection_changed_cb), session ); g_slice_free(InfTextSessionLocalUser, local); priv->local_users = g_slist_remove(priv->local_users, local); } static void inf_text_session_local_user_added_cb(InfUserTable* user_table, InfUser* user, gpointer user_data) { g_assert(INF_TEXT_IS_USER(user)); inf_text_session_add_local_user( INF_TEXT_SESSION(user_data), INF_TEXT_USER(user) ); } static void inf_text_session_local_user_removed_cb(InfUserTable* user_table, InfUser* user, gpointer user_data) { InfTextSession* session; InfTextSessionLocalUser* local; g_assert(INF_TEXT_IS_USER(user)); session = INF_TEXT_SESSION(user_data); local = inf_text_session_find_local_user(session, INF_TEXT_USER(user)); g_assert(local != NULL); inf_text_session_remove_local_user(session, local); } static void inf_text_session_block_local_users_selection_changed(InfTextSession* session) { InfTextSessionPrivate* priv; GSList* item; InfTextSessionLocalUser* local; priv = INF_TEXT_SESSION_PRIVATE(session); for(item = priv->local_users; item != NULL; item = g_slist_next(item)) { local = (InfTextSessionLocalUser*)item->data; inf_signal_handlers_block_by_func( G_OBJECT(local->user), G_CALLBACK(inf_text_session_selection_changed_cb), session ); } } static void inf_text_session_unblock_local_users_selection_changed(InfTextSession* sess) { InfTextSessionPrivate* priv; GSList* item; InfTextSessionLocalUser* local; priv = INF_TEXT_SESSION_PRIVATE(sess); for(item = priv->local_users; item != NULL; item = g_slist_next(item)) { local = (InfTextSessionLocalUser*)item->data; inf_signal_handlers_unblock_by_func( G_OBJECT(local->user), G_CALLBACK(inf_text_session_selection_changed_cb), sess ); } } static void inf_text_session_buffer_text_inserted_cb_foreach_func(InfUser* user, gpointer user_data) { InfTextSessionInsertForeachData* data; guint position; gint length; data = (InfTextSessionInsertForeachData*)user_data; if(inf_user_get_status(user) != INF_USER_UNAVAILABLE) { /* TODO: Handle separately if insert-caret */ position = inf_text_user_get_caret_position(INF_TEXT_USER(user)); length = inf_text_user_get_selection_length(INF_TEXT_USER(user)); inf_text_move_operation_transform_insert( data->position, inf_text_chunk_get_length(data->chunk), &position, &length, /* Right gravity for local insertions, left gravity for remote ones */ user == data->user ? FALSE : TRUE ); inf_text_user_set_selection( INF_TEXT_USER(user), position, length, user == data->user ? TRUE : FALSE ); } } static void inf_text_session_buffer_text_erased_cb_foreach_func(InfUser* user, gpointer user_data) { InfTextSessionEraseForeachData* data; guint position; gint length; data = (InfTextSessionEraseForeachData*)user_data; if(inf_user_get_status(user) != INF_USER_UNAVAILABLE) { /* TODO: Handle separately if erase-caret */ position = inf_text_user_get_caret_position(INF_TEXT_USER(user)); length = inf_text_user_get_selection_length(INF_TEXT_USER(user)); inf_text_move_operation_transform_delete( data->position, data->length, &position, &length ); inf_text_user_set_selection( INF_TEXT_USER(user), position, length, user == data->user ? TRUE : FALSE ); } } /* The after handlers readjust the caret and selection properties of the * users. Block handlers so we don't broadcast this. */ static void inf_text_session_buffer_text_inserted_cb(InfTextBuffer* buffer, guint pos, InfTextChunk* chunk, InfUser* user, gpointer user_data) { InfTextSession* session; InfTextSessionPrivate* priv; InfUserTable* user_table; InfAdoptedAlgorithm* algorithm; InfAdoptedRequest* execute_request; InfAdoptedOperation* operation; InfAdoptedRequest* request; InfTextSessionInsertForeachData data; g_assert(INF_TEXT_IS_USER(user)); session = INF_TEXT_SESSION(user_data); priv = INF_TEXT_SESSION_PRIVATE(session); user_table = inf_session_get_user_table(INF_SESSION(session)); algorithm = inf_adopted_session_get_algorithm(INF_ADOPTED_SESSION(session)); execute_request = inf_adopted_algorithm_get_execute_request(algorithm); if(execute_request == NULL) { operation = INF_ADOPTED_OPERATION( inf_text_default_insert_operation_new(pos, chunk) ); request = inf_adopted_algorithm_generate_request( algorithm, INF_ADOPTED_REQUEST_DO, INF_ADOPTED_USER(user), operation ); /* This cannot fail since operation is not applied */ inf_adopted_algorithm_execute_request(algorithm, request, FALSE, NULL); inf_adopted_session_broadcast_request( INF_ADOPTED_SESSION(session), request ); g_object_unref(request); g_object_unref(operation); } data.position = pos; data.chunk = chunk; data.user = user; inf_text_session_block_local_users_selection_changed(session); inf_user_table_foreach_user( user_table, inf_text_session_buffer_text_inserted_cb_foreach_func, &data ); #if 0 /* TODO: If that was an insert-caret request, then do this: */ if(user != NULL) { inf_text_user_set_selection( INF_TEXT_USER(user), pos + inf_text_chunk_get_length(chunk), 0, TRUE ); } #endif inf_text_session_unblock_local_users_selection_changed(session); } static void inf_text_session_buffer_text_erased_cb(InfTextBuffer* buffer, guint pos, InfTextChunk* chunk, InfUser* user, gpointer user_data) { InfTextSession* session; InfTextSessionPrivate* priv; InfUserTable* user_table; InfAdoptedAlgorithm* algorithm; InfAdoptedRequest* execute_request; InfAdoptedOperation* operation; InfAdoptedRequest* request; InfTextSessionEraseForeachData data; g_assert(INF_TEXT_IS_USER(user)); session = INF_TEXT_SESSION(user_data); priv = INF_TEXT_SESSION_PRIVATE(session); user_table = inf_session_get_user_table(INF_SESSION(session)); algorithm = inf_adopted_session_get_algorithm(INF_ADOPTED_SESSION(session)); execute_request = inf_adopted_algorithm_get_execute_request(algorithm); if(execute_request == NULL) { operation = INF_ADOPTED_OPERATION( inf_text_default_delete_operation_new(pos, chunk) ); request = inf_adopted_algorithm_generate_request( algorithm, INF_ADOPTED_REQUEST_DO, INF_ADOPTED_USER(user), operation ); /* This cannot fail since operation is not applied */ inf_adopted_algorithm_execute_request(algorithm, request, FALSE, NULL); inf_adopted_session_broadcast_request( INF_ADOPTED_SESSION(session), request ); g_object_unref(request); g_object_unref(operation); } data.position = pos; data.length = inf_text_chunk_get_length(chunk); data.user = user; inf_text_session_block_local_users_selection_changed(session); inf_user_table_foreach_user( user_table, inf_text_session_buffer_text_erased_cb_foreach_func, &data ); /* TODO: If that was an erase-caret request, then do this: */ #if 0 if(user != NULL) inf_text_user_set_selection(INF_TEXT_USER(user), pos, 0, TRUE); #endif inf_text_session_unblock_local_users_selection_changed(session); } static void inf_text_session_init_text_handlers_user_foreach_func(InfUser* user, gpointer user_data) { g_assert(INF_TEXT_IS_USER(user)); inf_text_session_add_local_user( INF_TEXT_SESSION(user_data), INF_TEXT_USER(user) ); } static void inf_text_session_init_text_handlers(InfTextSession* session) { InfTextBuffer* buffer; InfAdoptedAlgorithm* algorithm; InfUserTable* user_table; buffer = INF_TEXT_BUFFER(inf_session_get_buffer(INF_SESSION(session))); algorithm = inf_adopted_session_get_algorithm(INF_ADOPTED_SESSION(session)); user_table = inf_session_get_user_table(INF_SESSION(session)); g_signal_connect( G_OBJECT(buffer), "text-inserted", G_CALLBACK(inf_text_session_buffer_text_inserted_cb), session ); g_signal_connect( G_OBJECT(buffer), "text-erased", G_CALLBACK(inf_text_session_buffer_text_erased_cb), session ); g_signal_connect( G_OBJECT(user_table), "add-local-user", G_CALLBACK(inf_text_session_local_user_added_cb), session ); g_signal_connect( G_OBJECT(user_table), "remove-local-user", G_CALLBACK(inf_text_session_local_user_removed_cb), session ); inf_user_table_foreach_local_user( user_table, inf_text_session_init_text_handlers_user_foreach_func, session ); } /* * GObject overrides. */ static void inf_text_session_init(InfTextSession* session) { InfTextSessionPrivate* priv; priv = INF_TEXT_SESSION_PRIVATE(session); priv->caret_update_interval = 500; } static void inf_text_session_constructed(GObject* object) { InfTextSession* session; InfTextSessionPrivate* priv; InfTextBuffer* buffer; InfSessionStatus status; G_OBJECT_CLASS(inf_text_session_parent_class)->constructed(object); session = INF_TEXT_SESSION(object); priv = INF_TEXT_SESSION_PRIVATE(session); buffer = INF_TEXT_BUFFER(inf_session_get_buffer(INF_SESSION(session))); g_object_get(G_OBJECT(session), "status", &status, NULL); /* We can either be already synchronized in which case we use the given * buffer as initial buffer. This is used to initiate a new session with * predefined content. In that case, we can directly start through. In the * other case we are getting synchronized in which case the buffer must be * empty (we will fill it during synchronization). Text handlers are * connected when synchronization is complete. */ g_assert( status == INF_SESSION_RUNNING || inf_text_buffer_get_length(buffer) == 0 ); if(status == INF_SESSION_RUNNING) inf_text_session_init_text_handlers(session); } /*static void inf_text_session_dispose_foreach_local_user_func(InfUser* user, gpointer user_data) { g_assert(INF_TEXT_IS_USER(user)); g_signal_handlers_disconnect_matched( G_OBJECT(user), G_SIGNAL_MATCH_FUNC, 0, 0, NULL, G_CALLBACK(inf_text_session_selection_changed_cb), NULL ); }*/ static void inf_text_session_dispose(GObject* object) { InfTextSession* session; InfTextSessionPrivate* priv; InfTextBuffer* buffer; InfUserTable* user_table; InfAdoptedAlgorithm* algorithm; session = INF_TEXT_SESSION(object); priv = INF_TEXT_SESSION_PRIVATE(session); buffer = INF_TEXT_BUFFER(inf_session_get_buffer(INF_SESSION(session))); user_table = inf_session_get_user_table(INF_SESSION(session)); algorithm = inf_adopted_session_get_algorithm(INF_ADOPTED_SESSION(session)); while(priv->local_users != NULL) { inf_text_session_remove_local_user( session, (InfTextSessionLocalUser*)priv->local_users->data ); } inf_signal_handlers_disconnect_by_func( G_OBJECT(buffer), G_CALLBACK(inf_text_session_buffer_text_inserted_cb), session ); inf_signal_handlers_disconnect_by_func( G_OBJECT(buffer), G_CALLBACK(inf_text_session_buffer_text_erased_cb), session ); inf_signal_handlers_disconnect_by_func( G_OBJECT(user_table), G_CALLBACK(inf_text_session_local_user_added_cb), session ); inf_signal_handlers_disconnect_by_func( G_OBJECT(user_table), G_CALLBACK(inf_text_session_local_user_removed_cb), session ); G_OBJECT_CLASS(inf_text_session_parent_class)->dispose(object); } static void inf_text_session_finalize(GObject* object) { InfTextSession* session; InfTextSessionPrivate* priv; session = INF_TEXT_SESSION(object); priv = INF_TEXT_SESSION_PRIVATE(session); G_OBJECT_CLASS(inf_text_session_parent_class)->finalize(object); } static void inf_text_session_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfTextSession* session; InfTextSessionPrivate* priv; session = INF_TEXT_SESSION(object); priv = INF_TEXT_SESSION_PRIVATE(session); switch(prop_id) { case PROP_CARET_UPDATE_INTERVAL: priv->caret_update_interval = g_value_get_uint(value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void inf_text_session_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfTextSession* session; InfTextSessionPrivate* priv; session = INF_TEXT_SESSION(object); priv = INF_TEXT_SESSION_PRIVATE(session); switch(prop_id) { case PROP_CARET_UPDATE_INTERVAL: g_value_set_uint(value, priv->caret_update_interval); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } /* * Network command handlers */ static InfCommunicationScope inf_text_session_handle_user_color_change(InfTextSession* session, InfXmlConnection* connection, xmlNodePtr xml, GError** error) { InfUserTable* user_table; guint user_id; InfUser* user; gdouble hue; user_table = inf_session_get_user_table(INF_SESSION(session)); if(!inf_xml_util_get_attribute_uint_required(xml, "id", &user_id, error)) return INF_COMMUNICATION_SCOPE_PTP; if(!inf_xml_util_get_attribute_double_required(xml, "hue", &hue, error)) return INF_COMMUNICATION_SCOPE_PTP; /* TODO: A public function in InfSession that does the following two checks * (and returns the user). This can also be used in * inf_session_handle_user_status_change */ user = inf_user_table_lookup_user_by_id(user_table, user_id); if(user == NULL) { g_set_error( error, inf_user_error_quark(), INF_USER_ERROR_NO_SUCH_USER, _("No such user with ID '%u'"), user_id ); return INF_COMMUNICATION_SCOPE_PTP; } if(inf_user_get_status(user) == INF_USER_UNAVAILABLE || inf_user_get_connection(user) != connection) { g_set_error_literal( error, inf_user_error_quark(), INF_USER_ERROR_NOT_JOINED, _("User did not join from this connection") ); return INF_COMMUNICATION_SCOPE_PTP; } g_assert(INF_TEXT_IS_USER(user)); if(hue < 0.0 || hue > 1.0) { g_set_error( error, inf_text_session_error_quark, INF_TEXT_SESSION_ERROR_INVALID_HUE, _("Invalid hue value: '%g'"), hue ); return INF_COMMUNICATION_SCOPE_PTP; } g_object_set(G_OBJECT(user), "hue", hue, NULL); return INF_COMMUNICATION_SCOPE_GROUP; } /* * InfSession overrides */ static void inf_text_session_to_xml_sync(InfSession* session, xmlNodePtr parent) { InfTextBuffer* buffer; InfTextBufferIter* iter; xmlNodePtr xml; gboolean result; gchar* text; gsize total_bytes; gsize bytes_left; GIConv cd; INF_SESSION_CLASS(inf_text_session_parent_class)->to_xml_sync( session, parent ); buffer = INF_TEXT_BUFFER(inf_session_get_buffer(session)); cd = g_iconv_open("UTF-8", inf_text_buffer_get_encoding(buffer)); iter = inf_text_buffer_create_begin_iter(buffer); if(iter != NULL) { result = TRUE; while(result == TRUE) { /* Write segment in 1024 byte chunks */ text = inf_text_buffer_iter_get_text(buffer, iter); total_bytes = inf_text_buffer_iter_get_bytes(buffer, iter); bytes_left = total_bytes; while(bytes_left > 0) { xml = xmlNewChild(parent, NULL, (const xmlChar*)"sync-segment", NULL); inf_text_session_segment_to_xml( &cd, xml, text + total_bytes - bytes_left, &bytes_left, inf_text_buffer_iter_get_author(buffer, iter) ); } g_free(text); result = inf_text_buffer_iter_next(buffer, iter); } inf_text_buffer_destroy_iter(buffer, iter); } g_iconv_close(cd); } static gboolean inf_text_session_process_xml_sync(InfSession* session, InfXmlConnection* connection, const xmlNodePtr xml, GError** error) { InfTextBuffer* buffer; GIConv cd; gpointer text; gsize bytes; guint length; guint author; InfUser* user; if(strcmp((const char*)xml->name, "sync-segment") == 0) { buffer = INF_TEXT_BUFFER(inf_session_get_buffer(session)); cd = g_iconv_open(inf_text_buffer_get_encoding(buffer), "UTF-8"); text = inf_text_session_segment_from_xml( &cd, xml, &length, &bytes, &author, error ); g_iconv_close(cd); if(text == NULL) return FALSE; if(author != 0) { /* TODO: inf_user_table_lookup_user_by_id_required, with error. */ user = inf_user_table_lookup_user_by_id( inf_session_get_user_table(session), author ); if(user == NULL) { g_free(text); g_set_error( error, inf_user_error_quark(), INF_USER_ERROR_NO_SUCH_USER, _("No such user with ID '%u'"), author ); return FALSE; } } else { user = NULL; } inf_text_buffer_insert_text( buffer, inf_text_buffer_get_length(buffer), text, bytes, length, user ); g_free(text); return TRUE; } else { return INF_SESSION_CLASS(inf_text_session_parent_class)->process_xml_sync( session, connection, xml, error ); } } static InfCommunicationScope inf_text_session_process_xml_run(InfSession* session, InfXmlConnection* connection, const xmlNodePtr xml, GError** error) { if(strcmp((const char*)xml->name, "user-color-change") == 0) { return inf_text_session_handle_user_color_change( INF_TEXT_SESSION(session), connection, xml, error ); } else { return INF_SESSION_CLASS(inf_text_session_parent_class)->process_xml_run( session, connection, xml, error ); } } static GArray* inf_text_session_get_xml_user_props(InfSession* session, InfXmlConnection* connection, const xmlNodePtr xml) { InfSessionClass* parent_class; GArray* array; GParameter* parameter; guint caret; gint selection; gdouble hue; parent_class = INF_SESSION_CLASS(inf_text_session_parent_class); array = parent_class->get_xml_user_props(session, connection, xml); /* TODO: Error reporting for get_xml_user_props */ if(inf_xml_util_get_attribute_uint(xml, "caret", &caret, NULL)) { parameter = inf_session_get_user_property(array, "caret-position"); g_value_init(¶meter->value, G_TYPE_UINT); g_value_set_uint(¶meter->value, caret); } parameter = inf_session_get_user_property(array, "selection-length"); g_value_init(¶meter->value, G_TYPE_INT); if(inf_xml_util_get_attribute_int(xml, "selection", &selection, NULL)) g_value_set_int(¶meter->value, selection); else g_value_set_int(¶meter->value, 0); parameter = inf_session_get_user_property(array, "hue"); g_value_init(¶meter->value, G_TYPE_DOUBLE); /* Use a random hue if none set */ if(inf_xml_util_get_attribute_double(xml, "hue", &hue, NULL)) g_value_set_double(¶meter->value, hue); else g_value_set_double(¶meter->value, g_random_double()); return array; } static void inf_text_session_set_xml_user_props(InfSession* session, const GParameter* params, guint n_params, xmlNodePtr xml) { InfSessionClass* parent_class; const GParameter* param; parent_class = INF_SESSION_CLASS(inf_text_session_parent_class); parent_class->set_xml_user_props(session, params, n_params, xml); param = inf_session_lookup_user_property( params, n_params, "caret-position" ); if(param != NULL) { inf_xml_util_set_attribute_uint( xml, "caret", g_value_get_uint(¶m->value) ); } param = inf_session_lookup_user_property( params, n_params, "selection-length" ); if(param != NULL) { inf_xml_util_set_attribute_int( xml, "selection", g_value_get_int(¶m->value) ); } param = inf_session_lookup_user_property( params, n_params, "hue" ); if(param != NULL) { inf_xml_util_set_attribute_double( xml, "hue", g_value_get_double(¶m->value) ); } } static gboolean inf_text_session_validate_user_props(InfSession* session, const GParameter* params, guint n_params, InfUser* exclude, GError** error) { InfSessionClass* parent_class; const GParameter* caret; gboolean result; parent_class = INF_SESSION_CLASS(inf_text_session_parent_class); result = parent_class->validate_user_props( session, params, n_params, exclude, error ); if(result == FALSE) return FALSE; caret = inf_session_lookup_user_property( params, n_params, "caret-position" ); if(caret == NULL) { g_set_error_literal( error, inf_request_error_quark(), INF_REQUEST_ERROR_NO_SUCH_ATTRIBUTE, _("\"caret\" attribute in user message is missing") ); return FALSE; } /* Selection is optional and 0 if not given */ return result; } static InfUser* inf_text_session_user_new(InfSession* session, GParameter* params, guint n_params) { GObject* object; object = g_object_newv(INF_TEXT_TYPE_USER, n_params, params); return INF_USER(object); } static void inf_text_session_synchronization_complete(InfSession* session, InfXmlConnection* connection) { InfSessionClass* parent_class; InfSessionStatus status; parent_class = INF_SESSION_CLASS(inf_text_session_parent_class); status = inf_session_get_status(session); parent_class->synchronization_complete(session, connection); /* init_text_handlers needs to access the algorithm which is created in the * parent class default signal handler which is why we call this afterwards. * Note that we need to query status before, so we know whether the session * itself was synchronized (status == SYNCHRONIZING) or whether we just * synchronized the session to someone else (status == RUNNING). */ if(status == INF_SESSION_SYNCHRONIZING) inf_text_session_init_text_handlers(INF_TEXT_SESSION(session)); } /* * InfAdoptedSession overrides */ static void inf_text_session_request_to_xml(InfAdoptedSession* session, xmlNodePtr xml, InfAdoptedRequest* request, InfAdoptedStateVector* diff_vec, gboolean for_sync) { InfTextChunk* chunk; InfTextChunkIter iter; gboolean result; xmlNodePtr op_xml; gchar* utf8_text; gsize bytes_read; gsize bytes_written; GIConv cd; xmlNodePtr child; const gchar* text; gsize total_bytes; gsize bytes_left; InfAdoptedOperation* operation; switch(inf_adopted_request_get_request_type(request)) { case INF_ADOPTED_REQUEST_DO: operation = inf_adopted_request_get_operation(request); if(INF_TEXT_IS_INSERT_OPERATION(operation)) { op_xml = xmlNewNode(NULL, (const xmlChar*)"insert-caret"); inf_xml_util_set_attribute_uint( op_xml, "pos", inf_text_insert_operation_get_position( INF_TEXT_INSERT_OPERATION(operation) ) ); /* Must be default insert operation so we get the inserted text */ g_assert(INF_TEXT_IS_DEFAULT_INSERT_OPERATION(operation)); chunk = inf_text_default_insert_operation_get_chunk( INF_TEXT_DEFAULT_INSERT_OPERATION(operation) ); result = inf_text_chunk_iter_init_begin(chunk, &iter); g_assert(result == TRUE); utf8_text = g_convert( inf_text_chunk_iter_get_text(&iter), inf_text_chunk_iter_get_bytes(&iter), "UTF-8", inf_text_chunk_get_encoding(chunk), &bytes_read, &bytes_written, NULL ); /* Conversion to UTF-8 should always succeed */ g_assert(utf8_text != NULL); g_assert(bytes_read == inf_text_chunk_iter_get_bytes(&iter)); inf_xml_util_add_child_text(op_xml, utf8_text, bytes_written); g_free(utf8_text); /* We only allow a single segment because the whole inserted text must * be written by a single user. */ g_assert(inf_text_chunk_iter_next(&iter) == FALSE); } else if(INF_TEXT_IS_DELETE_OPERATION(operation)) { op_xml = xmlNewNode(NULL, (const xmlChar*)"delete-caret"); inf_xml_util_set_attribute_uint( op_xml, "pos", inf_text_delete_operation_get_position( INF_TEXT_DELETE_OPERATION(operation) ) ); if(for_sync == TRUE) { /* Must be default delete operation so we get chunk */ g_assert(INF_TEXT_IS_DEFAULT_DELETE_OPERATION(operation)); chunk = inf_text_default_delete_operation_get_chunk( INF_TEXT_DEFAULT_DELETE_OPERATION(operation) ); /* Need to transmit all deleted data */ cd = g_iconv_open("UTF-8", inf_text_chunk_get_encoding(chunk)); result = inf_text_chunk_iter_init_begin(chunk, &iter); while(result == TRUE) { text = inf_text_chunk_iter_get_text(&iter); total_bytes = inf_text_chunk_iter_get_bytes(&iter); bytes_left = total_bytes; child = xmlNewChild(op_xml, NULL, (const xmlChar*)"segment", NULL); while(bytes_left > 0) { inf_text_session_segment_to_xml( &cd, child, text + total_bytes - bytes_left, &bytes_left, inf_text_chunk_iter_get_author(&iter) ); } result = inf_text_chunk_iter_next(&iter); } g_iconv_close(cd); } else { /* Just transmit position and length, the other site generates a * InfTextRemoteDeleteOperation from that and is able to restore the * deleted text for potential Undo. */ inf_xml_util_set_attribute_uint( op_xml, "len", inf_text_delete_operation_get_length( INF_TEXT_DELETE_OPERATION(operation) ) ); } } else if(for_sync == FALSE && INF_TEXT_IS_MOVE_OPERATION(operation)) { op_xml = xmlNewNode(NULL, (const xmlChar*)"move"); inf_xml_util_set_attribute_uint( op_xml, "caret", inf_text_move_operation_get_position( INF_TEXT_MOVE_OPERATION(operation) ) ); inf_xml_util_set_attribute_int( op_xml, "selection", inf_text_move_operation_get_length(INF_TEXT_MOVE_OPERATION(operation)) ); } else if(for_sync == FALSE && INF_ADOPTED_IS_NO_OPERATION(operation)) { op_xml = xmlNewNode(NULL, (const xmlChar*)"no-op"); } else { g_assert_not_reached(); } break; case INF_ADOPTED_REQUEST_UNDO: op_xml = xmlNewNode(NULL, (const xmlChar*)"undo-caret"); break; case INF_ADOPTED_REQUEST_REDO: op_xml = xmlNewNode(NULL, (const xmlChar*)"redo-caret"); break; default: g_assert_not_reached(); break; } g_assert(op_xml != NULL); inf_adopted_session_write_request_info( session, request, diff_vec, xml, op_xml ); } static InfAdoptedRequest* inf_text_session_xml_to_request(InfAdoptedSession* session, xmlNodePtr xml, InfAdoptedStateVector* diff_vec, gboolean for_sync, GError** error) { InfTextBuffer* buffer; InfAdoptedUser* user; guint user_id; InfAdoptedStateVector* vector; xmlNodePtr op_xml; InfAdoptedOperation* operation; InfAdoptedRequestType type; InfAdoptedRequest* request; guint pos; gchar* text; gsize bytes; InfTextChunk* chunk; gchar* utf8_text; gsize in_bytes; guint length; xmlNodePtr child; GIConv cd; guint author; gboolean cmp; gint selection; buffer = INF_TEXT_BUFFER(inf_session_get_buffer(INF_SESSION(session))); cmp = inf_adopted_session_read_request_info( session, xml, diff_vec, &user, &vector, &op_xml, error ); if(cmp == FALSE) return FALSE; user_id = (user == NULL) ? 0 : inf_user_get_id(INF_USER(user)); if(strcmp((const char*)op_xml->name, "insert") == 0 || strcmp((const char*)op_xml->name, "insert-caret") == 0) { type = INF_ADOPTED_REQUEST_DO; if(!inf_xml_util_get_attribute_uint_required(op_xml, "pos", &pos, error)) goto fail; utf8_text = inf_xml_util_get_child_text(op_xml, &in_bytes, &length, error); if(!utf8_text) goto fail; text = g_convert( utf8_text, in_bytes, inf_text_buffer_get_encoding(buffer), "UTF-8", NULL, &bytes, error ); g_free(utf8_text); if(text == NULL) goto fail; chunk = inf_text_chunk_new(inf_text_buffer_get_encoding(buffer)); inf_text_chunk_insert_text(chunk, 0, text, bytes, length, user_id); g_free(text); operation = INF_ADOPTED_OPERATION( inf_text_default_insert_operation_new(pos, chunk) ); inf_text_chunk_free(chunk); } else if(strcmp((const char*)op_xml->name, "delete") == 0 || strcmp((const char*)op_xml->name, "delete-caret") == 0) { type = INF_ADOPTED_REQUEST_DO; if(!inf_xml_util_get_attribute_uint_required(op_xml, "pos", &pos, error)) goto fail; if(for_sync == TRUE) { chunk = inf_text_chunk_new(inf_text_buffer_get_encoding(buffer)); cd = g_iconv_open(inf_text_buffer_get_encoding(buffer), "UTF-8"); g_assert(cd != (GIConv)(-1)); for(child = op_xml->children; child != NULL; child = child->next) { if(strcmp((const char*)child->name, "segment") == 0) { text = inf_text_session_segment_from_xml( &cd, child, &length, &bytes, &author, error ); if(text == NULL) { inf_text_chunk_free(chunk); g_iconv_close(cd); goto fail; } else { inf_text_chunk_insert_text( chunk, inf_text_chunk_get_length(chunk), text, bytes, length, author ); g_free(text); } } else { /* TODO: Error */ } } g_iconv_close(cd); operation = INF_ADOPTED_OPERATION( inf_text_default_delete_operation_new(pos, chunk) ); inf_text_chunk_free(chunk); } else { cmp = inf_xml_util_get_attribute_uint_required( op_xml, "len", &length, error ); if(cmp == FALSE) goto fail; operation = INF_ADOPTED_OPERATION( inf_text_remote_delete_operation_new(pos, length) ); } } else if(strcmp((const char*)op_xml->name, "move") == 0) { type = INF_ADOPTED_REQUEST_DO; cmp = inf_xml_util_get_attribute_uint_required( op_xml, "caret", &pos, error ); if(cmp == FALSE) goto fail; cmp = inf_xml_util_get_attribute_int_required( op_xml, "selection", &selection, error ); if(cmp == FALSE) goto fail; operation = INF_ADOPTED_OPERATION( inf_text_move_operation_new(pos, selection) ); } else if(strcmp((const char*)op_xml->name, "no-op") == 0) { type = INF_ADOPTED_REQUEST_DO; operation = INF_ADOPTED_OPERATION(inf_adopted_no_operation_new()); } else if(strcmp((const char*)op_xml->name, "undo") == 0 || strcmp((const char*)op_xml->name, "undo-caret") == 0) { type = INF_ADOPTED_REQUEST_UNDO; } else if(strcmp((const char*)op_xml->name, "redo") == 0 || strcmp((const char*)op_xml->name, "redo-caret") == 0) { type = INF_ADOPTED_REQUEST_REDO; } else { /* TODO: Error */ goto fail; } switch(type) { case INF_ADOPTED_REQUEST_DO: g_assert(operation != NULL); request = inf_adopted_request_new_do( vector, user_id, operation, g_get_real_time() ); g_object_unref(operation); break; case INF_ADOPTED_REQUEST_UNDO: request = inf_adopted_request_new_undo( vector, user_id, g_get_real_time() ); break; case INF_ADOPTED_REQUEST_REDO: request = inf_adopted_request_new_redo( vector, user_id, g_get_real_time() ); break; default: g_assert_not_reached(); break; } inf_adopted_state_vector_free(vector); return request; fail: inf_adopted_state_vector_free(vector); return NULL; } /* * Gype registration. */ static void inf_text_session_class_init(InfTextSessionClass* text_session_class) { GObjectClass* object_class; InfSessionClass* session_class; InfAdoptedSessionClass* adopted_session_class; object_class = G_OBJECT_CLASS(text_session_class); session_class = INF_SESSION_CLASS(text_session_class); adopted_session_class = INF_ADOPTED_SESSION_CLASS(text_session_class); object_class->constructed = inf_text_session_constructed; object_class->dispose = inf_text_session_dispose; object_class->finalize = inf_text_session_finalize; object_class->set_property = inf_text_session_set_property; object_class->get_property = inf_text_session_get_property; session_class->to_xml_sync = inf_text_session_to_xml_sync; session_class->process_xml_sync = inf_text_session_process_xml_sync; session_class->process_xml_run = inf_text_session_process_xml_run; session_class->get_xml_user_props = inf_text_session_get_xml_user_props; session_class->set_xml_user_props = inf_text_session_set_xml_user_props; session_class->validate_user_props = inf_text_session_validate_user_props; session_class->user_new = inf_text_session_user_new; session_class->synchronization_complete = inf_text_session_synchronization_complete; adopted_session_class->xml_to_request = inf_text_session_xml_to_request; adopted_session_class->request_to_xml = inf_text_session_request_to_xml; inf_text_session_error_quark = g_quark_from_static_string( "INF_TEXT_SESSION_ERROR" ); g_object_class_install_property( object_class, PROP_CARET_UPDATE_INTERVAL, g_param_spec_uint( "caret-update-interval", "Caret update interval", "Minimum number of milliseconds between caret update broadcasts", 0, G_MAXUINT, 500, G_PARAM_READWRITE | G_PARAM_CONSTRUCT ) ); } /* * Public API. */ /** * inf_text_session_new: (constructor) * @manager: A #InfCommunicationManager. * @buffer: An initial #InfTextBuffer. * @io: A #InfIo object. * @status: The initial status of the session. * @sync_group: (allow-none): A group in which the session is synchronized. * Ignored if @status is %INF_SESSION_RUNNING. * @sync_connection: (allow-none): A connection to synchronize the session * from. Ignored if @status is %INF_SESSION_RUNNING. * * Creates a new #InfTextSession. The communication manager is used to send * and receive requests from subscription and synchronization. @buffer will be * set to be initially empty if the session is initially synchronized * (see below). @io is required to trigger timeouts. * * If @status is %INF_SESSION_PRESYNC or %INF_SESSION_SYNCHRONIZING, then the * session will initially be sychronized, meaning the initial content is * retrieved from @sync_connection. If you are subscribed to the session, set * the subscription group via inf_session_set_subscription_group(). * * Returns: (transfer full): A new #InfTextSession. **/ InfTextSession* inf_text_session_new(InfCommunicationManager* manager, InfTextBuffer* buffer, InfIo* io, InfSessionStatus status, InfCommunicationGroup* sync_group, InfXmlConnection* sync_connection) { GObject* object; g_return_val_if_fail(INF_COMMUNICATION_IS_MANAGER(manager), NULL); g_return_val_if_fail(INF_TEXT_IS_BUFFER(buffer), NULL); g_return_val_if_fail(INF_IS_IO(io), NULL); g_return_val_if_fail( (status == INF_SESSION_RUNNING && sync_group == NULL && sync_connection == NULL) || (status != INF_SESSION_RUNNING && INF_COMMUNICATION_IS_GROUP(sync_group) && INF_IS_XML_CONNECTION(sync_connection)), NULL ); object = g_object_new( INF_TEXT_TYPE_SESSION, "communication-manager", manager, "buffer", buffer, "status", status, "sync-group", sync_group, "sync-connection", sync_connection, "io", io, NULL ); return INF_TEXT_SESSION(object); } /** * inf_text_session_new_with_user_table: (constructor) * @manager: A #InfCommunicationManager. * @buffer: An initial #InfTextBuffer. * @io: A #InfIo object. * @user_table: A #InfUserTable. * @status: The initial status for the session. * @sync_group: (allow-none): A group in which the session is synchronized. * Ignored if @status is %INF_SESSION_RUNNING. * @sync_connection: (allow-none): A connection to synchronize the session * from. Ignored if @status is %INF_SESSION_RUNNING. * * Creates a new #InfTextSession. The connection manager is used to send and * receive requests from subscription and synchronization. @buffer will be * set to be initially empty if the session is initially synchronized * (see below). @io is required to trigger timeouts. * * If @status is %INF_SESSION_PRESYNC or %INF_SESSION_SYNCHRONIZING, then the * session will initially be sychronized, meaning the initial content is * retrieved from @sync_connection. If you are subscribed to the session, set * the subscription group via inf_session_set_subscription_group(). * * @user_table is used as an initial user table. The user table should only * contain unavailable users, if any, that may rejoin during the session. If * there was an available user in the user table, it would probably belong * to another session, but different sessions cannot share the same user * object. * * Returns: (transfer full): A new #InfTextSession. **/ InfTextSession* inf_text_session_new_with_user_table(InfCommunicationManager* manager, InfTextBuffer* buffer, InfIo* io, InfUserTable* user_table, InfSessionStatus status, InfCommunicationGroup* sync_group, InfXmlConnection* sync_connection) { /* TODO: Can it happen that the user_table is set explicitely PLUS the * session is synchronized? If not then this function can be simplified */ GObject* object; g_return_val_if_fail(INF_COMMUNICATION_IS_MANAGER(manager), NULL); g_return_val_if_fail(INF_TEXT_IS_BUFFER(buffer), NULL); g_return_val_if_fail(INF_IS_IO(io), NULL); g_return_val_if_fail(INF_IS_USER_TABLE(user_table), NULL); g_return_val_if_fail( (status == INF_SESSION_RUNNING && sync_group == NULL && sync_connection == NULL) || (status != INF_SESSION_RUNNING && INF_COMMUNICATION_IS_GROUP(sync_group) && INF_IS_XML_CONNECTION(sync_connection)), NULL ); object = g_object_new( INF_TEXT_TYPE_SESSION, "communication-manager", manager, "buffer", buffer, "user-table", user_table, "status", status, "sync-group", sync_group, "sync-connection", sync_connection, "io", io, NULL ); return INF_TEXT_SESSION(object); } /** * inf_text_session_set_user_color: * @session: A #InfTextSession. * @user: A local #InfTextUser from @session's user table. * @hue: New hue value for @user's color. Ranges from 0.0 (red) to 1.0 (red). * * Changes the user color of @user. @user must have the %INF_USER_LOCAL flag * set. */ void inf_text_session_set_user_color(InfTextSession* session, InfTextUser* user, gdouble hue) { xmlNodePtr xml; g_return_if_fail(INF_TEXT_IS_SESSION(session)); g_return_if_fail(INF_TEXT_IS_USER(user)); g_return_if_fail(hue >= 0.0 && hue <= 1.0); g_return_if_fail( inf_user_get_status(INF_USER(user)) != INF_USER_UNAVAILABLE ); g_return_if_fail( (inf_user_get_flags(INF_USER(user)) & INF_USER_LOCAL) != 0 ); xml = xmlNewNode(NULL, (const xmlChar*)"user-color-change"); inf_xml_util_set_attribute_uint(xml, "id", inf_user_get_id(INF_USER(user))); inf_xml_util_set_attribute_double(xml, "hue", hue); inf_session_send_to_subscriptions(INF_SESSION(session), xml); g_object_set(G_OBJECT(user), "hue", hue, NULL); } /** * inf_text_session_flush_requests_for_user: * @session: A #InfTextSession. * @user: The #InfTextUser for which to flush messages. * * This function sends all pending requests for @user immediately. Requests * that modify the buffer are not queued normally, but cursor movement * requests are delayed in case are issued frequently, to save bandwidth. * * The main purpose of this function is to send all pending requests before * changing a user's status to inactive or unavailable since inactive users * are automatically activated as soon as they issue a request. * * TODO: We should probably detect this automatically, without requiring * people to call this function, i.e. flush requests for local users just * before they become inactive. * * @user must have the %INF_USER_LOCAL flag set. */ void inf_text_session_flush_requests_for_user(InfTextSession* session, InfTextUser* user) { InfTextSessionLocalUser* local; g_return_if_fail(INF_TEXT_IS_SESSION(session)); g_return_if_fail(INF_TEXT_IS_USER(user)); local = inf_text_session_find_local_user(session, user); g_assert(local != NULL); if(local->caret_timeout != NULL) { inf_text_session_broadcast_caret_selection(session, local); } } /** * inf_text_session_join_user: * @proxy: A #InfSessionProxy with a #InfTextSession session. * @name: The name of the user to join. * @status: The initial status of the user to join. Must not be * @INF_USER_UNAVAILABLE. * @hue: The user color of the user to join. * @caret_position: The initial position of the new user's cursor. * @selection_length: The initial length of the new user's selection. * @func: (scope async): Function to call after completion of the request, * or %NULL. * @user_data: Additional data to pass to @func. * * This functions creates a user join request for an #InfTextSession. This is * a shortcut for inf_session_proxy_join_user(). * * Returns: (transfer full): A #InfRequest, or %NULL. */ InfRequest* inf_text_session_join_user(InfSessionProxy* proxy, const gchar* name, InfUserStatus status, gdouble hue, guint caret_position, int selection_length, InfRequestFunc func, gpointer user_data) { #define N_PARAMS 6u GParameter params[N_PARAMS] = { { "hue", { 0 } }, { "vector", { 0 } }, { "caret-position", { 0 } }, { "selection-length", { 0 } }, { "name", { 0 } }, { "status", { 0 } } }; InfSession* session; InfRequest* request; guint i; g_return_val_if_fail(INF_IS_SESSION_PROXY(proxy), NULL); g_object_get(G_OBJECT(proxy), "session", &session, NULL); g_return_val_if_fail(INF_TEXT_IS_SESSION(session), NULL); g_value_init(¶ms[0].value, G_TYPE_DOUBLE); g_value_set_double(¶ms[0].value, hue); g_value_init(¶ms[1].value, INF_ADOPTED_TYPE_STATE_VECTOR); g_value_set_boxed( ¶ms[1].value, inf_adopted_algorithm_get_current( inf_adopted_session_get_algorithm(INF_ADOPTED_SESSION(session)) ) ); g_value_init(¶ms[2].value, G_TYPE_UINT); g_value_set_uint(¶ms[2].value, caret_position); g_value_init(¶ms[3].value, G_TYPE_INT); g_value_set_int(¶ms[3].value, selection_length); g_value_init(¶ms[4].value, G_TYPE_STRING); g_value_set_string(¶ms[4].value, name); /* TODO: set_static_string? */ g_value_init(¶ms[5].value, INF_TYPE_USER_STATUS); g_value_set_enum(¶ms[5].value, status); request = inf_session_proxy_join_user( proxy, N_PARAMS, params, func, user_data ); for(i = 0; i < N_PARAMS; ++i) g_value_unset(¶ms[i].value); #undef N_PARAMS g_object_unref(session); return request; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinftext/PaxHeaders.26529/inf-text-remote-delete-operation.h0000644000000000000000000000013213034342512024406 xustar0030 mtime=1483851082.045718513 30 atime=1483851082.045718513 30 ctime=1488261589.196138637 libinfinity-0.7.1/libinftext/inf-text-remote-delete-operation.h0000644000175000017500000000474313034342512025150 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_TEXT_REMOTE_DELETE_OPERATION_H__ #define __INF_TEXT_REMOTE_DELETE_OPERATION_H__ #include #include G_BEGIN_DECLS #define INF_TEXT_TYPE_REMOTE_DELETE_OPERATION (inf_text_remote_delete_operation_get_type()) #define INF_TEXT_REMOTE_DELETE_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_TEXT_TYPE_REMOTE_DELETE_OPERATION, InfTextRemoteDeleteOperation)) #define INF_TEXT_REMOTE_DELETE_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INF_TEXT_TYPE_REMOTE_DELETE_OPERATION, InfTextRemoteDeleteOperationClass)) #define INF_TEXT_IS_REMOTE_DELETE_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_TEXT_TYPE_REMOTE_DELETE_OPERATION)) #define INF_TEXT_IS_REMOTE_DELETE_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INF_TEXT_TYPE_REMOTE_DELETE_OPERATION)) #define INF_TEXT_REMOTE_DELETE_OPERATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INF_TEXT_TYPE_REMOTE_DELETE_OPERATION, InfTextRemoteDeleteOperationClass)) typedef struct _InfTextRemoteDeleteOperation InfTextRemoteDeleteOperation; typedef struct _InfTextRemoteDeleteOperationClass InfTextRemoteDeleteOperationClass; struct _InfTextRemoteDeleteOperationClass { GObjectClass parent_class; }; struct _InfTextRemoteDeleteOperation { GObject parent; }; GType inf_text_remote_delete_operation_get_type(void) G_GNUC_CONST; InfTextRemoteDeleteOperation* inf_text_remote_delete_operation_new(guint position, guint length); G_END_DECLS #endif /* __INF_TEXT_REMOTE_DELETE_OPERATION_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinftext/PaxHeaders.26529/inf-text-default-delete-operation.h0000644000000000000000000000013213034342512024537 xustar0030 mtime=1483851082.045718513 30 atime=1483851082.045718513 30 ctime=1488261589.188138654 libinfinity-0.7.1/libinftext/inf-text-default-delete-operation.h0000644000175000017500000000515713034342512025301 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_TEXT_DEFAULT_DELETE_OPERATION_H__ #define __INF_TEXT_DEFAULT_DELETE_OPERATION_H__ #include #include G_BEGIN_DECLS #define INF_TEXT_TYPE_DEFAULT_DELETE_OPERATION (inf_text_default_delete_operation_get_type()) #define INF_TEXT_DEFAULT_DELETE_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_TEXT_TYPE_DEFAULT_DELETE_OPERATION, InfTextDefaultDeleteOperation)) #define INF_TEXT_DEFAULT_DELETE_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INF_TEXT_TYPE_DEFAULT_DELETE_OPERATION, InfTextDefaultDeleteOperationClass)) #define INF_TEXT_IS_DEFAULT_DELETE_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_TEXT_TYPE_DEFAULT_DELETE_OPERATION)) #define INF_TEXT_IS_DEFAULT_DELETE_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INF_TEXT_TYPE_DEFAULT_DELETE_OPERATION)) #define INF_TEXT_DEFAULT_DELETE_OPERATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INF_TEXT_TYPE_DEFAULT_DELETE_OPERATION, InfTextDefaultDeleteOperationClass)) typedef struct _InfTextDefaultDeleteOperation InfTextDefaultDeleteOperation; typedef struct _InfTextDefaultDeleteOperationClass InfTextDefaultDeleteOperationClass; struct _InfTextDefaultDeleteOperationClass { GObjectClass parent_class; }; struct _InfTextDefaultDeleteOperation { GObject parent; }; GType inf_text_default_delete_operation_get_type(void) G_GNUC_CONST; InfTextDefaultDeleteOperation* inf_text_default_delete_operation_new(guint position, InfTextChunk* chunk); InfTextChunk* inf_text_default_delete_operation_get_chunk( InfTextDefaultDeleteOperation* operation); G_END_DECLS #endif /* __INF_TEXT_DEFAULT_DELETE_OPERATION_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinftext/PaxHeaders.26529/inf-text-insert-operation.h0000644000000000000000000000013213034342512023157 xustar0030 mtime=1483851082.045718513 30 atime=1483851082.045718513 30 ctime=1488261589.192138646 libinfinity-0.7.1/libinftext/inf-text-insert-operation.h0000644000175000017500000000602413034342512023713 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_TEXT_INSERT_OPERATION_H__ #define __INF_TEXT_INSERT_OPERATION_H__ #include #include #include G_BEGIN_DECLS #define INF_TEXT_TYPE_INSERT_OPERATION (inf_text_insert_operation_get_type()) #define INF_TEXT_INSERT_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_TEXT_TYPE_INSERT_OPERATION, InfTextInsertOperation)) #define INF_TEXT_IS_INSERT_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_TEXT_TYPE_INSERT_OPERATION)) #define INF_TEXT_INSERT_OPERATION_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), INF_TEXT_TYPE_INSERT_OPERATION, InfTextInsertOperationInterface)) typedef struct _InfTextInsertOperationInterface InfTextInsertOperationInterface; struct _InfTextInsertOperationInterface { GTypeInterface parent; /* Virtual table */ guint(*get_position)(InfTextInsertOperation* operation); guint(*get_length)(InfTextInsertOperation* operation); InfTextInsertOperation*(*transform_position)(InfTextInsertOperation* op, guint position); }; GType inf_text_insert_operation_get_type(void) G_GNUC_CONST; guint inf_text_insert_operation_get_position(InfTextInsertOperation* operation); guint inf_text_insert_operation_get_length(InfTextInsertOperation* operation); gboolean inf_text_insert_operation_need_concurrency_id(InfTextInsertOperation* op, InfAdoptedOperation* against); InfAdoptedOperation* inf_text_insert_operation_transform_insert(InfTextInsertOperation* operation, InfTextInsertOperation* against, InfTextInsertOperation* op_lcs, InfTextInsertOperation* ag_lcs, InfAdoptedConcurrencyId cid); InfAdoptedOperation* inf_text_insert_operation_transform_delete(InfTextInsertOperation* operation, InfTextDeleteOperation* against); G_END_DECLS #endif /* __INF_TEXT_INSERT_OPERATION_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinftext/PaxHeaders.26529/inf-text-move-operation.c0000644000000000000000000000013213034342512022614 xustar0030 mtime=1483851082.045718513 30 atime=1483851082.045718513 30 ctime=1488261589.216138593 libinfinity-0.7.1/libinftext/inf-text-move-operation.c0000644000175000017500000003524413034342512023356 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include #include #include #include #include #include typedef struct _InfTextMoveOperationPrivate InfTextMoveOperationPrivate; struct _InfTextMoveOperationPrivate { guint position; gint length; }; enum { PROP_0, PROP_POSITION, PROP_LENGTH }; #define INF_TEXT_MOVE_OPERATION_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INF_TEXT_TYPE_MOVE_OPERATION, InfTextMoveOperationPrivate)) static void inf_text_move_operation_operation_iface_init(InfAdoptedOperationInterface* iface); G_DEFINE_TYPE_WITH_CODE(InfTextMoveOperation, inf_text_move_operation, G_TYPE_OBJECT, G_ADD_PRIVATE(InfTextMoveOperation) G_IMPLEMENT_INTERFACE(INF_ADOPTED_TYPE_OPERATION, inf_text_move_operation_operation_iface_init)) static void inf_text_move_operation_init(InfTextMoveOperation* operation) { InfTextMoveOperationPrivate* priv; priv = INF_TEXT_MOVE_OPERATION_PRIVATE(operation); priv->position = 0; priv->length = 0; } static void inf_text_move_operation_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfTextMoveOperation* operation; InfTextMoveOperationPrivate* priv; operation = INF_TEXT_MOVE_OPERATION(object); priv = INF_TEXT_MOVE_OPERATION_PRIVATE(operation); switch(prop_id) { case PROP_POSITION: priv->position = g_value_get_uint(value); break; case PROP_LENGTH: priv->length = g_value_get_int(value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void inf_text_move_operation_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfTextMoveOperation* operation; InfTextMoveOperationPrivate* priv; operation = INF_TEXT_MOVE_OPERATION(object); priv = INF_TEXT_MOVE_OPERATION_PRIVATE(operation); switch(prop_id) { case PROP_POSITION: g_value_set_uint(value, priv->position); break; case PROP_LENGTH: g_value_set_int(value, priv->length); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static gboolean inf_text_move_operation_need_concurrency_id(InfAdoptedOperation* operation, InfAdoptedOperation* against) { g_assert(INF_TEXT_IS_MOVE_OPERATION(operation)); return FALSE; } static InfAdoptedOperation* inf_text_move_operation_transform(InfAdoptedOperation* operation, InfAdoptedOperation* against, InfAdoptedOperation* operation_lcs, InfAdoptedOperation* against_lcs, gint concurrency_id) { InfTextMoveOperationPrivate* priv; guint new_pos; gint new_len; g_assert(INF_TEXT_IS_MOVE_OPERATION(operation)); priv = INF_TEXT_MOVE_OPERATION_PRIVATE(operation); new_pos = priv->position; new_len = priv->length; if(INF_TEXT_IS_INSERT_OPERATION(against)) { inf_text_move_operation_transform_insert( inf_text_insert_operation_get_position( INF_TEXT_INSERT_OPERATION(against) ), inf_text_insert_operation_get_length( INF_TEXT_INSERT_OPERATION(against) ), &new_pos, &new_len, TRUE /* left gravity */ ); } else if(INF_TEXT_IS_DELETE_OPERATION(against)) { inf_text_move_operation_transform_delete( inf_text_delete_operation_get_position( INF_TEXT_DELETE_OPERATION(against) ), inf_text_delete_operation_get_length( INF_TEXT_DELETE_OPERATION(against) ), &new_pos, &new_len ); } else { g_assert_not_reached(); return NULL; } return INF_ADOPTED_OPERATION( g_object_new( INF_TEXT_TYPE_MOVE_OPERATION, "position", new_pos, "length", new_len, NULL ) ); } static InfAdoptedOperation* inf_text_move_operation_copy(InfAdoptedOperation* operation) { InfTextMoveOperationPrivate* priv; GObject* object; g_assert(INF_TEXT_IS_MOVE_OPERATION(operation)); priv = INF_TEXT_MOVE_OPERATION_PRIVATE(operation); object = g_object_new( INF_TEXT_TYPE_MOVE_OPERATION, "position", priv->position, "length", priv->length, NULL ); return INF_ADOPTED_OPERATION(object); } static InfAdoptedOperationFlags inf_text_move_operation_get_flags(InfAdoptedOperation* operation) { /* Does not affect the buffer */ return 0; } static gboolean inf_text_move_operation_apply(InfAdoptedOperation* operation, InfAdoptedUser* by, InfBuffer* buffer, GError** error) { InfTextMoveOperationPrivate* priv; guint length; g_assert(INF_TEXT_IS_MOVE_OPERATION(operation)); g_assert(INF_TEXT_IS_USER(by)); priv = INF_TEXT_MOVE_OPERATION_PRIVATE(operation); length = inf_text_buffer_get_length(INF_TEXT_BUFFER(buffer)); if(priv->position > length || priv->position + priv->length > length) { g_set_error_literal( error, g_quark_from_static_string("INF_TEXT_OPERATION_ERROR"), INF_TEXT_OPERATION_ERROR_INVALID_MOVE, _("Attempt to move cursor or selection beyond the end of the document") ); return FALSE; } else { inf_text_user_set_selection( INF_TEXT_USER(by), priv->position, priv->length, TRUE /* explicit move request */ ); return TRUE; } } static void inf_text_move_operation_class_init( InfTextMoveOperationClass* move_operation_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(move_operation_class); object_class->set_property = inf_text_move_operation_set_property; object_class->get_property = inf_text_move_operation_get_property; g_object_class_install_property( object_class, PROP_POSITION, g_param_spec_uint( "position", "Position", "Position where to place the user's caret at", 0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_LENGTH, g_param_spec_int( "length", "Length", "The number of characters of the selected text", G_MININT, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); } static void inf_text_move_operation_operation_iface_init( InfAdoptedOperationInterface* iface) { iface->need_concurrency_id = inf_text_move_operation_need_concurrency_id; iface->transform = inf_text_move_operation_transform; iface->copy = inf_text_move_operation_copy; iface->get_flags = inf_text_move_operation_get_flags; iface->apply = inf_text_move_operation_apply; iface->apply_transformed = NULL; iface->revert = NULL; } /** * inf_text_move_operation_new: (constructor) * @position: The position to place the user's caret at. * @length: The number of characters to select. Negative means selection * towards the beginning of the buffer. * * Creates a new move operation that, when applied, changes the caret and * selection of the applying user. * * Returns: (transfer full): A new #InfTextMoveOperation. **/ InfTextMoveOperation* inf_text_move_operation_new(guint position, gint length) { GObject* object; object = g_object_new( INF_TEXT_TYPE_MOVE_OPERATION, "position", position, "length", length, NULL ); return INF_TEXT_MOVE_OPERATION(object); } /** * inf_text_move_operation_get_position: * @operation: A #InfTextMoveOperation. * * Returns the position at which @operation places the user's cursor. * * Returns: The position of @operation. **/ guint inf_text_move_operation_get_position(InfTextMoveOperation* operation) { g_return_val_if_fail(INF_TEXT_IS_MOVE_OPERATION(operation), 0); return INF_TEXT_MOVE_OPERATION_PRIVATE(operation)->position; } /** * inf_text_move_operation_get_length: * @operation: A #InfTextMoveOperation. * * Returns the length to which @operation changes the user's selection. * Negative means selection towards the beginning of the buffer. * * Returns: The length of @operation. **/ gint inf_text_move_operation_get_length(InfTextMoveOperation* operation) { g_return_val_if_fail(INF_TEXT_IS_MOVE_OPERATION(operation), 0); return INF_TEXT_MOVE_OPERATION_PRIVATE(operation)->length; } /** * inf_text_move_operation_transform_insert: * @insert_position: The position at which text is inserted. * @insert_length: The number of inserted characters. * @move_position: (inout): Points to the character offset to which the caret * is moved. * @move_length: (inout): Points to the number of characters selected. * Negative means towards the beginning. * @left_gravity: Whether the move position and length have left gravity. * * Changes *@move_position and *@move_length so that they point to the same * region when @insert_length characters are inserted at @insert_position. * * If text is inserted at the same position as @move_position, then * @move_position is kept at the position it currently is if @left_gravity is * %TRUE, otherwise it is shifted to the right. * * If *@move_length is nonzero, then the selection length is never enlarged if * text is inserted at the selection bounds, not depending on whether * @left_gravity is set or not. **/ void inf_text_move_operation_transform_insert(guint insert_position, guint insert_length, guint* move_position, gint* move_length, gboolean left_gravity) { guint cur_pos; guint cur_bound; g_return_if_fail(move_position != NULL); g_return_if_fail(move_length != NULL); cur_pos = *move_position; cur_bound = *move_position + *move_length; if(cur_pos == cur_bound) { if( (insert_position < cur_pos) || (insert_position == cur_pos && !left_gravity)) { cur_pos += insert_length; cur_bound += insert_length; } } else { if(cur_bound > cur_pos) { if(insert_position <= cur_pos) { cur_pos += insert_length; cur_bound += insert_length; } else if(insert_position < cur_bound) { cur_bound += insert_length; } } else { if(insert_position <= cur_bound) { cur_pos += insert_length; cur_bound += insert_length; } else if(insert_position < cur_pos) { cur_pos += insert_length; } } } *move_position = cur_pos; *move_length = (gint)cur_bound - (gint)cur_pos; } /** * inf_text_move_operation_transform_delete: * @delete_position: The position at which text is deleted. * @delete_length: The number of deleted characters. * @move_position: (inout): Points to the character offset to which the caret * is moved. * @move_length: (inout): Points to the number of characters selected. * Negative means towards the beginning. * * Changes *@move_position and *@move_length so that they point to the same * region when @delete_length characters are deleted starting from * @delete_position. **/ void inf_text_move_operation_transform_delete(guint delete_position, guint delete_length, guint* move_position, gint* move_length) { guint cur_pos; gint cur_len; g_return_if_fail(move_position != NULL); g_return_if_fail(move_length != NULL); cur_pos = *move_position; cur_len = *move_length; if(cur_pos >= delete_position + delete_length) *move_position = cur_pos - delete_length; else if(cur_pos > delete_position) *move_position = delete_position; else *move_position = cur_pos; if(cur_len < 0) { if(delete_position + delete_length <= cur_pos + cur_len) { *move_length = cur_len; } else if(delete_position >= cur_pos) { *move_length = cur_len; } else if(delete_position <= cur_pos + cur_len && delete_position + delete_length >= cur_pos) { *move_length = 0; } else if(delete_position <= cur_pos + cur_len && delete_position + delete_length > cur_pos + cur_len) { *move_length = -(gint)(cur_pos - (delete_position + delete_length)); } else if(delete_position > cur_pos + cur_len && delete_position + delete_length > cur_pos) { *move_length = delete_position - (cur_pos + cur_len); } else if(delete_position > cur_pos + cur_len && delete_position + delete_length <= cur_pos) { *move_length = cur_len + (gint)delete_length; } else { g_assert_not_reached(); } } else { if(delete_position + delete_length <= cur_pos) { *move_length = cur_len; } else if(delete_position >= cur_pos + cur_len) { *move_length = cur_len; } else if(delete_position <= cur_pos && delete_position + delete_length >= cur_pos + cur_len) { *move_length = 0; } else if(delete_position <= cur_pos && delete_position + delete_length > cur_pos) { *move_length = cur_pos + cur_len - (delete_position + delete_length); } else if(delete_position > cur_pos && delete_position + delete_length > cur_pos + cur_len) { *move_length = cur_pos - delete_position; } else if(delete_position > cur_pos && delete_position + delete_length <= cur_pos + cur_len) { *move_length = cur_len - delete_length; } else { g_assert_not_reached(); } } } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinftext/PaxHeaders.26529/inf-text-default-insert-operation.c0000644000000000000000000000013213034342512024574 xustar0030 mtime=1483851082.045718513 30 atime=1483851082.045718513 30 ctime=1488261589.212138602 libinfinity-0.7.1/libinftext/inf-text-default-insert-operation.c0000644000175000017500000002672513034342512025342 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include #include #include #include #include #include typedef struct _InfTextDefaultInsertOperationPrivate InfTextDefaultInsertOperationPrivate; struct _InfTextDefaultInsertOperationPrivate { guint position; InfTextChunk* chunk; }; enum { PROP_0, PROP_POSITION, PROP_CHUNK }; #define INF_TEXT_DEFAULT_INSERT_OPERATION_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INF_TEXT_TYPE_DEFAULT_INSERT_OPERATION, InfTextDefaultInsertOperationPrivate)) static void inf_text_default_insert_operation_operation_iface_init(InfAdoptedOperationInterface* iface); static void inf_text_default_insert_operation_insert_operation_iface_init(InfTextInsertOperationInterface* iface); G_DEFINE_TYPE_WITH_CODE(InfTextDefaultInsertOperation, inf_text_default_insert_operation, G_TYPE_OBJECT, G_ADD_PRIVATE(InfTextDefaultInsertOperation) G_IMPLEMENT_INTERFACE(INF_ADOPTED_TYPE_OPERATION, inf_text_default_insert_operation_operation_iface_init) G_IMPLEMENT_INTERFACE(INF_TEXT_TYPE_INSERT_OPERATION, inf_text_default_insert_operation_insert_operation_iface_init)) static void inf_text_default_insert_operation_init( InfTextDefaultInsertOperation* operation) { InfTextDefaultInsertOperationPrivate* priv; priv = INF_TEXT_DEFAULT_INSERT_OPERATION_PRIVATE(operation); priv->position = 0; priv->chunk = NULL; } static void inf_text_default_insert_operation_finalize(GObject* object) { InfTextDefaultInsertOperation* operation; InfTextDefaultInsertOperationPrivate* priv; operation = INF_TEXT_DEFAULT_INSERT_OPERATION(object); priv = INF_TEXT_DEFAULT_INSERT_OPERATION_PRIVATE(operation); inf_text_chunk_free(priv->chunk); G_OBJECT_CLASS(inf_text_default_insert_operation_parent_class)->finalize(object); } static void inf_text_default_insert_operation_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfTextDefaultInsertOperation* operation; InfTextDefaultInsertOperationPrivate* priv; operation = INF_TEXT_DEFAULT_INSERT_OPERATION(object); priv = INF_TEXT_DEFAULT_INSERT_OPERATION_PRIVATE(operation); switch(prop_id) { case PROP_POSITION: priv->position = g_value_get_uint(value); break; case PROP_CHUNK: g_assert(priv->chunk == NULL); /* construct only */ priv->chunk = (InfTextChunk*)g_value_dup_boxed(value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void inf_text_default_insert_operation_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfTextDefaultInsertOperation* operation; InfTextDefaultInsertOperationPrivate* priv; operation = INF_TEXT_DEFAULT_INSERT_OPERATION(object); priv = INF_TEXT_DEFAULT_INSERT_OPERATION_PRIVATE(operation); switch(prop_id) { case PROP_POSITION: g_value_set_uint(value, priv->position); break; case PROP_CHUNK: g_value_set_boxed(value, priv->chunk); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static gboolean inf_text_default_insert_operation_need_concurrency_id( InfAdoptedOperation* operation, InfAdoptedOperation* against) { g_assert(INF_TEXT_IS_DEFAULT_INSERT_OPERATION(operation)); return inf_text_insert_operation_need_concurrency_id( INF_TEXT_INSERT_OPERATION(operation), against ); } static InfAdoptedOperation* inf_text_default_insert_operation_transform(InfAdoptedOperation* operation, InfAdoptedOperation* against, InfAdoptedOperation* op_lcs, InfAdoptedOperation* against_lcs, InfAdoptedConcurrencyId cid) { g_assert(INF_TEXT_IS_DEFAULT_INSERT_OPERATION(operation)); if(INF_TEXT_IS_INSERT_OPERATION(against)) { g_assert(op_lcs == NULL || INF_TEXT_IS_INSERT_OPERATION(op_lcs)); g_assert(against_lcs == NULL || INF_TEXT_IS_INSERT_OPERATION(against_lcs)); return inf_text_insert_operation_transform_insert( INF_TEXT_INSERT_OPERATION(operation), INF_TEXT_INSERT_OPERATION(against), INF_TEXT_INSERT_OPERATION(op_lcs), INF_TEXT_INSERT_OPERATION(against_lcs), cid ); } else if(INF_TEXT_IS_DELETE_OPERATION(against)) { return inf_text_insert_operation_transform_delete( INF_TEXT_INSERT_OPERATION(operation), INF_TEXT_DELETE_OPERATION(against) ); } else { g_assert_not_reached(); return NULL; } } static InfAdoptedOperation* inf_text_default_insert_operation_copy(InfAdoptedOperation* operation) { InfTextDefaultInsertOperationPrivate* priv; priv = INF_TEXT_DEFAULT_INSERT_OPERATION_PRIVATE(operation); return INF_ADOPTED_OPERATION( g_object_new( INF_TEXT_TYPE_DEFAULT_INSERT_OPERATION, "position", priv->position, "chunk", priv->chunk, NULL ) ); } static InfAdoptedOperationFlags inf_text_default_insert_operation_get_flags(InfAdoptedOperation* operation) { return INF_ADOPTED_OPERATION_AFFECTS_BUFFER | INF_ADOPTED_OPERATION_REVERSIBLE; } static gboolean inf_text_default_insert_operation_apply(InfAdoptedOperation* operation, InfAdoptedUser* by, InfBuffer* buffer, GError** error) { InfTextDefaultInsertOperationPrivate* priv; g_assert(INF_TEXT_IS_DEFAULT_INSERT_OPERATION(operation)); g_assert(INF_TEXT_IS_BUFFER(buffer)); priv = INF_TEXT_DEFAULT_INSERT_OPERATION_PRIVATE(operation); if(priv->position > inf_text_buffer_get_length(INF_TEXT_BUFFER(buffer))) { g_set_error_literal( error, g_quark_from_static_string("INF_TEXT_OPERATION_ERROR"), INF_TEXT_OPERATION_ERROR_INVALID_INSERT, _("Attempt to insert text after the end of the document") ); return FALSE; } else { inf_text_buffer_insert_chunk( INF_TEXT_BUFFER(buffer), priv->position, priv->chunk, INF_USER(by) ); return TRUE; } } static InfAdoptedOperation* inf_text_default_insert_operation_revert(InfAdoptedOperation* operation) { InfTextDefaultInsertOperationPrivate* priv; priv = INF_TEXT_DEFAULT_INSERT_OPERATION_PRIVATE(operation); return INF_ADOPTED_OPERATION( inf_text_default_delete_operation_new(priv->position, priv->chunk) ); } static guint inf_text_default_insert_operation_get_position(InfTextInsertOperation* op) { return INF_TEXT_DEFAULT_INSERT_OPERATION_PRIVATE(op)->position; } static guint inf_text_default_insert_operation_get_length( InfTextInsertOperation* operation) { return inf_text_chunk_get_length( INF_TEXT_DEFAULT_INSERT_OPERATION_PRIVATE(operation)->chunk ); } static InfTextInsertOperation* inf_text_default_insert_operation_transform_position( InfTextInsertOperation* operation, guint position) { InfTextDefaultInsertOperationPrivate* priv; GObject* result; priv = INF_TEXT_DEFAULT_INSERT_OPERATION_PRIVATE(operation); result = g_object_new( INF_TEXT_TYPE_DEFAULT_INSERT_OPERATION, "position", position, "chunk", priv->chunk, NULL ); return INF_TEXT_INSERT_OPERATION(result); } static void inf_text_default_insert_operation_class_init( InfTextDefaultInsertOperationClass* default_insert_operation_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(default_insert_operation_class); object_class->finalize = inf_text_default_insert_operation_finalize; object_class->set_property = inf_text_default_insert_operation_set_property; object_class->get_property = inf_text_default_insert_operation_get_property; g_object_class_install_property( object_class, PROP_POSITION, g_param_spec_uint( "position", "Position", "Insertion position", 0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_CHUNK, g_param_spec_boxed( "chunk", "Chunk", "The text to insert", INF_TEXT_TYPE_CHUNK, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); } static void inf_text_default_insert_operation_operation_iface_init( InfAdoptedOperationInterface* iface) { iface->need_concurrency_id = inf_text_default_insert_operation_need_concurrency_id; iface->transform = inf_text_default_insert_operation_transform; iface->copy = inf_text_default_insert_operation_copy; iface->get_flags = inf_text_default_insert_operation_get_flags; iface->apply = inf_text_default_insert_operation_apply; iface->apply_transformed = NULL; iface->revert = inf_text_default_insert_operation_revert; } static void inf_text_default_insert_operation_insert_operation_iface_init( InfTextInsertOperationInterface* iface) { iface->get_position = inf_text_default_insert_operation_get_position; iface->get_length = inf_text_default_insert_operation_get_length; iface->transform_position = inf_text_default_insert_operation_transform_position; } /** * inf_text_default_insert_operation_new: (constructor) * @pos: The position at which to insert text. * @chunk: The text to insert. * * Creates a new insert operation that, when applied, inserts @chunk * at @pos. * * Returns: (transfer full): A new #InfTextDefaultInsertOperation. **/ InfTextDefaultInsertOperation* inf_text_default_insert_operation_new(guint pos, InfTextChunk* chunk) { GObject* object; g_return_val_if_fail(chunk != NULL, NULL); object = g_object_new( INF_TEXT_TYPE_DEFAULT_INSERT_OPERATION, "position", pos, "chunk", chunk, NULL ); return INF_TEXT_DEFAULT_INSERT_OPERATION(object); } /** * inf_text_default_insert_operation_get_chunk: * @operation: A #InfTextDefaultInsertOperation. * * Returns the text inserted by @operation. * * Returns: (transfer none): A #InfTextChunk, owned by the operation. **/ InfTextChunk* inf_text_default_insert_operation_get_chunk(InfTextDefaultInsertOperation* operation) { g_return_val_if_fail(INF_TEXT_IS_DEFAULT_INSERT_OPERATION(operation), NULL); return INF_TEXT_DEFAULT_INSERT_OPERATION_PRIVATE(operation)->chunk; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/PaxHeaders.26529/configure0000644000000000000000000000013213051241011015473 xustar0030 mtime=1487225353.053152708 30 atime=1487225352.869152123 30 ctime=1488261588.740139633 libinfinity-0.7.1/configure0000755000175000017500000212412313051241011016235 0ustar00arminarmin00000000000000#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for libinfinity 0.7.1. # # Report bugs to . # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 as_fn_exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test \$(( 1 + 1 )) = 2 || exit 1 test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || ( ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO PATH=/empty FPATH=/empty; export PATH FPATH test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\ || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org and armin@arbur.net $0: about your system, including any error possibly output $0: before this message. Then install a modern shell, or $0: manually run the script under such a shell if you do $0: have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" SHELL=${CONFIG_SHELL-/bin/sh} test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='libinfinity' PACKAGE_TARNAME='libinfinity' PACKAGE_VERSION='0.7.1' PACKAGE_STRING='libinfinity 0.7.1' PACKAGE_BUGREPORT='armin@arbur.net' PACKAGE_URL='' ac_unique_file="libinfinity/common/inf-init.c" # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS LIBOBJS HAVE_INTROSPECTION_FALSE HAVE_INTROSPECTION_TRUE INTROSPECTION_MAKEFILE INTROSPECTION_LIBS INTROSPECTION_CFLAGS INTROSPECTION_TYPELIBDIR INTROSPECTION_GIRDIR INTROSPECTION_GENERATE INTROSPECTION_COMPILER INTROSPECTION_SCANNER MKINSTALLDIRS POSUB POFILES PO_IN_DATADIR_FALSE PO_IN_DATADIR_TRUE INTLLIBS INSTOBJEXT GMOFILES DATADIRNAME CATOBJEXT CATALOGS XGETTEXT GMSGFMT MSGFMT_OPTS MSGFMT USE_NLS GETTEXT_PACKAGE LIBINFINITY_HAVE_LIBDAEMON_FALSE LIBINFINITY_HAVE_LIBDAEMON_TRUE libdaemon_LIBS libdaemon_CFLAGS LIBINFINITY_HAVE_GIO_FALSE LIBINFINITY_HAVE_GIO_TRUE gio_LIBS gio_CFLAGS LIBINFINITY_HAVE_AVAHI_FALSE LIBINFINITY_HAVE_AVAHI_TRUE avahi_LIBS avahi_CFLAGS WITH_INFINOTED_FALSE WITH_INFINOTED_TRUE infinoted_LIBS infinoted_CFLAGS WITH_INFGTK_FALSE WITH_INFGTK_TRUE infgtk_LIBS infgtk_CFLAGS gtk_requirement WITH_INFTEXTGTK_FALSE WITH_INFTEXTGTK_TRUE inftextgtk_LIBS inftextgtk_CFLAGS inftext_LIBS inftext_CFLAGS infinity_LIBS infinity_CFLAGS WIN32_FALSE WIN32_TRUE GTK_DOC_USE_REBASE_FALSE GTK_DOC_USE_REBASE_TRUE GTK_DOC_USE_LIBTOOL_FALSE GTK_DOC_USE_LIBTOOL_TRUE GTK_DOC_BUILD_PDF_FALSE GTK_DOC_BUILD_PDF_TRUE GTK_DOC_BUILD_HTML_FALSE GTK_DOC_BUILD_HTML_TRUE ENABLE_GTK_DOC_FALSE ENABLE_GTK_DOC_TRUE HAVE_GTK_DOC_FALSE HAVE_GTK_DOC_TRUE GTKDOC_DEPS_LIBS GTKDOC_DEPS_CFLAGS HTML_DIR GTKDOC_MKPDF GTKDOC_REBASE GTKDOC_CHECK_PATH GTKDOC_CHECK PKG_CONFIG_LIBDIR PKG_CONFIG_PATH PKG_CONFIG LT_SYS_LIBRARY_PATH OTOOL64 OTOOL LIPO NMEDIT DSYMUTIL MANIFEST_TOOL RANLIB DLLTOOL OBJDUMP NM ac_ct_DUMPBIN DUMPBIN LD FGREP SED LIBTOOL ac_ct_AR AR LN_S EGREP GREP CPP am__fastdepCC_FALSE am__fastdepCC_TRUE CCDEPMODE am__nodep AMDEPBACKSLASH AMDEP_FALSE AMDEP_TRUE am__quote am__include DEPDIR OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC host_os host_vendor host_cpu host build_os build_vendor build_cpu build LIBINFINITY_LIBTOOL_VERSION LIBINFINITY_API_VERSION LIBINFINITY_VERSION MAINT MAINTAINER_MODE_FALSE MAINTAINER_MODE_TRUE AM_BACKSLASH AM_DEFAULT_VERBOSITY AM_DEFAULT_V AM_V am__untar am__tar AMTAR am__leading_dot SET_MAKE AWK mkdir_p MKDIR_P INSTALL_STRIP_PROGRAM STRIP install_sh MAKEINFO AUTOHEADER AUTOMAKE AUTOCONF ACLOCAL VERSION PACKAGE CYGPATH_W am__isrc INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir runstatedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking enable_silent_rules enable_maintainer_mode enable_dependency_tracking enable_shared enable_static with_pic enable_fast_install with_aix_soname with_gnu_ld with_sysroot enable_libtool_lock with_html_dir enable_gtk_doc enable_gtk_doc_html enable_gtk_doc_pdf with_inftextgtk with_infgtk with_infinoted with_avahi with_gio with_libdaemon enable_introspection ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CPP LT_SYS_LIBRARY_PATH PKG_CONFIG PKG_CONFIG_PATH PKG_CONFIG_LIBDIR GTKDOC_DEPS_CFLAGS GTKDOC_DEPS_LIBS infinity_CFLAGS infinity_LIBS inftext_CFLAGS inftext_LIBS inftextgtk_CFLAGS inftextgtk_LIBS infgtk_CFLAGS infgtk_LIBS infinoted_CFLAGS infinoted_LIBS avahi_CFLAGS avahi_LIBS gio_CFLAGS gio_LIBS libdaemon_CFLAGS libdaemon_LIBS' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -runstatedir | --runstatedir | --runstatedi | --runstated \ | --runstate | --runstat | --runsta | --runst | --runs \ | --run | --ru | --r) ac_prev=runstatedir ;; -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ | --run=* | --ru=* | --r=*) runstatedir=$ac_optarg ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir runstatedir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures libinfinity 0.7.1 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/libinfinity] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF Program names: --program-prefix=PREFIX prepend PREFIX to installed program names --program-suffix=SUFFIX append SUFFIX to installed program names --program-transform-name=PROGRAM run sed PROGRAM on installed program names System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of libinfinity 0.7.1:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-silent-rules less verbose build output (undo: "make V=1") --disable-silent-rules verbose build output (undo: "make V=0") --enable-maintainer-mode enable make rules and dependencies not useful (and sometimes confusing) to the casual installer --enable-dependency-tracking do not reject slow dependency extractors --disable-dependency-tracking speeds up one-time build --enable-shared[=PKGS] build shared libraries [default=yes] --enable-static[=PKGS] build static libraries [default=yes] --enable-fast-install[=PKGS] optimize for fast installation [default=yes] --disable-libtool-lock avoid locking (might break parallel builds) --enable-gtk-doc use gtk-doc to build documentation [[default=no]] --enable-gtk-doc-html build documentation in html format [[default=yes]] --enable-gtk-doc-pdf build documentation in pdf format [[default=no]] --enable-introspection=[no/auto/yes] Enable introspection for this build Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use both] --with-aix-soname=aix|svr4|both shared library versioning (aka "SONAME") variant to provide on AIX, [default=aix]. --with-gnu-ld assume the C compiler uses GNU ld [default=no] --with-sysroot[=DIR] Search for dependent libraries within DIR (or the compiler's sysroot if not specified). --with-html-dir=PATH path to installed docs --with-inftextgtk Builds the libinftextgtk library [[default=auto]] --with-infgtk Builds the libinfgtk library [[default=auto]] --with-infinoted Build the infinote standalone server [[default=yes]] --with-avahi Enables avahi support [[default=auto]] --with-gio Enables avahi support [[default=auto]] --with-libdaemon Enables daemonizing support in infinoted [[default=auto]] Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor LT_SYS_LIBRARY_PATH User-defined run-time library search path. PKG_CONFIG path to pkg-config utility PKG_CONFIG_PATH directories to add to pkg-config's search path PKG_CONFIG_LIBDIR path overriding pkg-config's built-in search path GTKDOC_DEPS_CFLAGS C compiler flags for GTKDOC_DEPS, overriding pkg-config GTKDOC_DEPS_LIBS linker flags for GTKDOC_DEPS, overriding pkg-config infinity_CFLAGS C compiler flags for infinity, overriding pkg-config infinity_LIBS linker flags for infinity, overriding pkg-config inftext_CFLAGS C compiler flags for inftext, overriding pkg-config inftext_LIBS linker flags for inftext, overriding pkg-config inftextgtk_CFLAGS C compiler flags for inftextgtk, overriding pkg-config inftextgtk_LIBS linker flags for inftextgtk, overriding pkg-config infgtk_CFLAGS C compiler flags for infgtk, overriding pkg-config infgtk_LIBS linker flags for infgtk, overriding pkg-config infinoted_CFLAGS C compiler flags for infinoted, overriding pkg-config infinoted_LIBS linker flags for infinoted, overriding pkg-config avahi_CFLAGS C compiler flags for avahi, overriding pkg-config avahi_LIBS linker flags for avahi, overriding pkg-config gio_CFLAGS C compiler flags for gio, overriding pkg-config gio_LIBS linker flags for gio, overriding pkg-config libdaemon_CFLAGS C compiler flags for libdaemon, overriding pkg-config libdaemon_LIBS linker flags for libdaemon, overriding pkg-config Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to . _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF libinfinity configure 0.7.1 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using # the include files in INCLUDES and setting the cache variable VAR # accordingly. ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if eval \${$3+:} false; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 $as_echo_n "checking $2 usability... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_header_compiler=yes else ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 $as_echo_n "checking $2 presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$2> _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : ac_header_preproc=yes else ac_header_preproc=no fi rm -f conftest.err conftest.i conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( yes:no: ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; no:yes:* ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ( $as_echo "## ------------------------------ ## ## Report this to armin@arbur.net ## ## ------------------------------ ##" ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_mongrel # ac_fn_c_try_run LINENO # ---------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. Assumes # that executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : ac_retval=0 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main () { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by libinfinity $as_me 0.7.1, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu am__api_version='1.15' ac_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do if test -f "$ac_dir/install-sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f "$ac_dir/install.sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f "$ac_dir/shtool"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. # Reject install programs that cannot install multiple files. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 $as_echo_n "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then if ${ac_cv_path_install+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. # Account for people who put trailing slashes in PATH elements. case $as_dir/ in #(( ./ | .// | /[cC]/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else rm -rf conftest.one conftest.two conftest.dir echo one > conftest.one echo two > conftest.two mkdir conftest.dir if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && test -s conftest.one && test -s conftest.two && test -s conftest.dir/conftest.one && test -s conftest.dir/conftest.two then ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi fi done done ;; esac done IFS=$as_save_IFS rm -rf conftest.one conftest.two conftest.dir fi if test "${ac_cv_path_install+set}" = set; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. Don't cache a # value for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. INSTALL=$ac_install_sh fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 $as_echo "$INSTALL" >&6; } # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 $as_echo_n "checking whether build environment is sane... " >&6; } # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[\\\"\#\$\&\'\`$am_lf]*) as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; esac case $srcdir in *[\\\"\#\$\&\'\`$am_lf\ \ ]*) as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; esac # Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$*" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$*" != "X $srcdir/configure conftest.file" \ && test "$*" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". as_fn_error $? "ls -t appears to fail. Make sure there is not a broken alias in your environment" "$LINENO" 5 fi if test "$2" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$2" = conftest.file ) then # Ok. : else as_fn_error $? "newly created file is older than distributed files! Check your system clock" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi rm -f conftest.file test "$program_prefix" != NONE && program_transform_name="s&^&$program_prefix&;$program_transform_name" # Use a double $ so make ignores it. test "$program_suffix" != NONE && program_transform_name="s&\$&$program_suffix&;$program_transform_name" # Double any \ or $. # By default was `s,x,x', remove it if useless. ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` # Expand $ac_aux_dir to an absolute path. am_aux_dir=`cd "$ac_aux_dir" && pwd` if test x"${MISSING+set}" != xset; then case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --is-lightweight"; then am_missing_run="$MISSING " else am_missing_run= { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 $as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} fi if test x"${install_sh+set}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. if test "$cross_compiling" != no; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 $as_echo_n "checking for a thread-safe mkdir -p... " >&6; } if test -z "$MKDIR_P"; then if ${ac_cv_path_mkdir+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in mkdir gmkdir; do for ac_exec_ext in '' $ac_executable_extensions; do as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( 'mkdir (GNU coreutils) '* | \ 'mkdir (coreutils) '* | \ 'mkdir (fileutils) '4.1*) ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext break 3;; esac done done done IFS=$as_save_IFS fi test -d ./--version && rmdir ./--version if test "${ac_cv_path_mkdir+set}" = set; then MKDIR_P="$ac_cv_path_mkdir -p" else # As a last resort, use the slow shell script. Don't cache a # value for MKDIR_P within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. MKDIR_P="$ac_install_sh -d" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 $as_echo "$MKDIR_P" >&6; } for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AWK+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 $as_echo "$AWK" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AWK" && break done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SET_MAKE= else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null # Check whether --enable-silent-rules was given. if test "${enable_silent_rules+set}" = set; then : enableval=$enable_silent_rules; fi case $enable_silent_rules in # ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=1;; esac am_make=${MAKE-make} { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 $as_echo_n "checking whether $am_make supports nested variables... " >&6; } if ${am_cv_make_support_nested_variables+:} false; then : $as_echo_n "(cached) " >&6 else if $as_echo 'TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 $as_echo "$am_cv_make_support_nested_variables" >&6; } if test $am_cv_make_support_nested_variables = yes; then AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AM_BACKSLASH='\' if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." am__isrc=' -I$(srcdir)' # test to see if srcdir already configured if test -f $srcdir/config.status; then as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi # Define the identity of the package. PACKAGE='libinfinity' VERSION='0.7.1' cat >>confdefs.h <<_ACEOF #define PACKAGE "$PACKAGE" _ACEOF cat >>confdefs.h <<_ACEOF #define VERSION "$VERSION" _ACEOF # Some tools Automake needs. ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # mkdir_p='$(MKDIR_P)' # We need awk for the "check" target (and possibly the TAP driver). The # system "awk" is bad on some platforms. # Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AMTAR='$${TAR-tar}' # We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar pax cpio none' { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to create a pax tar archive" >&5 $as_echo_n "checking how to create a pax tar archive... " >&6; } # Go ahead even if we have the value already cached. We do so because we # need to set the values for the 'am__tar' and 'am__untar' variables. _am_tools=${am_cv_prog_tar_pax-$_am_tools} for _am_tool in $_am_tools; do case $_am_tool in gnutar) for _am_tar in tar gnutar gtar; do { echo "$as_me:$LINENO: $_am_tar --version" >&5 ($_am_tar --version) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } && break done am__tar="$_am_tar --format=posix -chf - "'"$$tardir"' am__tar_="$_am_tar --format=posix -chf - "'"$tardir"' am__untar="$_am_tar -xf -" ;; plaintar) # Must skip GNU tar: if it does not support --format= it doesn't create # ustar tarball either. (tar --version) >/dev/null 2>&1 && continue am__tar='tar chf - "$$tardir"' am__tar_='tar chf - "$tardir"' am__untar='tar xf -' ;; pax) am__tar='pax -L -x pax -w "$$tardir"' am__tar_='pax -L -x pax -w "$tardir"' am__untar='pax -r' ;; cpio) am__tar='find "$$tardir" -print | cpio -o -H pax -L' am__tar_='find "$tardir" -print | cpio -o -H pax -L' am__untar='cpio -i -H pax -d' ;; none) am__tar=false am__tar_=false am__untar=false ;; esac # If the value was cached, stop now. We just wanted to have am__tar # and am__untar set. test -n "${am_cv_prog_tar_pax}" && break # tar/untar a dummy directory, and stop if the command works. rm -rf conftest.dir mkdir conftest.dir echo GrepMe > conftest.dir/file { echo "$as_me:$LINENO: tardir=conftest.dir && eval $am__tar_ >conftest.tar" >&5 (tardir=conftest.dir && eval $am__tar_ >conftest.tar) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } rm -rf conftest.dir if test -s conftest.tar; then { echo "$as_me:$LINENO: $am__untar &5 ($am__untar &5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } { echo "$as_me:$LINENO: cat conftest.dir/file" >&5 (cat conftest.dir/file) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } grep GrepMe conftest.dir/file >/dev/null 2>&1 && break fi done rm -rf conftest.dir if ${am_cv_prog_tar_pax+:} false; then : $as_echo_n "(cached) " >&6 else am_cv_prog_tar_pax=$_am_tool fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_tar_pax" >&5 $as_echo "$am_cv_prog_tar_pax" >&6; } # POSIX will say in a future version that running "rm -f" with no argument # is OK; and we want to be able to make that assumption in our Makefile # recipes. So use an aggressive probe to check that the usage we want is # actually supported "in the wild" to an acceptable degree. # See automake bug#10828. # To make any issue more visible, cause the running configure to be aborted # by default if the 'rm' program in use doesn't match our expectations; the # user can still override this though. if rm -f && rm -fr && rm -rf; then : OK; else cat >&2 <<'END' Oops! Your 'rm' program seems unable to run without file operands specified on the command line, even when the '-f' option is present. This is contrary to the behaviour of most rm programs out there, and not conforming with the upcoming POSIX standard: Please tell bug-automake@gnu.org about your system, including the value of your $PATH and any error possibly output before this message. This can help us improve future automake versions. END if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then echo 'Configuration will proceed anyway, since you have set the' >&2 echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 echo >&2 else cat >&2 <<'END' Aborting the configuration process, to ensure you take notice of the issue. You can download and install GNU coreutils to get an 'rm' implementation that behaves properly: . If you want to complete the configuration process using your problematic 'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM to "yes", and re-run configure. END as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5 fi fi # Check whether --enable-silent-rules was given. if test "${enable_silent_rules+set}" = set; then : enableval=$enable_silent_rules; fi case $enable_silent_rules in # ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=1;; esac am_make=${MAKE-make} { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 $as_echo_n "checking whether $am_make supports nested variables... " >&6; } if ${am_cv_make_support_nested_variables+:} false; then : $as_echo_n "(cached) " >&6 else if $as_echo 'TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 $as_echo "$am_cv_make_support_nested_variables" >&6; } if test $am_cv_make_support_nested_variables = yes; then AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AM_BACKSLASH='\' { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5 $as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; } # Check whether --enable-maintainer-mode was given. if test "${enable_maintainer_mode+set}" = set; then : enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval else USE_MAINTAINER_MODE=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5 $as_echo "$USE_MAINTAINER_MODE" >&6; } if test $USE_MAINTAINER_MODE = yes; then MAINTAINER_MODE_TRUE= MAINTAINER_MODE_FALSE='#' else MAINTAINER_MODE_TRUE='#' MAINTAINER_MODE_FALSE= fi MAINT=$MAINTAINER_MODE_TRUE ac_config_headers="$ac_config_headers config.h libinfinity/inf-config.h" LIBINFINITY_VERSION=0.7.1 LIBINFINITY_API_VERSION=0.7 LIBINFINITY_LIBTOOL_VERSION=0:0:0 # Make sure we can run config.sub. $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 $as_echo_n "checking build system type... " >&6; } if ${ac_cv_build+:} false; then : $as_echo_n "(cached) " >&6 else ac_build_alias=$build_alias test "x$ac_build_alias" = x && ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` test "x$ac_build_alias" = x && as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 $as_echo "$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; *) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; esac build=$ac_cv_build ac_save_IFS=$IFS; IFS='-' set x $ac_cv_build shift build_cpu=$1 build_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: build_os=$* IFS=$ac_save_IFS case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 $as_echo_n "checking host system type... " >&6; } if ${ac_cv_host+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$host_alias" = x; then ac_cv_host=$ac_cv_build else ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 $as_echo "$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; *) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; esac host=$ac_cv_host ac_save_IFS=$IFS; IFS='-' set x $ac_cv_host shift host_cpu=$1 host_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: host_os=$* IFS=$ac_save_IFS case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac # Check whether --enable-silent-rules was given. if test "${enable_silent_rules+set}" = set; then : enableval=$enable_silent_rules; fi case $enable_silent_rules in # ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=0;; esac am_make=${MAKE-make} { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 $as_echo_n "checking whether $am_make supports nested variables... " >&6; } if ${am_cv_make_support_nested_variables+:} false; then : $as_echo_n "(cached) " >&6 else if $as_echo 'TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 $as_echo "$am_cv_make_support_nested_variables" >&6; } if test $am_cv_make_support_nested_variables = yes; then AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AM_BACKSLASH='\' # Remove -Wno-strict-prototypes for the feature tests has_strict_prototypes="" if (echo $CFLAGS | grep -- -Wstrict-prototype) then has_strict_prototypes="true" old_CFLAGS=$CFLAGS CFLAGS="$CFLAGS -Wno-strict-prototypes" fi # Make GNU and POSIX extensions such as readdir_r, O_NOFOLLOW and # fdopendir available DEPDIR="${am__leading_dot}deps" ac_config_commands="$ac_config_commands depfiles" am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 $as_echo_n "checking for style of include used by $am_make... " >&6; } am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # Ignore all kinds of additional output from 'make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 $as_echo "$_am_result" >&6; } rm -f confinc confmf # Check whether --enable-dependency-tracking was given. if test "${enable_dependency_tracking+set}" = set; then : enableval=$enable_dependency_tracking; fi if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi if test "x$enable_dependency_tracking" != xno; then AMDEP_TRUE= AMDEP_FALSE='#' else AMDEP_TRUE='#' AMDEP_FALSE= fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 $as_echo_n "checking whether $CC understands -c and -o together... " >&6; } if ${am_cv_prog_cc_c_o+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF # Make sure it works both with $CC and with simple cc. # Following AC_PROG_CC_C_O, we do the test twice because some # compilers refuse to overwrite an existing .o file with -o, # though they will create one. am_cv_prog_cc_c_o=yes for am_i in 1 2; do if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } \ && test -f conftest2.$ac_objext; then : OK else am_cv_prog_cc_c_o=no break fi done rm -f core conftest* unset am_i fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 $as_echo "$am_cv_prog_cc_c_o" >&6; } if test "$am_cv_prog_cc_c_o" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu depcc="$CC" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if ${am_cv_CC_dependencies_compiler_type+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 $as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if ${ac_cv_prog_CPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if ${ac_cv_path_GREP+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_GREP" || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if ${ac_cv_path_EGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_EGREP" || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done ac_fn_c_check_header_mongrel "$LINENO" "minix/config.h" "ac_cv_header_minix_config_h" "$ac_includes_default" if test "x$ac_cv_header_minix_config_h" = xyes; then : MINIX=yes else MINIX= fi if test "$MINIX" = yes; then $as_echo "#define _POSIX_SOURCE 1" >>confdefs.h $as_echo "#define _POSIX_1_SOURCE 2" >>confdefs.h $as_echo "#define _MINIX 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether it is safe to define __EXTENSIONS__" >&5 $as_echo_n "checking whether it is safe to define __EXTENSIONS__... " >&6; } if ${ac_cv_safe_to_define___extensions__+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ # define __EXTENSIONS__ 1 $ac_includes_default int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_safe_to_define___extensions__=yes else ac_cv_safe_to_define___extensions__=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_safe_to_define___extensions__" >&5 $as_echo "$ac_cv_safe_to_define___extensions__" >&6; } test $ac_cv_safe_to_define___extensions__ = yes && $as_echo "#define __EXTENSIONS__ 1" >>confdefs.h $as_echo "#define _ALL_SOURCE 1" >>confdefs.h $as_echo "#define _GNU_SOURCE 1" >>confdefs.h $as_echo "#define _POSIX_PTHREAD_SEMANTICS 1" >>confdefs.h $as_echo "#define _TANDEM_SOURCE 1" >>confdefs.h ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 $as_echo_n "checking whether $CC understands -c and -o together... " >&6; } if ${am_cv_prog_cc_c_o+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF # Make sure it works both with $CC and with simple cc. # Following AC_PROG_CC_C_O, we do the test twice because some # compilers refuse to overwrite an existing .o file with -o, # though they will create one. am_cv_prog_cc_c_o=yes for am_i in 1 2; do if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 ac_status=$? echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); } \ && test -f conftest2.$ac_objext; then : OK else am_cv_prog_cc_c_o=no break fi done rm -f core conftest* unset am_i fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 $as_echo "$am_cv_prog_cc_c_o" >&6; } if test "$am_cv_prog_cc_c_o" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu depcc="$CC" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if ${am_cv_CC_dependencies_compiler_type+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 $as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if ${ac_cv_prog_CPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 $as_echo_n "checking whether ln -s works... " >&6; } LN_S=$as_ln_s if test "$LN_S" = "ln -s"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 $as_echo "no, using $LN_S" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SET_MAKE= else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi if test -n "$ac_tool_prefix"; then for ac_prog in ar lib "link -lib" do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AR="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AR=$ac_cv_prog_AR if test -n "$AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 $as_echo "$AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AR" && break done fi if test -z "$AR"; then ac_ct_AR=$AR for ac_prog in ar lib "link -lib" do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_AR"; then ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_AR="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_AR=$ac_cv_prog_ac_ct_AR if test -n "$ac_ct_AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 $as_echo "$ac_ct_AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_AR" && break done if test "x$ac_ct_AR" = x; then AR="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac AR=$ac_ct_AR fi fi : ${AR=ar} { $as_echo "$as_me:${as_lineno-$LINENO}: checking the archiver ($AR) interface" >&5 $as_echo_n "checking the archiver ($AR) interface... " >&6; } if ${am_cv_ar_interface+:} false; then : $as_echo_n "(cached) " >&6 else ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu am_cv_ar_interface=ar cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int some_variable = 0; _ACEOF if ac_fn_c_try_compile "$LINENO"; then : am_ar_try='$AR cru libconftest.a conftest.$ac_objext >&5' { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$am_ar_try\""; } >&5 (eval $am_ar_try) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test "$ac_status" -eq 0; then am_cv_ar_interface=ar else am_ar_try='$AR -NOLOGO -OUT:conftest.lib conftest.$ac_objext >&5' { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$am_ar_try\""; } >&5 (eval $am_ar_try) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test "$ac_status" -eq 0; then am_cv_ar_interface=lib else am_cv_ar_interface=unknown fi fi rm -f conftest.lib libconftest.a fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_ar_interface" >&5 $as_echo "$am_cv_ar_interface" >&6; } case $am_cv_ar_interface in ar) ;; lib) # Microsoft lib, so override with the ar-lib wrapper script. # FIXME: It is wrong to rewrite AR. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__AR in this case, # and then we could set am__AR="$am_aux_dir/ar-lib \$(AR)" or something # similar. AR="$am_aux_dir/ar-lib $AR" ;; unknown) as_fn_error $? "could not determine $AR interface" "$LINENO" 5 ;; esac case `pwd` in *\ * | *\ *) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 $as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; esac macro_version='2.4.6' macro_revision='2.4.6' ltmain=$ac_aux_dir/ltmain.sh # Backslashify metacharacters that are still active within # double-quoted strings. sed_quote_subst='s/\(["`$\\]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\(["`\\]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 $as_echo_n "checking how to print strings... " >&6; } # Test print first, because it will be a builtin if present. if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='print -r --' elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='printf %s\n' else # Use this function as a fallback that always works. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $1 _LTECHO_EOF' } ECHO='func_fallback_echo' fi # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "" } case $ECHO in printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 $as_echo "printf" >&6; } ;; print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 $as_echo "print -r" >&6; } ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 $as_echo "cat" >&6; } ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 $as_echo_n "checking for a sed that does not truncate output... " >&6; } if ${ac_cv_path_SED+:} false; then : $as_echo_n "(cached) " >&6 else ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ for ac_i in 1 2 3 4 5 6 7; do ac_script="$ac_script$as_nl$ac_script" done echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed { ac_script=; unset ac_script;} if test -z "$SED"; then ac_path_SED_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_SED" || continue # Check for GNU ac_path_SED and select it if it is found. # Check for GNU $ac_path_SED case `"$ac_path_SED" --version 2>&1` in *GNU*) ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo '' >> "conftest.nl" "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_SED_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_SED="$ac_path_SED" ac_path_SED_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_SED_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_SED"; then as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 fi else ac_cv_path_SED=$SED fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 $as_echo "$ac_cv_path_SED" >&6; } SED="$ac_cv_path_SED" rm -f conftest.sed test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 $as_echo_n "checking for fgrep... " >&6; } if ${ac_cv_path_FGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 then ac_cv_path_FGREP="$GREP -F" else if test -z "$FGREP"; then ac_path_FGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in fgrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_FGREP" || continue # Check for GNU ac_path_FGREP and select it if it is found. # Check for GNU $ac_path_FGREP case `"$ac_path_FGREP" --version 2>&1` in *GNU*) ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'FGREP' >> "conftest.nl" "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_FGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_FGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_FGREP"; then as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_FGREP=$FGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 $as_echo "$ac_cv_path_FGREP" >&6; } FGREP="$ac_cv_path_FGREP" test -z "$GREP" && GREP=grep # Check whether --with-gnu-ld was given. if test "${with_gnu_ld+set}" = set; then : withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes else with_gnu_ld=no fi ac_prog=ld if test yes = "$GCC"; then # Check if gcc -print-prog-name=ld gives a path. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 $as_echo_n "checking for ld used by $CC... " >&6; } case $host in *-*-mingw*) # gcc leaves a trailing carriage return, which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [\\/]* | ?:[\\/]*) re_direlt='/[^/][^/]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD=$ac_prog ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test yes = "$with_gnu_ld"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 $as_echo_n "checking for GNU ld... " >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 $as_echo_n "checking for non-GNU ld... " >&6; } fi if ${lt_cv_path_LD+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$LD"; then lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD=$ac_dir/$ac_prog # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &5 $as_echo "$LD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 $as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } if ${lt_cv_prog_gnu_ld+:} false; then : $as_echo_n "(cached) " >&6 else # I'd rather use --version here, but apparently some GNU lds only accept -v. case `$LD -v 2>&1 &5 $as_echo "$lt_cv_prog_gnu_ld" >&6; } with_gnu_ld=$lt_cv_prog_gnu_ld { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 $as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } if ${lt_cv_path_NM+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM=$NM else lt_nm_to_check=${ac_tool_prefix}nm if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. tmp_nm=$ac_dir/$lt_tmp_nm if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then # Check to see if the nm accepts a BSD-compat flag. # Adding the 'sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty case $build_os in mingw*) lt_bad_file=conftest.nm/nofile ;; *) lt_bad_file=/dev/null ;; esac case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in *$lt_bad_file* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break 2 ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break 2 ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS=$lt_save_ifs done : ${lt_cv_path_NM=no} fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 $as_echo "$lt_cv_path_NM" >&6; } if test no != "$lt_cv_path_NM"; then NM=$lt_cv_path_NM else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$DUMPBIN"; then : # Let the user override the test. else if test -n "$ac_tool_prefix"; then for ac_prog in dumpbin "link -dump" do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DUMPBIN+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DUMPBIN"; then ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DUMPBIN=$ac_cv_prog_DUMPBIN if test -n "$DUMPBIN"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 $as_echo "$DUMPBIN" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$DUMPBIN" && break done fi if test -z "$DUMPBIN"; then ac_ct_DUMPBIN=$DUMPBIN for ac_prog in dumpbin "link -dump" do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DUMPBIN"; then ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN if test -n "$ac_ct_DUMPBIN"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 $as_echo "$ac_ct_DUMPBIN" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_DUMPBIN" && break done if test "x$ac_ct_DUMPBIN" = x; then DUMPBIN=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DUMPBIN=$ac_ct_DUMPBIN fi fi case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols -headers" ;; *) DUMPBIN=: ;; esac fi if test : != "$DUMPBIN"; then NM=$DUMPBIN fi fi test -z "$NM" && NM=nm { $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 $as_echo_n "checking the name lister ($NM) interface... " >&6; } if ${lt_cv_nm_interface+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&5 (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&5 (eval echo "\"\$as_me:$LINENO: output\"" >&5) cat conftest.out >&5 if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 $as_echo "$lt_cv_nm_interface" >&6; } # find the maximum length of command line arguments { $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 $as_echo_n "checking the maximum length of command line arguments... " >&6; } if ${lt_cv_sys_max_cmd_len+:} false; then : $as_echo_n "(cached) " >&6 else i=0 teststring=ABCD case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; mint*) # On MiNT this can take a long time and run out of memory. lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; os2*) # The test takes a long time on OS/2. lt_cv_sys_max_cmd_len=8192 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len" && \ test undefined != "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while { test X`env echo "$teststring$teststring" 2>/dev/null` \ = "X$teststring$teststring"; } >/dev/null 2>&1 && test 17 != "$i" # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` teststring= # Add a significant safety factor because C++ compilers can tack on # massive amounts of additional arguments before passing them to the # linker. It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac fi if test -n "$lt_cv_sys_max_cmd_len"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 $as_echo "$lt_cv_sys_max_cmd_len" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 $as_echo "none" >&6; } fi max_cmd_len=$lt_cv_sys_max_cmd_len : ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi # test EBCDIC or ASCII case `echo X|tr X '\101'` in A) # ASCII based system # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5 $as_echo_n "checking how to convert $build file names to $host format... " >&6; } if ${lt_cv_to_host_file_cmd+:} false; then : $as_echo_n "(cached) " >&6 else case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 ;; esac ;; *-*-cygwin* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_noop ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin ;; esac ;; * ) # unhandled hosts (and "normal" native builds) lt_cv_to_host_file_cmd=func_convert_file_noop ;; esac fi to_host_file_cmd=$lt_cv_to_host_file_cmd { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5 $as_echo "$lt_cv_to_host_file_cmd" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5 $as_echo_n "checking how to convert $build file names to toolchain format... " >&6; } if ${lt_cv_to_tool_file_cmd+:} false; then : $as_echo_n "(cached) " >&6 else #assume ordinary cross tools, or native build. lt_cv_to_tool_file_cmd=func_convert_file_noop case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 ;; esac ;; esac fi to_tool_file_cmd=$lt_cv_to_tool_file_cmd { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5 $as_echo "$lt_cv_to_tool_file_cmd" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 $as_echo_n "checking for $LD option to reload object files... " >&6; } if ${lt_cv_ld_reload_flag+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_reload_flag='-r' fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 $as_echo "$lt_cv_ld_reload_flag" >&6; } reload_flag=$lt_cv_ld_reload_flag case $reload_flag in "" | " "*) ;; *) reload_flag=" $reload_flag" ;; esac reload_cmds='$LD$reload_flag -o $output$reload_objs' case $host_os in cygwin* | mingw* | pw32* | cegcc*) if test yes != "$GCC"; then reload_cmds=false fi ;; darwin*) if test yes = "$GCC"; then reload_cmds='$LTCC $LTCFLAGS -nostdlib $wl-r -o $output$reload_objs' else reload_cmds='$LD$reload_flag -o $output$reload_objs' fi ;; esac if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. set dummy ${ac_tool_prefix}objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OBJDUMP"; then ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OBJDUMP=$ac_cv_prog_OBJDUMP if test -n "$OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 $as_echo "$OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OBJDUMP"; then ac_ct_OBJDUMP=$OBJDUMP # Extract the first word of "objdump", so it can be a program name with args. set dummy objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OBJDUMP"; then ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OBJDUMP="objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP if test -n "$ac_ct_OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 $as_echo "$ac_ct_OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OBJDUMP" = x; then OBJDUMP="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OBJDUMP=$ac_ct_OBJDUMP fi else OBJDUMP="$ac_cv_prog_OBJDUMP" fi test -z "$OBJDUMP" && OBJDUMP=objdump { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 $as_echo_n "checking how to recognize dependent libraries... " >&6; } if ${lt_cv_deplibs_check_method+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_file_magic_cmd='$MAGIC_CMD' lt_cv_file_magic_test_file= lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. # 'unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path # that responds to the $file_magic_cmd with a given extended regex. # If you have 'file' or equivalent on your system and you're not sure # whether 'pass_all' will *always* work, you probably want this one. case $host_os in aix[4-9]*) lt_cv_deplibs_check_method=pass_all ;; beos*) lt_cv_deplibs_check_method=pass_all ;; bsdi[45]*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' lt_cv_file_magic_cmd='/usr/bin/file -L' lt_cv_file_magic_test_file=/shlib/libc.so ;; cygwin*) # func_win32_libid is a shell function defined in ltmain.sh lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' ;; mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by # func_win32_libid shell function, so use a weaker test based on 'objdump', # unless we find 'file', for example because we are cross-compiling. if ( file / ) >/dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else # Keep this pattern in sync with the one in func_win32_libid. lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc*) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; haiku*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]' lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[3-9]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) lt_cv_deplibs_check_method=pass_all ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd* | bitrig*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; os2*) lt_cv_deplibs_check_method=pass_all ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 $as_echo "$lt_cv_deplibs_check_method" >&6; } file_magic_glob= want_nocaseglob=no if test "$build" = "$host"; then case $host_os in mingw* | pw32*) if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then want_nocaseglob=yes else file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"` fi ;; esac fi file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. set dummy ${ac_tool_prefix}dlltool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DLLTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DLLTOOL"; then ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DLLTOOL=$ac_cv_prog_DLLTOOL if test -n "$DLLTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 $as_echo "$DLLTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_DLLTOOL"; then ac_ct_DLLTOOL=$DLLTOOL # Extract the first word of "dlltool", so it can be a program name with args. set dummy dlltool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DLLTOOL"; then ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DLLTOOL="dlltool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL if test -n "$ac_ct_DLLTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 $as_echo "$ac_ct_DLLTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_DLLTOOL" = x; then DLLTOOL="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DLLTOOL=$ac_ct_DLLTOOL fi else DLLTOOL="$ac_cv_prog_DLLTOOL" fi test -z "$DLLTOOL" && DLLTOOL=dlltool { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 $as_echo_n "checking how to associate runtime and link libraries... " >&6; } if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_sharedlib_from_linklib_cmd='unknown' case $host_os in cygwin* | mingw* | pw32* | cegcc*) # two different shell functions defined in ltmain.sh; # decide which one to use based on capabilities of $DLLTOOL case `$DLLTOOL --help 2>&1` in *--identify-strict*) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib ;; *) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback ;; esac ;; *) # fallback: assume linklib IS sharedlib lt_cv_sharedlib_from_linklib_cmd=$ECHO ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5 $as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; } sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO if test -n "$ac_tool_prefix"; then for ac_prog in ar do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AR="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AR=$ac_cv_prog_AR if test -n "$AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 $as_echo "$AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AR" && break done fi if test -z "$AR"; then ac_ct_AR=$AR for ac_prog in ar do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_AR"; then ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_AR="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_AR=$ac_cv_prog_ac_ct_AR if test -n "$ac_ct_AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 $as_echo "$ac_ct_AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_AR" && break done if test "x$ac_ct_AR" = x; then AR="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac AR=$ac_ct_AR fi fi : ${AR=ar} : ${AR_FLAGS=cru} { $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5 $as_echo_n "checking for archiver @FILE support... " >&6; } if ${lt_cv_ar_at_file+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ar_at_file=no cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : echo conftest.$ac_objext > conftest.lst lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5' { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 (eval $lt_ar_try) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test 0 -eq "$ac_status"; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 (eval $lt_ar_try) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test 0 -ne "$ac_status"; then lt_cv_ar_at_file=@ fi fi rm -f conftest.* libconftest.a fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 $as_echo "$lt_cv_ar_at_file" >&6; } if test no = "$lt_cv_ar_at_file"; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi test -z "$STRIP" && STRIP=: if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 $as_echo "$RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 $as_echo "$ac_ct_RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi test -z "$RANLIB" && RANLIB=: # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in bitrig* | openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" fi case $host_os in darwin*) lock_old_archive_extraction=yes ;; *) lock_old_archive_extraction=no ;; esac # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Check for command to grab the raw symbol name followed by C symbol from nm. { $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 $as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } if ${lt_cv_sys_global_symbol_pipe+:} false; then : $as_echo_n "(cached) " >&6 else # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[BCDEGRST]' # Regexp to match symbols that can be accessed directly from C. sympat='\([_A-Za-z][_A-Za-z0-9]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[BCDT]' ;; cygwin* | mingw* | pw32* | cegcc*) symcode='[ABCDGISTW]' ;; hpux*) if test ia64 = "$host_cpu"; then symcode='[ABCDEGRST]' fi ;; irix* | nonstopux*) symcode='[BCDEGRST]' ;; osf*) symcode='[BCDEGQRST]' ;; solaris*) symcode='[BDRT]' ;; sco3.2v5*) symcode='[DT]' ;; sysv4.2uw2*) symcode='[DT]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[ABDT]' ;; sysv4) symcode='[DFNSTU]' ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[ABCDGIRSTW]' ;; esac if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Gets list of data symbols to import. lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" # Adjust the below global symbol transforms to fixup imported variables. lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" lt_c_name_lib_hook="\ -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" else # Disable hooks by default. lt_cv_sys_global_symbol_to_import= lt_cdecl_hook= lt_c_name_hook= lt_c_name_lib_hook= fi # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="sed -n"\ $lt_cdecl_hook\ " -e 's/^T .* \(.*\)$/extern int \1();/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ $lt_c_name_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" # Transform an extracted symbol line into symbol name with lib prefix and # symbol address. lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ $lt_c_name_lib_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function, # D for any global variable and I for any imported variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK '"\ " {last_section=section; section=\$ 3};"\ " /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ " /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ " /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ " {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ " s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then # Now try to grab the symbols. nlist=conftest.nm if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5 (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE /* DATA imports from DLLs on WIN32 can't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT_DLSYM_CONST #elif defined __osf__ /* This system does not cope well with relocations in const data. */ # define LT_DLSYM_CONST #else # define LT_DLSYM_CONST const #endif #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ LT_DLSYM_CONST struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS LIBS=conftstm.$ac_objext CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest$ac_exeext; then pipe_works=yes fi LIBS=$lt_globsym_save_LIBS CFLAGS=$lt_globsym_save_CFLAGS else echo "cannot find nm_test_func in $nlist" >&5 fi else echo "cannot find nm_test_var in $nlist" >&5 fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 fi else echo "$progname: failed program was:" >&5 cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test yes = "$pipe_works"; then break else lt_cv_sys_global_symbol_pipe= fi done fi if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 $as_echo "failed" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } fi # Response file support. if test "$lt_cv_nm_interface" = "MS dumpbin"; then nm_file_list_spec='@' elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then nm_file_list_spec='@' fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 $as_echo_n "checking for sysroot... " >&6; } # Check whether --with-sysroot was given. if test "${with_sysroot+set}" = set; then : withval=$with_sysroot; else with_sysroot=no fi lt_sysroot= case $with_sysroot in #( yes) if test yes = "$GCC"; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( /*) lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` ;; #( no|'') ;; #( *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_sysroot" >&5 $as_echo "$with_sysroot" >&6; } as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5 $as_echo "${lt_sysroot:-no}" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a working dd" >&5 $as_echo_n "checking for a working dd... " >&6; } if ${ac_cv_path_lt_DD+:} false; then : $as_echo_n "(cached) " >&6 else printf 0123456789abcdef0123456789abcdef >conftest.i cat conftest.i conftest.i >conftest2.i : ${lt_DD:=$DD} if test -z "$lt_DD"; then ac_path_lt_DD_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in dd; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_lt_DD="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_lt_DD" || continue if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then cmp -s conftest.i conftest.out \ && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: fi $ac_path_lt_DD_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_lt_DD"; then : fi else ac_cv_path_lt_DD=$lt_DD fi rm -f conftest.i conftest2.i conftest.out fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_lt_DD" >&5 $as_echo "$ac_cv_path_lt_DD" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to truncate binary pipes" >&5 $as_echo_n "checking how to truncate binary pipes... " >&6; } if ${lt_cv_truncate_bin+:} false; then : $as_echo_n "(cached) " >&6 else printf 0123456789abcdef0123456789abcdef >conftest.i cat conftest.i conftest.i >conftest2.i lt_cv_truncate_bin= if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then cmp -s conftest.i conftest.out \ && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" fi rm -f conftest.i conftest2.i conftest.out test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_truncate_bin" >&5 $as_echo "$lt_cv_truncate_bin" >&6; } # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. func_cc_basename () { for cc_temp in $*""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` } # Check whether --enable-libtool-lock was given. if test "${enable_libtool_lock+set}" = set; then : enableval=$enable_libtool_lock; fi test no = "$enable_libtool_lock" || enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out what ABI is being produced by ac_compile, and set mode # options accordingly. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE=32 ;; *ELF-64*) HPUX_IA64_MODE=64 ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo '#line '$LINENO' "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then if test yes = "$lt_cv_prog_gnu_ld"; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; mips64*-*linux*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo '#line '$LINENO' "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then emul=elf case `/usr/bin/file conftest.$ac_objext` in *32-bit*) emul="${emul}32" ;; *64-bit*) emul="${emul}64" ;; esac case `/usr/bin/file conftest.$ac_objext` in *MSB*) emul="${emul}btsmip" ;; *LSB*) emul="${emul}ltsmip" ;; esac case `/usr/bin/file conftest.$ac_objext` in *N32*) emul="${emul}n32" ;; esac LD="${LD-ld} -m $emul" fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. Note that the listed cases only cover the # situations where additional linker options are needed (such as when # doing 32-bit compilation for a host where ld defaults to 64-bit, or # vice versa); the common cases where no linker options are needed do # not appear in the list. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) case `/usr/bin/file conftest.o` in *x86-64*) LD="${LD-ld} -m elf32_x86_64" ;; *) LD="${LD-ld} -m elf_i386" ;; esac ;; powerpc64le-*linux*) LD="${LD-ld} -m elf32lppclinux" ;; powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; powerpcle-*linux*) LD="${LD-ld} -m elf64lppc" ;; powerpc-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS=$CFLAGS CFLAGS="$CFLAGS -belf" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 $as_echo_n "checking whether the C compiler needs -belf... " >&6; } if ${lt_cv_cc_needs_belf+:} false; then : $as_echo_n "(cached) " >&6 else ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_cc_needs_belf=yes else lt_cv_cc_needs_belf=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 $as_echo "$lt_cv_cc_needs_belf" >&6; } if test yes != "$lt_cv_cc_needs_belf"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS=$SAVE_CFLAGS fi ;; *-*solaris*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) case $host in i?86-*-solaris*|x86_64-*-solaris*) LD="${LD-ld} -m elf_x86_64" ;; sparc*-*-solaris*) LD="${LD-ld} -m elf64_sparc" ;; esac # GNU ld 2.21 introduced _sol2 emulations. Use them if available. if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then LD=${LD-ld}_sol2 fi ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks=$enable_libtool_lock if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args. set dummy ${ac_tool_prefix}mt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_MANIFEST_TOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$MANIFEST_TOOL"; then ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL if test -n "$MANIFEST_TOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5 $as_echo "$MANIFEST_TOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_MANIFEST_TOOL"; then ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL # Extract the first word of "mt", so it can be a program name with args. set dummy mt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_MANIFEST_TOOL"; then ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_MANIFEST_TOOL="mt" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL if test -n "$ac_ct_MANIFEST_TOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5 $as_echo "$ac_ct_MANIFEST_TOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_MANIFEST_TOOL" = x; then MANIFEST_TOOL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL fi else MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL" fi test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5 $as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; } if ${lt_cv_path_mainfest_tool+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_path_mainfest_tool=no echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5 $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out cat conftest.err >&5 if $GREP 'Manifest Tool' conftest.out > /dev/null; then lt_cv_path_mainfest_tool=yes fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 $as_echo "$lt_cv_path_mainfest_tool" >&6; } if test yes != "$lt_cv_path_mainfest_tool"; then MANIFEST_TOOL=: fi case $host_os in rhapsody* | darwin*) if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DSYMUTIL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DSYMUTIL"; then ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DSYMUTIL=$ac_cv_prog_DSYMUTIL if test -n "$DSYMUTIL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 $as_echo "$DSYMUTIL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_DSYMUTIL"; then ac_ct_DSYMUTIL=$DSYMUTIL # Extract the first word of "dsymutil", so it can be a program name with args. set dummy dsymutil; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DSYMUTIL"; then ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL if test -n "$ac_ct_DSYMUTIL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 $as_echo "$ac_ct_DSYMUTIL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_DSYMUTIL" = x; then DSYMUTIL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DSYMUTIL=$ac_ct_DSYMUTIL fi else DSYMUTIL="$ac_cv_prog_DSYMUTIL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. set dummy ${ac_tool_prefix}nmedit; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_NMEDIT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$NMEDIT"; then ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi NMEDIT=$ac_cv_prog_NMEDIT if test -n "$NMEDIT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 $as_echo "$NMEDIT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_NMEDIT"; then ac_ct_NMEDIT=$NMEDIT # Extract the first word of "nmedit", so it can be a program name with args. set dummy nmedit; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_NMEDIT"; then ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_NMEDIT="nmedit" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT if test -n "$ac_ct_NMEDIT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 $as_echo "$ac_ct_NMEDIT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_NMEDIT" = x; then NMEDIT=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac NMEDIT=$ac_ct_NMEDIT fi else NMEDIT="$ac_cv_prog_NMEDIT" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. set dummy ${ac_tool_prefix}lipo; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_LIPO+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$LIPO"; then ac_cv_prog_LIPO="$LIPO" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_LIPO="${ac_tool_prefix}lipo" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi LIPO=$ac_cv_prog_LIPO if test -n "$LIPO"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 $as_echo "$LIPO" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_LIPO"; then ac_ct_LIPO=$LIPO # Extract the first word of "lipo", so it can be a program name with args. set dummy lipo; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_LIPO+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_LIPO"; then ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_LIPO="lipo" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO if test -n "$ac_ct_LIPO"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 $as_echo "$ac_ct_LIPO" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_LIPO" = x; then LIPO=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac LIPO=$ac_ct_LIPO fi else LIPO="$ac_cv_prog_LIPO" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. set dummy ${ac_tool_prefix}otool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OTOOL"; then ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OTOOL="${ac_tool_prefix}otool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OTOOL=$ac_cv_prog_OTOOL if test -n "$OTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 $as_echo "$OTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OTOOL"; then ac_ct_OTOOL=$OTOOL # Extract the first word of "otool", so it can be a program name with args. set dummy otool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OTOOL"; then ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OTOOL="otool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL if test -n "$ac_ct_OTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 $as_echo "$ac_ct_OTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OTOOL" = x; then OTOOL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL=$ac_ct_OTOOL fi else OTOOL="$ac_cv_prog_OTOOL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. set dummy ${ac_tool_prefix}otool64; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OTOOL64+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OTOOL64"; then ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OTOOL64=$ac_cv_prog_OTOOL64 if test -n "$OTOOL64"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 $as_echo "$OTOOL64" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OTOOL64"; then ac_ct_OTOOL64=$OTOOL64 # Extract the first word of "otool64", so it can be a program name with args. set dummy otool64; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OTOOL64"; then ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OTOOL64="otool64" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 if test -n "$ac_ct_OTOOL64"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 $as_echo "$ac_ct_OTOOL64" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OTOOL64" = x; then OTOOL64=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL64=$ac_ct_OTOOL64 fi else OTOOL64="$ac_cv_prog_OTOOL64" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 $as_echo_n "checking for -single_module linker flag... " >&6; } if ${lt_cv_apple_cc_single_mod+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_apple_cc_single_mod=no if test -z "$LT_MULTI_MODULE"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&5 $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? # If there is a non-empty error log, and "single_module" # appears in it, assume the flag caused a linker warning if test -s conftest.err && $GREP single_module conftest.err; then cat conftest.err >&5 # Otherwise, if the output was created with a 0 exit code from # the compiler, it worked. elif test -f libconftest.dylib && test 0 = "$_lt_result"; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&5 fi rm -rf libconftest.dylib* rm -f conftest.* fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 $as_echo "$lt_cv_apple_cc_single_mod" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 $as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } if ${lt_cv_ld_exported_symbols_list+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_ld_exported_symbols_list=yes else lt_cv_ld_exported_symbols_list=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 $as_echo "$lt_cv_ld_exported_symbols_list" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 $as_echo_n "checking for -force_load linker flag... " >&6; } if ${lt_cv_ld_force_load+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_force_load=no cat > conftest.c << _LT_EOF int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 echo "$AR cru libconftest.a conftest.o" >&5 $AR cru libconftest.a conftest.o 2>&5 echo "$RANLIB libconftest.a" >&5 $RANLIB libconftest.a 2>&5 cat > conftest.c << _LT_EOF int main() { return 0;} _LT_EOF echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5 $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err _lt_result=$? if test -s conftest.err && $GREP force_load conftest.err; then cat conftest.err >&5 elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then lt_cv_ld_force_load=yes else cat conftest.err >&5 fi rm -f conftest.err libconftest.a conftest conftest.c rm -rf conftest.dSYM fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 $as_echo "$lt_cv_ld_force_load" >&6; } case $host_os in rhapsody* | darwin1.[012]) _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[91]*) _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; 10.[012][,.]*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; 10.*) _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test yes = "$lt_cv_apple_cc_single_mod"; then _lt_dar_single_mod='$single_module' fi if test yes = "$lt_cv_ld_exported_symbols_list"; then _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' fi if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac # func_munge_path_list VARIABLE PATH # ----------------------------------- # VARIABLE is name of variable containing _space_ separated list of # directories to be munged by the contents of PATH, which is string # having a format: # "DIR[:DIR]:" # string "DIR[ DIR]" will be prepended to VARIABLE # ":DIR[:DIR]" # string "DIR[ DIR]" will be appended to VARIABLE # "DIRP[:DIRP]::[DIRA:]DIRA" # string "DIRP[ DIRP]" will be prepended to VARIABLE and string # "DIRA[ DIRA]" will be appended to VARIABLE # "DIR[:DIR]" # VARIABLE will be replaced by "DIR[ DIR]" func_munge_path_list () { case x$2 in x) ;; *:) eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" ;; x:*) eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" ;; *::*) eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" ;; *) eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" ;; esac } for ac_header in dlfcn.h do : ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default " if test "x$ac_cv_header_dlfcn_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_DLFCN_H 1 _ACEOF fi done # Set options enable_dlopen=no enable_win32_dll=no # Check whether --enable-shared was given. if test "${enable_shared+set}" = set; then : enableval=$enable_shared; p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS=$lt_save_ifs ;; esac else enable_shared=yes fi # Check whether --enable-static was given. if test "${enable_static+set}" = set; then : enableval=$enable_static; p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS=$lt_save_ifs ;; esac else enable_static=yes fi # Check whether --with-pic was given. if test "${with_pic+set}" = set; then : withval=$with_pic; lt_p=${PACKAGE-default} case $withval in yes|no) pic_mode=$withval ;; *) pic_mode=default # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for lt_pkg in $withval; do IFS=$lt_save_ifs if test "X$lt_pkg" = "X$lt_p"; then pic_mode=yes fi done IFS=$lt_save_ifs ;; esac else pic_mode=default fi # Check whether --enable-fast-install was given. if test "${enable_fast_install+set}" = set; then : enableval=$enable_fast_install; p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS=$lt_save_ifs ;; esac else enable_fast_install=yes fi shared_archive_member_spec= case $host,$enable_shared in power*-*-aix[5-9]*,yes) { $as_echo "$as_me:${as_lineno-$LINENO}: checking which variant of shared library versioning to provide" >&5 $as_echo_n "checking which variant of shared library versioning to provide... " >&6; } # Check whether --with-aix-soname was given. if test "${with_aix_soname+set}" = set; then : withval=$with_aix_soname; case $withval in aix|svr4|both) ;; *) as_fn_error $? "Unknown argument to --with-aix-soname" "$LINENO" 5 ;; esac lt_cv_with_aix_soname=$with_aix_soname else if ${lt_cv_with_aix_soname+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_with_aix_soname=aix fi with_aix_soname=$lt_cv_with_aix_soname fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_aix_soname" >&5 $as_echo "$with_aix_soname" >&6; } if test aix != "$with_aix_soname"; then # For the AIX way of multilib, we name the shared archive member # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, # the AIX toolchain works better with OBJECT_MODE set (default 32). if test 64 = "${OBJECT_MODE-32}"; then shared_archive_member_spec=shr_64 else shared_archive_member_spec=shr fi fi ;; *) with_aix_soname=aix ;; esac # This can be used to rebuild libtool when needed LIBTOOL_DEPS=$ltmain # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' test -z "$LN_S" && LN_S="ln -s" if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 $as_echo_n "checking for objdir... " >&6; } if ${lt_cv_objdir+:} false; then : $as_echo_n "(cached) " >&6 else rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 $as_echo "$lt_cv_objdir" >&6; } objdir=$lt_cv_objdir cat >>confdefs.h <<_ACEOF #define LT_OBJDIR "$lt_cv_objdir/" _ACEOF case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a '.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a with_gnu_ld=$lt_cv_prog_gnu_ld old_CC=$CC old_CFLAGS=$CFLAGS # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o func_cc_basename $compiler cc_basename=$func_cc_basename_result # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 $as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } if ${lt_cv_path_MAGIC_CMD+:} false; then : $as_echo_n "(cached) " >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD=$MAGIC_CMD lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/${ac_tool_prefix}file"; then lt_cv_path_MAGIC_CMD=$ac_dir/"${ac_tool_prefix}file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD=$lt_cv_path_MAGIC_CMD if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS=$lt_save_ifs MAGIC_CMD=$lt_save_MAGIC_CMD ;; esac fi MAGIC_CMD=$lt_cv_path_MAGIC_CMD if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 $as_echo_n "checking for file... " >&6; } if ${lt_cv_path_MAGIC_CMD+:} false; then : $as_echo_n "(cached) " >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD=$MAGIC_CMD lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/file"; then lt_cv_path_MAGIC_CMD=$ac_dir/"file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD=$lt_cv_path_MAGIC_CMD if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS=$lt_save_ifs MAGIC_CMD=$lt_save_MAGIC_CMD ;; esac fi MAGIC_CMD=$lt_cv_path_MAGIC_CMD if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi else MAGIC_CMD=: fi fi fi ;; esac # Use C for the default configuration in the libtool script lt_save_CC=$CC ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o objext=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then lt_prog_compiler_no_builtin_flag= if test yes = "$GCC"; then case $cc_basename in nvcc*) lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; *) lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 $as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_rtti_exceptions=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-fno-rtti -fno-exceptions" ## exclude from sc_useless_quotes_in_assignment # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_rtti_exceptions=yes fi fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 $as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } if test yes = "$lt_cv_prog_compiler_rtti_exceptions"; then lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" else : fi fi lt_prog_compiler_wl= lt_prog_compiler_pic= lt_prog_compiler_static= if test yes = "$GCC"; then lt_prog_compiler_wl='-Wl,' lt_prog_compiler_static='-static' case $host_os in aix*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' fi lt_prog_compiler_pic='-fPIC' ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support lt_prog_compiler_pic='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the '-m68020' flag to GCC prevents building anything better, # like '-m68040'. lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries lt_prog_compiler_pic='-DDLL_EXPORT' case $host_os in os2*) lt_prog_compiler_static='$wl-static' ;; esac ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic='-fno-common' ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. lt_prog_compiler_static= ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) lt_prog_compiler_pic='-fPIC' ;; esac ;; interix[3-9]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. lt_prog_compiler_can_build_shared=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic=-Kconform_pic fi ;; *) lt_prog_compiler_pic='-fPIC' ;; esac case $cc_basename in nvcc*) # Cuda Compiler Driver 2.2 lt_prog_compiler_wl='-Xlinker ' if test -n "$lt_prog_compiler_pic"; then lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic" fi ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) lt_prog_compiler_wl='-Wl,' if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' else lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' fi ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic='-fno-common' case $cc_basename in nagfor*) # NAG Fortran compiler lt_prog_compiler_wl='-Wl,-Wl,,' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; esac ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic='-DDLL_EXPORT' case $host_os in os2*) lt_prog_compiler_static='$wl-static' ;; esac ;; hpux9* | hpux10* | hpux11*) lt_prog_compiler_wl='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? lt_prog_compiler_static='$wl-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) lt_prog_compiler_wl='-Wl,' # PIC (with -KPIC) is the default. lt_prog_compiler_static='-non_shared' ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in # old Intel for x86_64, which still supported -KPIC. ecc*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; # Lahey Fortran 8.1. lf95*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='--shared' lt_prog_compiler_static='--static' ;; nagfor*) # NAG Fortran compiler lt_prog_compiler_wl='-Wl,-Wl,,' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; tcc*) # Fabrice Bellard et al's Tiny C Compiler lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fpic' lt_prog_compiler_static='-Bstatic' ;; ccc*) lt_prog_compiler_wl='-Wl,' # All Alpha code is PIC. lt_prog_compiler_static='-non_shared' ;; xl* | bgxl* | bgf* | mpixl*) # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-qpic' lt_prog_compiler_static='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*) # Sun Fortran 8.3 passes all unrecognized flags to the linker lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='' ;; *Sun\ F* | *Sun*Fortran*) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='-Qoption ld ' ;; *Sun\ C*) # Sun C 5.9 lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='-Wl,' ;; *Intel*\ [CF]*Compiler*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; *Portland\ Group*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fpic' lt_prog_compiler_static='-Bstatic' ;; esac ;; esac ;; newsos6) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic='-fPIC -shared' ;; osf3* | osf4* | osf5*) lt_prog_compiler_wl='-Wl,' # All OSF/1 code is PIC. lt_prog_compiler_static='-non_shared' ;; rdos*) lt_prog_compiler_static='-non_shared' ;; solaris*) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' case $cc_basename in f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) lt_prog_compiler_wl='-Qoption ld ';; *) lt_prog_compiler_wl='-Wl,';; esac ;; sunos4*) lt_prog_compiler_wl='-Qoption ld ' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic='-Kconform_pic' lt_prog_compiler_static='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; unicos*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_can_build_shared=no ;; uts4*) lt_prog_compiler_pic='-pic' lt_prog_compiler_static='-Bstatic' ;; *) lt_prog_compiler_can_build_shared=no ;; esac fi case $host_os in # For platforms that do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic= ;; *) lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 $as_echo_n "checking for $compiler option to produce PIC... " >&6; } if ${lt_cv_prog_compiler_pic+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic=$lt_prog_compiler_pic fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5 $as_echo "$lt_cv_prog_compiler_pic" >&6; } lt_prog_compiler_pic=$lt_cv_prog_compiler_pic # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 $as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } if ${lt_cv_prog_compiler_pic_works+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic_works=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic -DPIC" ## exclude from sc_useless_quotes_in_assignment # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_pic_works=yes fi fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 $as_echo "$lt_cv_prog_compiler_pic_works" >&6; } if test yes = "$lt_cv_prog_compiler_pic_works"; then case $lt_prog_compiler_pic in "" | " "*) ;; *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; esac else lt_prog_compiler_pic= lt_prog_compiler_can_build_shared=no fi fi # # Check to make sure the static flag actually works. # wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 $as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } if ${lt_cv_prog_compiler_static_works+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_static_works=no save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS $lt_tmp_static_flag" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_static_works=yes fi else lt_cv_prog_compiler_static_works=yes fi fi $RM -r conftest* LDFLAGS=$save_LDFLAGS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 $as_echo "$lt_cv_prog_compiler_static_works" >&6; } if test yes = "$lt_cv_prog_compiler_static_works"; then : else lt_prog_compiler_static= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 $as_echo "$lt_cv_prog_compiler_c_o" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 $as_echo "$lt_cv_prog_compiler_c_o" >&6; } hard_links=nottested if test no = "$lt_cv_prog_compiler_c_o" && test no != "$need_locks"; then # do not overwrite the value of need_locks provided by the user { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 $as_echo_n "checking if we can lock with hard links... " >&6; } hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 $as_echo "$hard_links" >&6; } if test no = "$hard_links"; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5 $as_echo "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } runpath_var= allow_undefined_flag= always_export_symbols=no archive_cmds= archive_expsym_cmds= compiler_needs_object=no enable_shared_with_static_runtimes=no export_dynamic_flag_spec= export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' hardcode_automatic=no hardcode_direct=no hardcode_direct_absolute=no hardcode_libdir_flag_spec= hardcode_libdir_separator= hardcode_minus_L=no hardcode_shlibpath_var=unsupported inherit_rpath=no link_all_deplibs=unknown module_cmds= module_expsym_cmds= old_archive_from_new_cmds= old_archive_from_expsyms_cmds= thread_safe_flag_spec= whole_archive_flag_spec= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list include_expsyms= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ' (' and ')$', so one must not match beginning or # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', # as well as any symbol that contains 'd'. exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test yes != "$GCC"; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd* | bitrig*) with_gnu_ld=no ;; linux* | k*bsd*-gnu | gnu*) link_all_deplibs=no ;; esac ld_shlibs=yes # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no if test yes = "$with_gnu_ld"; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility # with the native linker. However, as the warning in the GNU ld # block says, versions before 2.19.5* couldn't really create working # shared libraries, regardless of the interface used. case `$LD -v 2>&1` in *\ \(GNU\ Binutils\)\ 2.19.5*) ;; *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;; *\ \(GNU\ Binutils\)\ [3-9]*) ;; *) lt_use_gnu_ld_interface=yes ;; esac ;; *) lt_use_gnu_ld_interface=yes ;; esac fi if test yes = "$lt_use_gnu_ld_interface"; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='$wl' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' export_dynamic_flag_spec='$wl--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then whole_archive_flag_spec=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else whole_archive_flag_spec= fi supports_anon_versioning=no case `$LD -v | $SED -e 's/(^)\+)\s\+//' 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[3-9]*) # On AIX/PPC, the GNU linker is very broken if test ia64 != "$host_cpu"; then ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.19, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to install binutils *** 2.20 or above, or modify your PATH so that a non-GNU linker is found. *** You will then need to restart the configuration process. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then allow_undefined_flag=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else ld_shlibs=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' export_dynamic_flag_spec='$wl--export-all-symbols' allow_undefined_flag=unsupported always_export_symbols=no enable_shared_with_static_runtimes=yes export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file, use it as # is; otherwise, prepend EXPORTS... archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs=no fi ;; haiku*) archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' link_all_deplibs=yes ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported shrext_cmds=.dll archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' enable_shared_with_static_runtimes=yes ;; interix[3-9]*) hardcode_direct=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='$wl-rpath,$libdir' export_dynamic_flag_spec='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' archive_expsym_cmds='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test linux-dietlibc = "$host_os"; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test no = "$tmp_diet" then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 whole_archive_flag_spec= tmp_sharedflag='--shared' ;; nagfor*) # NAGFOR 5.3 tmp_sharedflag='-Wl,-shared' ;; xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' compiler_needs_object=yes ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 whole_archive_flag_spec='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' compiler_needs_object=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' if test yes = "$supports_anon_versioning"; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi case $cc_basename in tcc*) export_dynamic_flag_spec='-rdynamic' ;; xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test yes = "$supports_anon_versioning"; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else ld_shlibs=no fi ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac ;; sunos4*) archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= hardcode_direct=yes hardcode_shlibpath_var=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac if test no = "$ld_shlibs"; then runpath_var= hardcode_libdir_flag_spec= export_dynamic_flag_spec= whole_archive_flag_spec= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) allow_undefined_flag=unsupported always_export_symbols=yes archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported fi ;; aix[4-9]*) if test ia64 = "$host_cpu"; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag= else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to GNU nm, but means don't demangle to AIX nm. # Without the "-l" option, or with the "-B" option, AIX nm treats # weak defined symbols like other global defined symbols, whereas # GNU nm marks them as "W". # While the 'weak' keyword is ignored in the Export File, we need # it in the Import File for the 'aix-soname' feature, so we have # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else export_symbols_cmds='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # have runtime linking enabled, and use it for executables. # For shared libraries, we enable/disable runtime linking # depending on the kind of the shared library created - # when "with_aix_soname,aix_use_runtimelinking" is: # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables # "aix,yes" lib.so shared, rtl:yes, for executables # lib.a static archive # "both,no" lib.so.V(shr.o) shared, rtl:yes # lib.a(lib.so.V) shared, rtl:no, for executables # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a(lib.so.V) shared, rtl:no # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a static archive case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then aix_use_runtimelinking=yes break fi done if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then # With aix-soname=svr4, we create the lib.so.V shared archives only, # so we don't have lib.a shared libs to link our executables. # We have to force runtime linking in this case. aix_use_runtimelinking=yes LDFLAGS="$LDFLAGS -Wl,-brtl" fi ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds='' hardcode_direct=yes hardcode_direct_absolute=yes hardcode_libdir_separator=':' link_all_deplibs=yes file_list_spec='$wl-f,' case $with_aix_soname,$aix_use_runtimelinking in aix,*) ;; # traditional, no import file svr4,* | *,yes) # use import file # The Import File defines what to hardcode. hardcode_direct=no hardcode_direct_absolute=no ;; esac if test yes = "$GCC"; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`$CC -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 hardcode_direct=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L=yes hardcode_libdir_flag_spec='-L$libdir' hardcode_libdir_separator= fi ;; esac shared_flag='-shared' if test yes = "$aix_use_runtimelinking"; then shared_flag="$shared_flag "'$wl-G' fi # Need to ensure runtime linking is disabled for the traditional # shared library, or the linker may eventually find shared libraries # /with/ Import File - we do not want to mix them. shared_flag_aix='-shared' shared_flag_svr4='-shared $wl-G' else # not using gcc if test ia64 = "$host_cpu"; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test yes = "$aix_use_runtimelinking"; then shared_flag='$wl-G' else shared_flag='$wl-bM:SRE' fi shared_flag_aix='$wl-bM:SRE' shared_flag_svr4='$wl-G' fi fi export_dynamic_flag_spec='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. always_export_symbols=yes if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag='-berok' # Determine the default libpath from the value encoded in an # empty executable. if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath_+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=/usr/lib:/lib fi fi aix_libpath=$lt_cv_aix_libpath_ fi hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else if test ia64 = "$host_cpu"; then hardcode_libdir_flag_spec='$wl-R $libdir:/usr/lib:/lib' allow_undefined_flag="-z nodefs" archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath_+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=/usr/lib:/lib fi fi aix_libpath=$lt_cv_aix_libpath_ fi hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag=' $wl-bernotok' allow_undefined_flag=' $wl-berok' if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. whole_archive_flag_spec='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec='$convenience' fi archive_cmds_need_lc=yes archive_expsym_cmds='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' # -brtl affects multiple linker settings, -berok does not and is overridden later compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`' if test svr4 != "$with_aix_soname"; then # This is similar to how AIX traditionally builds its shared libraries. archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' fi if test aix != "$with_aix_soname"; then archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' else # used by -dlpreopen to get the symbols archive_expsym_cmds="$archive_expsym_cmds"'~$MV $output_objdir/$realname.d/$soname $output_objdir' fi archive_expsym_cmds="$archive_expsym_cmds"'~$RM -r $output_objdir/$realname.d' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; esac ;; bsdi[45]*) export_dynamic_flag_spec=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. case $cc_basename in cl*) # Native MSVC hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported always_export_symbols=yes file_list_spec='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then cp "$export_symbols" "$output_objdir/$soname.def"; echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; else $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, )='true' enable_shared_with_static_runtimes=yes exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' # Don't use ranlib old_postinstall_cmds='chmod 644 $oldlib' postlink_cmds='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile=$lt_outputfile.exe lt_tool_outputfile=$lt_tool_outputfile.exe ;; esac~ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # Assume MSVC wrapper hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. old_archive_from_new_cmds='true' # FIXME: Should let the user specify the lib program. old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' enable_shared_with_static_runtimes=yes ;; esac ;; darwin* | rhapsody*) archive_cmds_need_lc=no hardcode_direct=no hardcode_automatic=yes hardcode_shlibpath_var=unsupported if test yes = "$lt_cv_ld_force_load"; then whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' else whole_archive_flag_spec='' fi link_all_deplibs=yes allow_undefined_flag=$_lt_dar_allow_undefined case $cc_basename in ifort*|nagfor*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test yes = "$_lt_dar_can_shared"; then output_verbose_link_cmd=func_echo_all archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" archive_expsym_cmds="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" module_expsym_cmds="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" else ld_shlibs=no fi ;; dgux*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2.*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; hpux9*) if test yes = "$GCC"; then archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' fi hardcode_libdir_flag_spec='$wl+b $wl$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes export_dynamic_flag_spec='$wl-E' ;; hpux10*) if test yes,no = "$GCC,$with_gnu_ld"; then archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test no = "$with_gnu_ld"; then hardcode_libdir_flag_spec='$wl+b $wl$libdir' hardcode_libdir_separator=: hardcode_direct=yes hardcode_direct_absolute=yes export_dynamic_flag_spec='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes fi ;; hpux11*) if test yes,no = "$GCC,$with_gnu_ld"; then case $host_cpu in hppa*64*) archive_cmds='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) archive_cmds='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) # Older versions of the 11.00 compiler do not understand -b yet # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 $as_echo_n "checking if $CC understands -b... " >&6; } if ${lt_cv_prog_compiler__b+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler__b=no save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS -b" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler__b=yes fi else lt_cv_prog_compiler__b=yes fi fi $RM -r conftest* LDFLAGS=$save_LDFLAGS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 $as_echo "$lt_cv_prog_compiler__b" >&6; } if test yes = "$lt_cv_prog_compiler__b"; then archive_cmds='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi ;; esac fi if test no = "$with_gnu_ld"; then hardcode_libdir_flag_spec='$wl+b $wl$libdir' hardcode_libdir_separator=: case $host_cpu in hppa*64*|ia64*) hardcode_direct=no hardcode_shlibpath_var=no ;; *) hardcode_direct=yes hardcode_direct_absolute=yes export_dynamic_flag_spec='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test yes = "$GCC"; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. # This should be the same for all languages, so no per-tag cache variable. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5 $as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; } if ${lt_cv_irix_exported_symbol+:} false; then : $as_echo_n "(cached) " >&6 else save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int foo (void) { return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_irix_exported_symbol=yes else lt_cv_irix_exported_symbol=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 $as_echo "$lt_cv_irix_exported_symbol" >&6; } if test yes = "$lt_cv_irix_exported_symbol"; then archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' fi link_all_deplibs=no else archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' hardcode_libdir_separator=: inherit_rpath=yes link_all_deplibs=yes ;; linux*) case $cc_basename in tcc*) # Fabrice Bellard et al's Tiny C Compiler ld_shlibs=yes archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; newsos6) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' hardcode_libdir_separator=: hardcode_shlibpath_var=no ;; *nto* | *qnx*) ;; openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then hardcode_direct=yes hardcode_shlibpath_var=no hardcode_direct_absolute=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' hardcode_libdir_flag_spec='$wl-rpath,$libdir' export_dynamic_flag_spec='$wl-E' else archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='$wl-rpath,$libdir' fi else ld_shlibs=no fi ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported shrext_cmds=.dll archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' enable_shared_with_static_runtimes=yes ;; osf3*) if test yes = "$GCC"; then allow_undefined_flag=' $wl-expect_unresolved $wl\*' archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test yes = "$GCC"; then allow_undefined_flag=' $wl-expect_unresolved $wl\*' archive_cmds='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' fi archive_cmds_need_lc='no' hardcode_libdir_separator=: ;; solaris*) no_undefined_flag=' -z defs' if test yes = "$GCC"; then wlarc='$wl' archive_cmds='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' archive_cmds='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='$wl' archive_cmds='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi hardcode_libdir_flag_spec='-R$libdir' hardcode_shlibpath_var=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands '-z linker_flag'. GCC discards it without '$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test yes = "$GCC"; then whole_archive_flag_spec='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' else whole_archive_flag_spec='-z allextract$convenience -z defaultextract' fi ;; esac link_all_deplibs=yes ;; sunos4*) if test sequent = "$host_vendor"; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. archive_cmds='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi hardcode_libdir_flag_spec='-L$libdir' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; sysv4) case $host_vendor in sni) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' reload_cmds='$CC -r -o $output$reload_objs' hardcode_direct=no ;; motorola) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' hardcode_shlibpath_var=no ;; sysv4.3*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no export_dynamic_flag_spec='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ld_shlibs=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) no_undefined_flag='$wl-z,text' archive_cmds_need_lc=no hardcode_shlibpath_var=no runpath_var='LD_RUN_PATH' if test yes = "$GCC"; then archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We CANNOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. no_undefined_flag='$wl-z,text' allow_undefined_flag='$wl-z,nodefs' archive_cmds_need_lc=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='$wl-R,$libdir' hardcode_libdir_separator=':' link_all_deplibs=yes export_dynamic_flag_spec='$wl-Bexport' runpath_var='LD_RUN_PATH' if test yes = "$GCC"; then archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; *) ld_shlibs=no ;; esac if test sni = "$host_vendor"; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) export_dynamic_flag_spec='$wl-Blargedynsym' ;; esac fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 $as_echo "$ld_shlibs" >&6; } test no = "$ld_shlibs" && can_build_shared=no with_gnu_ld=$with_gnu_ld # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc" in x|xyes) # Assume -lc should be added archive_cmds_need_lc=yes if test yes,yes = "$GCC,$enable_shared"; then case $archive_cmds in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 $as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } if ${lt_cv_archive_cmds_need_lc+:} false; then : $as_echo_n "(cached) " >&6 else $RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl pic_flag=$lt_prog_compiler_pic compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag allow_undefined_flag= if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then lt_cv_archive_cmds_need_lc=no else lt_cv_archive_cmds_need_lc=yes fi allow_undefined_flag=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 $as_echo "$lt_cv_archive_cmds_need_lc" >&6; } archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc ;; esac fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 $as_echo_n "checking dynamic linker characteristics... " >&6; } if test yes = "$GCC"; then case $host_os in darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; *) lt_awk_arg='/^libraries:/' ;; esac case $host_os in mingw* | cegcc*) lt_sed_strip_eq='s|=\([A-Za-z]:\)|\1|g' ;; *) lt_sed_strip_eq='s|=/|/|g' ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in *\;*) # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` ;; *) lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` ;; esac # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary... lt_tmp_lt_search_path_spec= lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` # ...but if some path component already ends with the multilib dir we assume # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). case "$lt_multi_os_dir; $lt_search_path_spec " in "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) lt_multi_os_dir= ;; esac for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" elif test -n "$lt_multi_os_dir"; then test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' BEGIN {RS = " "; FS = "/|\n";} { lt_foo = ""; lt_count = 0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo = "/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[lt_foo]++; } if (lt_freq[lt_foo] == 1) { print lt_foo; } }'` # AWK program above erroneously prepends '/' to C:/dos/paths # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ $SED 's|/\([A-Za-z]:\)|\1|g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=.so postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='$libname$release$shared_ext$major' ;; aix[4-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes if test ia64 = "$host_cpu"; then # AIX 5 supports IA64 library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line '#! .'. This would cause the generated library to # depend on '.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # Using Import Files as archive members, it is possible to support # filename-based versioning of shared library archives on AIX. While # this would work for both with and without runtime linking, it will # prevent static linking of such archives. So we do filename-based # shared library versioning with .so extension only, which is used # when both runtime linking and shared linking is enabled. # Unfortunately, runtime linking may impact performance, so we do # not want this to be the default eventually. Also, we use the # versioned .so libs for executables only if there is the -brtl # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. # To allow for filename-based versioning support, we need to create # libNAME.so.V as an archive file, containing: # *) an Import File, referring to the versioned filename of the # archive as well as the shared archive member, telling the # bitwidth (32 or 64) of that shared object, and providing the # list of exported symbols of that shared object, eventually # decorated with the 'weak' keyword # *) the shared object with the F_LOADONLY flag set, to really avoid # it being seen by the linker. # At run time we better use the real file rather than another symlink, # but for link time we create the symlink libNAME.so -> libNAME.so.V case $with_aix_soname,$aix_use_runtimelinking in # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. aix,yes) # traditional libtool dynamic_linker='AIX unversionable lib.so' # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; aix,no) # traditional AIX only dynamic_linker='AIX lib.a(lib.so.V)' # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' ;; svr4,*) # full svr4 only dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,yes) # both, prefer svr4 dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # unpreferred sharedlib libNAME.a needs extra handling postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,no) # both, prefer aix dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)" library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' ;; esac shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='$libname$shared_ext' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[45]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl*) # Native MSVC libname_spec='$name' soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' library_names_spec='$libname.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec=$LIB if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC wrapper library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' soname_spec='$libname$release$major$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[23].*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=no sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' if test 32 = "$HPUX_IA64_MODE"; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" sys_lib_dlsearch_path_spec=/usr/lib/hpux32 else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" sys_lib_dlsearch_path_spec=/usr/lib/hpux64 fi ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[3-9]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test yes = "$lt_cv_prog_gnu_ld"; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; linux*android*) version_type=none # Android doesn't support versioned libraries. need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext' soname_spec='$libname$release$shared_ext' finish_cmds= shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes dynamic_linker='Android linker' # Don't embed -rpath directories since the linker doesn't support them. hardcode_libdir_flag_spec='-L$libdir' ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH if ${lt_cv_shlibpath_overrides_runpath+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : lt_cv_shlibpath_overrides_runpath=yes fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS libdir=$save_libdir fi shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Ideally, we could use ldconfig to report *all* directores which are # searched for libraries, however this is still not possible. Aside from not # being certain /sbin/ldconfig is available, command # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, # even though it is searched at run-time. Try to do the best guess by # appending ld.so.conf contents (and includes) to the search path. if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsdelf*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='NetBSD ld.elf_so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd* | bitrig*) version_type=sunos sys_lib_dlsearch_path_spec=/usr/lib need_lib_prefix=no if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then need_version=no else need_version=yes fi library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; os2*) libname_spec='$name' version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no # OS/2 can only load a DLL with a base name of 8 characters or less. soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; v=$($ECHO $release$versuffix | tr -d .-); n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); $ECHO $n$v`$shared_ext' library_names_spec='${libname}_dll.$libext' dynamic_linker='OS/2 ld.exe' shlibpath_var=BEGINLIBPATH sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test yes = "$with_gnu_ld"; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec; then version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' soname_spec='$libname$shared_ext.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=sco need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test yes = "$with_gnu_ld"; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 $as_echo "$dynamic_linker" >&6; } test no = "$dynamic_linker" && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test yes = "$GCC"; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec fi if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec fi # remember unaugmented sys_lib_dlsearch_path content for libtool script decls... configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec # ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" # to be used as default LT_SYS_LIBRARY_PATH value in generated libtool configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 $as_echo_n "checking how to hardcode library paths into programs... " >&6; } hardcode_action= if test -n "$hardcode_libdir_flag_spec" || test -n "$runpath_var" || test yes = "$hardcode_automatic"; then # We can hardcode non-existent directories. if test no != "$hardcode_direct" && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, )" && test no != "$hardcode_minus_L"; then # Linking always hardcodes the temporary library directory. hardcode_action=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action=unsupported fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 $as_echo "$hardcode_action" >&6; } if test relink = "$hardcode_action" || test yes = "$inherit_rpath"; then # Fast installation is not supported enable_fast_install=no elif test yes = "$shlibpath_overrides_runpath" || test no = "$enable_shared"; then # Fast installation is not necessary enable_fast_install=needless fi if test yes != "$enable_dlopen"; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen=load_add_on lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) lt_cv_dlopen=LoadLibrary lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen=dlopen lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl else lt_cv_dlopen=dyld lt_cv_dlopen_libs= lt_cv_dlopen_self=yes fi ;; tpf*) # Don't try to run any link tests for TPF. We know it's impossible # because TPF is a cross-compiler, and we know how we open DSOs. lt_cv_dlopen=dlopen lt_cv_dlopen_libs= lt_cv_dlopen_self=no ;; *) ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" if test "x$ac_cv_func_shl_load" = xyes; then : lt_cv_dlopen=shl_load else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 $as_echo_n "checking for shl_load in -ldld... " >&6; } if ${ac_cv_lib_dld_shl_load+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char shl_load (); int main () { return shl_load (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_shl_load=yes else ac_cv_lib_dld_shl_load=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 $as_echo "$ac_cv_lib_dld_shl_load" >&6; } if test "x$ac_cv_lib_dld_shl_load" = xyes; then : lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld else ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" if test "x$ac_cv_func_dlopen" = xyes; then : lt_cv_dlopen=dlopen else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 $as_echo_n "checking for dlopen in -lsvld... " >&6; } if ${ac_cv_lib_svld_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsvld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_svld_dlopen=yes else ac_cv_lib_svld_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 $as_echo "$ac_cv_lib_svld_dlopen" >&6; } if test "x$ac_cv_lib_svld_dlopen" = xyes; then : lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 $as_echo_n "checking for dld_link in -ldld... " >&6; } if ${ac_cv_lib_dld_dld_link+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dld_link (); int main () { return dld_link (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_dld_link=yes else ac_cv_lib_dld_dld_link=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 $as_echo "$ac_cv_lib_dld_dld_link" >&6; } if test "x$ac_cv_lib_dld_dld_link" = xyes; then : lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld fi fi fi fi fi fi ;; esac if test no = "$lt_cv_dlopen"; then enable_dlopen=no else enable_dlopen=yes fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS=$CPPFLAGS test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS=$LDFLAGS wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS=$LIBS LIBS="$lt_cv_dlopen_libs $LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 $as_echo_n "checking whether a program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self+:} false; then : $as_echo_n "(cached) " >&6 else if test yes = "$cross_compiling"; then : lt_cv_dlopen_self=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF #line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisibility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; } _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; esac else : # compilation failed lt_cv_dlopen_self=no fi fi rm -fr conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 $as_echo "$lt_cv_dlopen_self" >&6; } if test yes = "$lt_cv_dlopen_self"; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 $as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self_static+:} false; then : $as_echo_n "(cached) " >&6 else if test yes = "$cross_compiling"; then : lt_cv_dlopen_self_static=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF #line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisibility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; } _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; esac else : # compilation failed lt_cv_dlopen_self_static=no fi fi rm -fr conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 $as_echo "$lt_cv_dlopen_self_static" >&6; } fi CPPFLAGS=$save_CPPFLAGS LDFLAGS=$save_LDFLAGS LIBS=$save_LIBS ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi striplib= old_striplib= { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 $as_echo_n "checking whether stripping libraries is possible... " >&6; } if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP"; then striplib="$STRIP -x" old_striplib="$STRIP -S" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ;; esac fi # Report what library types will actually be built { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 $as_echo_n "checking if libtool supports shared libraries... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 $as_echo "$can_build_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 $as_echo_n "checking whether to build shared libraries... " >&6; } test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[4-9]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 $as_echo "$enable_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 $as_echo_n "checking whether to build static libraries... " >&6; } # Make sure either enable_shared or enable_static is yes. test yes = "$enable_shared" || enable_static=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 $as_echo "$enable_static" >&6; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CC=$lt_save_CC ac_config_commands="$ac_config_commands libtool" # Only expand once: # Seems to be required for building a binary from multiple source files # automake complains without it in infinoted/. ################################### # Gtk-Doc ################################### if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_PKG_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else case $PKG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi PKG_CONFIG=$ac_cv_path_PKG_CONFIG if test -n "$PKG_CONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 $as_echo "$PKG_CONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_path_PKG_CONFIG"; then ac_pt_PKG_CONFIG=$PKG_CONFIG # Extract the first word of "pkg-config", so it can be a program name with args. set dummy pkg-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else case $ac_pt_PKG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG if test -n "$ac_pt_PKG_CONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 $as_echo "$ac_pt_PKG_CONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_pt_PKG_CONFIG" = x; then PKG_CONFIG="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac PKG_CONFIG=$ac_pt_PKG_CONFIG fi else PKG_CONFIG="$ac_cv_path_PKG_CONFIG" fi fi if test -n "$PKG_CONFIG"; then _pkg_min_version=0.9.0 { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 $as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } PKG_CONFIG="" fi fi gtk_doc_requires="gtk-doc >= 1.4" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gtk-doc" >&5 $as_echo_n "checking for gtk-doc... " >&6; } if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$gtk_doc_requires\""; } >&5 ($PKG_CONFIG --exists --print-errors "$gtk_doc_requires") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then have_gtk_doc=yes else have_gtk_doc=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_gtk_doc" >&5 $as_echo "$have_gtk_doc" >&6; } if test "$have_gtk_doc" = "no"; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: You will not be able to create source packages with 'make dist' because $gtk_doc_requires is not found." >&5 $as_echo "$as_me: WARNING: You will not be able to create source packages with 'make dist' because $gtk_doc_requires is not found." >&2;} fi # Extract the first word of "gtkdoc-check", so it can be a program name with args. set dummy gtkdoc-check; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_GTKDOC_CHECK+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$GTKDOC_CHECK"; then ac_cv_prog_GTKDOC_CHECK="$GTKDOC_CHECK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_GTKDOC_CHECK="gtkdoc-check.test" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi GTKDOC_CHECK=$ac_cv_prog_GTKDOC_CHECK if test -n "$GTKDOC_CHECK"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GTKDOC_CHECK" >&5 $as_echo "$GTKDOC_CHECK" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Extract the first word of "gtkdoc-check", so it can be a program name with args. set dummy gtkdoc-check; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_GTKDOC_CHECK_PATH+:} false; then : $as_echo_n "(cached) " >&6 else case $GTKDOC_CHECK_PATH in [\\/]* | ?:[\\/]*) ac_cv_path_GTKDOC_CHECK_PATH="$GTKDOC_CHECK_PATH" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_GTKDOC_CHECK_PATH="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi GTKDOC_CHECK_PATH=$ac_cv_path_GTKDOC_CHECK_PATH if test -n "$GTKDOC_CHECK_PATH"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GTKDOC_CHECK_PATH" >&5 $as_echo "$GTKDOC_CHECK_PATH" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi for ac_prog in gtkdoc-rebase do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_GTKDOC_REBASE+:} false; then : $as_echo_n "(cached) " >&6 else case $GTKDOC_REBASE in [\\/]* | ?:[\\/]*) ac_cv_path_GTKDOC_REBASE="$GTKDOC_REBASE" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_GTKDOC_REBASE="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi GTKDOC_REBASE=$ac_cv_path_GTKDOC_REBASE if test -n "$GTKDOC_REBASE"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GTKDOC_REBASE" >&5 $as_echo "$GTKDOC_REBASE" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$GTKDOC_REBASE" && break done test -n "$GTKDOC_REBASE" || GTKDOC_REBASE="true" # Extract the first word of "gtkdoc-mkpdf", so it can be a program name with args. set dummy gtkdoc-mkpdf; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_GTKDOC_MKPDF+:} false; then : $as_echo_n "(cached) " >&6 else case $GTKDOC_MKPDF in [\\/]* | ?:[\\/]*) ac_cv_path_GTKDOC_MKPDF="$GTKDOC_MKPDF" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_GTKDOC_MKPDF="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi GTKDOC_MKPDF=$ac_cv_path_GTKDOC_MKPDF if test -n "$GTKDOC_MKPDF"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GTKDOC_MKPDF" >&5 $as_echo "$GTKDOC_MKPDF" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Check whether --with-html-dir was given. if test "${with_html_dir+set}" = set; then : withval=$with_html_dir; else with_html_dir='${datadir}/gtk-doc/html' fi HTML_DIR="$with_html_dir" # Check whether --enable-gtk-doc was given. if test "${enable_gtk_doc+set}" = set; then : enableval=$enable_gtk_doc; else enable_gtk_doc=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build gtk-doc documentation" >&5 $as_echo_n "checking whether to build gtk-doc documentation... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_gtk_doc" >&5 $as_echo "$enable_gtk_doc" >&6; } if test "x$enable_gtk_doc" = "xyes" && test "$have_gtk_doc" = "no"; then as_fn_error $? " You must have $gtk_doc_requires installed to build documentation for $PACKAGE_NAME. Please install gtk-doc or disable building the documentation by adding '--disable-gtk-doc' to '$0'." "$LINENO" 5 fi if test "x$PACKAGE_NAME" != "xglib"; then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GTKDOC_DEPS" >&5 $as_echo_n "checking for GTKDOC_DEPS... " >&6; } if test -n "$GTKDOC_DEPS_CFLAGS"; then pkg_cv_GTKDOC_DEPS_CFLAGS="$GTKDOC_DEPS_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0\""; } >&5 ($PKG_CONFIG --exists --print-errors "glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_GTKDOC_DEPS_CFLAGS=`$PKG_CONFIG --cflags "glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$GTKDOC_DEPS_LIBS"; then pkg_cv_GTKDOC_DEPS_LIBS="$GTKDOC_DEPS_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0\""; } >&5 ($PKG_CONFIG --exists --print-errors "glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_GTKDOC_DEPS_LIBS=`$PKG_CONFIG --libs "glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then GTKDOC_DEPS_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0" 2>&1` else GTKDOC_DEPS_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$GTKDOC_DEPS_PKG_ERRORS" >&5 : elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } : else GTKDOC_DEPS_CFLAGS=$pkg_cv_GTKDOC_DEPS_CFLAGS GTKDOC_DEPS_LIBS=$pkg_cv_GTKDOC_DEPS_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi fi # Check whether --enable-gtk-doc-html was given. if test "${enable_gtk_doc_html+set}" = set; then : enableval=$enable_gtk_doc_html; else enable_gtk_doc_html=yes fi # Check whether --enable-gtk-doc-pdf was given. if test "${enable_gtk_doc_pdf+set}" = set; then : enableval=$enable_gtk_doc_pdf; else enable_gtk_doc_pdf=no fi if test -z "$GTKDOC_MKPDF"; then enable_gtk_doc_pdf=no fi if test -z "$AM_DEFAULT_VERBOSITY"; then AM_DEFAULT_VERBOSITY=1 fi if test x$have_gtk_doc = xyes; then HAVE_GTK_DOC_TRUE= HAVE_GTK_DOC_FALSE='#' else HAVE_GTK_DOC_TRUE='#' HAVE_GTK_DOC_FALSE= fi if test x$enable_gtk_doc = xyes; then ENABLE_GTK_DOC_TRUE= ENABLE_GTK_DOC_FALSE='#' else ENABLE_GTK_DOC_TRUE='#' ENABLE_GTK_DOC_FALSE= fi if test x$enable_gtk_doc_html = xyes; then GTK_DOC_BUILD_HTML_TRUE= GTK_DOC_BUILD_HTML_FALSE='#' else GTK_DOC_BUILD_HTML_TRUE='#' GTK_DOC_BUILD_HTML_FALSE= fi if test x$enable_gtk_doc_pdf = xyes; then GTK_DOC_BUILD_PDF_TRUE= GTK_DOC_BUILD_PDF_FALSE='#' else GTK_DOC_BUILD_PDF_TRUE='#' GTK_DOC_BUILD_PDF_FALSE= fi if test -n "$LIBTOOL"; then GTK_DOC_USE_LIBTOOL_TRUE= GTK_DOC_USE_LIBTOOL_FALSE='#' else GTK_DOC_USE_LIBTOOL_TRUE='#' GTK_DOC_USE_LIBTOOL_FALSE= fi if test -n "$GTKDOC_REBASE"; then GTK_DOC_USE_REBASE_TRUE= GTK_DOC_USE_REBASE_FALSE='#' else GTK_DOC_USE_REBASE_TRUE='#' GTK_DOC_USE_REBASE_FALSE= fi ################################### # Platform checks ################################### case "$host_os" in *mingw*) platform='win32' ;; *) platform='unix' ;; esac if test "$platform" = "win32"; then WIN32_TRUE= WIN32_FALSE='#' else WIN32_TRUE='#' WIN32_FALSE= fi # Check for MSG_NOSIGNAL { $as_echo "$as_me:${as_lineno-$LINENO}: checking for MSG_NOSIGNAL" >&5 $as_echo_n "checking for MSG_NOSIGNAL... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { int f = MSG_NOSIGNAL; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define HAVE_MSG_NOSIGNAL 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext # Check for SO_REUSEADDR { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SO_REUSEADDR" >&5 $as_echo_n "checking for SO_REUSEADDR... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { int f = SO_REUSEADDR; printf("%d\n", f); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define HAVE_SO_REUSEADDR 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext # Check for dirent.d_type { $as_echo "$as_me:${as_lineno-$LINENO}: checking for d_type" >&5 $as_echo_n "checking for d_type... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { struct dirent d; printf("%d\n", d.d_type); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define HAVE_D_TYPE 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext # Check for O_NOFOLLOW { $as_echo "$as_me:${as_lineno-$LINENO}: checking for O_NOFOLLOW" >&5 $as_echo_n "checking for O_NOFOLLOW... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include int main () { printf("%d\n", O_NOFOLLOW); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define HAVE_O_NOFOLLOW 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ################################### # Check for regular dependencies ################################### infinity_libraries='glib-2.0 >= 2.38 gobject-2.0 >= 2.38 gmodule-2.0 >= 2.38 libxml-2.0 gnutls >= 2.12.0 libgsasl >= 0.2.21' pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for infinity" >&5 $as_echo_n "checking for infinity... " >&6; } if test -n "$infinity_CFLAGS"; then pkg_cv_infinity_CFLAGS="$infinity_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$infinity_libraries\""; } >&5 ($PKG_CONFIG --exists --print-errors "$infinity_libraries") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_infinity_CFLAGS=`$PKG_CONFIG --cflags "$infinity_libraries" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$infinity_LIBS"; then pkg_cv_infinity_LIBS="$infinity_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$infinity_libraries\""; } >&5 ($PKG_CONFIG --exists --print-errors "$infinity_libraries") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_infinity_LIBS=`$PKG_CONFIG --libs "$infinity_libraries" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then infinity_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$infinity_libraries" 2>&1` else infinity_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$infinity_libraries" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$infinity_PKG_ERRORS" >&5 as_fn_error $? "Package requirements ($infinity_libraries) were not met: $infinity_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. Alternatively, you may set the environment variables infinity_CFLAGS and infinity_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details." "$LINENO" 5 elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. Alternatively, you may set the environment variables infinity_CFLAGS and infinity_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details. To get pkg-config, see . See \`config.log' for more details" "$LINENO" 5; } else infinity_CFLAGS=$pkg_cv_infinity_CFLAGS infinity_LIBS=$pkg_cv_infinity_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inftext" >&5 $as_echo_n "checking for inftext... " >&6; } if test -n "$inftext_CFLAGS"; then pkg_cv_inftext_CFLAGS="$inftext_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"glib-2.0 >= 2.38 gobject-2.0 >= 2.38 libxml-2.0\""; } >&5 ($PKG_CONFIG --exists --print-errors "glib-2.0 >= 2.38 gobject-2.0 >= 2.38 libxml-2.0") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_inftext_CFLAGS=`$PKG_CONFIG --cflags "glib-2.0 >= 2.38 gobject-2.0 >= 2.38 libxml-2.0" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$inftext_LIBS"; then pkg_cv_inftext_LIBS="$inftext_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"glib-2.0 >= 2.38 gobject-2.0 >= 2.38 libxml-2.0\""; } >&5 ($PKG_CONFIG --exists --print-errors "glib-2.0 >= 2.38 gobject-2.0 >= 2.38 libxml-2.0") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_inftext_LIBS=`$PKG_CONFIG --libs "glib-2.0 >= 2.38 gobject-2.0 >= 2.38 libxml-2.0" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then inftext_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "glib-2.0 >= 2.38 gobject-2.0 >= 2.38 libxml-2.0" 2>&1` else inftext_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "glib-2.0 >= 2.38 gobject-2.0 >= 2.38 libxml-2.0" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$inftext_PKG_ERRORS" >&5 as_fn_error $? "Package requirements (glib-2.0 >= 2.38 gobject-2.0 >= 2.38 libxml-2.0) were not met: $inftext_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. Alternatively, you may set the environment variables inftext_CFLAGS and inftext_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details." "$LINENO" 5 elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. Alternatively, you may set the environment variables inftext_CFLAGS and inftext_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details. To get pkg-config, see . See \`config.log' for more details" "$LINENO" 5; } else inftext_CFLAGS=$pkg_cv_inftext_CFLAGS inftext_LIBS=$pkg_cv_inftext_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi if test $platform = 'win32'; then infinity_LIBS="$infinity_LIBS -lws2_32 -ldnsapi" else # Check whether we need libresolv for res_query() # Can't use AC_SEARCH_LIBS because res_query is a macro defined in # resolv.h { $as_echo "$as_me:${as_lineno-$LINENO}: checking for res_query" >&5 $as_echo_n "checking for res_query... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { res_query(NULL, 0, 0, NULL, 0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : # res_init() available in libc { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else LIBS="-lresolv" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { res_query(NULL, 0, 0, NULL, 0); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: in libresolv" >&5 $as_echo "in libresolv" >&6; } LIBS="" infinity_LIBS="$infinity_LIBS -lresolv" # res_init available in libresolv else as_fn_error $? "res_query not provided by either libc or libresolv" "$LINENO" 5 fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi ################################### # libinftextgtk optional package ################################### # Check whether --with-inftextgtk was given. if test "${with_inftextgtk+set}" = set; then : withval=$with_inftextgtk; with_inftextgtk=$withval else with_inftextgtk=auto fi gtk_requirement="gtk+-3.0 >= 3.10.0" if test "x$with_inftextgtk" = "xauto" then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inftextgtk" >&5 $as_echo_n "checking for inftextgtk... " >&6; } if test -n "$inftextgtk_CFLAGS"; then pkg_cv_inftextgtk_CFLAGS="$inftextgtk_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$gtk_requirement\""; } >&5 ($PKG_CONFIG --exists --print-errors "$gtk_requirement") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_inftextgtk_CFLAGS=`$PKG_CONFIG --cflags "$gtk_requirement" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$inftextgtk_LIBS"; then pkg_cv_inftextgtk_LIBS="$inftextgtk_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$gtk_requirement\""; } >&5 ($PKG_CONFIG --exists --print-errors "$gtk_requirement") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_inftextgtk_LIBS=`$PKG_CONFIG --libs "$gtk_requirement" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then inftextgtk_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$gtk_requirement" 2>&1` else inftextgtk_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$gtk_requirement" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$inftextgtk_PKG_ERRORS" >&5 with_inftextgtk=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } with_inftextgtk=no else inftextgtk_CFLAGS=$pkg_cv_inftextgtk_CFLAGS inftextgtk_LIBS=$pkg_cv_inftextgtk_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } with_inftextgtk=yes fi elif test "x$with_inftextgtk" = "xyes" then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for inftextgtk" >&5 $as_echo_n "checking for inftextgtk... " >&6; } if test -n "$inftextgtk_CFLAGS"; then pkg_cv_inftextgtk_CFLAGS="$inftextgtk_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$gtk_requirement\""; } >&5 ($PKG_CONFIG --exists --print-errors "$gtk_requirement") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_inftextgtk_CFLAGS=`$PKG_CONFIG --cflags "$gtk_requirement" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$inftextgtk_LIBS"; then pkg_cv_inftextgtk_LIBS="$inftextgtk_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$gtk_requirement\""; } >&5 ($PKG_CONFIG --exists --print-errors "$gtk_requirement") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_inftextgtk_LIBS=`$PKG_CONFIG --libs "$gtk_requirement" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then inftextgtk_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$gtk_requirement" 2>&1` else inftextgtk_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$gtk_requirement" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$inftextgtk_PKG_ERRORS" >&5 as_fn_error $? "Package requirements ($gtk_requirement) were not met: $inftextgtk_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. Alternatively, you may set the environment variables inftextgtk_CFLAGS and inftextgtk_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details." "$LINENO" 5 elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. Alternatively, you may set the environment variables inftextgtk_CFLAGS and inftextgtk_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details. To get pkg-config, see . See \`config.log' for more details" "$LINENO" 5; } else inftextgtk_CFLAGS=$pkg_cv_inftextgtk_CFLAGS inftextgtk_LIBS=$pkg_cv_inftextgtk_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi fi if test "x$with_inftextgtk" = "xyes" then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for atan2 in -lm" >&5 $as_echo_n "checking for atan2 in -lm... " >&6; } if ${ac_cv_lib_m_atan2+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lm $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char atan2 (); int main () { return atan2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_m_atan2=yes else ac_cv_lib_m_atan2=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_atan2" >&5 $as_echo "$ac_cv_lib_m_atan2" >&6; } if test "x$ac_cv_lib_m_atan2" = xyes; then : inftextgtk_LIBS="$inftextgtk_LIBS -lm" else as_fn_error $? "libm not found" "$LINENO" 5 fi fi if test "x$with_inftextgtk" = "xyes"; then WITH_INFTEXTGTK_TRUE= WITH_INFTEXTGTK_FALSE='#' else WITH_INFTEXTGTK_TRUE='#' WITH_INFTEXTGTK_FALSE= fi ############################### # libinfgtk optional package ############################### # Check whether --with-infgtk was given. if test "${with_infgtk+set}" = set; then : withval=$with_infgtk; with_infgtk=$withval else with_infgtk=auto fi if test "x$with_infgtk" = "xauto" then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for infgtk" >&5 $as_echo_n "checking for infgtk... " >&6; } if test -n "$infgtk_CFLAGS"; then pkg_cv_infgtk_CFLAGS="$infgtk_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$gtk_requirement\""; } >&5 ($PKG_CONFIG --exists --print-errors "$gtk_requirement") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_infgtk_CFLAGS=`$PKG_CONFIG --cflags "$gtk_requirement" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$infgtk_LIBS"; then pkg_cv_infgtk_LIBS="$infgtk_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$gtk_requirement\""; } >&5 ($PKG_CONFIG --exists --print-errors "$gtk_requirement") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_infgtk_LIBS=`$PKG_CONFIG --libs "$gtk_requirement" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then infgtk_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$gtk_requirement" 2>&1` else infgtk_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$gtk_requirement" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$infgtk_PKG_ERRORS" >&5 with_infgtk=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } with_infgtk=no else infgtk_CFLAGS=$pkg_cv_infgtk_CFLAGS infgtk_LIBS=$pkg_cv_infgtk_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } with_infgtk=yes fi elif test "x$with_infgtk" = "xyes" then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for infgtk" >&5 $as_echo_n "checking for infgtk... " >&6; } if test -n "$infgtk_CFLAGS"; then pkg_cv_infgtk_CFLAGS="$infgtk_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$gtk_requirement\""; } >&5 ($PKG_CONFIG --exists --print-errors "$gtk_requirement") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_infgtk_CFLAGS=`$PKG_CONFIG --cflags "$gtk_requirement" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$infgtk_LIBS"; then pkg_cv_infgtk_LIBS="$infgtk_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"\$gtk_requirement\""; } >&5 ($PKG_CONFIG --exists --print-errors "$gtk_requirement") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_infgtk_LIBS=`$PKG_CONFIG --libs "$gtk_requirement" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then infgtk_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$gtk_requirement" 2>&1` else infgtk_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$gtk_requirement" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$infgtk_PKG_ERRORS" >&5 as_fn_error $? "Package requirements ($gtk_requirement) were not met: $infgtk_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. Alternatively, you may set the environment variables infgtk_CFLAGS and infgtk_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details." "$LINENO" 5 elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. Alternatively, you may set the environment variables infgtk_CFLAGS and infgtk_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details. To get pkg-config, see . See \`config.log' for more details" "$LINENO" 5; } else infgtk_CFLAGS=$pkg_cv_infgtk_CFLAGS infgtk_LIBS=$pkg_cv_infgtk_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi fi if test "x$with_infgtk" = "xyes"; then WITH_INFGTK_TRUE= WITH_INFGTK_FALSE='#' else WITH_INFGTK_TRUE='#' WITH_INFGTK_FALSE= fi ############################### # infinoted optional package ############################### # Check whether --with-infinoted was given. if test "${with_infinoted+set}" = set; then : withval=$with_infinoted; with_infinoted=$withval else with_infinoted=yes fi if test "x$with_infinoted" = "xyes" then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for infinoted" >&5 $as_echo_n "checking for infinoted... " >&6; } if test -n "$infinoted_CFLAGS"; then pkg_cv_infinoted_CFLAGS="$infinoted_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"glib-2.0 >= 2.38 gobject-2.0 >= 2.38 gmodule-2.0 >= 2.38 gnutls >= 2.12.0\""; } >&5 ($PKG_CONFIG --exists --print-errors "glib-2.0 >= 2.38 gobject-2.0 >= 2.38 gmodule-2.0 >= 2.38 gnutls >= 2.12.0") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_infinoted_CFLAGS=`$PKG_CONFIG --cflags "glib-2.0 >= 2.38 gobject-2.0 >= 2.38 gmodule-2.0 >= 2.38 gnutls >= 2.12.0" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$infinoted_LIBS"; then pkg_cv_infinoted_LIBS="$infinoted_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"glib-2.0 >= 2.38 gobject-2.0 >= 2.38 gmodule-2.0 >= 2.38 gnutls >= 2.12.0\""; } >&5 ($PKG_CONFIG --exists --print-errors "glib-2.0 >= 2.38 gobject-2.0 >= 2.38 gmodule-2.0 >= 2.38 gnutls >= 2.12.0") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_infinoted_LIBS=`$PKG_CONFIG --libs "glib-2.0 >= 2.38 gobject-2.0 >= 2.38 gmodule-2.0 >= 2.38 gnutls >= 2.12.0" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then infinoted_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "glib-2.0 >= 2.38 gobject-2.0 >= 2.38 gmodule-2.0 >= 2.38 gnutls >= 2.12.0" 2>&1` else infinoted_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "glib-2.0 >= 2.38 gobject-2.0 >= 2.38 gmodule-2.0 >= 2.38 gnutls >= 2.12.0" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$infinoted_PKG_ERRORS" >&5 as_fn_error $? "Package requirements (glib-2.0 >= 2.38 gobject-2.0 >= 2.38 gmodule-2.0 >= 2.38 gnutls >= 2.12.0) were not met: $infinoted_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. Alternatively, you may set the environment variables infinoted_CFLAGS and infinoted_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details." "$LINENO" 5 elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. Alternatively, you may set the environment variables infinoted_CFLAGS and infinoted_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details. To get pkg-config, see . See \`config.log' for more details" "$LINENO" 5; } else infinoted_CFLAGS=$pkg_cv_infinoted_CFLAGS infinoted_LIBS=$pkg_cv_infinoted_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi fi if test "x$with_infinoted" = "xyes"; then WITH_INFINOTED_TRUE= WITH_INFINOTED_FALSE='#' else WITH_INFINOTED_TRUE='#' WITH_INFINOTED_FALSE= fi #################### # Check for avahi #################### # Check whether --with-avahi was given. if test "${with_avahi+set}" = set; then : withval=$with_avahi; use_avahi=$withval else use_avahi=auto fi if test "x$use_avahi" = "xauto" then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for avahi" >&5 $as_echo_n "checking for avahi... " >&6; } if test -n "$avahi_CFLAGS"; then pkg_cv_avahi_CFLAGS="$avahi_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"avahi-client\""; } >&5 ($PKG_CONFIG --exists --print-errors "avahi-client") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_avahi_CFLAGS=`$PKG_CONFIG --cflags "avahi-client" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$avahi_LIBS"; then pkg_cv_avahi_LIBS="$avahi_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"avahi-client\""; } >&5 ($PKG_CONFIG --exists --print-errors "avahi-client") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_avahi_LIBS=`$PKG_CONFIG --libs "avahi-client" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then avahi_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "avahi-client" 2>&1` else avahi_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "avahi-client" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$avahi_PKG_ERRORS" >&5 use_avahi=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } use_avahi=no else avahi_CFLAGS=$pkg_cv_avahi_CFLAGS avahi_LIBS=$pkg_cv_avahi_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } use_avahi=yes fi elif test "x$use_avahi" = "xyes" then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for avahi" >&5 $as_echo_n "checking for avahi... " >&6; } if test -n "$avahi_CFLAGS"; then pkg_cv_avahi_CFLAGS="$avahi_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"avahi-client\""; } >&5 ($PKG_CONFIG --exists --print-errors "avahi-client") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_avahi_CFLAGS=`$PKG_CONFIG --cflags "avahi-client" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$avahi_LIBS"; then pkg_cv_avahi_LIBS="$avahi_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"avahi-client\""; } >&5 ($PKG_CONFIG --exists --print-errors "avahi-client") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_avahi_LIBS=`$PKG_CONFIG --libs "avahi-client" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then avahi_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "avahi-client" 2>&1` else avahi_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "avahi-client" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$avahi_PKG_ERRORS" >&5 as_fn_error $? "Package requirements (avahi-client) were not met: $avahi_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. Alternatively, you may set the environment variables avahi_CFLAGS and avahi_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details." "$LINENO" 5 elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. Alternatively, you may set the environment variables avahi_CFLAGS and avahi_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details. To get pkg-config, see . See \`config.log' for more details" "$LINENO" 5; } else avahi_CFLAGS=$pkg_cv_avahi_CFLAGS avahi_LIBS=$pkg_cv_avahi_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi fi if test "x$use_avahi" = "xyes" then $as_echo "#define LIBINFINITY_HAVE_AVAHI 1" >>confdefs.h fi if test "x$use_avahi" = "xyes"; then LIBINFINITY_HAVE_AVAHI_TRUE= LIBINFINITY_HAVE_AVAHI_FALSE='#' else LIBINFINITY_HAVE_AVAHI_TRUE='#' LIBINFINITY_HAVE_AVAHI_FALSE= fi #################### # Check for gio #################### # Check whether --with-gio was given. if test "${with_gio+set}" = set; then : withval=$with_gio; use_gio=$withval else use_gio=auto fi if test "x$use_gio" = "xauto" then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gio" >&5 $as_echo_n "checking for gio... " >&6; } if test -n "$gio_CFLAGS"; then pkg_cv_gio_CFLAGS="$gio_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gio-2.0 >= 2.40\""; } >&5 ($PKG_CONFIG --exists --print-errors "gio-2.0 >= 2.40") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_gio_CFLAGS=`$PKG_CONFIG --cflags "gio-2.0 >= 2.40" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$gio_LIBS"; then pkg_cv_gio_LIBS="$gio_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gio-2.0 >= 2.40\""; } >&5 ($PKG_CONFIG --exists --print-errors "gio-2.0 >= 2.40") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_gio_LIBS=`$PKG_CONFIG --libs "gio-2.0 >= 2.40" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then gio_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "gio-2.0 >= 2.40" 2>&1` else gio_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "gio-2.0 >= 2.40" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$gio_PKG_ERRORS" >&5 use_gio=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } use_gio=no else gio_CFLAGS=$pkg_cv_gio_CFLAGS gio_LIBS=$pkg_cv_gio_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } use_gio=yes fi elif test "x$use_avahi" = "xyes" then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gio" >&5 $as_echo_n "checking for gio... " >&6; } if test -n "$gio_CFLAGS"; then pkg_cv_gio_CFLAGS="$gio_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gio-2.0 >= 2.40\""; } >&5 ($PKG_CONFIG --exists --print-errors "gio-2.0 >= 2.40") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_gio_CFLAGS=`$PKG_CONFIG --cflags "gio-2.0 >= 2.40" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$gio_LIBS"; then pkg_cv_gio_LIBS="$gio_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gio-2.0 >= 2.40\""; } >&5 ($PKG_CONFIG --exists --print-errors "gio-2.0 >= 2.40") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_gio_LIBS=`$PKG_CONFIG --libs "gio-2.0 >= 2.40" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then gio_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "gio-2.0 >= 2.40" 2>&1` else gio_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "gio-2.0 >= 2.40" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$gio_PKG_ERRORS" >&5 as_fn_error $? "Package requirements (gio-2.0 >= 2.40) were not met: $gio_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. Alternatively, you may set the environment variables gio_CFLAGS and gio_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details." "$LINENO" 5 elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. Alternatively, you may set the environment variables gio_CFLAGS and gio_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details. To get pkg-config, see . See \`config.log' for more details" "$LINENO" 5; } else gio_CFLAGS=$pkg_cv_gio_CFLAGS gio_LIBS=$pkg_cv_gio_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi fi if test "x$use_gio" = "xyes" then $as_echo "#define LIBINFINITY_HAVE_GIO 1" >>confdefs.h fi if test "x$use_gio" = "xyes"; then LIBINFINITY_HAVE_GIO_TRUE= LIBINFINITY_HAVE_GIO_FALSE='#' else LIBINFINITY_HAVE_GIO_TRUE='#' LIBINFINITY_HAVE_GIO_FALSE= fi #################### # Check for libdaemon #################### # Check whether --with-libdaemon was given. if test "${with_libdaemon+set}" = set; then : withval=$with_libdaemon; use_libdaemon=$withval else use_libdaemon=auto fi if test "x$use_libdaemon" = "xauto" then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libdaemon" >&5 $as_echo_n "checking for libdaemon... " >&6; } if test -n "$libdaemon_CFLAGS"; then pkg_cv_libdaemon_CFLAGS="$libdaemon_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libdaemon\""; } >&5 ($PKG_CONFIG --exists --print-errors "libdaemon") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_libdaemon_CFLAGS=`$PKG_CONFIG --cflags "libdaemon" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$libdaemon_LIBS"; then pkg_cv_libdaemon_LIBS="$libdaemon_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libdaemon\""; } >&5 ($PKG_CONFIG --exists --print-errors "libdaemon") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_libdaemon_LIBS=`$PKG_CONFIG --libs "libdaemon" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then libdaemon_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libdaemon" 2>&1` else libdaemon_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libdaemon" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$libdaemon_PKG_ERRORS" >&5 use_libdaemon=no elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } use_libdaemon=no else libdaemon_CFLAGS=$pkg_cv_libdaemon_CFLAGS libdaemon_LIBS=$pkg_cv_libdaemon_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } use_libdaemon=yes fi elif test "x$use_libdaemon" = "xyes" then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libdaemon" >&5 $as_echo_n "checking for libdaemon... " >&6; } if test -n "$libdaemon_CFLAGS"; then pkg_cv_libdaemon_CFLAGS="$libdaemon_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libdaemon\""; } >&5 ($PKG_CONFIG --exists --print-errors "libdaemon") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_libdaemon_CFLAGS=`$PKG_CONFIG --cflags "libdaemon" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$libdaemon_LIBS"; then pkg_cv_libdaemon_LIBS="$libdaemon_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libdaemon\""; } >&5 ($PKG_CONFIG --exists --print-errors "libdaemon") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_libdaemon_LIBS=`$PKG_CONFIG --libs "libdaemon" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then libdaemon_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libdaemon" 2>&1` else libdaemon_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libdaemon" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$libdaemon_PKG_ERRORS" >&5 as_fn_error $? "Package requirements (libdaemon) were not met: $libdaemon_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. Alternatively, you may set the environment variables libdaemon_CFLAGS and libdaemon_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details." "$LINENO" 5 elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. Alternatively, you may set the environment variables libdaemon_CFLAGS and libdaemon_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details. To get pkg-config, see . See \`config.log' for more details" "$LINENO" 5; } else libdaemon_CFLAGS=$pkg_cv_libdaemon_CFLAGS libdaemon_LIBS=$pkg_cv_libdaemon_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi fi if test "x$use_libdaemon" = "xyes" then $as_echo "#define LIBINFINITY_HAVE_LIBDAEMON 1" >>confdefs.h fi if test "x$use_libdaemon" = "xyes"; then LIBINFINITY_HAVE_LIBDAEMON_TRUE= LIBINFINITY_HAVE_LIBDAEMON_FALSE='#' else LIBINFINITY_HAVE_LIBDAEMON_TRUE='#' LIBINFINITY_HAVE_LIBDAEMON_FALSE= fi ################# # Check for pam # ################# { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pam" >&5 $as_echo_n "checking for pam... " >&6; } as_ac_Lib=`$as_echo "ac_cv_lib_ pam ''_ pam_start " | $as_tr_sh` { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pam_start in -l pam " >&5 $as_echo_n "checking for pam_start in -l pam ... " >&6; } if eval \${$as_ac_Lib+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-l pam $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pam_start (); int main () { return pam_start (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$as_ac_Lib=yes" else eval "$as_ac_Lib=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi eval ac_res=\$$as_ac_Lib { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define LIBINFINITY_HAVE_PAM 1" >>confdefs.h use_pam=yes infinity_LIBS="$infinity_LIBS -lpam" else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } use_pam=no fi # Check for PAM_FAIL_DELAY { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PAM_FAIL_DELAY" >&5 $as_echo_n "checking for PAM_FAIL_DELAY... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include int main () { int f = PAM_FAIL_DELAY; printf("%d\n", f); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define HAVE_PAM_FAIL_DELAY 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ############ # gettext ############ GETTEXT_PACKAGE="libinfinity-0.7" cat >>confdefs.h <<_ACEOF #define GETTEXT_PACKAGE "$GETTEXT_PACKAGE" _ACEOF ALL_LINGUAS="`grep -v '^#' "$srcdir/po/LINGUAS" | tr '\n' ' '`" for ac_header in locale.h do : ac_fn_c_check_header_mongrel "$LINENO" "locale.h" "ac_cv_header_locale_h" "$ac_includes_default" if test "x$ac_cv_header_locale_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LOCALE_H 1 _ACEOF fi done if test $ac_cv_header_locale_h = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LC_MESSAGES" >&5 $as_echo_n "checking for LC_MESSAGES... " >&6; } if ${am_cv_val_LC_MESSAGES+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { return LC_MESSAGES ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : am_cv_val_LC_MESSAGES=yes else am_cv_val_LC_MESSAGES=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_val_LC_MESSAGES" >&5 $as_echo "$am_cv_val_LC_MESSAGES" >&6; } if test $am_cv_val_LC_MESSAGES = yes; then $as_echo "#define HAVE_LC_MESSAGES 1" >>confdefs.h fi fi USE_NLS=yes gt_cv_have_gettext=no CATOBJEXT=NONE XGETTEXT=: INTLLIBS= ac_fn_c_check_header_mongrel "$LINENO" "libintl.h" "ac_cv_header_libintl_h" "$ac_includes_default" if test "x$ac_cv_header_libintl_h" = xyes; then : gt_cv_func_dgettext_libintl="no" libintl_extra_libs="" # # First check in libc # { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ngettext in libc" >&5 $as_echo_n "checking for ngettext in libc... " >&6; } if ${gt_cv_func_ngettext_libc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { return !ngettext ("","", 1) ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : gt_cv_func_ngettext_libc=yes else gt_cv_func_ngettext_libc=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_cv_func_ngettext_libc" >&5 $as_echo "$gt_cv_func_ngettext_libc" >&6; } if test "$gt_cv_func_ngettext_libc" = "yes" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dgettext in libc" >&5 $as_echo_n "checking for dgettext in libc... " >&6; } if ${gt_cv_func_dgettext_libc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { return !dgettext ("","") ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : gt_cv_func_dgettext_libc=yes else gt_cv_func_dgettext_libc=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gt_cv_func_dgettext_libc" >&5 $as_echo "$gt_cv_func_dgettext_libc" >&6; } fi if test "$gt_cv_func_ngettext_libc" = "yes" ; then for ac_func in bind_textdomain_codeset do : ac_fn_c_check_func "$LINENO" "bind_textdomain_codeset" "ac_cv_func_bind_textdomain_codeset" if test "x$ac_cv_func_bind_textdomain_codeset" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_BIND_TEXTDOMAIN_CODESET 1 _ACEOF fi done fi # # If we don't have everything we want, check in libintl # if test "$gt_cv_func_dgettext_libc" != "yes" \ || test "$gt_cv_func_ngettext_libc" != "yes" \ || test "$ac_cv_func_bind_textdomain_codeset" != "yes" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for bindtextdomain in -lintl" >&5 $as_echo_n "checking for bindtextdomain in -lintl... " >&6; } if ${ac_cv_lib_intl_bindtextdomain+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lintl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char bindtextdomain (); int main () { return bindtextdomain (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_intl_bindtextdomain=yes else ac_cv_lib_intl_bindtextdomain=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_intl_bindtextdomain" >&5 $as_echo "$ac_cv_lib_intl_bindtextdomain" >&6; } if test "x$ac_cv_lib_intl_bindtextdomain" = xyes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ngettext in -lintl" >&5 $as_echo_n "checking for ngettext in -lintl... " >&6; } if ${ac_cv_lib_intl_ngettext+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lintl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char ngettext (); int main () { return ngettext (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_intl_ngettext=yes else ac_cv_lib_intl_ngettext=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_intl_ngettext" >&5 $as_echo "$ac_cv_lib_intl_ngettext" >&6; } if test "x$ac_cv_lib_intl_ngettext" = xyes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dgettext in -lintl" >&5 $as_echo_n "checking for dgettext in -lintl... " >&6; } if ${ac_cv_lib_intl_dgettext+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lintl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dgettext (); int main () { return dgettext (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_intl_dgettext=yes else ac_cv_lib_intl_dgettext=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_intl_dgettext" >&5 $as_echo "$ac_cv_lib_intl_dgettext" >&6; } if test "x$ac_cv_lib_intl_dgettext" = xyes; then : gt_cv_func_dgettext_libintl=yes fi fi fi if test "$gt_cv_func_dgettext_libintl" != "yes" ; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking if -liconv is needed to use gettext" >&5 $as_echo_n "checking if -liconv is needed to use gettext... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: " >&5 $as_echo "" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ngettext in -lintl" >&5 $as_echo_n "checking for ngettext in -lintl... " >&6; } if ${ac_cv_lib_intl_ngettext+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lintl -liconv $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char ngettext (); int main () { return ngettext (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_intl_ngettext=yes else ac_cv_lib_intl_ngettext=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_intl_ngettext" >&5 $as_echo "$ac_cv_lib_intl_ngettext" >&6; } if test "x$ac_cv_lib_intl_ngettext" = xyes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dcgettext in -lintl" >&5 $as_echo_n "checking for dcgettext in -lintl... " >&6; } if ${ac_cv_lib_intl_dcgettext+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lintl -liconv $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dcgettext (); int main () { return dcgettext (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_intl_dcgettext=yes else ac_cv_lib_intl_dcgettext=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_intl_dcgettext" >&5 $as_echo "$ac_cv_lib_intl_dcgettext" >&6; } if test "x$ac_cv_lib_intl_dcgettext" = xyes; then : gt_cv_func_dgettext_libintl=yes libintl_extra_libs=-liconv else : fi else : fi fi # # If we found libintl, then check in it for bind_textdomain_codeset(); # we'll prefer libc if neither have bind_textdomain_codeset(), # and both have dgettext and ngettext # if test "$gt_cv_func_dgettext_libintl" = "yes" ; then glib_save_LIBS="$LIBS" LIBS="$LIBS -lintl $libintl_extra_libs" unset ac_cv_func_bind_textdomain_codeset for ac_func in bind_textdomain_codeset do : ac_fn_c_check_func "$LINENO" "bind_textdomain_codeset" "ac_cv_func_bind_textdomain_codeset" if test "x$ac_cv_func_bind_textdomain_codeset" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_BIND_TEXTDOMAIN_CODESET 1 _ACEOF fi done LIBS="$glib_save_LIBS" if test "$ac_cv_func_bind_textdomain_codeset" = "yes" ; then gt_cv_func_dgettext_libc=no else if test "$gt_cv_func_dgettext_libc" = "yes" \ && test "$gt_cv_func_ngettext_libc" = "yes"; then gt_cv_func_dgettext_libintl=no fi fi fi fi if test "$gt_cv_func_dgettext_libc" = "yes" \ || test "$gt_cv_func_dgettext_libintl" = "yes"; then gt_cv_have_gettext=yes fi if test "$gt_cv_func_dgettext_libintl" = "yes"; then INTLLIBS="-lintl $libintl_extra_libs" fi if test "$gt_cv_have_gettext" = "yes"; then $as_echo "#define HAVE_GETTEXT 1" >>confdefs.h # Extract the first word of "msgfmt", so it can be a program name with args. set dummy msgfmt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_MSGFMT+:} false; then : $as_echo_n "(cached) " >&6 else case "$MSGFMT" in /*) ac_cv_path_MSGFMT="$MSGFMT" # Let the user override the test with a path. ;; *) IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" for ac_dir in $PATH; do test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$ac_word; then if test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"; then ac_cv_path_MSGFMT="$ac_dir/$ac_word" break fi fi done IFS="$ac_save_ifs" test -z "$ac_cv_path_MSGFMT" && ac_cv_path_MSGFMT="no" ;; esac fi MSGFMT="$ac_cv_path_MSGFMT" if test "$MSGFMT" != "no"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSGFMT" >&5 $as_echo "$MSGFMT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "$MSGFMT" != "no"; then glib_save_LIBS="$LIBS" LIBS="$LIBS $INTLLIBS" for ac_func in dcgettext do : ac_fn_c_check_func "$LINENO" "dcgettext" "ac_cv_func_dcgettext" if test "x$ac_cv_func_dcgettext" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_DCGETTEXT 1 _ACEOF fi done MSGFMT_OPTS= { $as_echo "$as_me:${as_lineno-$LINENO}: checking if msgfmt accepts -c" >&5 $as_echo_n "checking if msgfmt accepts -c... " >&6; } cat >conftest.foo <<_ACEOF msgid "" msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Project-Id-Version: test 1.0\n" "PO-Revision-Date: 2007-02-15 12:01+0100\n" "Last-Translator: test \n" "Language-Team: C \n" "MIME-Version: 1.0\n" "Content-Transfer-Encoding: 8bit\n" _ACEOF if { { $as_echo "$as_me:${as_lineno-$LINENO}: \$MSGFMT -c -o /dev/null conftest.foo"; } >&5 ($MSGFMT -c -o /dev/null conftest.foo) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then MSGFMT_OPTS=-c; { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } echo "$as_me: failed input was:" >&5 sed 's/^/| /' conftest.foo >&5 fi # Extract the first word of "gmsgfmt", so it can be a program name with args. set dummy gmsgfmt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_GMSGFMT+:} false; then : $as_echo_n "(cached) " >&6 else case $GMSGFMT in [\\/]* | ?:[\\/]*) ac_cv_path_GMSGFMT="$GMSGFMT" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_GMSGFMT="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_GMSGFMT" && ac_cv_path_GMSGFMT="$MSGFMT" ;; esac fi GMSGFMT=$ac_cv_path_GMSGFMT if test -n "$GMSGFMT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GMSGFMT" >&5 $as_echo "$GMSGFMT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Extract the first word of "xgettext", so it can be a program name with args. set dummy xgettext; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_XGETTEXT+:} false; then : $as_echo_n "(cached) " >&6 else case "$XGETTEXT" in /*) ac_cv_path_XGETTEXT="$XGETTEXT" # Let the user override the test with a path. ;; *) IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" for ac_dir in $PATH; do test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/$ac_word; then if test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"; then ac_cv_path_XGETTEXT="$ac_dir/$ac_word" break fi fi done IFS="$ac_save_ifs" test -z "$ac_cv_path_XGETTEXT" && ac_cv_path_XGETTEXT=":" ;; esac fi XGETTEXT="$ac_cv_path_XGETTEXT" if test "$XGETTEXT" != ":"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $XGETTEXT" >&5 $as_echo "$XGETTEXT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { extern int _nl_msg_cat_cntr; return _nl_msg_cat_cntr ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : CATOBJEXT=.gmo DATADIRNAME=share else case $host in *-*-solaris*) ac_fn_c_check_func "$LINENO" "bind_textdomain_codeset" "ac_cv_func_bind_textdomain_codeset" if test "x$ac_cv_func_bind_textdomain_codeset" = xyes; then : CATOBJEXT=.gmo DATADIRNAME=share else CATOBJEXT=.mo DATADIRNAME=lib fi ;; *-*-openbsd*) CATOBJEXT=.mo DATADIRNAME=share ;; *) CATOBJEXT=.mo DATADIRNAME=lib ;; esac fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS="$glib_save_LIBS" INSTOBJEXT=.mo else gt_cv_have_gettext=no fi fi fi if test "$gt_cv_have_gettext" = "yes" ; then $as_echo "#define ENABLE_NLS 1" >>confdefs.h fi if test "$XGETTEXT" != ":"; then if $XGETTEXT --omit-header /dev/null 2> /dev/null; then : ; else { $as_echo "$as_me:${as_lineno-$LINENO}: result: found xgettext program is not GNU xgettext; ignore it" >&5 $as_echo "found xgettext program is not GNU xgettext; ignore it" >&6; } XGETTEXT=":" fi fi # We need to process the po/ directory. POSUB=po ac_config_commands="$ac_config_commands default-1" for lang in $ALL_LINGUAS; do GMOFILES="$GMOFILES $lang.gmo" POFILES="$POFILES $lang.po" done if test "$gt_cv_have_gettext" = "yes"; then if test "x$ALL_LINGUAS" = "x"; then LINGUAS= else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for catalogs to be installed" >&5 $as_echo_n "checking for catalogs to be installed... " >&6; } NEW_LINGUAS= for presentlang in $ALL_LINGUAS; do useit=no if test "%UNSET%" != "${LINGUAS-%UNSET%}"; then desiredlanguages="$LINGUAS" else desiredlanguages="$ALL_LINGUAS" fi for desiredlang in $desiredlanguages; do # Use the presentlang catalog if desiredlang is # a. equal to presentlang, or # b. a variant of presentlang (because in this case, # presentlang can be used as a fallback for messages # which are not translated in the desiredlang catalog). case "$desiredlang" in "$presentlang"*) useit=yes;; esac done if test $useit = yes; then NEW_LINGUAS="$NEW_LINGUAS $presentlang" fi done LINGUAS=$NEW_LINGUAS { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LINGUAS" >&5 $as_echo "$LINGUAS" >&6; } fi if test -n "$LINGUAS"; then for lang in $LINGUAS; do CATALOGS="$CATALOGS $lang$CATOBJEXT"; done fi fi MKINSTALLDIRS= if test -n "$ac_aux_dir"; then MKINSTALLDIRS="$ac_aux_dir/mkinstalldirs" fi if test -z "$MKINSTALLDIRS"; then MKINSTALLDIRS="\$(top_srcdir)/mkinstalldirs" fi test -d po || mkdir po if test "x$srcdir" != "x."; then if test "x`echo $srcdir | sed 's@/.*@@'`" = "x"; then posrcprefix="$srcdir/" else posrcprefix="../$srcdir/" fi else posrcprefix="../" fi rm -f po/POTFILES sed -e "/^#/d" -e "/^\$/d" -e "s,.*, $posrcprefix& \\\\," -e "\$s/\(.*\) \\\\/\1/" \ < $srcdir/po/POTFILES.in > po/POTFILES glib_save_prefix="$prefix" glib_save_exec_prefix="$exec_prefix" glib_save_datarootdir="$datarootdir" test "x$prefix" = xNONE && prefix=$ac_default_prefix test "x$exec_prefix" = xNONE && exec_prefix=$prefix datarootdir=`eval echo "${datarootdir}"` if test "x$CATOBJEXT" = "x.mo" ; then localedir=`eval echo "${libdir}/locale"` else localedir=`eval echo "${datadir}/locale"` fi prefix="$glib_save_prefix" exec_prefix="$glib_save_exec_prefix" datarootdir="$glib_save_datarootdir" cat >>confdefs.h <<_ACEOF #define INF_LOCALEDIR "$localedir" _ACEOF ########### # GObject Introspection ########### # Check whether --enable-introspection was given. if test "${enable_introspection+set}" = set; then : enableval=$enable_introspection; else enable_introspection=auto fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gobject-introspection" >&5 $as_echo_n "checking for gobject-introspection... " >&6; } case $enable_introspection in #( no) : found_introspection="no (disabled, use --enable-introspection to enable)" ;; #( yes) : if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gobject-introspection-1.0\""; } >&5 ($PKG_CONFIG --exists --print-errors "gobject-introspection-1.0") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : else as_fn_error $? "gobject-introspection-1.0 is not installed" "$LINENO" 5 fi if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gobject-introspection-1.0 >= 1.0\""; } >&5 ($PKG_CONFIG --exists --print-errors "gobject-introspection-1.0 >= 1.0") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then found_introspection=yes else as_fn_error $? "You need to have gobject-introspection >= 1.0 installed to build libinfinity" "$LINENO" 5 fi ;; #( auto) : if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gobject-introspection-1.0 >= 1.0\""; } >&5 ($PKG_CONFIG --exists --print-errors "gobject-introspection-1.0 >= 1.0") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then found_introspection=yes else found_introspection=no fi enable_introspection=$found_introspection ;; #( *) : as_fn_error $? "invalid argument passed to --enable-introspection, should be one of [no/auto/yes]" "$LINENO" 5 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $found_introspection" >&5 $as_echo "$found_introspection" >&6; } INTROSPECTION_SCANNER= INTROSPECTION_COMPILER= INTROSPECTION_GENERATE= INTROSPECTION_GIRDIR= INTROSPECTION_TYPELIBDIR= if test "x$found_introspection" = "xyes"; then INTROSPECTION_SCANNER=`$PKG_CONFIG --variable=g_ir_scanner gobject-introspection-1.0` INTROSPECTION_COMPILER=`$PKG_CONFIG --variable=g_ir_compiler gobject-introspection-1.0` INTROSPECTION_GENERATE=`$PKG_CONFIG --variable=g_ir_generate gobject-introspection-1.0` INTROSPECTION_GIRDIR=`$PKG_CONFIG --variable=girdir gobject-introspection-1.0` INTROSPECTION_TYPELIBDIR="$($PKG_CONFIG --variable=typelibdir gobject-introspection-1.0)" INTROSPECTION_CFLAGS=`$PKG_CONFIG --cflags gobject-introspection-1.0` INTROSPECTION_LIBS=`$PKG_CONFIG --libs gobject-introspection-1.0` INTROSPECTION_MAKEFILE=`$PKG_CONFIG --variable=datadir gobject-introspection-1.0`/gobject-introspection-1.0/Makefile.introspection fi if test "x$found_introspection" = "xyes"; then HAVE_INTROSPECTION_TRUE= HAVE_INTROSPECTION_FALSE='#' else HAVE_INTROSPECTION_TRUE='#' HAVE_INTROSPECTION_FALSE= fi ########### # Output ########### if test -n $has_strict_prototypes then CFLAGS=$old_CFLAGS fi ac_config_files="$ac_config_files Makefile libinfinity/Makefile libinftext/Makefile libinfgtk/Makefile libinftextgtk/Makefile infinoted/Makefile infinoted/plugins/Makefile pixmaps/Makefile pixmaps/16x16/Makefile pixmaps/22x22/Makefile pixmaps/scalable/Makefile test/Makefile test/util/Makefile test/session/Makefile test/cleanup/Makefile test/certs/Makefile docs/Makefile docs/reference/Makefile docs/reference/version.xml.in docs/reference/api_version.xml.in docs/reference/libinfinity/Makefile docs/reference/libinftext/Makefile docs/reference/libinfgtk/Makefile docs/reference/libinftextgtk/Makefile docs/reference/libinfinoted-plugin-manager/Makefile po/Makefile.in" # These are separate for the macros to be expanded # (note no square brackets) ac_config_files="$ac_config_files libinfinity-0.7.pc:libinfinity.pc.in libinftext-0.7.pc:libinftext.pc.in libinfgtk-0.7.pc:libinfgtk.pc.in libinftextgtk-0.7.pc:libinftextgtk.pc.in libinfinoted-plugin-manager-0.7.pc:libinfinoted-plugin-manager.pc.in" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs { $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 $as_echo_n "checking that generated files are newer than configure... " >&6; } if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 $as_echo "done" >&6; } if test -n "$EXEEXT"; then am__EXEEXT_TRUE= am__EXEEXT_FALSE='#' else am__EXEEXT_TRUE='#' am__EXEEXT_FALSE= fi if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then as_fn_error $? "conditional \"MAINTAINER_MODE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then as_fn_error $? "conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_GTK_DOC_TRUE}" && test -z "${HAVE_GTK_DOC_FALSE}"; then as_fn_error $? "conditional \"HAVE_GTK_DOC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ENABLE_GTK_DOC_TRUE}" && test -z "${ENABLE_GTK_DOC_FALSE}"; then as_fn_error $? "conditional \"ENABLE_GTK_DOC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${GTK_DOC_BUILD_HTML_TRUE}" && test -z "${GTK_DOC_BUILD_HTML_FALSE}"; then as_fn_error $? "conditional \"GTK_DOC_BUILD_HTML\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${GTK_DOC_BUILD_PDF_TRUE}" && test -z "${GTK_DOC_BUILD_PDF_FALSE}"; then as_fn_error $? "conditional \"GTK_DOC_BUILD_PDF\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${GTK_DOC_USE_LIBTOOL_TRUE}" && test -z "${GTK_DOC_USE_LIBTOOL_FALSE}"; then as_fn_error $? "conditional \"GTK_DOC_USE_LIBTOOL\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${GTK_DOC_USE_REBASE_TRUE}" && test -z "${GTK_DOC_USE_REBASE_FALSE}"; then as_fn_error $? "conditional \"GTK_DOC_USE_REBASE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${WIN32_TRUE}" && test -z "${WIN32_FALSE}"; then as_fn_error $? "conditional \"WIN32\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${WITH_INFTEXTGTK_TRUE}" && test -z "${WITH_INFTEXTGTK_FALSE}"; then as_fn_error $? "conditional \"WITH_INFTEXTGTK\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${WITH_INFGTK_TRUE}" && test -z "${WITH_INFGTK_FALSE}"; then as_fn_error $? "conditional \"WITH_INFGTK\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${WITH_INFINOTED_TRUE}" && test -z "${WITH_INFINOTED_FALSE}"; then as_fn_error $? "conditional \"WITH_INFINOTED\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${LIBINFINITY_HAVE_AVAHI_TRUE}" && test -z "${LIBINFINITY_HAVE_AVAHI_FALSE}"; then as_fn_error $? "conditional \"LIBINFINITY_HAVE_AVAHI\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${LIBINFINITY_HAVE_GIO_TRUE}" && test -z "${LIBINFINITY_HAVE_GIO_FALSE}"; then as_fn_error $? "conditional \"LIBINFINITY_HAVE_GIO\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${LIBINFINITY_HAVE_LIBDAEMON_TRUE}" && test -z "${LIBINFINITY_HAVE_LIBDAEMON_FALSE}"; then as_fn_error $? "conditional \"LIBINFINITY_HAVE_LIBDAEMON\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_INTROSPECTION_TRUE}" && test -z "${HAVE_INTROSPECTION_FALSE}"; then as_fn_error $? "conditional \"HAVE_INTROSPECTION\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac fi as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by libinfinity $as_me 0.7.1, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac case $ac_config_headers in *" "*) set x $ac_config_headers; shift; ac_config_headers=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_headers="$ac_config_headers" config_commands="$ac_config_commands" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Configuration commands: $config_commands Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ libinfinity config.status 0.7.1 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' INSTALL='$INSTALL' MKDIR_P='$MKDIR_P' AWK='$AWK' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header as_fn_error $? "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # # INIT-COMMANDS # AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`' macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' shared_archive_member_spec='`$ECHO "$shared_archive_member_spec" | $SED "$delay_single_quote_subst"`' SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`' host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`' host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`' host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`' build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`' build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`' build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`' SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`' Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`' GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`' EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`' FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`' LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`' NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`' LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`' max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`' ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`' exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`' lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`' lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`' lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`' lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`' lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`' reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`' want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`' DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`' AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`' STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`' old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`' old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`' old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`' lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`' CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`' CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`' compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_import='`$ECHO "$lt_cv_sys_global_symbol_to_import" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' lt_cv_nm_interface='`$ECHO "$lt_cv_nm_interface" | $SED "$delay_single_quote_subst"`' nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`' lt_cv_truncate_bin='`$ECHO "$lt_cv_truncate_bin" | $SED "$delay_single_quote_subst"`' objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`' lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`' need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`' MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`' DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`' NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`' LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`' OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`' OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`' libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`' shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`' extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`' archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`' enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`' export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`' whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`' compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`' old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`' old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`' archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`' archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`' module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`' module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`' with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`' allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`' hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`' hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`' hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`' inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`' link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`' always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`' export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`' exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`' include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`' prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`' postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`' file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`' variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`' need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`' need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`' version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`' runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`' shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`' shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`' libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`' library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`' soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`' install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`' postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`' postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`' finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' configure_time_dlsearch_path='`$ECHO "$configure_time_dlsearch_path" | $SED "$delay_single_quote_subst"`' configure_time_lt_sys_library_path='`$ECHO "$configure_time_lt_sys_library_path" | $SED "$delay_single_quote_subst"`' hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`' old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`' striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`' LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$1 _LTECHO_EOF' } # Quote evaled strings. for var in SHELL \ ECHO \ PATH_SEPARATOR \ SED \ GREP \ EGREP \ FGREP \ LD \ NM \ LN_S \ lt_SP2NL \ lt_NL2SP \ reload_flag \ OBJDUMP \ deplibs_check_method \ file_magic_cmd \ file_magic_glob \ want_nocaseglob \ DLLTOOL \ sharedlib_from_linklib_cmd \ AR \ AR_FLAGS \ archiver_list_spec \ STRIP \ RANLIB \ CC \ CFLAGS \ compiler \ lt_cv_sys_global_symbol_pipe \ lt_cv_sys_global_symbol_to_cdecl \ lt_cv_sys_global_symbol_to_import \ lt_cv_sys_global_symbol_to_c_name_address \ lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ lt_cv_nm_interface \ nm_file_list_spec \ lt_cv_truncate_bin \ lt_prog_compiler_no_builtin_flag \ lt_prog_compiler_pic \ lt_prog_compiler_wl \ lt_prog_compiler_static \ lt_cv_prog_compiler_c_o \ need_locks \ MANIFEST_TOOL \ DSYMUTIL \ NMEDIT \ LIPO \ OTOOL \ OTOOL64 \ shrext_cmds \ export_dynamic_flag_spec \ whole_archive_flag_spec \ compiler_needs_object \ with_gnu_ld \ allow_undefined_flag \ no_undefined_flag \ hardcode_libdir_flag_spec \ hardcode_libdir_separator \ exclude_expsyms \ include_expsyms \ file_list_spec \ variables_saved_for_relink \ libname_spec \ library_names_spec \ soname_spec \ install_override_mode \ finish_eval \ old_striplib \ striplib; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in reload_cmds \ old_postinstall_cmds \ old_postuninstall_cmds \ old_archive_cmds \ extract_expsyms_cmds \ old_archive_from_new_cmds \ old_archive_from_expsyms_cmds \ archive_cmds \ archive_expsym_cmds \ module_cmds \ module_expsym_cmds \ export_symbols_cmds \ prelink_cmds \ postlink_cmds \ postinstall_cmds \ postuninstall_cmds \ finish_cmds \ sys_lib_search_path_spec \ configure_time_dlsearch_path \ configure_time_lt_sys_library_path; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done ac_aux_dir='$ac_aux_dir' # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi PACKAGE='$PACKAGE' VERSION='$VERSION' RM='$RM' ofile='$ofile' _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; "libinfinity/inf-config.h") CONFIG_HEADERS="$CONFIG_HEADERS libinfinity/inf-config.h" ;; "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; "default-1") CONFIG_COMMANDS="$CONFIG_COMMANDS default-1" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "libinfinity/Makefile") CONFIG_FILES="$CONFIG_FILES libinfinity/Makefile" ;; "libinftext/Makefile") CONFIG_FILES="$CONFIG_FILES libinftext/Makefile" ;; "libinfgtk/Makefile") CONFIG_FILES="$CONFIG_FILES libinfgtk/Makefile" ;; "libinftextgtk/Makefile") CONFIG_FILES="$CONFIG_FILES libinftextgtk/Makefile" ;; "infinoted/Makefile") CONFIG_FILES="$CONFIG_FILES infinoted/Makefile" ;; "infinoted/plugins/Makefile") CONFIG_FILES="$CONFIG_FILES infinoted/plugins/Makefile" ;; "pixmaps/Makefile") CONFIG_FILES="$CONFIG_FILES pixmaps/Makefile" ;; "pixmaps/16x16/Makefile") CONFIG_FILES="$CONFIG_FILES pixmaps/16x16/Makefile" ;; "pixmaps/22x22/Makefile") CONFIG_FILES="$CONFIG_FILES pixmaps/22x22/Makefile" ;; "pixmaps/scalable/Makefile") CONFIG_FILES="$CONFIG_FILES pixmaps/scalable/Makefile" ;; "test/Makefile") CONFIG_FILES="$CONFIG_FILES test/Makefile" ;; "test/util/Makefile") CONFIG_FILES="$CONFIG_FILES test/util/Makefile" ;; "test/session/Makefile") CONFIG_FILES="$CONFIG_FILES test/session/Makefile" ;; "test/cleanup/Makefile") CONFIG_FILES="$CONFIG_FILES test/cleanup/Makefile" ;; "test/certs/Makefile") CONFIG_FILES="$CONFIG_FILES test/certs/Makefile" ;; "docs/Makefile") CONFIG_FILES="$CONFIG_FILES docs/Makefile" ;; "docs/reference/Makefile") CONFIG_FILES="$CONFIG_FILES docs/reference/Makefile" ;; "docs/reference/version.xml.in") CONFIG_FILES="$CONFIG_FILES docs/reference/version.xml.in" ;; "docs/reference/api_version.xml.in") CONFIG_FILES="$CONFIG_FILES docs/reference/api_version.xml.in" ;; "docs/reference/libinfinity/Makefile") CONFIG_FILES="$CONFIG_FILES docs/reference/libinfinity/Makefile" ;; "docs/reference/libinftext/Makefile") CONFIG_FILES="$CONFIG_FILES docs/reference/libinftext/Makefile" ;; "docs/reference/libinfgtk/Makefile") CONFIG_FILES="$CONFIG_FILES docs/reference/libinfgtk/Makefile" ;; "docs/reference/libinftextgtk/Makefile") CONFIG_FILES="$CONFIG_FILES docs/reference/libinftextgtk/Makefile" ;; "docs/reference/libinfinoted-plugin-manager/Makefile") CONFIG_FILES="$CONFIG_FILES docs/reference/libinfinoted-plugin-manager/Makefile" ;; "po/Makefile.in") CONFIG_FILES="$CONFIG_FILES po/Makefile.in" ;; "libinfinity-0.7.pc") CONFIG_FILES="$CONFIG_FILES libinfinity-0.7.pc:libinfinity.pc.in" ;; "libinftext-0.7.pc") CONFIG_FILES="$CONFIG_FILES libinftext-0.7.pc:libinftext.pc.in" ;; "libinfgtk-0.7.pc") CONFIG_FILES="$CONFIG_FILES libinfgtk-0.7.pc:libinfgtk.pc.in" ;; "libinftextgtk-0.7.pc") CONFIG_FILES="$CONFIG_FILES libinftextgtk-0.7.pc:libinftextgtk.pc.in" ;; "libinfinoted-plugin-manager-0.7.pc") CONFIG_FILES="$CONFIG_FILES libinfinoted-plugin-manager-0.7.pc:libinfinoted-plugin-manager.pc.in" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" # Set up the scripts for CONFIG_HEADERS section. # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then cat >"$ac_tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF # Transform confdefs.h into an awk script `defines.awk', embedded as # here-document in config.status, that substitutes the proper values into # config.h.in to produce config.h. # Create a delimiter string that does not exist in confdefs.h, to ease # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do ac_tt=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_tt"; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done # For the awk script, D is an array of macro values keyed by name, # likewise P contains macro parameters if any. Preserve backslash # newline sequences. ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* sed -n ' s/.\{148\}/&'"$ac_delim"'/g t rset :rset s/^[ ]*#[ ]*define[ ][ ]*/ / t def d :def s/\\$// t bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3"/p s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p d :bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3\\\\\\n"\\/p t cont s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p t cont d :cont n s/.\{148\}/&'"$ac_delim"'/g t clear :clear s/\\$// t bsnlc s/["\\]/\\&/g; s/^/"/; s/$/"/p d :bsnlc s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p b cont ' >$CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 for (key in D) D_is_set[key] = 1 FS = "" } /^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { line = \$ 0 split(line, arg, " ") if (arg[1] == "#") { defundef = arg[2] mac1 = arg[3] } else { defundef = substr(arg[1], 2) mac1 = arg[2] } split(mac1, mac2, "(") #) macro = mac2[1] prefix = substr(line, 1, index(line, defundef) - 1) if (D_is_set[macro]) { # Preserve the white space surrounding the "#". print prefix "define", macro P[macro] D[macro] next } else { # Replace #undef with comments. This is necessary, for example, # in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. if (defundef == "undef") { print "/*", prefix defundef, macro, "*/" next } } } { print } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac ac_MKDIR_P=$MKDIR_P case $MKDIR_P in [\\/$]* | ?:[\\/]* ) ;; */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; esac _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t s&@MKDIR_P@&$ac_MKDIR_P&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :H) # # CONFIG_HEADER # if test x"$ac_file" != x-; then { $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 $as_echo "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi # Compute "$ac_file"'s index in $config_headers. _am_arg="$ac_file" _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || $as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$_am_arg" : 'X\(//\)[^/]' \| \ X"$_am_arg" : 'X\(//\)$' \| \ X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$_am_arg" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'`/stamp-h$_am_stamp_count ;; :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 $as_echo "$as_me: executing $ac_file commands" >&6;} ;; esac case $ac_file$ac_mode in "depfiles":C) test x"$AMDEP_TRUE" != x"" || { # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named 'Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`$as_dirname -- "$mf" || $as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$mf" : 'X\(//\)[^/]' \| \ X"$mf" : 'X\(//\)$' \| \ X"$mf" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running 'make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "$am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`$as_dirname -- "$file" || $as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$file" : 'X\(//\)[^/]' \| \ X"$file" : 'X\(//\)$' \| \ X"$file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir=$dirpart/$fdir; as_fn_mkdir_p # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ;; "libtool":C) # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi cfgfile=${ofile}T trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # Generated automatically by $as_me ($PACKAGE) $VERSION # NOTE: Changes made to this file will be lost: look at ltmain.sh. # Provide generalized library-building support services. # Written by Gordon Matzigkeit, 1996 # Copyright (C) 2014 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # GNU Libtool is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of of the License, or # (at your option) any later version. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program or library that is built # using GNU Libtool, you may include this file under the same # distribution terms that you use for the rest of that program. # # GNU Libtool is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # The names of the tagged configurations supported by this script. available_tags='' # Configured defaults for sys_lib_dlsearch_path munging. : \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} # ### BEGIN LIBTOOL CONFIG # Which release of libtool.m4 was used? macro_version=$macro_version macro_revision=$macro_revision # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Whether or not to build static libraries. build_old_libs=$enable_static # What type of objects to build. pic_mode=$pic_mode # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # Shared archive member basename,for filename based shared library versioning on AIX. shared_archive_member_spec=$shared_archive_member_spec # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # An echo program that protects backslashes. ECHO=$lt_ECHO # The PATH separator for the build system. PATH_SEPARATOR=$lt_PATH_SEPARATOR # The host system. host_alias=$host_alias host=$host host_os=$host_os # The build system. build_alias=$build_alias build=$build build_os=$build_os # A sed program that does not truncate output. SED=$lt_SED # Sed that helps us avoid accidentally triggering echo(1) options like -n. Xsed="\$SED -e 1s/^X//" # A grep program that handles long lines. GREP=$lt_GREP # An ERE matcher. EGREP=$lt_EGREP # A literal string matcher. FGREP=$lt_FGREP # A BSD- or MS-compatible name lister. NM=$lt_NM # Whether we need soft or hard links. LN_S=$lt_LN_S # What is the maximum length of a command? max_cmd_len=$max_cmd_len # Object file suffix (normally "o"). objext=$ac_objext # Executable file suffix (normally ""). exeext=$exeext # whether the shell understands "unset". lt_unset=$lt_unset # turn spaces into newlines. SP2NL=$lt_lt_SP2NL # turn newlines into spaces. NL2SP=$lt_lt_NL2SP # convert \$build file names to \$host format. to_host_file_cmd=$lt_cv_to_host_file_cmd # convert \$build files to toolchain format. to_tool_file_cmd=$lt_cv_to_tool_file_cmd # An object symbol dumper. OBJDUMP=$lt_OBJDUMP # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method = "file_magic". file_magic_cmd=$lt_file_magic_cmd # How to find potential files when deplibs_check_method = "file_magic". file_magic_glob=$lt_file_magic_glob # Find potential files using nocaseglob when deplibs_check_method = "file_magic". want_nocaseglob=$lt_want_nocaseglob # DLL creation program. DLLTOOL=$lt_DLLTOOL # Command to associate shared and link libraries. sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd # The archiver. AR=$lt_AR # Flags to create an archive. AR_FLAGS=$lt_AR_FLAGS # How to feed a file listing to the archiver. archiver_list_spec=$lt_archiver_list_spec # A symbol stripping program. STRIP=$lt_STRIP # Commands used to install an old-style archive. RANLIB=$lt_RANLIB old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # Whether to use a lock for old archive extraction. lock_old_archive_extraction=$lock_old_archive_extraction # A C compiler. LTCC=$lt_CC # LTCC compiler flags. LTCFLAGS=$lt_CFLAGS # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration. global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl # Transform the output of nm into a list of symbols to manually relocate. global_symbol_to_import=$lt_lt_cv_sys_global_symbol_to_import # Transform the output of nm in a C name address pair. global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # Transform the output of nm in a C name address pair when lib prefix is needed. global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix # The name lister interface. nm_interface=$lt_lt_cv_nm_interface # Specify filename containing input files for \$NM. nm_file_list_spec=$lt_nm_file_list_spec # The root where to search for dependent libraries,and where our libraries should be installed. lt_sysroot=$lt_sysroot # Command to truncate a binary pipe. lt_truncate_bin=$lt_lt_cv_truncate_bin # The name of the directory that contains temporary libtool files. objdir=$objdir # Used to examine libraries when file_magic_cmd begins with "file". MAGIC_CMD=$MAGIC_CMD # Must we lock files when doing compilation? need_locks=$lt_need_locks # Manifest tool. MANIFEST_TOOL=$lt_MANIFEST_TOOL # Tool to manipulate archived DWARF debug symbol files on Mac OS X. DSYMUTIL=$lt_DSYMUTIL # Tool to change global to local symbols on Mac OS X. NMEDIT=$lt_NMEDIT # Tool to manipulate fat objects and archives on Mac OS X. LIPO=$lt_LIPO # ldd/readelf like tool for Mach-O binaries on Mac OS X. OTOOL=$lt_OTOOL # ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. OTOOL64=$lt_OTOOL64 # Old archive suffix (normally "a"). libext=$libext # Shared library suffix (normally ".so"). shrext_cmds=$lt_shrext_cmds # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Variables whose values should be saved in libtool wrapper scripts and # restored at link time. variables_saved_for_relink=$lt_variables_saved_for_relink # Do we need the "lib" prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Library versioning type. version_type=$version_type # Shared library runtime path variable. runpath_var=$runpath_var # Shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Permission mode override for installation of shared libraries. install_override_mode=$lt_install_override_mode # Command to use after installation of a shared archive. postinstall_cmds=$lt_postinstall_cmds # Command to use after uninstallation of a shared archive. postuninstall_cmds=$lt_postuninstall_cmds # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # As "finish_cmds", except a single script fragment to be evaled but # not shown. finish_eval=$lt_finish_eval # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Compile-time system search path for libraries. sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Detected run-time system search path for libraries. sys_lib_dlsearch_path_spec=$lt_configure_time_dlsearch_path # Explicit LT_SYS_LIBRARY_PATH set during ./configure time. configure_time_lt_sys_library_path=$lt_configure_time_lt_sys_library_path # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # The linker used to build libraries. LD=$lt_LD # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # Commands used to build an old-style archive. old_archive_cmds=$lt_old_archive_cmds # A language specific compiler. CC=$lt_compiler # Is the compiler the GNU compiler? with_gcc=$GCC # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc # Whether or not to disallow shared libs when runtime libs are static. allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec # Whether the compiler copes with passing no objects directly. compiler_needs_object=$lt_compiler_needs_object # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds # Commands used to build a shared archive. archive_cmds=$lt_archive_cmds archive_expsym_cmds=$lt_archive_expsym_cmds # Commands used to build a loadable module if different from building # a shared archive. module_cmds=$lt_module_cmds module_expsym_cmds=$lt_module_expsym_cmds # Whether we are building with GNU ld or not. with_gnu_ld=$lt_with_gnu_ld # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag # Flag that enforces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec # Whether we need a single "-rpath" flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator # Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes # DIR into the resulting binary. hardcode_direct=$hardcode_direct # Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes # DIR into the resulting binary and the resulting library dependency is # "absolute",i.e impossible to change by setting \$shlibpath_var if the # library is relocated. hardcode_direct_absolute=$hardcode_direct_absolute # Set to "yes" if using the -LDIR flag during linking hardcodes DIR # into the resulting binary. hardcode_minus_L=$hardcode_minus_L # Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR # into the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var # Set to "yes" if building a shared library automatically hardcodes DIR # into the library and all subsequent libraries and executables linked # against it. hardcode_automatic=$hardcode_automatic # Set to yes if linker adds runtime paths of dependent libraries # to runtime path list. inherit_rpath=$inherit_rpath # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs # Set to "yes" if exported symbols are required. always_export_symbols=$always_export_symbols # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms # Symbols that must always be exported. include_expsyms=$lt_include_expsyms # Commands necessary for linking programs (against libraries) with templates. prelink_cmds=$lt_prelink_cmds # Commands necessary for finishing linking programs. postlink_cmds=$lt_postlink_cmds # Specify filename containing input files. file_list_spec=$lt_file_list_spec # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action # ### END LIBTOOL CONFIG _LT_EOF cat <<'_LT_EOF' >> "$cfgfile" # ### BEGIN FUNCTIONS SHARED WITH CONFIGURE # func_munge_path_list VARIABLE PATH # ----------------------------------- # VARIABLE is name of variable containing _space_ separated list of # directories to be munged by the contents of PATH, which is string # having a format: # "DIR[:DIR]:" # string "DIR[ DIR]" will be prepended to VARIABLE # ":DIR[:DIR]" # string "DIR[ DIR]" will be appended to VARIABLE # "DIRP[:DIRP]::[DIRA:]DIRA" # string "DIRP[ DIRP]" will be prepended to VARIABLE and string # "DIRA[ DIRA]" will be appended to VARIABLE # "DIR[:DIR]" # VARIABLE will be replaced by "DIR[ DIR]" func_munge_path_list () { case x$2 in x) ;; *:) eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" ;; x:*) eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" ;; *::*) eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" ;; *) eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" ;; esac } # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. func_cc_basename () { for cc_temp in $*""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` } # ### END FUNCTIONS SHARED WITH CONFIGURE _LT_EOF case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac ltmain=$ac_aux_dir/ltmain.sh # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" ;; "default-1":C) case "$CONFIG_FILES" in *po/Makefile.in*) sed -e "/POTFILES =/r po/POTFILES" po/Makefile.in > po/Makefile esac ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi echo " Build optional packages: libinfgtk: $with_infgtk libinftextgtk: $with_inftextgtk infinoted: $with_infinoted Enable support for: avahi: $use_avahi libdaemon: $use_libdaemon pam: $use_pam " # vim:set et: libinfinity-0.7.1/PaxHeaders.26529/ltmain.sh0000644000000000000000000000013213036062675015433 xustar0030 mtime=1484285373.315887364 30 atime=1484285373.315887364 30 ctime=1488261588.784139538 libinfinity-0.7.1/ltmain.sh0000644000175000017500000117147413036062675016204 0ustar00arminarmin00000000000000#! /bin/sh ## DO NOT EDIT - This file generated from ./build-aux/ltmain.in ## by inline-source v2014-01-03.01 # libtool (GNU libtool) 2.4.6 # Provide generalized library-building support services. # Written by Gordon Matzigkeit , 1996 # Copyright (C) 1996-2015 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # GNU Libtool is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . PROGRAM=libtool PACKAGE=libtool VERSION="2.4.6 Debian-2.4.6-2" package_revision=2.4.6 ## ------ ## ## Usage. ## ## ------ ## # Run './libtool --help' for help with using this script from the # command line. ## ------------------------------- ## ## User overridable command paths. ## ## ------------------------------- ## # After configure completes, it has a better idea of some of the # shell tools we need than the defaults used by the functions shared # with bootstrap, so set those here where they can still be over- # ridden by the user, but otherwise take precedence. : ${AUTOCONF="autoconf"} : ${AUTOMAKE="automake"} ## -------------------------- ## ## Source external libraries. ## ## -------------------------- ## # Much of our low-level functionality needs to be sourced from external # libraries, which are installed to $pkgauxdir. # Set a version string for this script. scriptversion=2015-01-20.17; # UTC # General shell script boiler plate, and helper functions. # Written by Gary V. Vaughan, 2004 # Copyright (C) 2004-2015 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # As a special exception to the GNU General Public License, if you distribute # this file as part of a program or library that is built using GNU Libtool, # you may include this file under the same distribution terms that you use # for the rest of that program. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNES 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 . # Please report bugs or propose patches to gary@gnu.org. ## ------ ## ## Usage. ## ## ------ ## # Evaluate this file near the top of your script to gain access to # the functions and variables defined here: # # . `echo "$0" | ${SED-sed} 's|[^/]*$||'`/build-aux/funclib.sh # # If you need to override any of the default environment variable # settings, do that before evaluating this file. ## -------------------- ## ## Shell normalisation. ## ## -------------------- ## # Some shells need a little help to be as Bourne compatible as possible. # Before doing anything else, make sure all that help has been provided! DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac fi # NLS nuisances: We save the old values in case they are required later. _G_user_locale= _G_safe_locale= for _G_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do eval "if test set = \"\${$_G_var+set}\"; then save_$_G_var=\$$_G_var $_G_var=C export $_G_var _G_user_locale=\"$_G_var=\\\$save_\$_G_var; \$_G_user_locale\" _G_safe_locale=\"$_G_var=C; \$_G_safe_locale\" fi" done # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Make sure IFS has a sensible default sp=' ' nl=' ' IFS="$sp $nl" # There are apparently some retarded systems that use ';' as a PATH separator! if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi ## ------------------------- ## ## Locate command utilities. ## ## ------------------------- ## # func_executable_p FILE # ---------------------- # Check that FILE is an executable regular file. func_executable_p () { test -f "$1" && test -x "$1" } # func_path_progs PROGS_LIST CHECK_FUNC [PATH] # -------------------------------------------- # Search for either a program that responds to --version with output # containing "GNU", or else returned by CHECK_FUNC otherwise, by # trying all the directories in PATH with each of the elements of # PROGS_LIST. # # CHECK_FUNC should accept the path to a candidate program, and # set $func_check_prog_result if it truncates its output less than # $_G_path_prog_max characters. func_path_progs () { _G_progs_list=$1 _G_check_func=$2 _G_PATH=${3-"$PATH"} _G_path_prog_max=0 _G_path_prog_found=false _G_save_IFS=$IFS; IFS=${PATH_SEPARATOR-:} for _G_dir in $_G_PATH; do IFS=$_G_save_IFS test -z "$_G_dir" && _G_dir=. for _G_prog_name in $_G_progs_list; do for _exeext in '' .EXE; do _G_path_prog=$_G_dir/$_G_prog_name$_exeext func_executable_p "$_G_path_prog" || continue case `"$_G_path_prog" --version 2>&1` in *GNU*) func_path_progs_result=$_G_path_prog _G_path_prog_found=: ;; *) $_G_check_func $_G_path_prog func_path_progs_result=$func_check_prog_result ;; esac $_G_path_prog_found && break 3 done done done IFS=$_G_save_IFS test -z "$func_path_progs_result" && { echo "no acceptable sed could be found in \$PATH" >&2 exit 1 } } # We want to be able to use the functions in this file before configure # has figured out where the best binaries are kept, which means we have # to search for them ourselves - except when the results are already set # where we skip the searches. # Unless the user overrides by setting SED, search the path for either GNU # sed, or the sed that truncates its output the least. test -z "$SED" && { _G_sed_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ for _G_i in 1 2 3 4 5 6 7; do _G_sed_script=$_G_sed_script$nl$_G_sed_script done echo "$_G_sed_script" 2>/dev/null | sed 99q >conftest.sed _G_sed_script= func_check_prog_sed () { _G_path_prog=$1 _G_count=0 printf 0123456789 >conftest.in while : do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo '' >> conftest.nl "$_G_path_prog" -f conftest.sed conftest.out 2>/dev/null || break diff conftest.out conftest.nl >/dev/null 2>&1 || break _G_count=`expr $_G_count + 1` if test "$_G_count" -gt "$_G_path_prog_max"; then # Best one so far, save it but keep looking for a better one func_check_prog_result=$_G_path_prog _G_path_prog_max=$_G_count fi # 10*(2^10) chars as input seems more than enough test 10 -lt "$_G_count" && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out } func_path_progs "sed gsed" func_check_prog_sed $PATH:/usr/xpg4/bin rm -f conftest.sed SED=$func_path_progs_result } # Unless the user overrides by setting GREP, search the path for either GNU # grep, or the grep that truncates its output the least. test -z "$GREP" && { func_check_prog_grep () { _G_path_prog=$1 _G_count=0 _G_path_prog_max=0 printf 0123456789 >conftest.in while : do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo 'GREP' >> conftest.nl "$_G_path_prog" -e 'GREP$' -e '-(cannot match)-' conftest.out 2>/dev/null || break diff conftest.out conftest.nl >/dev/null 2>&1 || break _G_count=`expr $_G_count + 1` if test "$_G_count" -gt "$_G_path_prog_max"; then # Best one so far, save it but keep looking for a better one func_check_prog_result=$_G_path_prog _G_path_prog_max=$_G_count fi # 10*(2^10) chars as input seems more than enough test 10 -lt "$_G_count" && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out } func_path_progs "grep ggrep" func_check_prog_grep $PATH:/usr/xpg4/bin GREP=$func_path_progs_result } ## ------------------------------- ## ## User overridable command paths. ## ## ------------------------------- ## # All uppercase variable names are used for environment variables. These # variables can be overridden by the user before calling a script that # uses them if a suitable command of that name is not already available # in the command search PATH. : ${CP="cp -f"} : ${ECHO="printf %s\n"} : ${EGREP="$GREP -E"} : ${FGREP="$GREP -F"} : ${LN_S="ln -s"} : ${MAKE="make"} : ${MKDIR="mkdir"} : ${MV="mv -f"} : ${RM="rm -f"} : ${SHELL="${CONFIG_SHELL-/bin/sh}"} ## -------------------- ## ## Useful sed snippets. ## ## -------------------- ## sed_dirname='s|/[^/]*$||' sed_basename='s|^.*/||' # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. sed_quote_subst='s|\([`"$\\]\)|\\\1|g' # Same as above, but do not quote variable references. sed_double_quote_subst='s/\(["`\\]\)/\\\1/g' # Sed substitution that turns a string into a regex matching for the # string literally. sed_make_literal_regex='s|[].[^$\\*\/]|\\&|g' # Sed substitution that converts a w32 file name or path # that contains forward slashes, into one that contains # (escaped) backslashes. A very naive implementation. sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' # Re-'\' parameter expansions in output of sed_double_quote_subst that # were '\'-ed in input to the same. If an odd number of '\' preceded a # '$' in input to sed_double_quote_subst, that '$' was protected from # expansion. Since each input '\' is now two '\'s, look for any number # of runs of four '\'s followed by two '\'s and then a '$'. '\' that '$'. _G_bs='\\' _G_bs2='\\\\' _G_bs4='\\\\\\\\' _G_dollar='\$' sed_double_backslash="\ s/$_G_bs4/&\\ /g s/^$_G_bs2$_G_dollar/$_G_bs&/ s/\\([^$_G_bs]\\)$_G_bs2$_G_dollar/\\1$_G_bs2$_G_bs$_G_dollar/g s/\n//g" ## ----------------- ## ## Global variables. ## ## ----------------- ## # Except for the global variables explicitly listed below, the following # functions in the '^func_' namespace, and the '^require_' namespace # variables initialised in the 'Resource management' section, sourcing # this file will not pollute your global namespace with anything # else. There's no portable way to scope variables in Bourne shell # though, so actually running these functions will sometimes place # results into a variable named after the function, and often use # temporary variables in the '^_G_' namespace. If you are careful to # avoid using those namespaces casually in your sourcing script, things # should continue to work as you expect. And, of course, you can freely # overwrite any of the functions or variables defined here before # calling anything to customize them. EXIT_SUCCESS=0 EXIT_FAILURE=1 EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. # Allow overriding, eg assuming that you follow the convention of # putting '$debug_cmd' at the start of all your functions, you can get # bash to show function call trace with: # # debug_cmd='eval echo "${FUNCNAME[0]} $*" >&2' bash your-script-name debug_cmd=${debug_cmd-":"} exit_cmd=: # By convention, finish your script with: # # exit $exit_status # # so that you can set exit_status to non-zero if you want to indicate # something went wrong during execution without actually bailing out at # the point of failure. exit_status=$EXIT_SUCCESS # Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh # is ksh but when the shell is invoked as "sh" and the current value of # the _XPG environment variable is not equal to 1 (one), the special # positional parameter $0, within a function call, is the name of the # function. progpath=$0 # The name of this program. progname=`$ECHO "$progpath" |$SED "$sed_basename"` # Make sure we have an absolute progpath for reexecution: case $progpath in [\\/]*|[A-Za-z]:\\*) ;; *[\\/]*) progdir=`$ECHO "$progpath" |$SED "$sed_dirname"` progdir=`cd "$progdir" && pwd` progpath=$progdir/$progname ;; *) _G_IFS=$IFS IFS=${PATH_SEPARATOR-:} for progdir in $PATH; do IFS=$_G_IFS test -x "$progdir/$progname" && break done IFS=$_G_IFS test -n "$progdir" || progdir=`pwd` progpath=$progdir/$progname ;; esac ## ----------------- ## ## Standard options. ## ## ----------------- ## # The following options affect the operation of the functions defined # below, and should be set appropriately depending on run-time para- # meters passed on the command line. opt_dry_run=false opt_quiet=false opt_verbose=false # Categories 'all' and 'none' are always available. Append any others # you will pass as the first argument to func_warning from your own # code. warning_categories= # By default, display warnings according to 'opt_warning_types'. Set # 'warning_func' to ':' to elide all warnings, or func_fatal_error to # treat the next displayed warning as a fatal error. warning_func=func_warn_and_continue # Set to 'all' to display all warnings, 'none' to suppress all # warnings, or a space delimited list of some subset of # 'warning_categories' to display only the listed warnings. opt_warning_types=all ## -------------------- ## ## Resource management. ## ## -------------------- ## # This section contains definitions for functions that each ensure a # particular resource (a file, or a non-empty configuration variable for # example) is available, and if appropriate to extract default values # from pertinent package files. Call them using their associated # 'require_*' variable to ensure that they are executed, at most, once. # # It's entirely deliberate that calling these functions can set # variables that don't obey the namespace limitations obeyed by the rest # of this file, in order that that they be as useful as possible to # callers. # require_term_colors # ------------------- # Allow display of bold text on terminals that support it. require_term_colors=func_require_term_colors func_require_term_colors () { $debug_cmd test -t 1 && { # COLORTERM and USE_ANSI_COLORS environment variables take # precedence, because most terminfo databases neglect to describe # whether color sequences are supported. test -n "${COLORTERM+set}" && : ${USE_ANSI_COLORS="1"} if test 1 = "$USE_ANSI_COLORS"; then # Standard ANSI escape sequences tc_reset='' tc_bold=''; tc_standout='' tc_red=''; tc_green='' tc_blue=''; tc_cyan='' else # Otherwise trust the terminfo database after all. test -n "`tput sgr0 2>/dev/null`" && { tc_reset=`tput sgr0` test -n "`tput bold 2>/dev/null`" && tc_bold=`tput bold` tc_standout=$tc_bold test -n "`tput smso 2>/dev/null`" && tc_standout=`tput smso` test -n "`tput setaf 1 2>/dev/null`" && tc_red=`tput setaf 1` test -n "`tput setaf 2 2>/dev/null`" && tc_green=`tput setaf 2` test -n "`tput setaf 4 2>/dev/null`" && tc_blue=`tput setaf 4` test -n "`tput setaf 5 2>/dev/null`" && tc_cyan=`tput setaf 5` } fi } require_term_colors=: } ## ----------------- ## ## Function library. ## ## ----------------- ## # This section contains a variety of useful functions to call in your # scripts. Take note of the portable wrappers for features provided by # some modern shells, which will fall back to slower equivalents on # less featureful shells. # func_append VAR VALUE # --------------------- # Append VALUE onto the existing contents of VAR. # We should try to minimise forks, especially on Windows where they are # unreasonably slow, so skip the feature probes when bash or zsh are # being used: if test set = "${BASH_VERSION+set}${ZSH_VERSION+set}"; then : ${_G_HAVE_ARITH_OP="yes"} : ${_G_HAVE_XSI_OPS="yes"} # The += operator was introduced in bash 3.1 case $BASH_VERSION in [12].* | 3.0 | 3.0*) ;; *) : ${_G_HAVE_PLUSEQ_OP="yes"} ;; esac fi # _G_HAVE_PLUSEQ_OP # Can be empty, in which case the shell is probed, "yes" if += is # useable or anything else if it does not work. test -z "$_G_HAVE_PLUSEQ_OP" \ && (eval 'x=a; x+=" b"; test "a b" = "$x"') 2>/dev/null \ && _G_HAVE_PLUSEQ_OP=yes if test yes = "$_G_HAVE_PLUSEQ_OP" then # This is an XSI compatible shell, allowing a faster implementation... eval 'func_append () { $debug_cmd eval "$1+=\$2" }' else # ...otherwise fall back to using expr, which is often a shell builtin. func_append () { $debug_cmd eval "$1=\$$1\$2" } fi # func_append_quoted VAR VALUE # ---------------------------- # Quote VALUE and append to the end of shell variable VAR, separated # by a space. if test yes = "$_G_HAVE_PLUSEQ_OP"; then eval 'func_append_quoted () { $debug_cmd func_quote_for_eval "$2" eval "$1+=\\ \$func_quote_for_eval_result" }' else func_append_quoted () { $debug_cmd func_quote_for_eval "$2" eval "$1=\$$1\\ \$func_quote_for_eval_result" } fi # func_append_uniq VAR VALUE # -------------------------- # Append unique VALUE onto the existing contents of VAR, assuming # entries are delimited by the first character of VALUE. For example: # # func_append_uniq options " --another-option option-argument" # # will only append to $options if " --another-option option-argument " # is not already present somewhere in $options already (note spaces at # each end implied by leading space in second argument). func_append_uniq () { $debug_cmd eval _G_current_value='`$ECHO $'$1'`' _G_delim=`expr "$2" : '\(.\)'` case $_G_delim$_G_current_value$_G_delim in *"$2$_G_delim"*) ;; *) func_append "$@" ;; esac } # func_arith TERM... # ------------------ # Set func_arith_result to the result of evaluating TERMs. test -z "$_G_HAVE_ARITH_OP" \ && (eval 'test 2 = $(( 1 + 1 ))') 2>/dev/null \ && _G_HAVE_ARITH_OP=yes if test yes = "$_G_HAVE_ARITH_OP"; then eval 'func_arith () { $debug_cmd func_arith_result=$(( $* )) }' else func_arith () { $debug_cmd func_arith_result=`expr "$@"` } fi # func_basename FILE # ------------------ # Set func_basename_result to FILE with everything up to and including # the last / stripped. if test yes = "$_G_HAVE_XSI_OPS"; then # If this shell supports suffix pattern removal, then use it to avoid # forking. Hide the definitions single quotes in case the shell chokes # on unsupported syntax... _b='func_basename_result=${1##*/}' _d='case $1 in */*) func_dirname_result=${1%/*}$2 ;; * ) func_dirname_result=$3 ;; esac' else # ...otherwise fall back to using sed. _b='func_basename_result=`$ECHO "$1" |$SED "$sed_basename"`' _d='func_dirname_result=`$ECHO "$1" |$SED "$sed_dirname"` if test "X$func_dirname_result" = "X$1"; then func_dirname_result=$3 else func_append func_dirname_result "$2" fi' fi eval 'func_basename () { $debug_cmd '"$_b"' }' # func_dirname FILE APPEND NONDIR_REPLACEMENT # ------------------------------------------- # Compute the dirname of FILE. If nonempty, add APPEND to the result, # otherwise set result to NONDIR_REPLACEMENT. eval 'func_dirname () { $debug_cmd '"$_d"' }' # func_dirname_and_basename FILE APPEND NONDIR_REPLACEMENT # -------------------------------------------------------- # Perform func_basename and func_dirname in a single function # call: # dirname: Compute the dirname of FILE. If nonempty, # add APPEND to the result, otherwise set result # to NONDIR_REPLACEMENT. # value returned in "$func_dirname_result" # basename: Compute filename of FILE. # value retuned in "$func_basename_result" # For efficiency, we do not delegate to the functions above but instead # duplicate the functionality here. eval 'func_dirname_and_basename () { $debug_cmd '"$_b"' '"$_d"' }' # func_echo ARG... # ---------------- # Echo program name prefixed message. func_echo () { $debug_cmd _G_message=$* func_echo_IFS=$IFS IFS=$nl for _G_line in $_G_message; do IFS=$func_echo_IFS $ECHO "$progname: $_G_line" done IFS=$func_echo_IFS } # func_echo_all ARG... # -------------------- # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "$*" } # func_echo_infix_1 INFIX ARG... # ------------------------------ # Echo program name, followed by INFIX on the first line, with any # additional lines not showing INFIX. func_echo_infix_1 () { $debug_cmd $require_term_colors _G_infix=$1; shift _G_indent=$_G_infix _G_prefix="$progname: $_G_infix: " _G_message=$* # Strip color escape sequences before counting printable length for _G_tc in "$tc_reset" "$tc_bold" "$tc_standout" "$tc_red" "$tc_green" "$tc_blue" "$tc_cyan" do test -n "$_G_tc" && { _G_esc_tc=`$ECHO "$_G_tc" | $SED "$sed_make_literal_regex"` _G_indent=`$ECHO "$_G_indent" | $SED "s|$_G_esc_tc||g"` } done _G_indent="$progname: "`echo "$_G_indent" | $SED 's|.| |g'`" " ## exclude from sc_prohibit_nested_quotes func_echo_infix_1_IFS=$IFS IFS=$nl for _G_line in $_G_message; do IFS=$func_echo_infix_1_IFS $ECHO "$_G_prefix$tc_bold$_G_line$tc_reset" >&2 _G_prefix=$_G_indent done IFS=$func_echo_infix_1_IFS } # func_error ARG... # ----------------- # Echo program name prefixed message to standard error. func_error () { $debug_cmd $require_term_colors func_echo_infix_1 " $tc_standout${tc_red}error$tc_reset" "$*" >&2 } # func_fatal_error ARG... # ----------------------- # Echo program name prefixed message to standard error, and exit. func_fatal_error () { $debug_cmd func_error "$*" exit $EXIT_FAILURE } # func_grep EXPRESSION FILENAME # ----------------------------- # Check whether EXPRESSION matches any line of FILENAME, without output. func_grep () { $debug_cmd $GREP "$1" "$2" >/dev/null 2>&1 } # func_len STRING # --------------- # Set func_len_result to the length of STRING. STRING may not # start with a hyphen. test -z "$_G_HAVE_XSI_OPS" \ && (eval 'x=a/b/c; test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ && _G_HAVE_XSI_OPS=yes if test yes = "$_G_HAVE_XSI_OPS"; then eval 'func_len () { $debug_cmd func_len_result=${#1} }' else func_len () { $debug_cmd func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len` } fi # func_mkdir_p DIRECTORY-PATH # --------------------------- # Make sure the entire path to DIRECTORY-PATH is available. func_mkdir_p () { $debug_cmd _G_directory_path=$1 _G_dir_list= if test -n "$_G_directory_path" && test : != "$opt_dry_run"; then # Protect directory names starting with '-' case $_G_directory_path in -*) _G_directory_path=./$_G_directory_path ;; esac # While some portion of DIR does not yet exist... while test ! -d "$_G_directory_path"; do # ...make a list in topmost first order. Use a colon delimited # list incase some portion of path contains whitespace. _G_dir_list=$_G_directory_path:$_G_dir_list # If the last portion added has no slash in it, the list is done case $_G_directory_path in */*) ;; *) break ;; esac # ...otherwise throw away the child directory and loop _G_directory_path=`$ECHO "$_G_directory_path" | $SED -e "$sed_dirname"` done _G_dir_list=`$ECHO "$_G_dir_list" | $SED 's|:*$||'` func_mkdir_p_IFS=$IFS; IFS=: for _G_dir in $_G_dir_list; do IFS=$func_mkdir_p_IFS # mkdir can fail with a 'File exist' error if two processes # try to create one of the directories concurrently. Don't # stop in that case! $MKDIR "$_G_dir" 2>/dev/null || : done IFS=$func_mkdir_p_IFS # Bail out if we (or some other process) failed to create a directory. test -d "$_G_directory_path" || \ func_fatal_error "Failed to create '$1'" fi } # func_mktempdir [BASENAME] # ------------------------- # Make a temporary directory that won't clash with other running # libtool processes, and avoids race conditions if possible. If # given, BASENAME is the basename for that directory. func_mktempdir () { $debug_cmd _G_template=${TMPDIR-/tmp}/${1-$progname} if test : = "$opt_dry_run"; then # Return a directory name, but don't create it in dry-run mode _G_tmpdir=$_G_template-$$ else # If mktemp works, use that first and foremost _G_tmpdir=`mktemp -d "$_G_template-XXXXXXXX" 2>/dev/null` if test ! -d "$_G_tmpdir"; then # Failing that, at least try and use $RANDOM to avoid a race _G_tmpdir=$_G_template-${RANDOM-0}$$ func_mktempdir_umask=`umask` umask 0077 $MKDIR "$_G_tmpdir" umask $func_mktempdir_umask fi # If we're not in dry-run mode, bomb out on failure test -d "$_G_tmpdir" || \ func_fatal_error "cannot create temporary directory '$_G_tmpdir'" fi $ECHO "$_G_tmpdir" } # func_normal_abspath PATH # ------------------------ # Remove doubled-up and trailing slashes, "." path components, # and cancel out any ".." path components in PATH after making # it an absolute path. func_normal_abspath () { $debug_cmd # These SED scripts presuppose an absolute path with a trailing slash. _G_pathcar='s|^/\([^/]*\).*$|\1|' _G_pathcdr='s|^/[^/]*||' _G_removedotparts=':dotsl s|/\./|/|g t dotsl s|/\.$|/|' _G_collapseslashes='s|/\{1,\}|/|g' _G_finalslash='s|/*$|/|' # Start from root dir and reassemble the path. func_normal_abspath_result= func_normal_abspath_tpath=$1 func_normal_abspath_altnamespace= case $func_normal_abspath_tpath in "") # Empty path, that just means $cwd. func_stripname '' '/' "`pwd`" func_normal_abspath_result=$func_stripname_result return ;; # The next three entries are used to spot a run of precisely # two leading slashes without using negated character classes; # we take advantage of case's first-match behaviour. ///*) # Unusual form of absolute path, do nothing. ;; //*) # Not necessarily an ordinary path; POSIX reserves leading '//' # and for example Cygwin uses it to access remote file shares # over CIFS/SMB, so we conserve a leading double slash if found. func_normal_abspath_altnamespace=/ ;; /*) # Absolute path, do nothing. ;; *) # Relative path, prepend $cwd. func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath ;; esac # Cancel out all the simple stuff to save iterations. We also want # the path to end with a slash for ease of parsing, so make sure # there is one (and only one) here. func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$_G_removedotparts" -e "$_G_collapseslashes" -e "$_G_finalslash"` while :; do # Processed it all yet? if test / = "$func_normal_abspath_tpath"; then # If we ascended to the root using ".." the result may be empty now. if test -z "$func_normal_abspath_result"; then func_normal_abspath_result=/ fi break fi func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$_G_pathcar"` func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ -e "$_G_pathcdr"` # Figure out what to do with it case $func_normal_abspath_tcomponent in "") # Trailing empty path component, ignore it. ;; ..) # Parent dir; strip last assembled component from result. func_dirname "$func_normal_abspath_result" func_normal_abspath_result=$func_dirname_result ;; *) # Actual path component, append it. func_append func_normal_abspath_result "/$func_normal_abspath_tcomponent" ;; esac done # Restore leading double-slash if one was found on entry. func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result } # func_notquiet ARG... # -------------------- # Echo program name prefixed message only when not in quiet mode. func_notquiet () { $debug_cmd $opt_quiet || func_echo ${1+"$@"} # A bug in bash halts the script if the last line of a function # fails when set -e is in force, so we need another command to # work around that: : } # func_relative_path SRCDIR DSTDIR # -------------------------------- # Set func_relative_path_result to the relative path from SRCDIR to DSTDIR. func_relative_path () { $debug_cmd func_relative_path_result= func_normal_abspath "$1" func_relative_path_tlibdir=$func_normal_abspath_result func_normal_abspath "$2" func_relative_path_tbindir=$func_normal_abspath_result # Ascend the tree starting from libdir while :; do # check if we have found a prefix of bindir case $func_relative_path_tbindir in $func_relative_path_tlibdir) # found an exact match func_relative_path_tcancelled= break ;; $func_relative_path_tlibdir*) # found a matching prefix func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" func_relative_path_tcancelled=$func_stripname_result if test -z "$func_relative_path_result"; then func_relative_path_result=. fi break ;; *) func_dirname $func_relative_path_tlibdir func_relative_path_tlibdir=$func_dirname_result if test -z "$func_relative_path_tlibdir"; then # Have to descend all the way to the root! func_relative_path_result=../$func_relative_path_result func_relative_path_tcancelled=$func_relative_path_tbindir break fi func_relative_path_result=../$func_relative_path_result ;; esac done # Now calculate path; take care to avoid doubling-up slashes. func_stripname '' '/' "$func_relative_path_result" func_relative_path_result=$func_stripname_result func_stripname '/' '/' "$func_relative_path_tcancelled" if test -n "$func_stripname_result"; then func_append func_relative_path_result "/$func_stripname_result" fi # Normalisation. If bindir is libdir, return '.' else relative path. if test -n "$func_relative_path_result"; then func_stripname './' '' "$func_relative_path_result" func_relative_path_result=$func_stripname_result fi test -n "$func_relative_path_result" || func_relative_path_result=. : } # func_quote_for_eval ARG... # -------------------------- # Aesthetically quote ARGs to be evaled later. # This function returns two values: # i) func_quote_for_eval_result # double-quoted, suitable for a subsequent eval # ii) func_quote_for_eval_unquoted_result # has all characters that are still active within double # quotes backslashified. func_quote_for_eval () { $debug_cmd func_quote_for_eval_unquoted_result= func_quote_for_eval_result= while test 0 -lt $#; do case $1 in *[\\\`\"\$]*) _G_unquoted_arg=`printf '%s\n' "$1" |$SED "$sed_quote_subst"` ;; *) _G_unquoted_arg=$1 ;; esac if test -n "$func_quote_for_eval_unquoted_result"; then func_append func_quote_for_eval_unquoted_result " $_G_unquoted_arg" else func_append func_quote_for_eval_unquoted_result "$_G_unquoted_arg" fi case $_G_unquoted_arg in # Double-quote args containing shell metacharacters to delay # word splitting, command substitution and variable expansion # for a subsequent eval. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") _G_quoted_arg=\"$_G_unquoted_arg\" ;; *) _G_quoted_arg=$_G_unquoted_arg ;; esac if test -n "$func_quote_for_eval_result"; then func_append func_quote_for_eval_result " $_G_quoted_arg" else func_append func_quote_for_eval_result "$_G_quoted_arg" fi shift done } # func_quote_for_expand ARG # ------------------------- # Aesthetically quote ARG to be evaled later; same as above, # but do not quote variable references. func_quote_for_expand () { $debug_cmd case $1 in *[\\\`\"]*) _G_arg=`$ECHO "$1" | $SED \ -e "$sed_double_quote_subst" -e "$sed_double_backslash"` ;; *) _G_arg=$1 ;; esac case $_G_arg in # Double-quote args containing shell metacharacters to delay # word splitting and command substitution for a subsequent eval. # Many Bourne shells cannot handle close brackets correctly # in scan sets, so we specify it separately. *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") _G_arg=\"$_G_arg\" ;; esac func_quote_for_expand_result=$_G_arg } # func_stripname PREFIX SUFFIX NAME # --------------------------------- # strip PREFIX and SUFFIX from NAME, and store in func_stripname_result. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). if test yes = "$_G_HAVE_XSI_OPS"; then eval 'func_stripname () { $debug_cmd # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are # positional parameters, so assign one to ordinary variable first. func_stripname_result=$3 func_stripname_result=${func_stripname_result#"$1"} func_stripname_result=${func_stripname_result%"$2"} }' else func_stripname () { $debug_cmd case $2 in .*) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%\\\\$2\$%%"`;; *) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%$2\$%%"`;; esac } fi # func_show_eval CMD [FAIL_EXP] # ----------------------------- # Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is # not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP # is given, then evaluate it. func_show_eval () { $debug_cmd _G_cmd=$1 _G_fail_exp=${2-':'} func_quote_for_expand "$_G_cmd" eval "func_notquiet $func_quote_for_expand_result" $opt_dry_run || { eval "$_G_cmd" _G_status=$? if test 0 -ne "$_G_status"; then eval "(exit $_G_status); $_G_fail_exp" fi } } # func_show_eval_locale CMD [FAIL_EXP] # ------------------------------------ # Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is # not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP # is given, then evaluate it. Use the saved locale for evaluation. func_show_eval_locale () { $debug_cmd _G_cmd=$1 _G_fail_exp=${2-':'} $opt_quiet || { func_quote_for_expand "$_G_cmd" eval "func_echo $func_quote_for_expand_result" } $opt_dry_run || { eval "$_G_user_locale $_G_cmd" _G_status=$? eval "$_G_safe_locale" if test 0 -ne "$_G_status"; then eval "(exit $_G_status); $_G_fail_exp" fi } } # func_tr_sh # ---------- # Turn $1 into a string suitable for a shell variable name. # Result is stored in $func_tr_sh_result. All characters # not in the set a-zA-Z0-9_ are replaced with '_'. Further, # if $1 begins with a digit, a '_' is prepended as well. func_tr_sh () { $debug_cmd case $1 in [0-9]* | *[!a-zA-Z0-9_]*) func_tr_sh_result=`$ECHO "$1" | $SED -e 's/^\([0-9]\)/_\1/' -e 's/[^a-zA-Z0-9_]/_/g'` ;; * ) func_tr_sh_result=$1 ;; esac } # func_verbose ARG... # ------------------- # Echo program name prefixed message in verbose mode only. func_verbose () { $debug_cmd $opt_verbose && func_echo "$*" : } # func_warn_and_continue ARG... # ----------------------------- # Echo program name prefixed warning message to standard error. func_warn_and_continue () { $debug_cmd $require_term_colors func_echo_infix_1 "${tc_red}warning$tc_reset" "$*" >&2 } # func_warning CATEGORY ARG... # ---------------------------- # Echo program name prefixed warning message to standard error. Warning # messages can be filtered according to CATEGORY, where this function # elides messages where CATEGORY is not listed in the global variable # 'opt_warning_types'. func_warning () { $debug_cmd # CATEGORY must be in the warning_categories list! case " $warning_categories " in *" $1 "*) ;; *) func_internal_error "invalid warning category '$1'" ;; esac _G_category=$1 shift case " $opt_warning_types " in *" $_G_category "*) $warning_func ${1+"$@"} ;; esac } # func_sort_ver VER1 VER2 # ----------------------- # 'sort -V' is not generally available. # Note this deviates from the version comparison in automake # in that it treats 1.5 < 1.5.0, and treats 1.4.4a < 1.4-p3a # but this should suffice as we won't be specifying old # version formats or redundant trailing .0 in bootstrap.conf. # If we did want full compatibility then we should probably # use m4_version_compare from autoconf. func_sort_ver () { $debug_cmd printf '%s\n%s\n' "$1" "$2" \ | sort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n -k 5,5n -k 6,6n -k 7,7n -k 8,8n -k 9,9n } # func_lt_ver PREV CURR # --------------------- # Return true if PREV and CURR are in the correct order according to # func_sort_ver, otherwise false. Use it like this: # # func_lt_ver "$prev_ver" "$proposed_ver" || func_fatal_error "..." func_lt_ver () { $debug_cmd test "x$1" = x`func_sort_ver "$1" "$2" | $SED 1q` } # Local variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" # time-stamp-time-zone: "UTC" # End: #! /bin/sh # Set a version string for this script. scriptversion=2014-01-07.03; # UTC # A portable, pluggable option parser for Bourne shell. # Written by Gary V. Vaughan, 2010 # Copyright (C) 2010-2015 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # Please report bugs or propose patches to gary@gnu.org. ## ------ ## ## Usage. ## ## ------ ## # This file is a library for parsing options in your shell scripts along # with assorted other useful supporting features that you can make use # of too. # # For the simplest scripts you might need only: # # #!/bin/sh # . relative/path/to/funclib.sh # . relative/path/to/options-parser # scriptversion=1.0 # func_options ${1+"$@"} # eval set dummy "$func_options_result"; shift # ...rest of your script... # # In order for the '--version' option to work, you will need to have a # suitably formatted comment like the one at the top of this file # starting with '# Written by ' and ending with '# warranty; '. # # For '-h' and '--help' to work, you will also need a one line # description of your script's purpose in a comment directly above the # '# Written by ' line, like the one at the top of this file. # # The default options also support '--debug', which will turn on shell # execution tracing (see the comment above debug_cmd below for another # use), and '--verbose' and the func_verbose function to allow your script # to display verbose messages only when your user has specified # '--verbose'. # # After sourcing this file, you can plug processing for additional # options by amending the variables from the 'Configuration' section # below, and following the instructions in the 'Option parsing' # section further down. ## -------------- ## ## Configuration. ## ## -------------- ## # You should override these variables in your script after sourcing this # file so that they reflect the customisations you have added to the # option parser. # The usage line for option parsing errors and the start of '-h' and # '--help' output messages. You can embed shell variables for delayed # expansion at the time the message is displayed, but you will need to # quote other shell meta-characters carefully to prevent them being # expanded when the contents are evaled. usage='$progpath [OPTION]...' # Short help message in response to '-h' and '--help'. Add to this or # override it after sourcing this library to reflect the full set of # options your script accepts. usage_message="\ --debug enable verbose shell tracing -W, --warnings=CATEGORY report the warnings falling in CATEGORY [all] -v, --verbose verbosely report processing --version print version information and exit -h, --help print short or long help message and exit " # Additional text appended to 'usage_message' in response to '--help'. long_help_message=" Warning categories include: 'all' show all warnings 'none' turn off all the warnings 'error' warnings are treated as fatal errors" # Help message printed before fatal option parsing errors. fatal_help="Try '\$progname --help' for more information." ## ------------------------- ## ## Hook function management. ## ## ------------------------- ## # This section contains functions for adding, removing, and running hooks # to the main code. A hook is just a named list of of function, that can # be run in order later on. # func_hookable FUNC_NAME # ----------------------- # Declare that FUNC_NAME will run hooks added with # 'func_add_hook FUNC_NAME ...'. func_hookable () { $debug_cmd func_append hookable_fns " $1" } # func_add_hook FUNC_NAME HOOK_FUNC # --------------------------------- # Request that FUNC_NAME call HOOK_FUNC before it returns. FUNC_NAME must # first have been declared "hookable" by a call to 'func_hookable'. func_add_hook () { $debug_cmd case " $hookable_fns " in *" $1 "*) ;; *) func_fatal_error "'$1' does not accept hook functions." ;; esac eval func_append ${1}_hooks '" $2"' } # func_remove_hook FUNC_NAME HOOK_FUNC # ------------------------------------ # Remove HOOK_FUNC from the list of functions called by FUNC_NAME. func_remove_hook () { $debug_cmd eval ${1}_hooks='`$ECHO "\$'$1'_hooks" |$SED "s| '$2'||"`' } # func_run_hooks FUNC_NAME [ARG]... # --------------------------------- # Run all hook functions registered to FUNC_NAME. # It is assumed that the list of hook functions contains nothing more # than a whitespace-delimited list of legal shell function names, and # no effort is wasted trying to catch shell meta-characters or preserve # whitespace. func_run_hooks () { $debug_cmd case " $hookable_fns " in *" $1 "*) ;; *) func_fatal_error "'$1' does not support hook funcions.n" ;; esac eval _G_hook_fns=\$$1_hooks; shift for _G_hook in $_G_hook_fns; do eval $_G_hook '"$@"' # store returned options list back into positional # parameters for next 'cmd' execution. eval _G_hook_result=\$${_G_hook}_result eval set dummy "$_G_hook_result"; shift done func_quote_for_eval ${1+"$@"} func_run_hooks_result=$func_quote_for_eval_result } ## --------------- ## ## Option parsing. ## ## --------------- ## # In order to add your own option parsing hooks, you must accept the # full positional parameter list in your hook function, remove any # options that you action, and then pass back the remaining unprocessed # options in '_result', escaped suitably for # 'eval'. Like this: # # my_options_prep () # { # $debug_cmd # # # Extend the existing usage message. # usage_message=$usage_message' # -s, --silent don'\''t print informational messages # ' # # func_quote_for_eval ${1+"$@"} # my_options_prep_result=$func_quote_for_eval_result # } # func_add_hook func_options_prep my_options_prep # # # my_silent_option () # { # $debug_cmd # # # Note that for efficiency, we parse as many options as we can # # recognise in a loop before passing the remainder back to the # # caller on the first unrecognised argument we encounter. # while test $# -gt 0; do # opt=$1; shift # case $opt in # --silent|-s) opt_silent=: ;; # # Separate non-argument short options: # -s*) func_split_short_opt "$_G_opt" # set dummy "$func_split_short_opt_name" \ # "-$func_split_short_opt_arg" ${1+"$@"} # shift # ;; # *) set dummy "$_G_opt" "$*"; shift; break ;; # esac # done # # func_quote_for_eval ${1+"$@"} # my_silent_option_result=$func_quote_for_eval_result # } # func_add_hook func_parse_options my_silent_option # # # my_option_validation () # { # $debug_cmd # # $opt_silent && $opt_verbose && func_fatal_help "\ # '--silent' and '--verbose' options are mutually exclusive." # # func_quote_for_eval ${1+"$@"} # my_option_validation_result=$func_quote_for_eval_result # } # func_add_hook func_validate_options my_option_validation # # You'll alse need to manually amend $usage_message to reflect the extra # options you parse. It's preferable to append if you can, so that # multiple option parsing hooks can be added safely. # func_options [ARG]... # --------------------- # All the functions called inside func_options are hookable. See the # individual implementations for details. func_hookable func_options func_options () { $debug_cmd func_options_prep ${1+"$@"} eval func_parse_options \ ${func_options_prep_result+"$func_options_prep_result"} eval func_validate_options \ ${func_parse_options_result+"$func_parse_options_result"} eval func_run_hooks func_options \ ${func_validate_options_result+"$func_validate_options_result"} # save modified positional parameters for caller func_options_result=$func_run_hooks_result } # func_options_prep [ARG]... # -------------------------- # All initialisations required before starting the option parse loop. # Note that when calling hook functions, we pass through the list of # positional parameters. If a hook function modifies that list, and # needs to propogate that back to rest of this script, then the complete # modified list must be put in 'func_run_hooks_result' before # returning. func_hookable func_options_prep func_options_prep () { $debug_cmd # Option defaults: opt_verbose=false opt_warning_types= func_run_hooks func_options_prep ${1+"$@"} # save modified positional parameters for caller func_options_prep_result=$func_run_hooks_result } # func_parse_options [ARG]... # --------------------------- # The main option parsing loop. func_hookable func_parse_options func_parse_options () { $debug_cmd func_parse_options_result= # this just eases exit handling while test $# -gt 0; do # Defer to hook functions for initial option parsing, so they # get priority in the event of reusing an option name. func_run_hooks func_parse_options ${1+"$@"} # Adjust func_parse_options positional parameters to match eval set dummy "$func_run_hooks_result"; shift # Break out of the loop if we already parsed every option. test $# -gt 0 || break _G_opt=$1 shift case $_G_opt in --debug|-x) debug_cmd='set -x' func_echo "enabling shell trace mode" $debug_cmd ;; --no-warnings|--no-warning|--no-warn) set dummy --warnings none ${1+"$@"} shift ;; --warnings|--warning|-W) test $# = 0 && func_missing_arg $_G_opt && break case " $warning_categories $1" in *" $1 "*) # trailing space prevents matching last $1 above func_append_uniq opt_warning_types " $1" ;; *all) opt_warning_types=$warning_categories ;; *none) opt_warning_types=none warning_func=: ;; *error) opt_warning_types=$warning_categories warning_func=func_fatal_error ;; *) func_fatal_error \ "unsupported warning category: '$1'" ;; esac shift ;; --verbose|-v) opt_verbose=: ;; --version) func_version ;; -\?|-h) func_usage ;; --help) func_help ;; # Separate optargs to long options (plugins may need this): --*=*) func_split_equals "$_G_opt" set dummy "$func_split_equals_lhs" \ "$func_split_equals_rhs" ${1+"$@"} shift ;; # Separate optargs to short options: -W*) func_split_short_opt "$_G_opt" set dummy "$func_split_short_opt_name" \ "$func_split_short_opt_arg" ${1+"$@"} shift ;; # Separate non-argument short options: -\?*|-h*|-v*|-x*) func_split_short_opt "$_G_opt" set dummy "$func_split_short_opt_name" \ "-$func_split_short_opt_arg" ${1+"$@"} shift ;; --) break ;; -*) func_fatal_help "unrecognised option: '$_G_opt'" ;; *) set dummy "$_G_opt" ${1+"$@"}; shift; break ;; esac done # save modified positional parameters for caller func_quote_for_eval ${1+"$@"} func_parse_options_result=$func_quote_for_eval_result } # func_validate_options [ARG]... # ------------------------------ # Perform any sanity checks on option settings and/or unconsumed # arguments. func_hookable func_validate_options func_validate_options () { $debug_cmd # Display all warnings if -W was not given. test -n "$opt_warning_types" || opt_warning_types=" $warning_categories" func_run_hooks func_validate_options ${1+"$@"} # Bail if the options were screwed! $exit_cmd $EXIT_FAILURE # save modified positional parameters for caller func_validate_options_result=$func_run_hooks_result } ## ----------------- ## ## Helper functions. ## ## ----------------- ## # This section contains the helper functions used by the rest of the # hookable option parser framework in ascii-betical order. # func_fatal_help ARG... # ---------------------- # Echo program name prefixed message to standard error, followed by # a help hint, and exit. func_fatal_help () { $debug_cmd eval \$ECHO \""Usage: $usage"\" eval \$ECHO \""$fatal_help"\" func_error ${1+"$@"} exit $EXIT_FAILURE } # func_help # --------- # Echo long help message to standard output and exit. func_help () { $debug_cmd func_usage_message $ECHO "$long_help_message" exit 0 } # func_missing_arg ARGNAME # ------------------------ # Echo program name prefixed message to standard error and set global # exit_cmd. func_missing_arg () { $debug_cmd func_error "Missing argument for '$1'." exit_cmd=exit } # func_split_equals STRING # ------------------------ # Set func_split_equals_lhs and func_split_equals_rhs shell variables after # splitting STRING at the '=' sign. test -z "$_G_HAVE_XSI_OPS" \ && (eval 'x=a/b/c; test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ && _G_HAVE_XSI_OPS=yes if test yes = "$_G_HAVE_XSI_OPS" then # This is an XSI compatible shell, allowing a faster implementation... eval 'func_split_equals () { $debug_cmd func_split_equals_lhs=${1%%=*} func_split_equals_rhs=${1#*=} test "x$func_split_equals_lhs" = "x$1" \ && func_split_equals_rhs= }' else # ...otherwise fall back to using expr, which is often a shell builtin. func_split_equals () { $debug_cmd func_split_equals_lhs=`expr "x$1" : 'x\([^=]*\)'` func_split_equals_rhs= test "x$func_split_equals_lhs" = "x$1" \ || func_split_equals_rhs=`expr "x$1" : 'x[^=]*=\(.*\)$'` } fi #func_split_equals # func_split_short_opt SHORTOPT # ----------------------------- # Set func_split_short_opt_name and func_split_short_opt_arg shell # variables after splitting SHORTOPT after the 2nd character. if test yes = "$_G_HAVE_XSI_OPS" then # This is an XSI compatible shell, allowing a faster implementation... eval 'func_split_short_opt () { $debug_cmd func_split_short_opt_arg=${1#??} func_split_short_opt_name=${1%"$func_split_short_opt_arg"} }' else # ...otherwise fall back to using expr, which is often a shell builtin. func_split_short_opt () { $debug_cmd func_split_short_opt_name=`expr "x$1" : 'x-\(.\)'` func_split_short_opt_arg=`expr "x$1" : 'x-.\(.*\)$'` } fi #func_split_short_opt # func_usage # ---------- # Echo short help message to standard output and exit. func_usage () { $debug_cmd func_usage_message $ECHO "Run '$progname --help |${PAGER-more}' for full usage" exit 0 } # func_usage_message # ------------------ # Echo short help message to standard output. func_usage_message () { $debug_cmd eval \$ECHO \""Usage: $usage"\" echo $SED -n 's|^# || /^Written by/{ x;p;x } h /^Written by/q' < "$progpath" echo eval \$ECHO \""$usage_message"\" } # func_version # ------------ # Echo version message to standard output and exit. func_version () { $debug_cmd printf '%s\n' "$progname $scriptversion" $SED -n ' /(C)/!b go :more /\./!{ N s|\n# | | b more } :go /^# Written by /,/# warranty; / { s|^# || s|^# *$|| s|\((C)\)[ 0-9,-]*[ ,-]\([1-9][0-9]* \)|\1 \2| p } /^# Written by / { s|^# || p } /^warranty; /q' < "$progpath" exit $? } # Local variables: # mode: shell-script # sh-indentation: 2 # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" # time-stamp-time-zone: "UTC" # End: # Set a version string. scriptversion='(GNU libtool) 2.4.6' # func_echo ARG... # ---------------- # Libtool also displays the current mode in messages, so override # funclib.sh func_echo with this custom definition. func_echo () { $debug_cmd _G_message=$* func_echo_IFS=$IFS IFS=$nl for _G_line in $_G_message; do IFS=$func_echo_IFS $ECHO "$progname${opt_mode+: $opt_mode}: $_G_line" done IFS=$func_echo_IFS } # func_warning ARG... # ------------------- # Libtool warnings are not categorized, so override funclib.sh # func_warning with this simpler definition. func_warning () { $debug_cmd $warning_func ${1+"$@"} } ## ---------------- ## ## Options parsing. ## ## ---------------- ## # Hook in the functions to make sure our own options are parsed during # the option parsing loop. usage='$progpath [OPTION]... [MODE-ARG]...' # Short help message in response to '-h'. usage_message="Options: --config show all configuration variables --debug enable verbose shell tracing -n, --dry-run display commands without modifying any files --features display basic configuration information and exit --mode=MODE use operation mode MODE --no-warnings equivalent to '-Wnone' --preserve-dup-deps don't remove duplicate dependency libraries --quiet, --silent don't print informational messages --tag=TAG use configuration variables from tag TAG -v, --verbose print more informational messages than default --version print version information -W, --warnings=CATEGORY report the warnings falling in CATEGORY [all] -h, --help, --help-all print short, long, or detailed help message " # Additional text appended to 'usage_message' in response to '--help'. func_help () { $debug_cmd func_usage_message $ECHO "$long_help_message MODE must be one of the following: clean remove files from the build directory compile compile a source file into a libtool object execute automatically set library path, then run a program finish complete the installation of libtool libraries install install libraries or executables link create a library or an executable uninstall remove libraries from an installed directory MODE-ARGS vary depending on the MODE. When passed as first option, '--mode=MODE' may be abbreviated as 'MODE' or a unique abbreviation of that. Try '$progname --help --mode=MODE' for a more detailed description of MODE. When reporting a bug, please describe a test case to reproduce it and include the following information: host-triplet: $host shell: $SHELL compiler: $LTCC compiler flags: $LTCFLAGS linker: $LD (gnu? $with_gnu_ld) version: $progname $scriptversion Debian-2.4.6-2 automake: `($AUTOMAKE --version) 2>/dev/null |$SED 1q` autoconf: `($AUTOCONF --version) 2>/dev/null |$SED 1q` Report bugs to . GNU libtool home page: . General help using GNU software: ." exit 0 } # func_lo2o OBJECT-NAME # --------------------- # Transform OBJECT-NAME from a '.lo' suffix to the platform specific # object suffix. lo2o=s/\\.lo\$/.$objext/ o2lo=s/\\.$objext\$/.lo/ if test yes = "$_G_HAVE_XSI_OPS"; then eval 'func_lo2o () { case $1 in *.lo) func_lo2o_result=${1%.lo}.$objext ;; * ) func_lo2o_result=$1 ;; esac }' # func_xform LIBOBJ-OR-SOURCE # --------------------------- # Transform LIBOBJ-OR-SOURCE from a '.o' or '.c' (or otherwise) # suffix to a '.lo' libtool-object suffix. eval 'func_xform () { func_xform_result=${1%.*}.lo }' else # ...otherwise fall back to using sed. func_lo2o () { func_lo2o_result=`$ECHO "$1" | $SED "$lo2o"` } func_xform () { func_xform_result=`$ECHO "$1" | $SED 's|\.[^.]*$|.lo|'` } fi # func_fatal_configuration ARG... # ------------------------------- # Echo program name prefixed message to standard error, followed by # a configuration failure hint, and exit. func_fatal_configuration () { func__fatal_error ${1+"$@"} \ "See the $PACKAGE documentation for more information." \ "Fatal configuration error." } # func_config # ----------- # Display the configuration for all the tags in this script. func_config () { re_begincf='^# ### BEGIN LIBTOOL' re_endcf='^# ### END LIBTOOL' # Default configuration. $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath" # Now print the configurations for the tags. for tagname in $taglist; do $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath" done exit $? } # func_features # ------------- # Display the features supported by this script. func_features () { echo "host: $host" if test yes = "$build_libtool_libs"; then echo "enable shared libraries" else echo "disable shared libraries" fi if test yes = "$build_old_libs"; then echo "enable static libraries" else echo "disable static libraries" fi exit $? } # func_enable_tag TAGNAME # ----------------------- # Verify that TAGNAME is valid, and either flag an error and exit, or # enable the TAGNAME tag. We also add TAGNAME to the global $taglist # variable here. func_enable_tag () { # Global variable: tagname=$1 re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" sed_extractcf=/$re_begincf/,/$re_endcf/p # Validate tagname. case $tagname in *[!-_A-Za-z0-9,/]*) func_fatal_error "invalid tag name: $tagname" ;; esac # Don't test for the "default" C tag, as we know it's # there but not specially marked. case $tagname in CC) ;; *) if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then taglist="$taglist $tagname" # Evaluate the configuration. Be careful to quote the path # and the sed script, to avoid splitting on whitespace, but # also don't use non-portable quotes within backquotes within # quotes we have to do it in 2 steps: extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` eval "$extractedcf" else func_error "ignoring unknown tag $tagname" fi ;; esac } # func_check_version_match # ------------------------ # Ensure that we are using m4 macros, and libtool script from the same # release of libtool. func_check_version_match () { if test "$package_revision" != "$macro_revision"; then if test "$VERSION" != "$macro_version"; then if test -z "$macro_version"; then cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from an older release. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF else cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, but the $progname: definition of this LT_INIT comes from $PACKAGE $macro_version. $progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION $progname: and run autoconf again. _LT_EOF fi else cat >&2 <<_LT_EOF $progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, $progname: but the definition of this LT_INIT comes from revision $macro_revision. $progname: You should recreate aclocal.m4 with macros from revision $package_revision $progname: of $PACKAGE $VERSION and run autoconf again. _LT_EOF fi exit $EXIT_MISMATCH fi } # libtool_options_prep [ARG]... # ----------------------------- # Preparation for options parsed by libtool. libtool_options_prep () { $debug_mode # Option defaults: opt_config=false opt_dlopen= opt_dry_run=false opt_help=false opt_mode= opt_preserve_dup_deps=false opt_quiet=false nonopt= preserve_args= # Shorthand for --mode=foo, only valid as the first argument case $1 in clean|clea|cle|cl) shift; set dummy --mode clean ${1+"$@"}; shift ;; compile|compil|compi|comp|com|co|c) shift; set dummy --mode compile ${1+"$@"}; shift ;; execute|execut|execu|exec|exe|ex|e) shift; set dummy --mode execute ${1+"$@"}; shift ;; finish|finis|fini|fin|fi|f) shift; set dummy --mode finish ${1+"$@"}; shift ;; install|instal|insta|inst|ins|in|i) shift; set dummy --mode install ${1+"$@"}; shift ;; link|lin|li|l) shift; set dummy --mode link ${1+"$@"}; shift ;; uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) shift; set dummy --mode uninstall ${1+"$@"}; shift ;; esac # Pass back the list of options. func_quote_for_eval ${1+"$@"} libtool_options_prep_result=$func_quote_for_eval_result } func_add_hook func_options_prep libtool_options_prep # libtool_parse_options [ARG]... # --------------------------------- # Provide handling for libtool specific options. libtool_parse_options () { $debug_cmd # Perform our own loop to consume as many options as possible in # each iteration. while test $# -gt 0; do _G_opt=$1 shift case $_G_opt in --dry-run|--dryrun|-n) opt_dry_run=: ;; --config) func_config ;; --dlopen|-dlopen) opt_dlopen="${opt_dlopen+$opt_dlopen }$1" shift ;; --preserve-dup-deps) opt_preserve_dup_deps=: ;; --features) func_features ;; --finish) set dummy --mode finish ${1+"$@"}; shift ;; --help) opt_help=: ;; --help-all) opt_help=': help-all' ;; --mode) test $# = 0 && func_missing_arg $_G_opt && break opt_mode=$1 case $1 in # Valid mode arguments: clean|compile|execute|finish|install|link|relink|uninstall) ;; # Catch anything else as an error *) func_error "invalid argument for $_G_opt" exit_cmd=exit break ;; esac shift ;; --no-silent|--no-quiet) opt_quiet=false func_append preserve_args " $_G_opt" ;; --no-warnings|--no-warning|--no-warn) opt_warning=false func_append preserve_args " $_G_opt" ;; --no-verbose) opt_verbose=false func_append preserve_args " $_G_opt" ;; --silent|--quiet) opt_quiet=: opt_verbose=false func_append preserve_args " $_G_opt" ;; --tag) test $# = 0 && func_missing_arg $_G_opt && break opt_tag=$1 func_append preserve_args " $_G_opt $1" func_enable_tag "$1" shift ;; --verbose|-v) opt_quiet=false opt_verbose=: func_append preserve_args " $_G_opt" ;; # An option not handled by this hook function: *) set dummy "$_G_opt" ${1+"$@"}; shift; break ;; esac done # save modified positional parameters for caller func_quote_for_eval ${1+"$@"} libtool_parse_options_result=$func_quote_for_eval_result } func_add_hook func_parse_options libtool_parse_options # libtool_validate_options [ARG]... # --------------------------------- # Perform any sanity checks on option settings and/or unconsumed # arguments. libtool_validate_options () { # save first non-option argument if test 0 -lt $#; then nonopt=$1 shift fi # preserve --debug test : = "$debug_cmd" || func_append preserve_args " --debug" case $host in # Solaris2 added to fix http://debbugs.gnu.org/cgi/bugreport.cgi?bug=16452 # see also: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=59788 *cygwin* | *mingw* | *pw32* | *cegcc* | *solaris2* | *os2*) # don't eliminate duplications in $postdeps and $predeps opt_duplicate_compiler_generated_deps=: ;; *) opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps ;; esac $opt_help || { # Sanity checks first: func_check_version_match test yes != "$build_libtool_libs" \ && test yes != "$build_old_libs" \ && func_fatal_configuration "not configured to build any kind of library" # Darwin sucks eval std_shrext=\"$shrext_cmds\" # Only execute mode is allowed to have -dlopen flags. if test -n "$opt_dlopen" && test execute != "$opt_mode"; then func_error "unrecognized option '-dlopen'" $ECHO "$help" 1>&2 exit $EXIT_FAILURE fi # Change the help message to a mode-specific one. generic_help=$help help="Try '$progname --help --mode=$opt_mode' for more information." } # Pass back the unparsed argument list func_quote_for_eval ${1+"$@"} libtool_validate_options_result=$func_quote_for_eval_result } func_add_hook func_validate_options libtool_validate_options # Process options as early as possible so that --help and --version # can return quickly. func_options ${1+"$@"} eval set dummy "$func_options_result"; shift ## ----------- ## ## Main. ## ## ----------- ## magic='%%%MAGIC variable%%%' magic_exe='%%%MAGIC EXE variable%%%' # Global variables. extracted_archives= extracted_serial=0 # If this variable is set in any of the actions, the command in it # will be execed at the end. This prevents here-documents from being # left over by shells. exec_cmd= # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $1 _LTECHO_EOF' } # func_generated_by_libtool # True iff stdin has been generated by Libtool. This function is only # a basic sanity check; it will hardly flush out determined imposters. func_generated_by_libtool_p () { $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 } # func_lalib_p file # True iff FILE is a libtool '.la' library or '.lo' object file. # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_lalib_p () { test -f "$1" && $SED -e 4q "$1" 2>/dev/null | func_generated_by_libtool_p } # func_lalib_unsafe_p file # True iff FILE is a libtool '.la' library or '.lo' object file. # This function implements the same check as func_lalib_p without # resorting to external programs. To this end, it redirects stdin and # closes it afterwards, without saving the original file descriptor. # As a safety measure, use it only where a negative result would be # fatal anyway. Works if 'file' does not exist. func_lalib_unsafe_p () { lalib_p=no if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then for lalib_p_l in 1 2 3 4 do read lalib_p_line case $lalib_p_line in \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; esac done exec 0<&5 5<&- fi test yes = "$lalib_p" } # func_ltwrapper_script_p file # True iff FILE is a libtool wrapper script # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_script_p () { test -f "$1" && $lt_truncate_bin < "$1" 2>/dev/null | func_generated_by_libtool_p } # func_ltwrapper_executable_p file # True iff FILE is a libtool wrapper executable # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_executable_p () { func_ltwrapper_exec_suffix= case $1 in *.exe) ;; *) func_ltwrapper_exec_suffix=.exe ;; esac $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 } # func_ltwrapper_scriptname file # Assumes file is an ltwrapper_executable # uses $file to determine the appropriate filename for a # temporary ltwrapper_script. func_ltwrapper_scriptname () { func_dirname_and_basename "$1" "" "." func_stripname '' '.exe' "$func_basename_result" func_ltwrapper_scriptname_result=$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper } # func_ltwrapper_p file # True iff FILE is a libtool wrapper script or wrapper executable # This function is only a basic sanity check; it will hardly flush out # determined imposters. func_ltwrapper_p () { func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" } # func_execute_cmds commands fail_cmd # Execute tilde-delimited COMMANDS. # If FAIL_CMD is given, eval that upon failure. # FAIL_CMD may read-access the current command in variable CMD! func_execute_cmds () { $debug_cmd save_ifs=$IFS; IFS='~' for cmd in $1; do IFS=$sp$nl eval cmd=\"$cmd\" IFS=$save_ifs func_show_eval "$cmd" "${2-:}" done IFS=$save_ifs } # func_source file # Source FILE, adding directory component if necessary. # Note that it is not necessary on cygwin/mingw to append a dot to # FILE even if both FILE and FILE.exe exist: automatic-append-.exe # behavior happens only for exec(3), not for open(2)! Also, sourcing # 'FILE.' does not work on cygwin managed mounts. func_source () { $debug_cmd case $1 in */* | *\\*) . "$1" ;; *) . "./$1" ;; esac } # func_resolve_sysroot PATH # Replace a leading = in PATH with a sysroot. Store the result into # func_resolve_sysroot_result func_resolve_sysroot () { func_resolve_sysroot_result=$1 case $func_resolve_sysroot_result in =*) func_stripname '=' '' "$func_resolve_sysroot_result" func_resolve_sysroot_result=$lt_sysroot$func_stripname_result ;; esac } # func_replace_sysroot PATH # If PATH begins with the sysroot, replace it with = and # store the result into func_replace_sysroot_result. func_replace_sysroot () { case $lt_sysroot:$1 in ?*:"$lt_sysroot"*) func_stripname "$lt_sysroot" '' "$1" func_replace_sysroot_result='='$func_stripname_result ;; *) # Including no sysroot. func_replace_sysroot_result=$1 ;; esac } # func_infer_tag arg # Infer tagged configuration to use if any are available and # if one wasn't chosen via the "--tag" command line option. # Only attempt this if the compiler in the base compile # command doesn't match the default compiler. # arg is usually of the form 'gcc ...' func_infer_tag () { $debug_cmd if test -n "$available_tags" && test -z "$tagname"; then CC_quoted= for arg in $CC; do func_append_quoted CC_quoted "$arg" done CC_expanded=`func_echo_all $CC` CC_quoted_expanded=`func_echo_all $CC_quoted` case $@ in # Blanks in the command may have been stripped by the calling shell, # but not from the CC environment variable when configure was run. " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; # Blanks at the start of $base_compile will cause this to fail # if we don't check for them as well. *) for z in $available_tags; do if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then # Evaluate the configuration. eval "`$SED -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" CC_quoted= for arg in $CC; do # Double-quote args containing other shell metacharacters. func_append_quoted CC_quoted "$arg" done CC_expanded=`func_echo_all $CC` CC_quoted_expanded=`func_echo_all $CC_quoted` case "$@ " in " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) # The compiler in the base compile command matches # the one in the tagged configuration. # Assume this is the tagged configuration we want. tagname=$z break ;; esac fi done # If $tagname still isn't set, then no tagged configuration # was found and let the user know that the "--tag" command # line option must be used. if test -z "$tagname"; then func_echo "unable to infer tagged configuration" func_fatal_error "specify a tag with '--tag'" # else # func_verbose "using $tagname tagged configuration" fi ;; esac fi } # func_write_libtool_object output_name pic_name nonpic_name # Create a libtool object file (analogous to a ".la" file), # but don't create it if we're doing a dry run. func_write_libtool_object () { write_libobj=$1 if test yes = "$build_libtool_libs"; then write_lobj=\'$2\' else write_lobj=none fi if test yes = "$build_old_libs"; then write_oldobj=\'$3\' else write_oldobj=none fi $opt_dry_run || { cat >${write_libobj}T </dev/null` if test "$?" -eq 0 && test -n "$func_convert_core_file_wine_to_w32_tmp"; then func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | $SED -e "$sed_naive_backslashify"` else func_convert_core_file_wine_to_w32_result= fi fi } # end: func_convert_core_file_wine_to_w32 # func_convert_core_path_wine_to_w32 ARG # Helper function used by path conversion functions when $build is *nix, and # $host is mingw, cygwin, or some other w32 environment. Relies on a correctly # configured wine environment available, with the winepath program in $build's # $PATH. Assumes ARG has no leading or trailing path separator characters. # # ARG is path to be converted from $build format to win32. # Result is available in $func_convert_core_path_wine_to_w32_result. # Unconvertible file (directory) names in ARG are skipped; if no directory names # are convertible, then the result may be empty. func_convert_core_path_wine_to_w32 () { $debug_cmd # unfortunately, winepath doesn't convert paths, only file names func_convert_core_path_wine_to_w32_result= if test -n "$1"; then oldIFS=$IFS IFS=: for func_convert_core_path_wine_to_w32_f in $1; do IFS=$oldIFS func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" if test -n "$func_convert_core_file_wine_to_w32_result"; then if test -z "$func_convert_core_path_wine_to_w32_result"; then func_convert_core_path_wine_to_w32_result=$func_convert_core_file_wine_to_w32_result else func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" fi fi done IFS=$oldIFS fi } # end: func_convert_core_path_wine_to_w32 # func_cygpath ARGS... # Wrapper around calling the cygpath program via LT_CYGPATH. This is used when # when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2) # $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or # (2), returns the Cygwin file name or path in func_cygpath_result (input # file name or path is assumed to be in w32 format, as previously converted # from $build's *nix or MSYS format). In case (3), returns the w32 file name # or path in func_cygpath_result (input file name or path is assumed to be in # Cygwin format). Returns an empty string on error. # # ARGS are passed to cygpath, with the last one being the file name or path to # be converted. # # Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH # environment variable; do not put it in $PATH. func_cygpath () { $debug_cmd if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` if test "$?" -ne 0; then # on failure, ensure result is empty func_cygpath_result= fi else func_cygpath_result= func_error "LT_CYGPATH is empty or specifies non-existent file: '$LT_CYGPATH'" fi } #end: func_cygpath # func_convert_core_msys_to_w32 ARG # Convert file name or path ARG from MSYS format to w32 format. Return # result in func_convert_core_msys_to_w32_result. func_convert_core_msys_to_w32 () { $debug_cmd # awkward: cmd appends spaces to result func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | $SED -e 's/[ ]*$//' -e "$sed_naive_backslashify"` } #end: func_convert_core_msys_to_w32 # func_convert_file_check ARG1 ARG2 # Verify that ARG1 (a file name in $build format) was converted to $host # format in ARG2. Otherwise, emit an error message, but continue (resetting # func_to_host_file_result to ARG1). func_convert_file_check () { $debug_cmd if test -z "$2" && test -n "$1"; then func_error "Could not determine host file name corresponding to" func_error " '$1'" func_error "Continuing, but uninstalled executables may not work." # Fallback: func_to_host_file_result=$1 fi } # end func_convert_file_check # func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH # Verify that FROM_PATH (a path in $build format) was converted to $host # format in TO_PATH. Otherwise, emit an error message, but continue, resetting # func_to_host_file_result to a simplistic fallback value (see below). func_convert_path_check () { $debug_cmd if test -z "$4" && test -n "$3"; then func_error "Could not determine the host path corresponding to" func_error " '$3'" func_error "Continuing, but uninstalled executables may not work." # Fallback. This is a deliberately simplistic "conversion" and # should not be "improved". See libtool.info. if test "x$1" != "x$2"; then lt_replace_pathsep_chars="s|$1|$2|g" func_to_host_path_result=`echo "$3" | $SED -e "$lt_replace_pathsep_chars"` else func_to_host_path_result=$3 fi fi } # end func_convert_path_check # func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG # Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT # and appending REPL if ORIG matches BACKPAT. func_convert_path_front_back_pathsep () { $debug_cmd case $4 in $1 ) func_to_host_path_result=$3$func_to_host_path_result ;; esac case $4 in $2 ) func_append func_to_host_path_result "$3" ;; esac } # end func_convert_path_front_back_pathsep ################################################## # $build to $host FILE NAME CONVERSION FUNCTIONS # ################################################## # invoked via '$to_host_file_cmd ARG' # # In each case, ARG is the path to be converted from $build to $host format. # Result will be available in $func_to_host_file_result. # func_to_host_file ARG # Converts the file name ARG from $build format to $host format. Return result # in func_to_host_file_result. func_to_host_file () { $debug_cmd $to_host_file_cmd "$1" } # end func_to_host_file # func_to_tool_file ARG LAZY # converts the file name ARG from $build format to toolchain format. Return # result in func_to_tool_file_result. If the conversion in use is listed # in (the comma separated) LAZY, no conversion takes place. func_to_tool_file () { $debug_cmd case ,$2, in *,"$to_tool_file_cmd",*) func_to_tool_file_result=$1 ;; *) $to_tool_file_cmd "$1" func_to_tool_file_result=$func_to_host_file_result ;; esac } # end func_to_tool_file # func_convert_file_noop ARG # Copy ARG to func_to_host_file_result. func_convert_file_noop () { func_to_host_file_result=$1 } # end func_convert_file_noop # func_convert_file_msys_to_w32 ARG # Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic # conversion to w32 is not available inside the cwrapper. Returns result in # func_to_host_file_result. func_convert_file_msys_to_w32 () { $debug_cmd func_to_host_file_result=$1 if test -n "$1"; then func_convert_core_msys_to_w32 "$1" func_to_host_file_result=$func_convert_core_msys_to_w32_result fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_msys_to_w32 # func_convert_file_cygwin_to_w32 ARG # Convert file name ARG from Cygwin to w32 format. Returns result in # func_to_host_file_result. func_convert_file_cygwin_to_w32 () { $debug_cmd func_to_host_file_result=$1 if test -n "$1"; then # because $build is cygwin, we call "the" cygpath in $PATH; no need to use # LT_CYGPATH in this case. func_to_host_file_result=`cygpath -m "$1"` fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_cygwin_to_w32 # func_convert_file_nix_to_w32 ARG # Convert file name ARG from *nix to w32 format. Requires a wine environment # and a working winepath. Returns result in func_to_host_file_result. func_convert_file_nix_to_w32 () { $debug_cmd func_to_host_file_result=$1 if test -n "$1"; then func_convert_core_file_wine_to_w32 "$1" func_to_host_file_result=$func_convert_core_file_wine_to_w32_result fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_nix_to_w32 # func_convert_file_msys_to_cygwin ARG # Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. # Returns result in func_to_host_file_result. func_convert_file_msys_to_cygwin () { $debug_cmd func_to_host_file_result=$1 if test -n "$1"; then func_convert_core_msys_to_w32 "$1" func_cygpath -u "$func_convert_core_msys_to_w32_result" func_to_host_file_result=$func_cygpath_result fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_msys_to_cygwin # func_convert_file_nix_to_cygwin ARG # Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed # in a wine environment, working winepath, and LT_CYGPATH set. Returns result # in func_to_host_file_result. func_convert_file_nix_to_cygwin () { $debug_cmd func_to_host_file_result=$1 if test -n "$1"; then # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. func_convert_core_file_wine_to_w32 "$1" func_cygpath -u "$func_convert_core_file_wine_to_w32_result" func_to_host_file_result=$func_cygpath_result fi func_convert_file_check "$1" "$func_to_host_file_result" } # end func_convert_file_nix_to_cygwin ############################################# # $build to $host PATH CONVERSION FUNCTIONS # ############################################# # invoked via '$to_host_path_cmd ARG' # # In each case, ARG is the path to be converted from $build to $host format. # The result will be available in $func_to_host_path_result. # # Path separators are also converted from $build format to $host format. If # ARG begins or ends with a path separator character, it is preserved (but # converted to $host format) on output. # # All path conversion functions are named using the following convention: # file name conversion function : func_convert_file_X_to_Y () # path conversion function : func_convert_path_X_to_Y () # where, for any given $build/$host combination the 'X_to_Y' value is the # same. If conversion functions are added for new $build/$host combinations, # the two new functions must follow this pattern, or func_init_to_host_path_cmd # will break. # func_init_to_host_path_cmd # Ensures that function "pointer" variable $to_host_path_cmd is set to the # appropriate value, based on the value of $to_host_file_cmd. to_host_path_cmd= func_init_to_host_path_cmd () { $debug_cmd if test -z "$to_host_path_cmd"; then func_stripname 'func_convert_file_' '' "$to_host_file_cmd" to_host_path_cmd=func_convert_path_$func_stripname_result fi } # func_to_host_path ARG # Converts the path ARG from $build format to $host format. Return result # in func_to_host_path_result. func_to_host_path () { $debug_cmd func_init_to_host_path_cmd $to_host_path_cmd "$1" } # end func_to_host_path # func_convert_path_noop ARG # Copy ARG to func_to_host_path_result. func_convert_path_noop () { func_to_host_path_result=$1 } # end func_convert_path_noop # func_convert_path_msys_to_w32 ARG # Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic # conversion to w32 is not available inside the cwrapper. Returns result in # func_to_host_path_result. func_convert_path_msys_to_w32 () { $debug_cmd func_to_host_path_result=$1 if test -n "$1"; then # Remove leading and trailing path separator characters from ARG. MSYS # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; # and winepath ignores them completely. func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" func_to_host_path_result=$func_convert_core_msys_to_w32_result func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_msys_to_w32 # func_convert_path_cygwin_to_w32 ARG # Convert path ARG from Cygwin to w32 format. Returns result in # func_to_host_file_result. func_convert_path_cygwin_to_w32 () { $debug_cmd func_to_host_path_result=$1 if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"` func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_cygwin_to_w32 # func_convert_path_nix_to_w32 ARG # Convert path ARG from *nix to w32 format. Requires a wine environment and # a working winepath. Returns result in func_to_host_file_result. func_convert_path_nix_to_w32 () { $debug_cmd func_to_host_path_result=$1 if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" func_to_host_path_result=$func_convert_core_path_wine_to_w32_result func_convert_path_check : ";" \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" fi } # end func_convert_path_nix_to_w32 # func_convert_path_msys_to_cygwin ARG # Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. # Returns result in func_to_host_file_result. func_convert_path_msys_to_cygwin () { $debug_cmd func_to_host_path_result=$1 if test -n "$1"; then # See func_convert_path_msys_to_w32: func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" func_cygpath -u -p "$func_convert_core_msys_to_w32_result" func_to_host_path_result=$func_cygpath_result func_convert_path_check : : \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" : "$1" fi } # end func_convert_path_msys_to_cygwin # func_convert_path_nix_to_cygwin ARG # Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a # a wine environment, working winepath, and LT_CYGPATH set. Returns result in # func_to_host_file_result. func_convert_path_nix_to_cygwin () { $debug_cmd func_to_host_path_result=$1 if test -n "$1"; then # Remove leading and trailing path separator characters from # ARG. msys behavior is inconsistent here, cygpath turns them # into '.;' and ';.', and winepath ignores them completely. func_stripname : : "$1" func_to_host_path_tmp1=$func_stripname_result func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" func_to_host_path_result=$func_cygpath_result func_convert_path_check : : \ "$func_to_host_path_tmp1" "$func_to_host_path_result" func_convert_path_front_back_pathsep ":*" "*:" : "$1" fi } # end func_convert_path_nix_to_cygwin # func_dll_def_p FILE # True iff FILE is a Windows DLL '.def' file. # Keep in sync with _LT_DLL_DEF_P in libtool.m4 func_dll_def_p () { $debug_cmd func_dll_def_p_tmp=`$SED -n \ -e 's/^[ ]*//' \ -e '/^\(;.*\)*$/d' \ -e 's/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p' \ -e q \ "$1"` test DEF = "$func_dll_def_p_tmp" } # func_mode_compile arg... func_mode_compile () { $debug_cmd # Get the compilation command and the source file. base_compile= srcfile=$nonopt # always keep a non-empty value in "srcfile" suppress_opt=yes suppress_output= arg_mode=normal libobj= later= pie_flag= for arg do case $arg_mode in arg ) # do not "continue". Instead, add this to base_compile lastarg=$arg arg_mode=normal ;; target ) libobj=$arg arg_mode=normal continue ;; normal ) # Accept any command-line options. case $arg in -o) test -n "$libobj" && \ func_fatal_error "you cannot specify '-o' more than once" arg_mode=target continue ;; -pie | -fpie | -fPIE) func_append pie_flag " $arg" continue ;; -shared | -static | -prefer-pic | -prefer-non-pic) func_append later " $arg" continue ;; -no-suppress) suppress_opt=no continue ;; -Xcompiler) arg_mode=arg # the next one goes into the "base_compile" arg list continue # The current "srcfile" will either be retained or ;; # replaced later. I would guess that would be a bug. -Wc,*) func_stripname '-Wc,' '' "$arg" args=$func_stripname_result lastarg= save_ifs=$IFS; IFS=, for arg in $args; do IFS=$save_ifs func_append_quoted lastarg "$arg" done IFS=$save_ifs func_stripname ' ' '' "$lastarg" lastarg=$func_stripname_result # Add the arguments to base_compile. func_append base_compile " $lastarg" continue ;; *) # Accept the current argument as the source file. # The previous "srcfile" becomes the current argument. # lastarg=$srcfile srcfile=$arg ;; esac # case $arg ;; esac # case $arg_mode # Aesthetically quote the previous argument. func_append_quoted base_compile "$lastarg" done # for arg case $arg_mode in arg) func_fatal_error "you must specify an argument for -Xcompile" ;; target) func_fatal_error "you must specify a target with '-o'" ;; *) # Get the name of the library object. test -z "$libobj" && { func_basename "$srcfile" libobj=$func_basename_result } ;; esac # Recognize several different file suffixes. # If the user specifies -o file.o, it is replaced with file.lo case $libobj in *.[cCFSifmso] | \ *.ada | *.adb | *.ads | *.asm | \ *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \ *.[fF][09]? | *.for | *.java | *.go | *.obj | *.sx | *.cu | *.cup) func_xform "$libobj" libobj=$func_xform_result ;; esac case $libobj in *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; *) func_fatal_error "cannot determine name of library object from '$libobj'" ;; esac func_infer_tag $base_compile for arg in $later; do case $arg in -shared) test yes = "$build_libtool_libs" \ || func_fatal_configuration "cannot build a shared library" build_old_libs=no continue ;; -static) build_libtool_libs=no build_old_libs=yes continue ;; -prefer-pic) pic_mode=yes continue ;; -prefer-non-pic) pic_mode=no continue ;; esac done func_quote_for_eval "$libobj" test "X$libobj" != "X$func_quote_for_eval_result" \ && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ && func_warning "libobj name '$libobj' may not contain shell special characters." func_dirname_and_basename "$obj" "/" "" objname=$func_basename_result xdir=$func_dirname_result lobj=$xdir$objdir/$objname test -z "$base_compile" && \ func_fatal_help "you must specify a compilation command" # Delete any leftover library objects. if test yes = "$build_old_libs"; then removelist="$obj $lobj $libobj ${libobj}T" else removelist="$lobj $libobj ${libobj}T" fi # On Cygwin there's no "real" PIC flag so we must build both object types case $host_os in cygwin* | mingw* | pw32* | os2* | cegcc*) pic_mode=default ;; esac if test no = "$pic_mode" && test pass_all != "$deplibs_check_method"; then # non-PIC code in shared libraries is not supported pic_mode=default fi # Calculate the filename of the output object if compiler does # not support -o with -c if test no = "$compiler_c_o"; then output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.$objext lockfile=$output_obj.lock else output_obj= need_locks=no lockfile= fi # Lock this critical section if it is needed # We use this script file to make the link, it avoids creating a new file if test yes = "$need_locks"; then until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" sleep 2 done elif test warn = "$need_locks"; then if test -f "$lockfile"; then $ECHO "\ *** ERROR, $lockfile exists and contains: `cat $lockfile 2>/dev/null` This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support '-c' and '-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi func_append removelist " $output_obj" $ECHO "$srcfile" > "$lockfile" fi $opt_dry_run || $RM $removelist func_append removelist " $lockfile" trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 srcfile=$func_to_tool_file_result func_quote_for_eval "$srcfile" qsrcfile=$func_quote_for_eval_result # Only build a PIC object if we are building libtool libraries. if test yes = "$build_libtool_libs"; then # Without this assignment, base_compile gets emptied. fbsd_hideous_sh_bug=$base_compile if test no != "$pic_mode"; then command="$base_compile $qsrcfile $pic_flag" else # Don't build PIC code command="$base_compile $qsrcfile" fi func_mkdir_p "$xdir$objdir" if test -z "$output_obj"; then # Place PIC objects in $objdir func_append command " -o $lobj" fi func_show_eval_locale "$command" \ 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' if test warn = "$need_locks" && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support '-c' and '-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi # Just move the object if needed, then go on to compile the next one if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then func_show_eval '$MV "$output_obj" "$lobj"' \ 'error=$?; $opt_dry_run || $RM $removelist; exit $error' fi # Allow error messages only from the first compilation. if test yes = "$suppress_opt"; then suppress_output=' >/dev/null 2>&1' fi fi # Only build a position-dependent object if we build old libraries. if test yes = "$build_old_libs"; then if test yes != "$pic_mode"; then # Don't build PIC code command="$base_compile $qsrcfile$pie_flag" else command="$base_compile $qsrcfile $pic_flag" fi if test yes = "$compiler_c_o"; then func_append command " -o $obj" fi # Suppress compiler output if we already did a PIC compilation. func_append command "$suppress_output" func_show_eval_locale "$command" \ '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' if test warn = "$need_locks" && test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then $ECHO "\ *** ERROR, $lockfile contains: `cat $lockfile 2>/dev/null` but it should contain: $srcfile This indicates that another process is trying to use the same temporary object file, and libtool could not work around it because your compiler does not support '-c' and '-o' together. If you repeat this compilation, it may succeed, by chance, but you had better avoid parallel builds (make -j) in this platform, or get a better compiler." $opt_dry_run || $RM $removelist exit $EXIT_FAILURE fi # Just move the object if needed if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then func_show_eval '$MV "$output_obj" "$obj"' \ 'error=$?; $opt_dry_run || $RM $removelist; exit $error' fi fi $opt_dry_run || { func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" # Unlock the critical section if it was locked if test no != "$need_locks"; then removelist=$lockfile $RM "$lockfile" fi } exit $EXIT_SUCCESS } $opt_help || { test compile = "$opt_mode" && func_mode_compile ${1+"$@"} } func_mode_help () { # We need to display help for each of the modes. case $opt_mode in "") # Generic help is extracted from the usage comments # at the start of this file. func_help ;; clean) $ECHO \ "Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... Remove files from the build directory. RM is the name of the program to use to delete files associated with each FILE (typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed to RM. If FILE is a libtool library, object or program, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; compile) $ECHO \ "Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE Compile a source file into a libtool library object. This mode accepts the following additional options: -o OUTPUT-FILE set the output file name to OUTPUT-FILE -no-suppress do not suppress compiler output for multiple passes -prefer-pic try to build PIC objects only -prefer-non-pic try to build non-PIC objects only -shared do not build a '.o' file suitable for static linking -static only build a '.o' file suitable for static linking -Wc,FLAG pass FLAG directly to the compiler COMPILE-COMMAND is a command to be used in creating a 'standard' object file from the given SOURCEFILE. The output file name is determined by removing the directory component from SOURCEFILE, then substituting the C source code suffix '.c' with the library object suffix, '.lo'." ;; execute) $ECHO \ "Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... Automatically set library path, then run a program. This mode accepts the following additional options: -dlopen FILE add the directory containing FILE to the library path This mode sets the library path environment variable according to '-dlopen' flags. If any of the ARGS are libtool executable wrappers, then they are translated into their corresponding uninstalled binary, and any of their required library directories are added to the library path. Then, COMMAND is executed, with ARGS as arguments." ;; finish) $ECHO \ "Usage: $progname [OPTION]... --mode=finish [LIBDIR]... Complete the installation of libtool libraries. Each LIBDIR is a directory that contains libtool libraries. The commands that this mode executes may require superuser privileges. Use the '--dry-run' option if you just want to see what would be executed." ;; install) $ECHO \ "Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... Install executables or libraries. INSTALL-COMMAND is the installation command. The first component should be either the 'install' or 'cp' program. The following components of INSTALL-COMMAND are treated specially: -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation The rest of the components are interpreted as arguments to that command (only BSD-compatible install options are recognized)." ;; link) $ECHO \ "Usage: $progname [OPTION]... --mode=link LINK-COMMAND... Link object files or libraries together to form another library, or to create an executable program. LINK-COMMAND is a command using the C compiler that you would use to create a program from several object files. The following components of LINK-COMMAND are treated specially: -all-static do not do any dynamic linking at all -avoid-version do not add a version suffix if possible -bindir BINDIR specify path to binaries directory (for systems where libraries must be found in the PATH setting at runtime) -dlopen FILE '-dlpreopen' FILE if it cannot be dlopened at runtime -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) -export-symbols SYMFILE try to export only the symbols listed in SYMFILE -export-symbols-regex REGEX try to export only the symbols matching REGEX -LLIBDIR search LIBDIR for required installed libraries -lNAME OUTPUT-FILE requires the installed library libNAME -module build a library that can dlopened -no-fast-install disable the fast-install mode -no-install link a not-installable executable -no-undefined declare that a library does not refer to external symbols -o OUTPUT-FILE create OUTPUT-FILE from the specified objects -objectlist FILE use a list of object files found in FILE to specify objects -os2dllname NAME force a short DLL name on OS/2 (no effect on other OSes) -precious-files-regex REGEX don't remove output files matching REGEX -release RELEASE specify package release information -rpath LIBDIR the created library will eventually be installed in LIBDIR -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries -shared only do dynamic linking of libtool libraries -shrext SUFFIX override the standard shared library file extension -static do not do any dynamic linking of uninstalled libtool libraries -static-libtool-libs do not do any dynamic linking of libtool libraries -version-info CURRENT[:REVISION[:AGE]] specify library version info [each variable defaults to 0] -weak LIBNAME declare that the target provides the LIBNAME interface -Wc,FLAG -Xcompiler FLAG pass linker-specific FLAG directly to the compiler -Wl,FLAG -Xlinker FLAG pass linker-specific FLAG directly to the linker -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) All other options (arguments beginning with '-') are ignored. Every other argument is treated as a filename. Files ending in '.la' are treated as uninstalled libtool libraries, other files are standard or library object files. If the OUTPUT-FILE ends in '.la', then a libtool library is created, only library objects ('.lo' files) may be specified, and '-rpath' is required, except when creating a convenience library. If OUTPUT-FILE ends in '.a' or '.lib', then a standard library is created using 'ar' and 'ranlib', or on Windows using 'lib'. If OUTPUT-FILE ends in '.lo' or '.$objext', then a reloadable object file is created, otherwise an executable program is created." ;; uninstall) $ECHO \ "Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... Remove libraries from an installation directory. RM is the name of the program to use to delete files associated with each FILE (typically '/bin/rm'). RM-OPTIONS are options (such as '-f') to be passed to RM. If FILE is a libtool library, all the files associated with it are deleted. Otherwise, only FILE itself is deleted using RM." ;; *) func_fatal_help "invalid operation mode '$opt_mode'" ;; esac echo $ECHO "Try '$progname --help' for more information about other modes." } # Now that we've collected a possible --mode arg, show help if necessary if $opt_help; then if test : = "$opt_help"; then func_mode_help else { func_help noexit for opt_mode in compile link execute install finish uninstall clean; do func_mode_help done } | $SED -n '1p; 2,$s/^Usage:/ or: /p' { func_help noexit for opt_mode in compile link execute install finish uninstall clean; do echo func_mode_help done } | $SED '1d /^When reporting/,/^Report/{ H d } $x /information about other modes/d /more detailed .*MODE/d s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' fi exit $? fi # func_mode_execute arg... func_mode_execute () { $debug_cmd # The first argument is the command name. cmd=$nonopt test -z "$cmd" && \ func_fatal_help "you must specify a COMMAND" # Handle -dlopen flags immediately. for file in $opt_dlopen; do test -f "$file" \ || func_fatal_help "'$file' is not a file" dir= case $file in *.la) func_resolve_sysroot "$file" file=$func_resolve_sysroot_result # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ || func_fatal_help "'$lib' is not a valid libtool archive" # Read the libtool library. dlname= library_names= func_source "$file" # Skip this library if it cannot be dlopened. if test -z "$dlname"; then # Warn if it was a shared library. test -n "$library_names" && \ func_warning "'$file' was not linked with '-export-dynamic'" continue fi func_dirname "$file" "" "." dir=$func_dirname_result if test -f "$dir/$objdir/$dlname"; then func_append dir "/$objdir" else if test ! -f "$dir/$dlname"; then func_fatal_error "cannot find '$dlname' in '$dir' or '$dir/$objdir'" fi fi ;; *.lo) # Just add the directory containing the .lo file. func_dirname "$file" "" "." dir=$func_dirname_result ;; *) func_warning "'-dlopen' is ignored for non-libtool libraries and objects" continue ;; esac # Get the absolute pathname. absdir=`cd "$dir" && pwd` test -n "$absdir" && dir=$absdir # Now add the directory to shlibpath_var. if eval "test -z \"\$$shlibpath_var\""; then eval "$shlibpath_var=\"\$dir\"" else eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" fi done # This variable tells wrapper scripts just to set shlibpath_var # rather than running their programs. libtool_execute_magic=$magic # Check if any of the arguments is a wrapper script. args= for file do case $file in -* | *.la | *.lo ) ;; *) # Do a test to see if this is really a libtool program. if func_ltwrapper_script_p "$file"; then func_source "$file" # Transform arg to wrapped name. file=$progdir/$program elif func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" func_source "$func_ltwrapper_scriptname_result" # Transform arg to wrapped name. file=$progdir/$program fi ;; esac # Quote arguments (to preserve shell metacharacters). func_append_quoted args "$file" done if $opt_dry_run; then # Display what would be done. if test -n "$shlibpath_var"; then eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" echo "export $shlibpath_var" fi $ECHO "$cmd$args" exit $EXIT_SUCCESS else if test -n "$shlibpath_var"; then # Export the shlibpath_var. eval "export $shlibpath_var" fi # Restore saved environment variables for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES do eval "if test \"\${save_$lt_var+set}\" = set; then $lt_var=\$save_$lt_var; export $lt_var else $lt_unset $lt_var fi" done # Now prepare to actually exec the command. exec_cmd=\$cmd$args fi } test execute = "$opt_mode" && func_mode_execute ${1+"$@"} # func_mode_finish arg... func_mode_finish () { $debug_cmd libs= libdirs= admincmds= for opt in "$nonopt" ${1+"$@"} do if test -d "$opt"; then func_append libdirs " $opt" elif test -f "$opt"; then if func_lalib_unsafe_p "$opt"; then func_append libs " $opt" else func_warning "'$opt' is not a valid libtool archive" fi else func_fatal_error "invalid argument '$opt'" fi done if test -n "$libs"; then if test -n "$lt_sysroot"; then sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"` sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;" else sysroot_cmd= fi # Remove sysroot references if $opt_dry_run; then for lib in $libs; do echo "removing references to $lt_sysroot and '=' prefixes from $lib" done else tmpdir=`func_mktempdir` for lib in $libs; do $SED -e "$sysroot_cmd s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ > $tmpdir/tmp-la mv -f $tmpdir/tmp-la $lib done ${RM}r "$tmpdir" fi fi if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then for libdir in $libdirs; do if test -n "$finish_cmds"; then # Do each command in the finish commands. func_execute_cmds "$finish_cmds" 'admincmds="$admincmds '"$cmd"'"' fi if test -n "$finish_eval"; then # Do the single finish_eval. eval cmds=\"$finish_eval\" $opt_dry_run || eval "$cmds" || func_append admincmds " $cmds" fi done fi # Exit here if they wanted silent mode. $opt_quiet && exit $EXIT_SUCCESS if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then echo "----------------------------------------------------------------------" echo "Libraries have been installed in:" for libdir in $libdirs; do $ECHO " $libdir" done echo echo "If you ever happen to want to link against installed libraries" echo "in a given directory, LIBDIR, you must either use libtool, and" echo "specify the full pathname of the library, or use the '-LLIBDIR'" echo "flag during linking and do at least one of the following:" if test -n "$shlibpath_var"; then echo " - add LIBDIR to the '$shlibpath_var' environment variable" echo " during execution" fi if test -n "$runpath_var"; then echo " - add LIBDIR to the '$runpath_var' environment variable" echo " during linking" fi if test -n "$hardcode_libdir_flag_spec"; then libdir=LIBDIR eval flag=\"$hardcode_libdir_flag_spec\" $ECHO " - use the '$flag' linker flag" fi if test -n "$admincmds"; then $ECHO " - have your system administrator run these commands:$admincmds" fi if test -f /etc/ld.so.conf; then echo " - have your system administrator add LIBDIR to '/etc/ld.so.conf'" fi echo echo "See any operating system documentation about shared libraries for" case $host in solaris2.[6789]|solaris2.1[0-9]) echo "more information, such as the ld(1), crle(1) and ld.so(8) manual" echo "pages." ;; *) echo "more information, such as the ld(1) and ld.so(8) manual pages." ;; esac echo "----------------------------------------------------------------------" fi exit $EXIT_SUCCESS } test finish = "$opt_mode" && func_mode_finish ${1+"$@"} # func_mode_install arg... func_mode_install () { $debug_cmd # There may be an optional sh(1) argument at the beginning of # install_prog (especially on Windows NT). if test "$SHELL" = "$nonopt" || test /bin/sh = "$nonopt" || # Allow the use of GNU shtool's install command. case $nonopt in *shtool*) :;; *) false;; esac then # Aesthetically quote it. func_quote_for_eval "$nonopt" install_prog="$func_quote_for_eval_result " arg=$1 shift else install_prog= arg=$nonopt fi # The real first argument should be the name of the installation program. # Aesthetically quote it. func_quote_for_eval "$arg" func_append install_prog "$func_quote_for_eval_result" install_shared_prog=$install_prog case " $install_prog " in *[\\\ /]cp\ *) install_cp=: ;; *) install_cp=false ;; esac # We need to accept at least all the BSD install flags. dest= files= opts= prev= install_type= isdir=false stripme= no_mode=: for arg do arg2= if test -n "$dest"; then func_append files " $dest" dest=$arg continue fi case $arg in -d) isdir=: ;; -f) if $install_cp; then :; else prev=$arg fi ;; -g | -m | -o) prev=$arg ;; -s) stripme=" -s" continue ;; -*) ;; *) # If the previous option needed an argument, then skip it. if test -n "$prev"; then if test X-m = "X$prev" && test -n "$install_override_mode"; then arg2=$install_override_mode no_mode=false fi prev= else dest=$arg continue fi ;; esac # Aesthetically quote the argument. func_quote_for_eval "$arg" func_append install_prog " $func_quote_for_eval_result" if test -n "$arg2"; then func_quote_for_eval "$arg2" fi func_append install_shared_prog " $func_quote_for_eval_result" done test -z "$install_prog" && \ func_fatal_help "you must specify an install program" test -n "$prev" && \ func_fatal_help "the '$prev' option requires an argument" if test -n "$install_override_mode" && $no_mode; then if $install_cp; then :; else func_quote_for_eval "$install_override_mode" func_append install_shared_prog " -m $func_quote_for_eval_result" fi fi if test -z "$files"; then if test -z "$dest"; then func_fatal_help "no file or destination specified" else func_fatal_help "you must specify a destination" fi fi # Strip any trailing slash from the destination. func_stripname '' '/' "$dest" dest=$func_stripname_result # Check to see that the destination is a directory. test -d "$dest" && isdir=: if $isdir; then destdir=$dest destname= else func_dirname_and_basename "$dest" "" "." destdir=$func_dirname_result destname=$func_basename_result # Not a directory, so check to see that there is only one file specified. set dummy $files; shift test "$#" -gt 1 && \ func_fatal_help "'$dest' is not a directory" fi case $destdir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) for file in $files; do case $file in *.lo) ;; *) func_fatal_help "'$destdir' must be an absolute directory name" ;; esac done ;; esac # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic=$magic staticlibs= future_libdirs= current_libdirs= for file in $files; do # Do each installation. case $file in *.$libext) # Do the static libraries later. func_append staticlibs " $file" ;; *.la) func_resolve_sysroot "$file" file=$func_resolve_sysroot_result # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$file" \ || func_fatal_help "'$file' is not a valid libtool archive" library_names= old_library= relink_command= func_source "$file" # Add the libdir to current_libdirs if it is the destination. if test "X$destdir" = "X$libdir"; then case "$current_libdirs " in *" $libdir "*) ;; *) func_append current_libdirs " $libdir" ;; esac else # Note the libdir as a future libdir. case "$future_libdirs " in *" $libdir "*) ;; *) func_append future_libdirs " $libdir" ;; esac fi func_dirname "$file" "/" "" dir=$func_dirname_result func_append dir "$objdir" if test -n "$relink_command"; then # Determine the prefix the user has applied to our future dir. inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"` # Don't allow the user to place us outside of our expected # location b/c this prevents finding dependent libraries that # are installed to the same prefix. # At present, this check doesn't affect windows .dll's that # are installed into $libdir/../bin (currently, that works fine) # but it's something to keep an eye on. test "$inst_prefix_dir" = "$destdir" && \ func_fatal_error "error: cannot install '$file' to a directory not ending in $libdir" if test -n "$inst_prefix_dir"; then # Stick the inst_prefix_dir data into the link command. relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` else relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` fi func_warning "relinking '$file'" func_show_eval "$relink_command" \ 'func_fatal_error "error: relink '\''$file'\'' with the above command before installing it"' fi # See the names of the shared library. set dummy $library_names; shift if test -n "$1"; then realname=$1 shift srcname=$realname test -n "$relink_command" && srcname=${realname}T # Install the shared library and build the symlinks. func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ 'exit $?' tstripme=$stripme case $host_os in cygwin* | mingw* | pw32* | cegcc*) case $realname in *.dll.a) tstripme= ;; esac ;; os2*) case $realname in *_dll.a) tstripme= ;; esac ;; esac if test -n "$tstripme" && test -n "$striplib"; then func_show_eval "$striplib $destdir/$realname" 'exit $?' fi if test "$#" -gt 0; then # Delete the old symlinks, and create new ones. # Try 'ln -sf' first, because the 'ln' binary might depend on # the symlink we replace! Solaris /bin/ln does not understand -f, # so we also need to try rm && ln -s. for linkname do test "$linkname" != "$realname" \ && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" done fi # Do each command in the postinstall commands. lib=$destdir/$realname func_execute_cmds "$postinstall_cmds" 'exit $?' fi # Install the pseudo-library for information purposes. func_basename "$file" name=$func_basename_result instname=$dir/${name}i func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' # Maybe install the static library, too. test -n "$old_library" && func_append staticlibs " $dir/$old_library" ;; *.lo) # Install (i.e. copy) a libtool object. # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile=$destdir/$destname else func_basename "$file" destfile=$func_basename_result destfile=$destdir/$destfile fi # Deduce the name of the destination old-style object file. case $destfile in *.lo) func_lo2o "$destfile" staticdest=$func_lo2o_result ;; *.$objext) staticdest=$destfile destfile= ;; *) func_fatal_help "cannot copy a libtool object to '$destfile'" ;; esac # Install the libtool object if requested. test -n "$destfile" && \ func_show_eval "$install_prog $file $destfile" 'exit $?' # Install the old object if enabled. if test yes = "$build_old_libs"; then # Deduce the name of the old-style object file. func_lo2o "$file" staticobj=$func_lo2o_result func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' fi exit $EXIT_SUCCESS ;; *) # Figure out destination file name, if it wasn't already specified. if test -n "$destname"; then destfile=$destdir/$destname else func_basename "$file" destfile=$func_basename_result destfile=$destdir/$destfile fi # If the file is missing, and there is a .exe on the end, strip it # because it is most likely a libtool script we actually want to # install stripped_ext= case $file in *.exe) if test ! -f "$file"; then func_stripname '' '.exe' "$file" file=$func_stripname_result stripped_ext=.exe fi ;; esac # Do a test to see if this is really a libtool program. case $host in *cygwin* | *mingw*) if func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" wrapper=$func_ltwrapper_scriptname_result else func_stripname '' '.exe' "$file" wrapper=$func_stripname_result fi ;; *) wrapper=$file ;; esac if func_ltwrapper_script_p "$wrapper"; then notinst_deplibs= relink_command= func_source "$wrapper" # Check the variables that should have been set. test -z "$generated_by_libtool_version" && \ func_fatal_error "invalid libtool wrapper script '$wrapper'" finalize=: for lib in $notinst_deplibs; do # Check to see that each library is installed. libdir= if test -f "$lib"; then func_source "$lib" fi libfile=$libdir/`$ECHO "$lib" | $SED 's%^.*/%%g'` if test -n "$libdir" && test ! -f "$libfile"; then func_warning "'$lib' has not been installed in '$libdir'" finalize=false fi done relink_command= func_source "$wrapper" outputname= if test no = "$fast_install" && test -n "$relink_command"; then $opt_dry_run || { if $finalize; then tmpdir=`func_mktempdir` func_basename "$file$stripped_ext" file=$func_basename_result outputname=$tmpdir/$file # Replace the output file specification. relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` $opt_quiet || { func_quote_for_expand "$relink_command" eval "func_echo $func_quote_for_expand_result" } if eval "$relink_command"; then : else func_error "error: relink '$file' with the above command before installing it" $opt_dry_run || ${RM}r "$tmpdir" continue fi file=$outputname else func_warning "cannot relink '$file'" fi } else # Install the binary that we compiled earlier. file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"` fi fi # remove .exe since cygwin /usr/bin/install will append another # one anyway case $install_prog,$host in */usr/bin/install*,*cygwin*) case $file:$destfile in *.exe:*.exe) # this is ok ;; *.exe:*) destfile=$destfile.exe ;; *:*.exe) func_stripname '' '.exe' "$destfile" destfile=$func_stripname_result ;; esac ;; esac func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' $opt_dry_run || if test -n "$outputname"; then ${RM}r "$tmpdir" fi ;; esac done for file in $staticlibs; do func_basename "$file" name=$func_basename_result # Set up the ranlib parameters. oldlib=$destdir/$name func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 tool_oldlib=$func_to_tool_file_result func_show_eval "$install_prog \$file \$oldlib" 'exit $?' if test -n "$stripme" && test -n "$old_striplib"; then func_show_eval "$old_striplib $tool_oldlib" 'exit $?' fi # Do each command in the postinstall commands. func_execute_cmds "$old_postinstall_cmds" 'exit $?' done test -n "$future_libdirs" && \ func_warning "remember to run '$progname --finish$future_libdirs'" if test -n "$current_libdirs"; then # Maybe just do a dry run. $opt_dry_run && current_libdirs=" -n$current_libdirs" exec_cmd='$SHELL "$progpath" $preserve_args --finish$current_libdirs' else exit $EXIT_SUCCESS fi } test install = "$opt_mode" && func_mode_install ${1+"$@"} # func_generate_dlsyms outputname originator pic_p # Extract symbols from dlprefiles and create ${outputname}S.o with # a dlpreopen symbol table. func_generate_dlsyms () { $debug_cmd my_outputname=$1 my_originator=$2 my_pic_p=${3-false} my_prefix=`$ECHO "$my_originator" | $SED 's%[^a-zA-Z0-9]%_%g'` my_dlsyms= if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then if test -n "$NM" && test -n "$global_symbol_pipe"; then my_dlsyms=${my_outputname}S.c else func_error "not configured to extract global symbols from dlpreopened files" fi fi if test -n "$my_dlsyms"; then case $my_dlsyms in "") ;; *.c) # Discover the nlist of each of the dlfiles. nlist=$output_objdir/$my_outputname.nm func_show_eval "$RM $nlist ${nlist}S ${nlist}T" # Parse the name list into a source file. func_verbose "creating $output_objdir/$my_dlsyms" $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ /* $my_dlsyms - symbol resolution table for '$my_outputname' dlsym emulation. */ /* Generated by $PROGRAM (GNU $PACKAGE) $VERSION */ #ifdef __cplusplus extern \"C\" { #endif #if defined __GNUC__ && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) #pragma GCC diagnostic ignored \"-Wstrict-prototypes\" #endif /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE /* DATA imports from DLLs on WIN32 can't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT_DLSYM_CONST #elif defined __osf__ /* This system does not cope well with relocations in const data. */ # define LT_DLSYM_CONST #else # define LT_DLSYM_CONST const #endif #define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) /* External symbol declarations for the compiler. */\ " if test yes = "$dlself"; then func_verbose "generating symbol list for '$output'" $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" # Add our own program objects to the symbol list. progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` for progfile in $progfiles; do func_to_tool_file "$progfile" func_convert_file_msys_to_w32 func_verbose "extracting global C symbols from '$func_to_tool_file_result'" $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" done if test -n "$exclude_expsyms"; then $opt_dry_run || { eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' } fi if test -n "$export_symbols_regex"; then $opt_dry_run || { eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' } fi # Prepare the list of exported symbols if test -z "$export_symbols"; then export_symbols=$output_objdir/$outputname.exp $opt_dry_run || { $RM $export_symbols eval "$SED -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' case $host in *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' ;; esac } else $opt_dry_run || { eval "$SED -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' case $host in *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' ;; esac } fi fi for dlprefile in $dlprefiles; do func_verbose "extracting global C symbols from '$dlprefile'" func_basename "$dlprefile" name=$func_basename_result case $host in *cygwin* | *mingw* | *cegcc* ) # if an import library, we need to obtain dlname if func_win32_import_lib_p "$dlprefile"; then func_tr_sh "$dlprefile" eval "curr_lafile=\$libfile_$func_tr_sh_result" dlprefile_dlbasename= if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then # Use subshell, to avoid clobbering current variable values dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` if test -n "$dlprefile_dlname"; then func_basename "$dlprefile_dlname" dlprefile_dlbasename=$func_basename_result else # no lafile. user explicitly requested -dlpreopen . $sharedlib_from_linklib_cmd "$dlprefile" dlprefile_dlbasename=$sharedlib_from_linklib_result fi fi $opt_dry_run || { if test -n "$dlprefile_dlbasename"; then eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' else func_warning "Could not compute DLL name from $name" eval '$ECHO ": $name " >> "$nlist"' fi func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe | $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" } else # not an import lib $opt_dry_run || { eval '$ECHO ": $name " >> "$nlist"' func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" } fi ;; *) $opt_dry_run || { eval '$ECHO ": $name " >> "$nlist"' func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" } ;; esac done $opt_dry_run || { # Make sure we have at least an empty file. test -f "$nlist" || : > "$nlist" if test -n "$exclude_expsyms"; then $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T $MV "$nlist"T "$nlist" fi # Try sorting and uniquifying the output. if $GREP -v "^: " < "$nlist" | if sort -k 3 /dev/null 2>&1; then sort -k 3 else sort +2 fi | uniq > "$nlist"S; then : else $GREP -v "^: " < "$nlist" > "$nlist"S fi if test -f "$nlist"S; then eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' else echo '/* NONE */' >> "$output_objdir/$my_dlsyms" fi func_show_eval '$RM "${nlist}I"' if test -n "$global_symbol_to_import"; then eval "$global_symbol_to_import"' < "$nlist"S > "$nlist"I' fi echo >> "$output_objdir/$my_dlsyms" "\ /* The mapping between symbol names and symbols. */ typedef struct { const char *name; void *address; } lt_dlsymlist; extern LT_DLSYM_CONST lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[];\ " if test -s "$nlist"I; then echo >> "$output_objdir/$my_dlsyms" "\ static void lt_syminit(void) { LT_DLSYM_CONST lt_dlsymlist *symbol = lt_${my_prefix}_LTX_preloaded_symbols; for (; symbol->name; ++symbol) {" $SED 's/.*/ if (STREQ (symbol->name, \"&\")) symbol->address = (void *) \&&;/' < "$nlist"I >> "$output_objdir/$my_dlsyms" echo >> "$output_objdir/$my_dlsyms" "\ } }" fi echo >> "$output_objdir/$my_dlsyms" "\ LT_DLSYM_CONST lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[] = { {\"$my_originator\", (void *) 0}," if test -s "$nlist"I; then echo >> "$output_objdir/$my_dlsyms" "\ {\"@INIT@\", (void *) <_syminit}," fi case $need_lib_prefix in no) eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; *) eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; esac echo >> "$output_objdir/$my_dlsyms" "\ {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt_${my_prefix}_LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif\ " } # !$opt_dry_run pic_flag_for_symtable= case "$compile_command " in *" -static "*) ;; *) case $host in # compiling the symbol table file with pic_flag works around # a FreeBSD bug that causes programs to crash when -lm is # linked before any other PIC object. But we must not use # pic_flag when linking with -static. The problem exists in # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. *-*-freebsd2.*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; *-*-hpux*) pic_flag_for_symtable=" $pic_flag" ;; *) $my_pic_p && pic_flag_for_symtable=" $pic_flag" ;; esac ;; esac symtab_cflags= for arg in $LTCFLAGS; do case $arg in -pie | -fpie | -fPIE) ;; *) func_append symtab_cflags " $arg" ;; esac done # Now compile the dynamic symbol file. func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' # Clean up the generated files. func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T" "${nlist}I"' # Transform the symbol file into the correct name. symfileobj=$output_objdir/${my_outputname}S.$objext case $host in *cygwin* | *mingw* | *cegcc* ) if test -f "$output_objdir/$my_outputname.def"; then compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` else compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` fi ;; *) compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` ;; esac ;; *) func_fatal_error "unknown suffix for '$my_dlsyms'" ;; esac else # We keep going just in case the user didn't refer to # lt_preloaded_symbols. The linker will fail if global_symbol_pipe # really was required. # Nullify the symbol file. compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"` finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` fi } # func_cygming_gnu_implib_p ARG # This predicate returns with zero status (TRUE) if # ARG is a GNU/binutils-style import library. Returns # with nonzero status (FALSE) otherwise. func_cygming_gnu_implib_p () { $debug_cmd func_to_tool_file "$1" func_convert_file_msys_to_w32 func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` test -n "$func_cygming_gnu_implib_tmp" } # func_cygming_ms_implib_p ARG # This predicate returns with zero status (TRUE) if # ARG is an MS-style import library. Returns # with nonzero status (FALSE) otherwise. func_cygming_ms_implib_p () { $debug_cmd func_to_tool_file "$1" func_convert_file_msys_to_w32 func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` test -n "$func_cygming_ms_implib_tmp" } # func_win32_libid arg # return the library type of file 'arg' # # Need a lot of goo to handle *both* DLLs and import libs # Has to be a shell function in order to 'eat' the argument # that is supplied when $file_magic_command is called. # Despite the name, also deal with 64 bit binaries. func_win32_libid () { $debug_cmd win32_libid_type=unknown win32_fileres=`file -L $1 2>/dev/null` case $win32_fileres in *ar\ archive\ import\ library*) # definitely import win32_libid_type="x86 archive import" ;; *ar\ archive*) # could be an import, or static # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then case $nm_interface in "MS dumpbin") if func_cygming_ms_implib_p "$1" || func_cygming_gnu_implib_p "$1" then win32_nmres=import else win32_nmres= fi ;; *) func_to_tool_file "$1" func_convert_file_msys_to_w32 win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | $SED -n -e ' 1,100{ / I /{ s|.*|import| p q } }'` ;; esac case $win32_nmres in import*) win32_libid_type="x86 archive import";; *) win32_libid_type="x86 archive static";; esac fi ;; *DLL*) win32_libid_type="x86 DLL" ;; *executable*) # but shell scripts are "executable" too... case $win32_fileres in *MS\ Windows\ PE\ Intel*) win32_libid_type="x86 DLL" ;; esac ;; esac $ECHO "$win32_libid_type" } # func_cygming_dll_for_implib ARG # # Platform-specific function to extract the # name of the DLL associated with the specified # import library ARG. # Invoked by eval'ing the libtool variable # $sharedlib_from_linklib_cmd # Result is available in the variable # $sharedlib_from_linklib_result func_cygming_dll_for_implib () { $debug_cmd sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` } # func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs # # The is the core of a fallback implementation of a # platform-specific function to extract the name of the # DLL associated with the specified import library LIBNAME. # # SECTION_NAME is either .idata$6 or .idata$7, depending # on the platform and compiler that created the implib. # # Echos the name of the DLL associated with the # specified import library. func_cygming_dll_for_implib_fallback_core () { $debug_cmd match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` $OBJDUMP -s --section "$1" "$2" 2>/dev/null | $SED '/^Contents of section '"$match_literal"':/{ # Place marker at beginning of archive member dllname section s/.*/====MARK====/ p d } # These lines can sometimes be longer than 43 characters, but # are always uninteresting /:[ ]*file format pe[i]\{,1\}-/d /^In archive [^:]*:/d # Ensure marker is printed /^====MARK====/p # Remove all lines with less than 43 characters /^.\{43\}/!d # From remaining lines, remove first 43 characters s/^.\{43\}//' | $SED -n ' # Join marker and all lines until next marker into a single line /^====MARK====/ b para H $ b para b :para x s/\n//g # Remove the marker s/^====MARK====// # Remove trailing dots and whitespace s/[\. \t]*$// # Print /./p' | # we now have a list, one entry per line, of the stringified # contents of the appropriate section of all members of the # archive that possess that section. Heuristic: eliminate # all those that have a first or second character that is # a '.' (that is, objdump's representation of an unprintable # character.) This should work for all archives with less than # 0x302f exports -- but will fail for DLLs whose name actually # begins with a literal '.' or a single character followed by # a '.'. # # Of those that remain, print the first one. $SED -e '/^\./d;/^.\./d;q' } # func_cygming_dll_for_implib_fallback ARG # Platform-specific function to extract the # name of the DLL associated with the specified # import library ARG. # # This fallback implementation is for use when $DLLTOOL # does not support the --identify-strict option. # Invoked by eval'ing the libtool variable # $sharedlib_from_linklib_cmd # Result is available in the variable # $sharedlib_from_linklib_result func_cygming_dll_for_implib_fallback () { $debug_cmd if func_cygming_gnu_implib_p "$1"; then # binutils import library sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` elif func_cygming_ms_implib_p "$1"; then # ms-generated import library sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` else # unknown sharedlib_from_linklib_result= fi } # func_extract_an_archive dir oldlib func_extract_an_archive () { $debug_cmd f_ex_an_ar_dir=$1; shift f_ex_an_ar_oldlib=$1 if test yes = "$lock_old_archive_extraction"; then lockfile=$f_ex_an_ar_oldlib.lock until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do func_echo "Waiting for $lockfile to be removed" sleep 2 done fi func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ 'stat=$?; rm -f "$lockfile"; exit $stat' if test yes = "$lock_old_archive_extraction"; then $opt_dry_run || rm -f "$lockfile" fi if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then : else func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" fi } # func_extract_archives gentop oldlib ... func_extract_archives () { $debug_cmd my_gentop=$1; shift my_oldlibs=${1+"$@"} my_oldobjs= my_xlib= my_xabs= my_xdir= for my_xlib in $my_oldlibs; do # Extract the objects. case $my_xlib in [\\/]* | [A-Za-z]:[\\/]*) my_xabs=$my_xlib ;; *) my_xabs=`pwd`"/$my_xlib" ;; esac func_basename "$my_xlib" my_xlib=$func_basename_result my_xlib_u=$my_xlib while :; do case " $extracted_archives " in *" $my_xlib_u "*) func_arith $extracted_serial + 1 extracted_serial=$func_arith_result my_xlib_u=lt$extracted_serial-$my_xlib ;; *) break ;; esac done extracted_archives="$extracted_archives $my_xlib_u" my_xdir=$my_gentop/$my_xlib_u func_mkdir_p "$my_xdir" case $host in *-darwin*) func_verbose "Extracting $my_xabs" # Do not bother doing anything if just a dry run $opt_dry_run || { darwin_orig_dir=`pwd` cd $my_xdir || exit $? darwin_archive=$my_xabs darwin_curdir=`pwd` func_basename "$darwin_archive" darwin_base_archive=$func_basename_result darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` if test -n "$darwin_arches"; then darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` darwin_arch= func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" for darwin_arch in $darwin_arches; do func_mkdir_p "unfat-$$/$darwin_base_archive-$darwin_arch" $LIPO -thin $darwin_arch -output "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" "$darwin_archive" cd "unfat-$$/$darwin_base_archive-$darwin_arch" func_extract_an_archive "`pwd`" "$darwin_base_archive" cd "$darwin_curdir" $RM "unfat-$$/$darwin_base_archive-$darwin_arch/$darwin_base_archive" done # $darwin_arches ## Okay now we've a bunch of thin objects, gotta fatten them up :) darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$sed_basename" | sort -u` darwin_file= darwin_files= for darwin_file in $darwin_filelist; do darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` $LIPO -create -output "$darwin_file" $darwin_files done # $darwin_filelist $RM -rf unfat-$$ cd "$darwin_orig_dir" else cd $darwin_orig_dir func_extract_an_archive "$my_xdir" "$my_xabs" fi # $darwin_arches } # !$opt_dry_run ;; *) func_extract_an_archive "$my_xdir" "$my_xabs" ;; esac my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` done func_extract_archives_result=$my_oldobjs } # func_emit_wrapper [arg=no] # # Emit a libtool wrapper script on stdout. # Don't directly open a file because we may want to # incorporate the script contents within a cygwin/mingw # wrapper executable. Must ONLY be called from within # func_mode_link because it depends on a number of variables # set therein. # # ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR # variable will take. If 'yes', then the emitted script # will assume that the directory where it is stored is # the $objdir directory. This is a cygwin/mingw-specific # behavior. func_emit_wrapper () { func_emit_wrapper_arg1=${1-no} $ECHO "\ #! $SHELL # $output - temporary wrapper script for $objdir/$outputname # Generated by $PROGRAM (GNU $PACKAGE) $VERSION # # The $output program cannot be directly executed until all the libtool # libraries that it depends on are installed. # # This wrapper script should never be moved out of the build directory. # If it is, it will not operate correctly. # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. sed_quote_subst='$sed_quote_subst' # Be Bourne compatible if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then emulate sh NULLCMD=: # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac fi BIN_SH=xpg4; export BIN_SH # for Tru64 DUALCASE=1; export DUALCASE # for MKS sh # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH relink_command=\"$relink_command\" # This environment variable determines our operation mode. if test \"\$libtool_install_magic\" = \"$magic\"; then # install mode needs the following variables: generated_by_libtool_version='$macro_version' notinst_deplibs='$notinst_deplibs' else # When we are sourced in execute mode, \$file and \$ECHO are already set. if test \"\$libtool_execute_magic\" != \"$magic\"; then file=\"\$0\"" qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` $ECHO "\ # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$1 _LTECHO_EOF' } ECHO=\"$qECHO\" fi # Very basic option parsing. These options are (a) specific to # the libtool wrapper, (b) are identical between the wrapper # /script/ and the wrapper /executable/ that is used only on # windows platforms, and (c) all begin with the string "--lt-" # (application programs are unlikely to have options that match # this pattern). # # There are only two supported options: --lt-debug and # --lt-dump-script. There is, deliberately, no --lt-help. # # The first argument to this parsing function should be the # script's $0 value, followed by "$@". lt_option_debug= func_parse_lt_options () { lt_script_arg0=\$0 shift for lt_opt do case \"\$lt_opt\" in --lt-debug) lt_option_debug=1 ;; --lt-dump-script) lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` cat \"\$lt_dump_D/\$lt_dump_F\" exit 0 ;; --lt-*) \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 exit 1 ;; esac done # Print the debug banner immediately: if test -n \"\$lt_option_debug\"; then echo \"$outputname:$output:\$LINENO: libtool wrapper (GNU $PACKAGE) $VERSION\" 1>&2 fi } # Used when --lt-debug. Prints its arguments to stdout # (redirection is the responsibility of the caller) func_lt_dump_args () { lt_dump_args_N=1; for lt_arg do \$ECHO \"$outputname:$output:\$LINENO: newargv[\$lt_dump_args_N]: \$lt_arg\" lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` done } # Core function for launching the target application func_exec_program_core () { " case $host in # Backslashes separate directories on plain windows *-*-mingw | *-*-os2* | *-cegcc*) $ECHO "\ if test -n \"\$lt_option_debug\"; then \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir\\\\\$program\" 1>&2 func_lt_dump_args \${1+\"\$@\"} 1>&2 fi exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} " ;; *) $ECHO "\ if test -n \"\$lt_option_debug\"; then \$ECHO \"$outputname:$output:\$LINENO: newargv[0]: \$progdir/\$program\" 1>&2 func_lt_dump_args \${1+\"\$@\"} 1>&2 fi exec \"\$progdir/\$program\" \${1+\"\$@\"} " ;; esac $ECHO "\ \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 exit 1 } # A function to encapsulate launching the target application # Strips options in the --lt-* namespace from \$@ and # launches target application with the remaining arguments. func_exec_program () { case \" \$* \" in *\\ --lt-*) for lt_wr_arg do case \$lt_wr_arg in --lt-*) ;; *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; esac shift done ;; esac func_exec_program_core \${1+\"\$@\"} } # Parse options func_parse_lt_options \"\$0\" \${1+\"\$@\"} # Find the directory that this script lives in. thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\` test \"x\$thisdir\" = \"x\$file\" && thisdir=. # Follow symbolic links until we get to the real thisdir. file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\` while test -n \"\$file\"; do destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\` # If there was a directory component, then change thisdir. if test \"x\$destdir\" != \"x\$file\"; then case \"\$destdir\" in [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; *) thisdir=\"\$thisdir/\$destdir\" ;; esac fi file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\` file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` done # Usually 'no', except on cygwin/mingw when embedded into # the cwrapper. WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then # special case for '.' if test \"\$thisdir\" = \".\"; then thisdir=\`pwd\` fi # remove .libs from thisdir case \"\$thisdir\" in *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; $objdir ) thisdir=. ;; esac fi # Try to get the absolute directory name. absdir=\`cd \"\$thisdir\" && pwd\` test -n \"\$absdir\" && thisdir=\"\$absdir\" " if test yes = "$fast_install"; then $ECHO "\ program=lt-'$outputname'$exeext progdir=\"\$thisdir/$objdir\" if test ! -f \"\$progdir/\$program\" || { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | $SED 1q\`; \\ test \"X\$file\" != \"X\$progdir/\$program\"; }; then file=\"\$\$-\$program\" if test ! -d \"\$progdir\"; then $MKDIR \"\$progdir\" else $RM \"\$progdir/\$file\" fi" $ECHO "\ # relink executable if necessary if test -n \"\$relink_command\"; then if relink_command_output=\`eval \$relink_command 2>&1\`; then : else \$ECHO \"\$relink_command_output\" >&2 $RM \"\$progdir/\$file\" exit 1 fi fi $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || { $RM \"\$progdir/\$program\"; $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } $RM \"\$progdir/\$file\" fi" else $ECHO "\ program='$outputname' progdir=\"\$thisdir/$objdir\" " fi $ECHO "\ if test -f \"\$progdir/\$program\"; then" # fixup the dll searchpath if we need to. # # Fix the DLL searchpath if we need to. Do this before prepending # to shlibpath, because on Windows, both are PATH and uninstalled # libraries must come first. if test -n "$dllsearchpath"; then $ECHO "\ # Add the dll search path components to the executable PATH PATH=$dllsearchpath:\$PATH " fi # Export our shlibpath_var if we have one. if test yes = "$shlibpath_overrides_runpath" && test -n "$shlibpath_var" && test -n "$temp_rpath"; then $ECHO "\ # Add our own library path to $shlibpath_var $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" # Some systems cannot cope with colon-terminated $shlibpath_var # The second colon is a workaround for a bug in BeOS R4 sed $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\` export $shlibpath_var " fi $ECHO "\ if test \"\$libtool_execute_magic\" != \"$magic\"; then # Run the actual program with our arguments. func_exec_program \${1+\"\$@\"} fi else # The program doesn't exist. \$ECHO \"\$0: error: '\$progdir/\$program' does not exist\" 1>&2 \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 exit 1 fi fi\ " } # func_emit_cwrapperexe_src # emit the source code for a wrapper executable on stdout # Must ONLY be called from within func_mode_link because # it depends on a number of variable set therein. func_emit_cwrapperexe_src () { cat < #include #ifdef _MSC_VER # include # include # include #else # include # include # ifdef __CYGWIN__ # include # endif #endif #include #include #include #include #include #include #include #include #define STREQ(s1, s2) (strcmp ((s1), (s2)) == 0) /* declarations of non-ANSI functions */ #if defined __MINGW32__ # ifdef __STRICT_ANSI__ int _putenv (const char *); # endif #elif defined __CYGWIN__ # ifdef __STRICT_ANSI__ char *realpath (const char *, char *); int putenv (char *); int setenv (const char *, const char *, int); # endif /* #elif defined other_platform || defined ... */ #endif /* portability defines, excluding path handling macros */ #if defined _MSC_VER # define setmode _setmode # define stat _stat # define chmod _chmod # define getcwd _getcwd # define putenv _putenv # define S_IXUSR _S_IEXEC #elif defined __MINGW32__ # define setmode _setmode # define stat _stat # define chmod _chmod # define getcwd _getcwd # define putenv _putenv #elif defined __CYGWIN__ # define HAVE_SETENV # define FOPEN_WB "wb" /* #elif defined other platforms ... */ #endif #if defined PATH_MAX # define LT_PATHMAX PATH_MAX #elif defined MAXPATHLEN # define LT_PATHMAX MAXPATHLEN #else # define LT_PATHMAX 1024 #endif #ifndef S_IXOTH # define S_IXOTH 0 #endif #ifndef S_IXGRP # define S_IXGRP 0 #endif /* path handling portability macros */ #ifndef DIR_SEPARATOR # define DIR_SEPARATOR '/' # define PATH_SEPARATOR ':' #endif #if defined _WIN32 || defined __MSDOS__ || defined __DJGPP__ || \ defined __OS2__ # define HAVE_DOS_BASED_FILE_SYSTEM # define FOPEN_WB "wb" # ifndef DIR_SEPARATOR_2 # define DIR_SEPARATOR_2 '\\' # endif # ifndef PATH_SEPARATOR_2 # define PATH_SEPARATOR_2 ';' # endif #endif #ifndef DIR_SEPARATOR_2 # define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) #else /* DIR_SEPARATOR_2 */ # define IS_DIR_SEPARATOR(ch) \ (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) #endif /* DIR_SEPARATOR_2 */ #ifndef PATH_SEPARATOR_2 # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) #else /* PATH_SEPARATOR_2 */ # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) #endif /* PATH_SEPARATOR_2 */ #ifndef FOPEN_WB # define FOPEN_WB "w" #endif #ifndef _O_BINARY # define _O_BINARY 0 #endif #define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) #define XFREE(stale) do { \ if (stale) { free (stale); stale = 0; } \ } while (0) #if defined LT_DEBUGWRAPPER static int lt_debug = 1; #else static int lt_debug = 0; #endif const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ void *xmalloc (size_t num); char *xstrdup (const char *string); const char *base_name (const char *name); char *find_executable (const char *wrapper); char *chase_symlinks (const char *pathspec); int make_executable (const char *path); int check_executable (const char *path); char *strendzap (char *str, const char *pat); void lt_debugprintf (const char *file, int line, const char *fmt, ...); void lt_fatal (const char *file, int line, const char *message, ...); static const char *nonnull (const char *s); static const char *nonempty (const char *s); void lt_setenv (const char *name, const char *value); char *lt_extend_str (const char *orig_value, const char *add, int to_end); void lt_update_exe_path (const char *name, const char *value); void lt_update_lib_path (const char *name, const char *value); char **prepare_spawn (char **argv); void lt_dump_script (FILE *f); EOF cat <= 0) && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) return 1; else return 0; } int make_executable (const char *path) { int rval = 0; struct stat st; lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", nonempty (path)); if ((!path) || (!*path)) return 0; if (stat (path, &st) >= 0) { rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); } return rval; } /* Searches for the full path of the wrapper. Returns newly allocated full path name if found, NULL otherwise Does not chase symlinks, even on platforms that support them. */ char * find_executable (const char *wrapper) { int has_slash = 0; const char *p; const char *p_next; /* static buffer for getcwd */ char tmp[LT_PATHMAX + 1]; size_t tmp_len; char *concat_name; lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", nonempty (wrapper)); if ((wrapper == NULL) || (*wrapper == '\0')) return NULL; /* Absolute path? */ #if defined HAVE_DOS_BASED_FILE_SYSTEM if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') { concat_name = xstrdup (wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } else { #endif if (IS_DIR_SEPARATOR (wrapper[0])) { concat_name = xstrdup (wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } #if defined HAVE_DOS_BASED_FILE_SYSTEM } #endif for (p = wrapper; *p; p++) if (*p == '/') { has_slash = 1; break; } if (!has_slash) { /* no slashes; search PATH */ const char *path = getenv ("PATH"); if (path != NULL) { for (p = path; *p; p = p_next) { const char *q; size_t p_len; for (q = p; *q; q++) if (IS_PATH_SEPARATOR (*q)) break; p_len = (size_t) (q - p); p_next = (*q == '\0' ? q : q + 1); if (p_len == 0) { /* empty path: current directory */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", nonnull (strerror (errno))); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); } else { concat_name = XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, p, p_len); concat_name[p_len] = '/'; strcpy (concat_name + p_len + 1, wrapper); } if (check_executable (concat_name)) return concat_name; XFREE (concat_name); } } /* not found in PATH; assume curdir */ } /* Relative path | not found in path: prepend cwd */ if (getcwd (tmp, LT_PATHMAX) == NULL) lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", nonnull (strerror (errno))); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); concat_name[tmp_len] = '/'; strcpy (concat_name + tmp_len + 1, wrapper); if (check_executable (concat_name)) return concat_name; XFREE (concat_name); return NULL; } char * chase_symlinks (const char *pathspec) { #ifndef S_ISLNK return xstrdup (pathspec); #else char buf[LT_PATHMAX]; struct stat s; char *tmp_pathspec = xstrdup (pathspec); char *p; int has_symlinks = 0; while (strlen (tmp_pathspec) && !has_symlinks) { lt_debugprintf (__FILE__, __LINE__, "checking path component for symlinks: %s\n", tmp_pathspec); if (lstat (tmp_pathspec, &s) == 0) { if (S_ISLNK (s.st_mode) != 0) { has_symlinks = 1; break; } /* search backwards for last DIR_SEPARATOR */ p = tmp_pathspec + strlen (tmp_pathspec) - 1; while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) p--; if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) { /* no more DIR_SEPARATORS left */ break; } *p = '\0'; } else { lt_fatal (__FILE__, __LINE__, "error accessing file \"%s\": %s", tmp_pathspec, nonnull (strerror (errno))); } } XFREE (tmp_pathspec); if (!has_symlinks) { return xstrdup (pathspec); } tmp_pathspec = realpath (pathspec, buf); if (tmp_pathspec == 0) { lt_fatal (__FILE__, __LINE__, "could not follow symlinks for %s", pathspec); } return xstrdup (tmp_pathspec); #endif } char * strendzap (char *str, const char *pat) { size_t len, patlen; assert (str != NULL); assert (pat != NULL); len = strlen (str); patlen = strlen (pat); if (patlen <= len) { str += len - patlen; if (STREQ (str, pat)) *str = '\0'; } return str; } void lt_debugprintf (const char *file, int line, const char *fmt, ...) { va_list args; if (lt_debug) { (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); va_start (args, fmt); (void) vfprintf (stderr, fmt, args); va_end (args); } } static void lt_error_core (int exit_status, const char *file, int line, const char *mode, const char *message, va_list ap) { fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); vfprintf (stderr, message, ap); fprintf (stderr, ".\n"); if (exit_status >= 0) exit (exit_status); } void lt_fatal (const char *file, int line, const char *message, ...) { va_list ap; va_start (ap, message); lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); va_end (ap); } static const char * nonnull (const char *s) { return s ? s : "(null)"; } static const char * nonempty (const char *s) { return (s && !*s) ? "(empty)" : nonnull (s); } void lt_setenv (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_setenv) setting '%s' to '%s'\n", nonnull (name), nonnull (value)); { #ifdef HAVE_SETENV /* always make a copy, for consistency with !HAVE_SETENV */ char *str = xstrdup (value); setenv (name, str, 1); #else size_t len = strlen (name) + 1 + strlen (value) + 1; char *str = XMALLOC (char, len); sprintf (str, "%s=%s", name, value); if (putenv (str) != EXIT_SUCCESS) { XFREE (str); } #endif } } char * lt_extend_str (const char *orig_value, const char *add, int to_end) { char *new_value; if (orig_value && *orig_value) { size_t orig_value_len = strlen (orig_value); size_t add_len = strlen (add); new_value = XMALLOC (char, add_len + orig_value_len + 1); if (to_end) { strcpy (new_value, orig_value); strcpy (new_value + orig_value_len, add); } else { strcpy (new_value, add); strcpy (new_value + add_len, orig_value); } } else { new_value = xstrdup (add); } return new_value; } void lt_update_exe_path (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", nonnull (name), nonnull (value)); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); /* some systems can't cope with a ':'-terminated path #' */ size_t len = strlen (new_value); while ((len > 0) && IS_PATH_SEPARATOR (new_value[len-1])) { new_value[--len] = '\0'; } lt_setenv (name, new_value); XFREE (new_value); } } void lt_update_lib_path (const char *name, const char *value) { lt_debugprintf (__FILE__, __LINE__, "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", nonnull (name), nonnull (value)); if (name && *name && value && *value) { char *new_value = lt_extend_str (getenv (name), value, 0); lt_setenv (name, new_value); XFREE (new_value); } } EOF case $host_os in mingw*) cat <<"EOF" /* Prepares an argument vector before calling spawn(). Note that spawn() does not by itself call the command interpreter (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&v); v.dwPlatformId == VER_PLATFORM_WIN32_NT; }) ? "cmd.exe" : "command.com"). Instead it simply concatenates the arguments, separated by ' ', and calls CreateProcess(). We must quote the arguments since Win32 CreateProcess() interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a special way: - Space and tab are interpreted as delimiters. They are not treated as delimiters if they are surrounded by double quotes: "...". - Unescaped double quotes are removed from the input. Their only effect is that within double quotes, space and tab are treated like normal characters. - Backslashes not followed by double quotes are not special. - But 2*n+1 backslashes followed by a double quote become n backslashes followed by a double quote (n >= 0): \" -> " \\\" -> \" \\\\\" -> \\" */ #define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" #define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" char ** prepare_spawn (char **argv) { size_t argc; char **new_argv; size_t i; /* Count number of arguments. */ for (argc = 0; argv[argc] != NULL; argc++) ; /* Allocate new argument vector. */ new_argv = XMALLOC (char *, argc + 1); /* Put quoted arguments into the new argument vector. */ for (i = 0; i < argc; i++) { const char *string = argv[i]; if (string[0] == '\0') new_argv[i] = xstrdup ("\"\""); else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) { int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); size_t length; unsigned int backslashes; const char *s; char *quoted_string; char *p; length = 0; backslashes = 0; if (quote_around) length++; for (s = string; *s != '\0'; s++) { char c = *s; if (c == '"') length += backslashes + 1; length++; if (c == '\\') backslashes++; else backslashes = 0; } if (quote_around) length += backslashes + 1; quoted_string = XMALLOC (char, length + 1); p = quoted_string; backslashes = 0; if (quote_around) *p++ = '"'; for (s = string; *s != '\0'; s++) { char c = *s; if (c == '"') { unsigned int j; for (j = backslashes + 1; j > 0; j--) *p++ = '\\'; } *p++ = c; if (c == '\\') backslashes++; else backslashes = 0; } if (quote_around) { unsigned int j; for (j = backslashes; j > 0; j--) *p++ = '\\'; *p++ = '"'; } *p = '\0'; new_argv[i] = quoted_string; } else new_argv[i] = (char *) string; } new_argv[argc] = NULL; return new_argv; } EOF ;; esac cat <<"EOF" void lt_dump_script (FILE* f) { EOF func_emit_wrapper yes | $SED -n -e ' s/^\(.\{79\}\)\(..*\)/\1\ \2/ h s/\([\\"]\)/\\\1/g s/$/\\n/ s/\([^\n]*\).*/ fputs ("\1", f);/p g D' cat <<"EOF" } EOF } # end: func_emit_cwrapperexe_src # func_win32_import_lib_p ARG # True if ARG is an import lib, as indicated by $file_magic_cmd func_win32_import_lib_p () { $debug_cmd case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in *import*) : ;; *) false ;; esac } # func_suncc_cstd_abi # !!ONLY CALL THIS FOR SUN CC AFTER $compile_command IS FULLY EXPANDED!! # Several compiler flags select an ABI that is incompatible with the # Cstd library. Avoid specifying it if any are in CXXFLAGS. func_suncc_cstd_abi () { $debug_cmd case " $compile_command " in *" -compat=g "*|*\ -std=c++[0-9][0-9]\ *|*" -library=stdcxx4 "*|*" -library=stlport4 "*) suncc_use_cstd_abi=no ;; *) suncc_use_cstd_abi=yes ;; esac } # func_mode_link arg... func_mode_link () { $debug_cmd case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) # It is impossible to link a dll without this setting, and # we shouldn't force the makefile maintainer to figure out # what system we are compiling for in order to pass an extra # flag for every libtool invocation. # allow_undefined=no # FIXME: Unfortunately, there are problems with the above when trying # to make a dll that has undefined symbols, in which case not # even a static library is built. For now, we need to specify # -no-undefined on the libtool link line when we can be certain # that all symbols are satisfied, otherwise we get a static library. allow_undefined=yes ;; *) allow_undefined=yes ;; esac libtool_args=$nonopt base_compile="$nonopt $@" compile_command=$nonopt finalize_command=$nonopt compile_rpath= finalize_rpath= compile_shlibpath= finalize_shlibpath= convenience= old_convenience= deplibs= old_deplibs= compiler_flags= linker_flags= dllsearchpath= lib_search_path=`pwd` inst_prefix_dir= new_inherited_linker_flags= avoid_version=no bindir= dlfiles= dlprefiles= dlself=no export_dynamic=no export_symbols= export_symbols_regex= generated= libobjs= ltlibs= module=no no_install=no objs= os2dllname= non_pic_objects= precious_files_regex= prefer_static_libs=no preload=false prev= prevarg= release= rpath= xrpath= perm_rpath= temp_rpath= thread_safe=no vinfo= vinfo_number=no weak_libs= single_module=$wl-single_module func_infer_tag $base_compile # We need to know -static, to get the right output filenames. for arg do case $arg in -shared) test yes != "$build_libtool_libs" \ && func_fatal_configuration "cannot build a shared library" build_old_libs=no break ;; -all-static | -static | -static-libtool-libs) case $arg in -all-static) if test yes = "$build_libtool_libs" && test -z "$link_static_flag"; then func_warning "complete static linking is impossible in this configuration" fi if test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes ;; -static) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=built ;; -static-libtool-libs) if test -z "$pic_flag" && test -n "$link_static_flag"; then dlopen_self=$dlopen_self_static fi prefer_static_libs=yes ;; esac build_libtool_libs=no build_old_libs=yes break ;; esac done # See if our shared archives depend on static archives. test -n "$old_archive_from_new_cmds" && build_old_libs=yes # Go through the arguments, transforming them on the way. while test "$#" -gt 0; do arg=$1 shift func_quote_for_eval "$arg" qarg=$func_quote_for_eval_unquoted_result func_append libtool_args " $func_quote_for_eval_result" # If the previous option needs an argument, assign it. if test -n "$prev"; then case $prev in output) func_append compile_command " @OUTPUT@" func_append finalize_command " @OUTPUT@" ;; esac case $prev in bindir) bindir=$arg prev= continue ;; dlfiles|dlprefiles) $preload || { # Add the symbol object into the linking commands. func_append compile_command " @SYMFILE@" func_append finalize_command " @SYMFILE@" preload=: } case $arg in *.la | *.lo) ;; # We handle these cases below. force) if test no = "$dlself"; then dlself=needless export_dynamic=yes fi prev= continue ;; self) if test dlprefiles = "$prev"; then dlself=yes elif test dlfiles = "$prev" && test yes != "$dlopen_self"; then dlself=yes else dlself=needless export_dynamic=yes fi prev= continue ;; *) if test dlfiles = "$prev"; then func_append dlfiles " $arg" else func_append dlprefiles " $arg" fi prev= continue ;; esac ;; expsyms) export_symbols=$arg test -f "$arg" \ || func_fatal_error "symbol file '$arg' does not exist" prev= continue ;; expsyms_regex) export_symbols_regex=$arg prev= continue ;; framework) case $host in *-*-darwin*) case "$deplibs " in *" $qarg.ltframework "*) ;; *) func_append deplibs " $qarg.ltframework" # this is fixed later ;; esac ;; esac prev= continue ;; inst_prefix) inst_prefix_dir=$arg prev= continue ;; mllvm) # Clang does not use LLVM to link, so we can simply discard any # '-mllvm $arg' options when doing the link step. prev= continue ;; objectlist) if test -f "$arg"; then save_arg=$arg moreargs= for fil in `cat "$save_arg"` do # func_append moreargs " $fil" arg=$fil # A libtool-controlled object. # Check to see that this really is a libtool object. if func_lalib_unsafe_p "$arg"; then pic_object= non_pic_object= # Read the .lo file func_source "$arg" if test -z "$pic_object" || test -z "$non_pic_object" || test none = "$pic_object" && test none = "$non_pic_object"; then func_fatal_error "cannot find name of object for '$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir=$func_dirname_result if test none != "$pic_object"; then # Prepend the subdirectory the object is found in. pic_object=$xdir$pic_object if test dlfiles = "$prev"; then if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then func_append dlfiles " $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test dlprefiles = "$prev"; then # Preload the old-style object. func_append dlprefiles " $pic_object" prev= fi # A PIC object. func_append libobjs " $pic_object" arg=$pic_object fi # Non-PIC object. if test none != "$non_pic_object"; then # Prepend the subdirectory the object is found in. non_pic_object=$xdir$non_pic_object # A standard non-PIC object func_append non_pic_objects " $non_pic_object" if test -z "$pic_object" || test none = "$pic_object"; then arg=$non_pic_object fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object=$pic_object func_append non_pic_objects " $non_pic_object" fi else # Only an error if not doing a dry-run. if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir=$func_dirname_result func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result non_pic_object=$xdir$func_lo2o_result func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else func_fatal_error "'$arg' is not a valid libtool object" fi fi done else func_fatal_error "link input file '$arg' does not exist" fi arg=$save_arg prev= continue ;; os2dllname) os2dllname=$arg prev= continue ;; precious_regex) precious_files_regex=$arg prev= continue ;; release) release=-$arg prev= continue ;; rpath | xrpath) # We need an absolute path. case $arg in [\\/]* | [A-Za-z]:[\\/]*) ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac if test rpath = "$prev"; then case "$rpath " in *" $arg "*) ;; *) func_append rpath " $arg" ;; esac else case "$xrpath " in *" $arg "*) ;; *) func_append xrpath " $arg" ;; esac fi prev= continue ;; shrext) shrext_cmds=$arg prev= continue ;; weak) func_append weak_libs " $arg" prev= continue ;; xcclinker) func_append linker_flags " $qarg" func_append compiler_flags " $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xcompiler) func_append compiler_flags " $qarg" prev= func_append compile_command " $qarg" func_append finalize_command " $qarg" continue ;; xlinker) func_append linker_flags " $qarg" func_append compiler_flags " $wl$qarg" prev= func_append compile_command " $wl$qarg" func_append finalize_command " $wl$qarg" continue ;; *) eval "$prev=\"\$arg\"" prev= continue ;; esac fi # test -n "$prev" prevarg=$arg case $arg in -all-static) if test -n "$link_static_flag"; then # See comment for -static flag below, for more details. func_append compile_command " $link_static_flag" func_append finalize_command " $link_static_flag" fi continue ;; -allow-undefined) # FIXME: remove this flag sometime in the future. func_fatal_error "'-allow-undefined' must not be used because it is the default" ;; -avoid-version) avoid_version=yes continue ;; -bindir) prev=bindir continue ;; -dlopen) prev=dlfiles continue ;; -dlpreopen) prev=dlprefiles continue ;; -export-dynamic) export_dynamic=yes continue ;; -export-symbols | -export-symbols-regex) if test -n "$export_symbols" || test -n "$export_symbols_regex"; then func_fatal_error "more than one -exported-symbols argument is not allowed" fi if test X-export-symbols = "X$arg"; then prev=expsyms else prev=expsyms_regex fi continue ;; -framework) prev=framework continue ;; -inst-prefix-dir) prev=inst_prefix continue ;; # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* # so, if we see these flags be careful not to treat them like -L -L[A-Z][A-Z]*:*) case $with_gcc/$host in no/*-*-irix* | /*-*-irix*) func_append compile_command " $arg" func_append finalize_command " $arg" ;; esac continue ;; -L*) func_stripname "-L" '' "$arg" if test -z "$func_stripname_result"; then if test "$#" -gt 0; then func_fatal_error "require no space between '-L' and '$1'" else func_fatal_error "need path for '-L' option" fi fi func_resolve_sysroot "$func_stripname_result" dir=$func_resolve_sysroot_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; *) absdir=`cd "$dir" && pwd` test -z "$absdir" && \ func_fatal_error "cannot determine absolute directory name of '$dir'" dir=$absdir ;; esac case "$deplibs " in *" -L$dir "* | *" $arg "*) # Will only happen for absolute or sysroot arguments ;; *) # Preserve sysroot, but never include relative directories case $dir in [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; *) func_append deplibs " -L$dir" ;; esac func_append lib_search_path " $dir" ;; esac case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` case :$dllsearchpath: in *":$dir:"*) ;; ::) dllsearchpath=$dir;; *) func_append dllsearchpath ":$dir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$testbindir;; *) func_append dllsearchpath ":$testbindir";; esac ;; esac continue ;; -l*) if test X-lc = "X$arg" || test X-lm = "X$arg"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) # These systems don't actually have a C or math library (as such) continue ;; *-*-os2*) # These systems don't actually have a C library (as such) test X-lc = "X$arg" && continue ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) # Do not include libc due to us having libc/libc_r. test X-lc = "X$arg" && continue ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C and math libraries are in the System framework func_append deplibs " System.ltframework" continue ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype test X-lc = "X$arg" && continue ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work test X-lc = "X$arg" && continue ;; esac elif test X-lc_r = "X$arg"; then case $host in *-*-openbsd* | *-*-freebsd* | *-*-dragonfly* | *-*-bitrig*) # Do not include libc_r directly, use -pthread flag. continue ;; esac fi func_append deplibs " $arg" continue ;; -mllvm) prev=mllvm continue ;; -module) module=yes continue ;; # Tru64 UNIX uses -model [arg] to determine the layout of C++ # classes, name mangling, and exception handling. # Darwin uses the -arch flag to determine output architecture. -model|-arch|-isysroot|--sysroot) func_append compiler_flags " $arg" func_append compile_command " $arg" func_append finalize_command " $arg" prev=xcompiler continue ;; -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) func_append compiler_flags " $arg" func_append compile_command " $arg" func_append finalize_command " $arg" case "$new_inherited_linker_flags " in *" $arg "*) ;; * ) func_append new_inherited_linker_flags " $arg" ;; esac continue ;; -multi_module) single_module=$wl-multi_module continue ;; -no-fast-install) fast_install=no continue ;; -no-install) case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) # The PATH hackery in wrapper scripts is required on Windows # and Darwin in order for the loader to find any dlls it needs. func_warning "'-no-install' is ignored for $host" func_warning "assuming '-no-fast-install' instead" fast_install=no ;; *) no_install=yes ;; esac continue ;; -no-undefined) allow_undefined=no continue ;; -objectlist) prev=objectlist continue ;; -os2dllname) prev=os2dllname continue ;; -o) prev=output ;; -precious-files-regex) prev=precious_regex continue ;; -release) prev=release continue ;; -rpath) prev=rpath continue ;; -R) prev=xrpath continue ;; -R*) func_stripname '-R' '' "$arg" dir=$func_stripname_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) ;; =*) func_stripname '=' '' "$dir" dir=$lt_sysroot$func_stripname_result ;; *) func_fatal_error "only absolute run-paths are allowed" ;; esac case "$xrpath " in *" $dir "*) ;; *) func_append xrpath " $dir" ;; esac continue ;; -shared) # The effects of -shared are defined in a previous loop. continue ;; -shrext) prev=shrext continue ;; -static | -static-libtool-libs) # The effects of -static are defined in a previous loop. # We used to do the same as -all-static on platforms that # didn't have a PIC flag, but the assumption that the effects # would be equivalent was wrong. It would break on at least # Digital Unix and AIX. continue ;; -thread-safe) thread_safe=yes continue ;; -version-info) prev=vinfo continue ;; -version-number) prev=vinfo vinfo_number=yes continue ;; -weak) prev=weak continue ;; -Wc,*) func_stripname '-Wc,' '' "$arg" args=$func_stripname_result arg= save_ifs=$IFS; IFS=, for flag in $args; do IFS=$save_ifs func_quote_for_eval "$flag" func_append arg " $func_quote_for_eval_result" func_append compiler_flags " $func_quote_for_eval_result" done IFS=$save_ifs func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Wl,*) func_stripname '-Wl,' '' "$arg" args=$func_stripname_result arg= save_ifs=$IFS; IFS=, for flag in $args; do IFS=$save_ifs func_quote_for_eval "$flag" func_append arg " $wl$func_quote_for_eval_result" func_append compiler_flags " $wl$func_quote_for_eval_result" func_append linker_flags " $func_quote_for_eval_result" done IFS=$save_ifs func_stripname ' ' '' "$arg" arg=$func_stripname_result ;; -Xcompiler) prev=xcompiler continue ;; -Xlinker) prev=xlinker continue ;; -XCClinker) prev=xcclinker continue ;; # -msg_* for osf cc -msg_*) func_quote_for_eval "$arg" arg=$func_quote_for_eval_result ;; # Flags to be passed through unchanged, with rationale: # -64, -mips[0-9] enable 64-bit mode for the SGI compiler # -r[0-9][0-9]* specify processor for the SGI compiler # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler # +DA*, +DD* enable 64-bit mode for the HP compiler # -q* compiler args for the IBM compiler # -m*, -t[45]*, -txscale* architecture-specific flags for GCC # -F/path path to uninstalled frameworks, gcc on darwin # -p, -pg, --coverage, -fprofile-* profiling flags for GCC # -fstack-protector* stack protector flags for GCC # @file GCC response files # -tp=* Portland pgcc target processor selection # --sysroot=* for sysroot support # -O*, -g*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization # -specs=* GCC specs files # -stdlib=* select c++ std lib with clang # -fsanitize=* Clang/GCC memory and address sanitizer -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*| \ -specs=*|-fsanitize=*) func_quote_for_eval "$arg" arg=$func_quote_for_eval_result func_append compile_command " $arg" func_append finalize_command " $arg" func_append compiler_flags " $arg" continue ;; -Z*) if test os2 = "`expr $host : '.*\(os2\)'`"; then # OS/2 uses -Zxxx to specify OS/2-specific options compiler_flags="$compiler_flags $arg" func_append compile_command " $arg" func_append finalize_command " $arg" case $arg in -Zlinker | -Zstack) prev=xcompiler ;; esac continue else # Otherwise treat like 'Some other compiler flag' below func_quote_for_eval "$arg" arg=$func_quote_for_eval_result fi ;; # Some other compiler flag. -* | +*) func_quote_for_eval "$arg" arg=$func_quote_for_eval_result ;; *.$objext) # A standard object. func_append objs " $arg" ;; *.lo) # A libtool-controlled object. # Check to see that this really is a libtool object. if func_lalib_unsafe_p "$arg"; then pic_object= non_pic_object= # Read the .lo file func_source "$arg" if test -z "$pic_object" || test -z "$non_pic_object" || test none = "$pic_object" && test none = "$non_pic_object"; then func_fatal_error "cannot find name of object for '$arg'" fi # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir=$func_dirname_result test none = "$pic_object" || { # Prepend the subdirectory the object is found in. pic_object=$xdir$pic_object if test dlfiles = "$prev"; then if test yes = "$build_libtool_libs" && test yes = "$dlopen_support"; then func_append dlfiles " $pic_object" prev= continue else # If libtool objects are unsupported, then we need to preload. prev=dlprefiles fi fi # CHECK ME: I think I busted this. -Ossama if test dlprefiles = "$prev"; then # Preload the old-style object. func_append dlprefiles " $pic_object" prev= fi # A PIC object. func_append libobjs " $pic_object" arg=$pic_object } # Non-PIC object. if test none != "$non_pic_object"; then # Prepend the subdirectory the object is found in. non_pic_object=$xdir$non_pic_object # A standard non-PIC object func_append non_pic_objects " $non_pic_object" if test -z "$pic_object" || test none = "$pic_object"; then arg=$non_pic_object fi else # If the PIC object exists, use it instead. # $xdir was prepended to $pic_object above. non_pic_object=$pic_object func_append non_pic_objects " $non_pic_object" fi else # Only an error if not doing a dry-run. if $opt_dry_run; then # Extract subdirectory from the argument. func_dirname "$arg" "/" "" xdir=$func_dirname_result func_lo2o "$arg" pic_object=$xdir$objdir/$func_lo2o_result non_pic_object=$xdir$func_lo2o_result func_append libobjs " $pic_object" func_append non_pic_objects " $non_pic_object" else func_fatal_error "'$arg' is not a valid libtool object" fi fi ;; *.$libext) # An archive. func_append deplibs " $arg" func_append old_deplibs " $arg" continue ;; *.la) # A libtool-controlled library. func_resolve_sysroot "$arg" if test dlfiles = "$prev"; then # This library was specified with -dlopen. func_append dlfiles " $func_resolve_sysroot_result" prev= elif test dlprefiles = "$prev"; then # The library was specified with -dlpreopen. func_append dlprefiles " $func_resolve_sysroot_result" prev= else func_append deplibs " $func_resolve_sysroot_result" fi continue ;; # Some other compiler argument. *) # Unknown arguments in both finalize_command and compile_command need # to be aesthetically quoted because they are evaled later. func_quote_for_eval "$arg" arg=$func_quote_for_eval_result ;; esac # arg # Now actually substitute the argument into the commands. if test -n "$arg"; then func_append compile_command " $arg" func_append finalize_command " $arg" fi done # argument parsing loop test -n "$prev" && \ func_fatal_help "the '$prevarg' option requires an argument" if test yes = "$export_dynamic" && test -n "$export_dynamic_flag_spec"; then eval arg=\"$export_dynamic_flag_spec\" func_append compile_command " $arg" func_append finalize_command " $arg" fi oldlibs= # calculate the name of the file, without its directory func_basename "$output" outputname=$func_basename_result libobjs_save=$libobjs if test -n "$shlibpath_var"; then # get the directories listed in $shlibpath_var eval shlib_search_path=\`\$ECHO \"\$$shlibpath_var\" \| \$SED \'s/:/ /g\'\` else shlib_search_path= fi eval sys_lib_search_path=\"$sys_lib_search_path_spec\" eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" # Definition is injected by LT_CONFIG during libtool generation. func_munge_path_list sys_lib_dlsearch_path "$LT_SYS_LIBRARY_PATH" func_dirname "$output" "/" "" output_objdir=$func_dirname_result$objdir func_to_tool_file "$output_objdir/" tool_output_objdir=$func_to_tool_file_result # Create the object directory. func_mkdir_p "$output_objdir" # Determine the type of output case $output in "") func_fatal_help "you must specify an output file" ;; *.$libext) linkmode=oldlib ;; *.lo | *.$objext) linkmode=obj ;; *.la) linkmode=lib ;; *) linkmode=prog ;; # Anything else should be a program. esac specialdeplibs= libs= # Find all interdependent deplibs by searching for libraries # that are linked more than once (e.g. -la -lb -la) for deplib in $deplibs; do if $opt_preserve_dup_deps; then case "$libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append libs " $deplib" done if test lib = "$linkmode"; then libs="$predeps $libs $compiler_lib_search_path $postdeps" # Compute libraries that are listed more than once in $predeps # $postdeps and mark them as special (i.e., whose duplicates are # not to be eliminated). pre_post_deps= if $opt_duplicate_compiler_generated_deps; then for pre_post_dep in $predeps $postdeps; do case "$pre_post_deps " in *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; esac func_append pre_post_deps " $pre_post_dep" done fi pre_post_deps= fi deplibs= newdependency_libs= newlib_search_path= need_relink=no # whether we're linking any uninstalled libtool libraries notinst_deplibs= # not-installed libtool libraries notinst_path= # paths that contain not-installed libtool libraries case $linkmode in lib) passes="conv dlpreopen link" for file in $dlfiles $dlprefiles; do case $file in *.la) ;; *) func_fatal_help "libraries can '-dlopen' only libtool libraries: $file" ;; esac done ;; prog) compile_deplibs= finalize_deplibs= alldeplibs=false newdlfiles= newdlprefiles= passes="conv scan dlopen dlpreopen link" ;; *) passes="conv" ;; esac for pass in $passes; do # The preopen pass in lib mode reverses $deplibs; put it back here # so that -L comes before libs that need it for instance... if test lib,link = "$linkmode,$pass"; then ## FIXME: Find the place where the list is rebuilt in the wrong ## order, and fix it there properly tmp_deplibs= for deplib in $deplibs; do tmp_deplibs="$deplib $tmp_deplibs" done deplibs=$tmp_deplibs fi if test lib,link = "$linkmode,$pass" || test prog,scan = "$linkmode,$pass"; then libs=$deplibs deplibs= fi if test prog = "$linkmode"; then case $pass in dlopen) libs=$dlfiles ;; dlpreopen) libs=$dlprefiles ;; link) libs="$deplibs %DEPLIBS%" test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs" ;; esac fi if test lib,dlpreopen = "$linkmode,$pass"; then # Collect and forward deplibs of preopened libtool libs for lib in $dlprefiles; do # Ignore non-libtool-libs dependency_libs= func_resolve_sysroot "$lib" case $lib in *.la) func_source "$func_resolve_sysroot_result" ;; esac # Collect preopened libtool deplibs, except any this library # has declared as weak libs for deplib in $dependency_libs; do func_basename "$deplib" deplib_base=$func_basename_result case " $weak_libs " in *" $deplib_base "*) ;; *) func_append deplibs " $deplib" ;; esac done done libs=$dlprefiles fi if test dlopen = "$pass"; then # Collect dlpreopened libraries save_deplibs=$deplibs deplibs= fi for deplib in $libs; do lib= found=false case $deplib in -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe \ |-threads|-fopenmp|-openmp|-mp|-xopenmp|-omp|-qsmp=*) if test prog,link = "$linkmode,$pass"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else func_append compiler_flags " $deplib" if test lib = "$linkmode"; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) func_append new_inherited_linker_flags " $deplib" ;; esac fi fi continue ;; -l*) if test lib != "$linkmode" && test prog != "$linkmode"; then func_warning "'-l' is ignored for archives/objects" continue fi func_stripname '-l' '' "$deplib" name=$func_stripname_result if test lib = "$linkmode"; then searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" else searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" fi for searchdir in $searchdirs; do for search_ext in .la $std_shrext .so .a; do # Search the libtool library lib=$searchdir/lib$name$search_ext if test -f "$lib"; then if test .la = "$search_ext"; then found=: else found=false fi break 2 fi done done if $found; then # deplib is a libtool library # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, # We need to do some special things here, and not later. if test yes = "$allow_libtool_libs_with_static_runtimes"; then case " $predeps $postdeps " in *" $deplib "*) if func_lalib_p "$lib"; then library_names= old_library= func_source "$lib" for l in $old_library $library_names; do ll=$l done if test "X$ll" = "X$old_library"; then # only static version available found=false func_dirname "$lib" "" "." ladir=$func_dirname_result lib=$ladir/$old_library if test prog,link = "$linkmode,$pass"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" fi continue fi fi ;; *) ;; esac fi else # deplib doesn't seem to be a libtool library if test prog,link = "$linkmode,$pass"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" test lib = "$linkmode" && newdependency_libs="$deplib $newdependency_libs" fi continue fi ;; # -l *.ltframework) if test prog,link = "$linkmode,$pass"; then compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else deplibs="$deplib $deplibs" if test lib = "$linkmode"; then case "$new_inherited_linker_flags " in *" $deplib "*) ;; * ) func_append new_inherited_linker_flags " $deplib" ;; esac fi fi continue ;; -L*) case $linkmode in lib) deplibs="$deplib $deplibs" test conv = "$pass" && continue newdependency_libs="$deplib $newdependency_libs" func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; prog) if test conv = "$pass"; then deplibs="$deplib $deplibs" continue fi if test scan = "$pass"; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; *) func_warning "'-L' is ignored for archives/objects" ;; esac # linkmode continue ;; # -L -R*) if test link = "$pass"; then func_stripname '-R' '' "$deplib" func_resolve_sysroot "$func_stripname_result" dir=$func_resolve_sysroot_result # Make sure the xrpath contains only unique directories. case "$xrpath " in *" $dir "*) ;; *) func_append xrpath " $dir" ;; esac fi deplibs="$deplib $deplibs" continue ;; *.la) func_resolve_sysroot "$deplib" lib=$func_resolve_sysroot_result ;; *.$libext) if test conv = "$pass"; then deplibs="$deplib $deplibs" continue fi case $linkmode in lib) # Linking convenience modules into shared libraries is allowed, # but linking other static libraries is non-portable. case " $dlpreconveniencelibs " in *" $deplib "*) ;; *) valid_a_lib=false case $deplibs_check_method in match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ | $EGREP "$match_pattern_regex" > /dev/null; then valid_a_lib=: fi ;; pass_all) valid_a_lib=: ;; esac if $valid_a_lib; then echo $ECHO "*** Warning: Linking the shared library $output against the" $ECHO "*** static library $deplib is not portable!" deplibs="$deplib $deplibs" else echo $ECHO "*** Warning: Trying to link with static lib archive $deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because the file extensions .$libext of this argument makes me believe" echo "*** that it is just a static archive that I should not use here." fi ;; esac continue ;; prog) if test link != "$pass"; then deplibs="$deplib $deplibs" else compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" fi continue ;; esac # linkmode ;; # *.$libext *.lo | *.$objext) if test conv = "$pass"; then deplibs="$deplib $deplibs" elif test prog = "$linkmode"; then if test dlpreopen = "$pass" || test yes != "$dlopen_support" || test no = "$build_libtool_libs"; then # If there is no dlopen support or we're linking statically, # we need to preload. func_append newdlprefiles " $deplib" compile_deplibs="$deplib $compile_deplibs" finalize_deplibs="$deplib $finalize_deplibs" else func_append newdlfiles " $deplib" fi fi continue ;; %DEPLIBS%) alldeplibs=: continue ;; esac # case $deplib $found || test -f "$lib" \ || func_fatal_error "cannot find the library '$lib' or unhandled argument '$deplib'" # Check to see that this really is a libtool archive. func_lalib_unsafe_p "$lib" \ || func_fatal_error "'$lib' is not a valid libtool archive" func_dirname "$lib" "" "." ladir=$func_dirname_result dlname= dlopen= dlpreopen= libdir= library_names= old_library= inherited_linker_flags= # If the library was installed with an old release of libtool, # it will not redefine variables installed, or shouldnotlink installed=yes shouldnotlink=no avoidtemprpath= # Read the .la file func_source "$lib" # Convert "-framework foo" to "foo.ltframework" if test -n "$inherited_linker_flags"; then tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do case " $new_inherited_linker_flags " in *" $tmp_inherited_linker_flag "*) ;; *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; esac done fi dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` if test lib,link = "$linkmode,$pass" || test prog,scan = "$linkmode,$pass" || { test prog != "$linkmode" && test lib != "$linkmode"; }; then test -n "$dlopen" && func_append dlfiles " $dlopen" test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" fi if test conv = "$pass"; then # Only check for convenience libraries deplibs="$lib $deplibs" if test -z "$libdir"; then if test -z "$old_library"; then func_fatal_error "cannot find name of link library for '$lib'" fi # It is a libtool convenience library, so add in its objects. func_append convenience " $ladir/$objdir/$old_library" func_append old_convenience " $ladir/$objdir/$old_library" tmp_libs= for deplib in $dependency_libs; do deplibs="$deplib $deplibs" if $opt_preserve_dup_deps; then case "$tmp_libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append tmp_libs " $deplib" done elif test prog != "$linkmode" && test lib != "$linkmode"; then func_fatal_error "'$lib' is not a convenience library" fi continue fi # $pass = conv # Get the name of the library we link against. linklib= if test -n "$old_library" && { test yes = "$prefer_static_libs" || test built,no = "$prefer_static_libs,$installed"; }; then linklib=$old_library else for l in $old_library $library_names; do linklib=$l done fi if test -z "$linklib"; then func_fatal_error "cannot find name of link library for '$lib'" fi # This library was specified with -dlopen. if test dlopen = "$pass"; then test -z "$libdir" \ && func_fatal_error "cannot -dlopen a convenience library: '$lib'" if test -z "$dlname" || test yes != "$dlopen_support" || test no = "$build_libtool_libs" then # If there is no dlname, no dlopen support or we're linking # statically, we need to preload. We also need to preload any # dependent libraries so libltdl's deplib preloader doesn't # bomb out in the load deplibs phase. func_append dlprefiles " $lib $dependency_libs" else func_append newdlfiles " $lib" fi continue fi # $pass = dlopen # We need an absolute path. case $ladir in [\\/]* | [A-Za-z]:[\\/]*) abs_ladir=$ladir ;; *) abs_ladir=`cd "$ladir" && pwd` if test -z "$abs_ladir"; then func_warning "cannot determine absolute directory name of '$ladir'" func_warning "passing it literally to the linker, although it might fail" abs_ladir=$ladir fi ;; esac func_basename "$lib" laname=$func_basename_result # Find the relevant object directory and library name. if test yes = "$installed"; then if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then func_warning "library '$lib' was moved." dir=$ladir absdir=$abs_ladir libdir=$abs_ladir else dir=$lt_sysroot$libdir absdir=$lt_sysroot$libdir fi test yes = "$hardcode_automatic" && avoidtemprpath=yes else if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then dir=$ladir absdir=$abs_ladir # Remove this search path later func_append notinst_path " $abs_ladir" else dir=$ladir/$objdir absdir=$abs_ladir/$objdir # Remove this search path later func_append notinst_path " $abs_ladir" fi fi # $installed = yes func_stripname 'lib' '.la' "$laname" name=$func_stripname_result # This library was specified with -dlpreopen. if test dlpreopen = "$pass"; then if test -z "$libdir" && test prog = "$linkmode"; then func_fatal_error "only libraries may -dlpreopen a convenience library: '$lib'" fi case $host in # special handling for platforms with PE-DLLs. *cygwin* | *mingw* | *cegcc* ) # Linker will automatically link against shared library if both # static and shared are present. Therefore, ensure we extract # symbols from the import library if a shared library is present # (otherwise, the dlopen module name will be incorrect). We do # this by putting the import library name into $newdlprefiles. # We recover the dlopen module name by 'saving' the la file # name in a special purpose variable, and (later) extracting the # dlname from the la file. if test -n "$dlname"; then func_tr_sh "$dir/$linklib" eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" func_append newdlprefiles " $dir/$linklib" else func_append newdlprefiles " $dir/$old_library" # Keep a list of preopened convenience libraries to check # that they are being used correctly in the link pass. test -z "$libdir" && \ func_append dlpreconveniencelibs " $dir/$old_library" fi ;; * ) # Prefer using a static library (so that no silly _DYNAMIC symbols # are required to link). if test -n "$old_library"; then func_append newdlprefiles " $dir/$old_library" # Keep a list of preopened convenience libraries to check # that they are being used correctly in the link pass. test -z "$libdir" && \ func_append dlpreconveniencelibs " $dir/$old_library" # Otherwise, use the dlname, so that lt_dlopen finds it. elif test -n "$dlname"; then func_append newdlprefiles " $dir/$dlname" else func_append newdlprefiles " $dir/$linklib" fi ;; esac fi # $pass = dlpreopen if test -z "$libdir"; then # Link the convenience library if test lib = "$linkmode"; then deplibs="$dir/$old_library $deplibs" elif test prog,link = "$linkmode,$pass"; then compile_deplibs="$dir/$old_library $compile_deplibs" finalize_deplibs="$dir/$old_library $finalize_deplibs" else deplibs="$lib $deplibs" # used for prog,scan pass fi continue fi if test prog = "$linkmode" && test link != "$pass"; then func_append newlib_search_path " $ladir" deplibs="$lib $deplibs" linkalldeplibs=false if test no != "$link_all_deplibs" || test -z "$library_names" || test no = "$build_libtool_libs"; then linkalldeplibs=: fi tmp_libs= for deplib in $dependency_libs; do case $deplib in -L*) func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result" func_append newlib_search_path " $func_resolve_sysroot_result" ;; esac # Need to link against all dependency_libs? if $linkalldeplibs; then deplibs="$deplib $deplibs" else # Need to hardcode shared library paths # or/and link against static libraries newdependency_libs="$deplib $newdependency_libs" fi if $opt_preserve_dup_deps; then case "$tmp_libs " in *" $deplib "*) func_append specialdeplibs " $deplib" ;; esac fi func_append tmp_libs " $deplib" done # for deplib continue fi # $linkmode = prog... if test prog,link = "$linkmode,$pass"; then if test -n "$library_names" && { { test no = "$prefer_static_libs" || test built,yes = "$prefer_static_libs,$installed"; } || test -z "$old_library"; }; then # We need to hardcode the library path if test -n "$shlibpath_var" && test -z "$avoidtemprpath"; then # Make sure the rpath contains only unique directories. case $temp_rpath: in *"$absdir:"*) ;; *) func_append temp_rpath "$absdir:" ;; esac fi # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) func_append compile_rpath " $absdir" ;; esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac ;; esac fi # $linkmode,$pass = prog,link... if $alldeplibs && { test pass_all = "$deplibs_check_method" || { test yes = "$build_libtool_libs" && test -n "$library_names"; }; }; then # We only need to search for static libraries continue fi fi link_static=no # Whether the deplib will be linked statically use_static_libs=$prefer_static_libs if test built = "$use_static_libs" && test yes = "$installed"; then use_static_libs=no fi if test -n "$library_names" && { test no = "$use_static_libs" || test -z "$old_library"; }; then case $host in *cygwin* | *mingw* | *cegcc* | *os2*) # No point in relinking DLLs because paths are not encoded func_append notinst_deplibs " $lib" need_relink=no ;; *) if test no = "$installed"; then func_append notinst_deplibs " $lib" need_relink=yes fi ;; esac # This is a shared library # Warn about portability, can't link against -module's on some # systems (darwin). Don't bleat about dlopened modules though! dlopenmodule= for dlpremoduletest in $dlprefiles; do if test "X$dlpremoduletest" = "X$lib"; then dlopenmodule=$dlpremoduletest break fi done if test -z "$dlopenmodule" && test yes = "$shouldnotlink" && test link = "$pass"; then echo if test prog = "$linkmode"; then $ECHO "*** Warning: Linking the executable $output against the loadable module" else $ECHO "*** Warning: Linking the shared library $output against the loadable module" fi $ECHO "*** $linklib is not portable!" fi if test lib = "$linkmode" && test yes = "$hardcode_into_libs"; then # Hardcode the library path. # Skip directories that are in the system default run-time # search path. case " $sys_lib_dlsearch_path " in *" $absdir "*) ;; *) case "$compile_rpath " in *" $absdir "*) ;; *) func_append compile_rpath " $absdir" ;; esac ;; esac case " $sys_lib_dlsearch_path " in *" $libdir "*) ;; *) case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac ;; esac fi if test -n "$old_archive_from_expsyms_cmds"; then # figure out the soname set dummy $library_names shift realname=$1 shift libname=`eval "\\$ECHO \"$libname_spec\""` # use dlname if we got it. it's perfectly good, no? if test -n "$dlname"; then soname=$dlname elif test -n "$soname_spec"; then # bleh windows case $host in *cygwin* | mingw* | *cegcc* | *os2*) func_arith $current - $age major=$func_arith_result versuffix=-$major ;; esac eval soname=\"$soname_spec\" else soname=$realname fi # Make a new name for the extract_expsyms_cmds to use soroot=$soname func_basename "$soroot" soname=$func_basename_result func_stripname 'lib' '.dll' "$soname" newlib=libimp-$func_stripname_result.a # If the library has no export list, then create one now if test -f "$output_objdir/$soname-def"; then : else func_verbose "extracting exported symbol list from '$soname'" func_execute_cmds "$extract_expsyms_cmds" 'exit $?' fi # Create $newlib if test -f "$output_objdir/$newlib"; then :; else func_verbose "generating import library for '$soname'" func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' fi # make sure the library variables are pointing to the new library dir=$output_objdir linklib=$newlib fi # test -n "$old_archive_from_expsyms_cmds" if test prog = "$linkmode" || test relink != "$opt_mode"; then add_shlibpath= add_dir= add= lib_linked=yes case $hardcode_action in immediate | unsupported) if test no = "$hardcode_direct"; then add=$dir/$linklib case $host in *-*-sco3.2v5.0.[024]*) add_dir=-L$dir ;; *-*-sysv4*uw2*) add_dir=-L$dir ;; *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ *-*-unixware7*) add_dir=-L$dir ;; *-*-darwin* ) # if the lib is a (non-dlopened) module then we cannot # link against it, someone is ignoring the earlier warnings if /usr/bin/file -L $add 2> /dev/null | $GREP ": [^:]* bundle" >/dev/null; then if test "X$dlopenmodule" != "X$lib"; then $ECHO "*** Warning: lib $linklib is a module, not a shared library" if test -z "$old_library"; then echo echo "*** And there doesn't seem to be a static archive available" echo "*** The link will probably fail, sorry" else add=$dir/$old_library fi elif test -n "$old_library"; then add=$dir/$old_library fi fi esac elif test no = "$hardcode_minus_L"; then case $host in *-*-sunos*) add_shlibpath=$dir ;; esac add_dir=-L$dir add=-l$name elif test no = "$hardcode_shlibpath_var"; then add_shlibpath=$dir add=-l$name else lib_linked=no fi ;; relink) if test yes = "$hardcode_direct" && test no = "$hardcode_direct_absolute"; then add=$dir/$linklib elif test yes = "$hardcode_minus_L"; then add_dir=-L$absdir # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) func_append add_dir " -L$inst_prefix_dir$libdir" ;; esac fi add=-l$name elif test yes = "$hardcode_shlibpath_var"; then add_shlibpath=$dir add=-l$name else lib_linked=no fi ;; *) lib_linked=no ;; esac if test yes != "$lib_linked"; then func_fatal_configuration "unsupported hardcode properties" fi if test -n "$add_shlibpath"; then case :$compile_shlibpath: in *":$add_shlibpath:"*) ;; *) func_append compile_shlibpath "$add_shlibpath:" ;; esac fi if test prog = "$linkmode"; then test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" test -n "$add" && compile_deplibs="$add $compile_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" if test yes != "$hardcode_direct" && test yes != "$hardcode_minus_L" && test yes = "$hardcode_shlibpath_var"; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) func_append finalize_shlibpath "$libdir:" ;; esac fi fi fi if test prog = "$linkmode" || test relink = "$opt_mode"; then add_shlibpath= add_dir= add= # Finalize command for both is simple: just hardcode it. if test yes = "$hardcode_direct" && test no = "$hardcode_direct_absolute"; then add=$libdir/$linklib elif test yes = "$hardcode_minus_L"; then add_dir=-L$libdir add=-l$name elif test yes = "$hardcode_shlibpath_var"; then case :$finalize_shlibpath: in *":$libdir:"*) ;; *) func_append finalize_shlibpath "$libdir:" ;; esac add=-l$name elif test yes = "$hardcode_automatic"; then if test -n "$inst_prefix_dir" && test -f "$inst_prefix_dir$libdir/$linklib"; then add=$inst_prefix_dir$libdir/$linklib else add=$libdir/$linklib fi else # We cannot seem to hardcode it, guess we'll fake it. add_dir=-L$libdir # Try looking first in the location we're being installed to. if test -n "$inst_prefix_dir"; then case $libdir in [\\/]*) func_append add_dir " -L$inst_prefix_dir$libdir" ;; esac fi add=-l$name fi if test prog = "$linkmode"; then test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" test -n "$add" && finalize_deplibs="$add $finalize_deplibs" else test -n "$add_dir" && deplibs="$add_dir $deplibs" test -n "$add" && deplibs="$add $deplibs" fi fi elif test prog = "$linkmode"; then # Here we assume that one of hardcode_direct or hardcode_minus_L # is not unsupported. This is valid on all known static and # shared platforms. if test unsupported != "$hardcode_direct"; then test -n "$old_library" && linklib=$old_library compile_deplibs="$dir/$linklib $compile_deplibs" finalize_deplibs="$dir/$linklib $finalize_deplibs" else compile_deplibs="-l$name -L$dir $compile_deplibs" finalize_deplibs="-l$name -L$dir $finalize_deplibs" fi elif test yes = "$build_libtool_libs"; then # Not a shared library if test pass_all != "$deplibs_check_method"; then # We're trying link a shared library against a static one # but the system doesn't support it. # Just print a warning and add the library to dependency_libs so # that the program can be linked against the static library. echo $ECHO "*** Warning: This system cannot link to static lib archive $lib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have." if test yes = "$module"; then echo "*** But as you try to build a module library, libtool will still create " echo "*** a static module, that should work as long as the dlopening application" echo "*** is linked with the -dlopen flag to resolve symbols at runtime." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" echo "*** lists from a program, using 'nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." echo "*** 'nm' from GNU binutils and a full rebuild may help." fi if test no = "$build_old_libs"; then build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi else deplibs="$dir/$old_library $deplibs" link_static=yes fi fi # link shared/static library? if test lib = "$linkmode"; then if test -n "$dependency_libs" && { test yes != "$hardcode_into_libs" || test yes = "$build_old_libs" || test yes = "$link_static"; }; then # Extract -R from dependency_libs temp_deplibs= for libdir in $dependency_libs; do case $libdir in -R*) func_stripname '-R' '' "$libdir" temp_xrpath=$func_stripname_result case " $xrpath " in *" $temp_xrpath "*) ;; *) func_append xrpath " $temp_xrpath";; esac;; *) func_append temp_deplibs " $libdir";; esac done dependency_libs=$temp_deplibs fi func_append newlib_search_path " $absdir" # Link against this library test no = "$link_static" && newdependency_libs="$abs_ladir/$laname $newdependency_libs" # ... and its dependency_libs tmp_libs= for deplib in $dependency_libs; do newdependency_libs="$deplib $newdependency_libs" case $deplib in -L*) func_stripname '-L' '' "$deplib" func_resolve_sysroot "$func_stripname_result";; *) func_resolve_sysroot "$deplib" ;; esac if $opt_preserve_dup_deps; then case "$tmp_libs " in *" $func_resolve_sysroot_result "*) func_append specialdeplibs " $func_resolve_sysroot_result" ;; esac fi func_append tmp_libs " $func_resolve_sysroot_result" done if test no != "$link_all_deplibs"; then # Add the search paths of all dependency libraries for deplib in $dependency_libs; do path= case $deplib in -L*) path=$deplib ;; *.la) func_resolve_sysroot "$deplib" deplib=$func_resolve_sysroot_result func_dirname "$deplib" "" "." dir=$func_dirname_result # We need an absolute path. case $dir in [\\/]* | [A-Za-z]:[\\/]*) absdir=$dir ;; *) absdir=`cd "$dir" && pwd` if test -z "$absdir"; then func_warning "cannot determine absolute directory name of '$dir'" absdir=$dir fi ;; esac if $GREP "^installed=no" $deplib > /dev/null; then case $host in *-*-darwin*) depdepl= eval deplibrary_names=`$SED -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` if test -n "$deplibrary_names"; then for tmp in $deplibrary_names; do depdepl=$tmp done if test -f "$absdir/$objdir/$depdepl"; then depdepl=$absdir/$objdir/$depdepl darwin_install_name=`$OTOOL -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` if test -z "$darwin_install_name"; then darwin_install_name=`$OTOOL64 -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` fi func_append compiler_flags " $wl-dylib_file $wl$darwin_install_name:$depdepl" func_append linker_flags " -dylib_file $darwin_install_name:$depdepl" path= fi fi ;; *) path=-L$absdir/$objdir ;; esac else eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` test -z "$libdir" && \ func_fatal_error "'$deplib' is not a valid libtool archive" test "$absdir" != "$libdir" && \ func_warning "'$deplib' seems to be moved" path=-L$absdir fi ;; esac case " $deplibs " in *" $path "*) ;; *) deplibs="$path $deplibs" ;; esac done fi # link_all_deplibs != no fi # linkmode = lib done # for deplib in $libs if test link = "$pass"; then if test prog = "$linkmode"; then compile_deplibs="$new_inherited_linker_flags $compile_deplibs" finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" else compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` fi fi dependency_libs=$newdependency_libs if test dlpreopen = "$pass"; then # Link the dlpreopened libraries before other libraries for deplib in $save_deplibs; do deplibs="$deplib $deplibs" done fi if test dlopen != "$pass"; then test conv = "$pass" || { # Make sure lib_search_path contains only unique directories. lib_search_path= for dir in $newlib_search_path; do case "$lib_search_path " in *" $dir "*) ;; *) func_append lib_search_path " $dir" ;; esac done newlib_search_path= } if test prog,link = "$linkmode,$pass"; then vars="compile_deplibs finalize_deplibs" else vars=deplibs fi for var in $vars dependency_libs; do # Add libraries to $var in reverse order eval tmp_libs=\"\$$var\" new_libs= for deplib in $tmp_libs; do # FIXME: Pedantically, this is the right thing to do, so # that some nasty dependency loop isn't accidentally # broken: #new_libs="$deplib $new_libs" # Pragmatically, this seems to cause very few problems in # practice: case $deplib in -L*) new_libs="$deplib $new_libs" ;; -R*) ;; *) # And here is the reason: when a library appears more # than once as an explicit dependence of a library, or # is implicitly linked in more than once by the # compiler, it is considered special, and multiple # occurrences thereof are not removed. Compare this # with having the same library being listed as a # dependency of multiple other libraries: in this case, # we know (pedantically, we assume) the library does not # need to be listed more than once, so we keep only the # last copy. This is not always right, but it is rare # enough that we require users that really mean to play # such unportable linking tricks to link the library # using -Wl,-lname, so that libtool does not consider it # for duplicate removal. case " $specialdeplibs " in *" $deplib "*) new_libs="$deplib $new_libs" ;; *) case " $new_libs " in *" $deplib "*) ;; *) new_libs="$deplib $new_libs" ;; esac ;; esac ;; esac done tmp_libs= for deplib in $new_libs; do case $deplib in -L*) case " $tmp_libs " in *" $deplib "*) ;; *) func_append tmp_libs " $deplib" ;; esac ;; *) func_append tmp_libs " $deplib" ;; esac done eval $var=\"$tmp_libs\" done # for var fi # Add Sun CC postdeps if required: test CXX = "$tagname" && { case $host_os in linux*) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 func_suncc_cstd_abi if test no != "$suncc_use_cstd_abi"; then func_append postdeps ' -library=Cstd -library=Crun' fi ;; esac ;; solaris*) func_cc_basename "$CC" case $func_cc_basename_result in CC* | sunCC*) func_suncc_cstd_abi if test no != "$suncc_use_cstd_abi"; then func_append postdeps ' -library=Cstd -library=Crun' fi ;; esac ;; esac } # Last step: remove runtime libs from dependency_libs # (they stay in deplibs) tmp_libs= for i in $dependency_libs; do case " $predeps $postdeps $compiler_lib_search_path " in *" $i "*) i= ;; esac if test -n "$i"; then func_append tmp_libs " $i" fi done dependency_libs=$tmp_libs done # for pass if test prog = "$linkmode"; then dlfiles=$newdlfiles fi if test prog = "$linkmode" || test lib = "$linkmode"; then dlprefiles=$newdlprefiles fi case $linkmode in oldlib) if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then func_warning "'-dlopen' is ignored for archives" fi case " $deplibs" in *\ -l* | *\ -L*) func_warning "'-l' and '-L' are ignored for archives" ;; esac test -n "$rpath" && \ func_warning "'-rpath' is ignored for archives" test -n "$xrpath" && \ func_warning "'-R' is ignored for archives" test -n "$vinfo" && \ func_warning "'-version-info/-version-number' is ignored for archives" test -n "$release" && \ func_warning "'-release' is ignored for archives" test -n "$export_symbols$export_symbols_regex" && \ func_warning "'-export-symbols' is ignored for archives" # Now set the variables for building old libraries. build_libtool_libs=no oldlibs=$output func_append objs "$old_deplibs" ;; lib) # Make sure we only generate libraries of the form 'libNAME.la'. case $outputname in lib*) func_stripname 'lib' '.la' "$outputname" name=$func_stripname_result eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" ;; *) test no = "$module" \ && func_fatal_help "libtool library '$output' must begin with 'lib'" if test no != "$need_lib_prefix"; then # Add the "lib" prefix for modules if required func_stripname '' '.la' "$outputname" name=$func_stripname_result eval shared_ext=\"$shrext_cmds\" eval libname=\"$libname_spec\" else func_stripname '' '.la' "$outputname" libname=$func_stripname_result fi ;; esac if test -n "$objs"; then if test pass_all != "$deplibs_check_method"; then func_fatal_error "cannot build libtool library '$output' from non-libtool objects on this host:$objs" else echo $ECHO "*** Warning: Linking the shared library $output against the non-libtool" $ECHO "*** objects $objs is not portable!" func_append libobjs " $objs" fi fi test no = "$dlself" \ || func_warning "'-dlopen self' is ignored for libtool libraries" set dummy $rpath shift test 1 -lt "$#" \ && func_warning "ignoring multiple '-rpath's for a libtool library" install_libdir=$1 oldlibs= if test -z "$rpath"; then if test yes = "$build_libtool_libs"; then # Building a libtool convenience library. # Some compilers have problems with a '.al' extension so # convenience libraries should have the same extension an # archive normally would. oldlibs="$output_objdir/$libname.$libext $oldlibs" build_libtool_libs=convenience build_old_libs=yes fi test -n "$vinfo" && \ func_warning "'-version-info/-version-number' is ignored for convenience libraries" test -n "$release" && \ func_warning "'-release' is ignored for convenience libraries" else # Parse the version information argument. save_ifs=$IFS; IFS=: set dummy $vinfo 0 0 0 shift IFS=$save_ifs test -n "$7" && \ func_fatal_help "too many parameters to '-version-info'" # convert absolute version numbers to libtool ages # this retains compatibility with .la files and attempts # to make the code below a bit more comprehensible case $vinfo_number in yes) number_major=$1 number_minor=$2 number_revision=$3 # # There are really only two kinds -- those that # use the current revision as the major version # and those that subtract age and use age as # a minor version. But, then there is irix # that has an extra 1 added just for fun # case $version_type in # correct linux to gnu/linux during the next big refactor darwin|freebsd-elf|linux|osf|windows|none) func_arith $number_major + $number_minor current=$func_arith_result age=$number_minor revision=$number_revision ;; freebsd-aout|qnx|sunos) current=$number_major revision=$number_minor age=0 ;; irix|nonstopux) func_arith $number_major + $number_minor current=$func_arith_result age=$number_minor revision=$number_minor lt_irix_increment=no ;; *) func_fatal_configuration "$modename: unknown library version type '$version_type'" ;; esac ;; no) current=$1 revision=$2 age=$3 ;; esac # Check that each of the things are valid numbers. case $current in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "CURRENT '$current' must be a nonnegative integer" func_fatal_error "'$vinfo' is not valid version information" ;; esac case $revision in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "REVISION '$revision' must be a nonnegative integer" func_fatal_error "'$vinfo' is not valid version information" ;; esac case $age in 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; *) func_error "AGE '$age' must be a nonnegative integer" func_fatal_error "'$vinfo' is not valid version information" ;; esac if test "$age" -gt "$current"; then func_error "AGE '$age' is greater than the current interface number '$current'" func_fatal_error "'$vinfo' is not valid version information" fi # Calculate the version variables. major= versuffix= verstring= case $version_type in none) ;; darwin) # Like Linux, but with the current version available in # verstring for coding it into the library header func_arith $current - $age major=.$func_arith_result versuffix=$major.$age.$revision # Darwin ld doesn't like 0 for these options... func_arith $current + 1 minor_current=$func_arith_result xlcverstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" # On Darwin other compilers case $CC in nagfor*) verstring="$wl-compatibility_version $wl$minor_current $wl-current_version $wl$minor_current.$revision" ;; *) verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" ;; esac ;; freebsd-aout) major=.$current versuffix=.$current.$revision ;; freebsd-elf) func_arith $current - $age major=.$func_arith_result versuffix=$major.$age.$revision ;; irix | nonstopux) if test no = "$lt_irix_increment"; then func_arith $current - $age else func_arith $current - $age + 1 fi major=$func_arith_result case $version_type in nonstopux) verstring_prefix=nonstopux ;; *) verstring_prefix=sgi ;; esac verstring=$verstring_prefix$major.$revision # Add in all the interfaces that we are compatible with. loop=$revision while test 0 -ne "$loop"; do func_arith $revision - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result verstring=$verstring_prefix$major.$iface:$verstring done # Before this point, $major must not contain '.'. major=.$major versuffix=$major.$revision ;; linux) # correct to gnu/linux during the next big refactor func_arith $current - $age major=.$func_arith_result versuffix=$major.$age.$revision ;; osf) func_arith $current - $age major=.$func_arith_result versuffix=.$current.$age.$revision verstring=$current.$age.$revision # Add in all the interfaces that we are compatible with. loop=$age while test 0 -ne "$loop"; do func_arith $current - $loop iface=$func_arith_result func_arith $loop - 1 loop=$func_arith_result verstring=$verstring:$iface.0 done # Make executables depend on our current version. func_append verstring ":$current.0" ;; qnx) major=.$current versuffix=.$current ;; sco) major=.$current versuffix=.$current ;; sunos) major=.$current versuffix=.$current.$revision ;; windows) # Use '-' rather than '.', since we only want one # extension on DOS 8.3 file systems. func_arith $current - $age major=$func_arith_result versuffix=-$major ;; *) func_fatal_configuration "unknown library version type '$version_type'" ;; esac # Clear the version info if we defaulted, and they specified a release. if test -z "$vinfo" && test -n "$release"; then major= case $version_type in darwin) # we can't check for "0.0" in archive_cmds due to quoting # problems, so we reset it completely verstring= ;; *) verstring=0.0 ;; esac if test no = "$need_version"; then versuffix= else versuffix=.0.0 fi fi # Remove version info from name if versioning should be avoided if test yes,no = "$avoid_version,$need_version"; then major= versuffix= verstring= fi # Check to see if the archive will have undefined symbols. if test yes = "$allow_undefined"; then if test unsupported = "$allow_undefined_flag"; then if test yes = "$build_old_libs"; then func_warning "undefined symbols not allowed in $host shared libraries; building static only" build_libtool_libs=no else func_fatal_error "can't build $host shared library unless -no-undefined is specified" fi fi else # Don't allow undefined symbols. allow_undefined_flag=$no_undefined_flag fi fi func_generate_dlsyms "$libname" "$libname" : func_append libobjs " $symfileobj" test " " = "$libobjs" && libobjs= if test relink != "$opt_mode"; then # Remove our outputs, but don't remove object files since they # may have been created when compiling PIC objects. removelist= tempremovelist=`$ECHO "$output_objdir/*"` for p in $tempremovelist; do case $p in *.$objext | *.gcno) ;; $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/$libname$release.*) if test -n "$precious_files_regex"; then if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 then continue fi fi func_append removelist " $p" ;; *) ;; esac done test -n "$removelist" && \ func_show_eval "${RM}r \$removelist" fi # Now set the variables for building old libraries. if test yes = "$build_old_libs" && test convenience != "$build_libtool_libs"; then func_append oldlibs " $output_objdir/$libname.$libext" # Transform .lo files to .o files. oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; $lo2o" | $NL2SP` fi # Eliminate all temporary directories. #for path in $notinst_path; do # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"` #done if test -n "$xrpath"; then # If the user specified any rpath flags, then add them. temp_xrpath= for libdir in $xrpath; do func_replace_sysroot "$libdir" func_append temp_xrpath " -R$func_replace_sysroot_result" case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac done if test yes != "$hardcode_into_libs" || test yes = "$build_old_libs"; then dependency_libs="$temp_xrpath $dependency_libs" fi fi # Make sure dlfiles contains only unique files that won't be dlpreopened old_dlfiles=$dlfiles dlfiles= for lib in $old_dlfiles; do case " $dlprefiles $dlfiles " in *" $lib "*) ;; *) func_append dlfiles " $lib" ;; esac done # Make sure dlprefiles contains only unique files old_dlprefiles=$dlprefiles dlprefiles= for lib in $old_dlprefiles; do case "$dlprefiles " in *" $lib "*) ;; *) func_append dlprefiles " $lib" ;; esac done if test yes = "$build_libtool_libs"; then if test -n "$rpath"; then case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) # these systems don't actually have a c library (as such)! ;; *-*-rhapsody* | *-*-darwin1.[012]) # Rhapsody C library is in the System framework func_append deplibs " System.ltframework" ;; *-*-netbsd*) # Don't link with libc until the a.out ld.so is fixed. ;; *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) # Do not include libc due to us having libc/libc_r. ;; *-*-sco3.2v5* | *-*-sco5v6*) # Causes problems with __ctype ;; *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) # Compiler inserts libc in the correct place for threads to work ;; *) # Add libc to deplibs on all other systems if necessary. if test yes = "$build_libtool_need_lc"; then func_append deplibs " -lc" fi ;; esac fi # Transform deplibs into only deplibs that can be linked in shared. name_save=$name libname_save=$libname release_save=$release versuffix_save=$versuffix major_save=$major # I'm not sure if I'm treating the release correctly. I think # release should show up in the -l (ie -lgmp5) so we don't want to # add it in twice. Is that correct? release= versuffix= major= newdeplibs= droppeddeps=no case $deplibs_check_method in pass_all) # Don't check for shared/static. Everything works. # This might be a little naive. We might want to check # whether the library exists or not. But this is on # osf3 & osf4 and I'm not really sure... Just # implementing what was already the behavior. newdeplibs=$deplibs ;; test_compile) # This code stresses the "libraries are programs" paradigm to its # limits. Maybe even breaks it. We compile a program, linking it # against the deplibs as a proxy for the library. Then we can check # whether they linked in statically or dynamically with ldd. $opt_dry_run || $RM conftest.c cat > conftest.c </dev/null` $nocaseglob else potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` fi for potent_lib in $potential_libs; do # Follow soft links. if ls -lLd "$potent_lib" 2>/dev/null | $GREP " -> " >/dev/null; then continue fi # The statement above tries to avoid entering an # endless loop below, in case of cyclic links. # We might still enter an endless loop, since a link # loop can be closed while we follow links, # but so what? potlib=$potent_lib while test -h "$potlib" 2>/dev/null; do potliblink=`ls -ld $potlib | $SED 's/.* -> //'` case $potliblink in [\\/]* | [A-Za-z]:[\\/]*) potlib=$potliblink;; *) potlib=`$ECHO "$potlib" | $SED 's|[^/]*$||'`"$potliblink";; esac done if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | $SED -e 10q | $EGREP "$file_magic_regex" > /dev/null; then func_append newdeplibs " $a_deplib" a_deplib= break 2 fi done done fi if test -n "$a_deplib"; then droppeddeps=yes echo $ECHO "*** Warning: linker path does not have real file for library $a_deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib"; then $ECHO "*** with $libname but no candidates were found. (...for file magic test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" $ECHO "*** using a file magic. Last file checked: $potlib" fi fi ;; *) # Add a -L argument. func_append newdeplibs " $a_deplib" ;; esac done # Gone through all deplibs. ;; match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` for a_deplib in $deplibs; do case $a_deplib in -l*) func_stripname -l '' "$a_deplib" name=$func_stripname_result if test yes = "$allow_libtool_libs_with_static_runtimes"; then case " $predeps $postdeps " in *" $a_deplib "*) func_append newdeplibs " $a_deplib" a_deplib= ;; esac fi if test -n "$a_deplib"; then libname=`eval "\\$ECHO \"$libname_spec\""` for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do potential_libs=`ls $i/$libname[.-]* 2>/dev/null` for potent_lib in $potential_libs; do potlib=$potent_lib # see symlink-check above in file_magic test if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ $EGREP "$match_pattern_regex" > /dev/null; then func_append newdeplibs " $a_deplib" a_deplib= break 2 fi done done fi if test -n "$a_deplib"; then droppeddeps=yes echo $ECHO "*** Warning: linker path does not have real file for library $a_deplib." echo "*** I have the capability to make that library automatically link in when" echo "*** you link to this library. But I can only do this if you have a" echo "*** shared version of the library, which you do not appear to have" echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib"; then $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" else $ECHO "*** with $libname and none of the candidates passed a file format test" $ECHO "*** using a regex pattern. Last file checked: $potlib" fi fi ;; *) # Add a -L argument. func_append newdeplibs " $a_deplib" ;; esac done # Gone through all deplibs. ;; none | unknown | *) newdeplibs= tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` if test yes = "$allow_libtool_libs_with_static_runtimes"; then for i in $predeps $postdeps; do # can't use Xsed below, because $i might contain '/' tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s|$i||"` done fi case $tmp_deplibs in *[!\ \ ]*) echo if test none = "$deplibs_check_method"; then echo "*** Warning: inter-library dependencies are not supported in this platform." else echo "*** Warning: inter-library dependencies are not known to be supported." fi echo "*** All declared inter-library dependencies are being dropped." droppeddeps=yes ;; esac ;; esac versuffix=$versuffix_save major=$major_save release=$release_save libname=$libname_save name=$name_save case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library with the System framework newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` ;; esac if test yes = "$droppeddeps"; then if test yes = "$module"; then echo echo "*** Warning: libtool could not satisfy all declared inter-library" $ECHO "*** dependencies of module $libname. Therefore, libtool will create" echo "*** a static module, that should work as long as the dlopening" echo "*** application is linked with the -dlopen flag." if test -z "$global_symbol_pipe"; then echo echo "*** However, this would only work if libtool was able to extract symbol" echo "*** lists from a program, using 'nm' or equivalent, but libtool could" echo "*** not find such a program. So, this module is probably useless." echo "*** 'nm' from GNU binutils and a full rebuild may help." fi if test no = "$build_old_libs"; then oldlibs=$output_objdir/$libname.$libext build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi else echo "*** The inter-library dependencies that have been dropped here will be" echo "*** automatically added whenever a program is linked with this library" echo "*** or is declared to -dlopen it." if test no = "$allow_undefined"; then echo echo "*** Since this library must not contain undefined symbols," echo "*** because either the platform does not support them or" echo "*** it was explicitly requested with -no-undefined," echo "*** libtool will only create a static version of it." if test no = "$build_old_libs"; then oldlibs=$output_objdir/$libname.$libext build_libtool_libs=module build_old_libs=yes else build_libtool_libs=no fi fi fi fi # Done checking deplibs! deplibs=$newdeplibs fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" case $host in *-*-darwin*) newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $deplibs " in *" -L$path/$objdir "*) func_append new_libs " -L$path/$objdir" ;; esac ;; esac done for deplib in $deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) func_append new_libs " $deplib" ;; esac ;; *) func_append new_libs " $deplib" ;; esac done deplibs=$new_libs # All the library-specific variables (install_libdir is set above). library_names= old_library= dlname= # Test again, we may have decided not to build it any more if test yes = "$build_libtool_libs"; then # Remove $wl instances when linking with ld. # FIXME: should test the right _cmds variable. case $archive_cmds in *\$LD\ *) wl= ;; esac if test yes = "$hardcode_into_libs"; then # Hardcode the library paths hardcode_libdirs= dep_rpath= rpath=$finalize_rpath test relink = "$opt_mode" || rpath=$compile_rpath$rpath for libdir in $rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then func_replace_sysroot "$libdir" libdir=$func_replace_sysroot_result if test -z "$hardcode_libdirs"; then hardcode_libdirs=$libdir else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append dep_rpath " $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) func_append perm_rpath " $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir=$hardcode_libdirs eval "dep_rpath=\"$hardcode_libdir_flag_spec\"" fi if test -n "$runpath_var" && test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do func_append rpath "$dir:" done eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" fi test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" fi shlibpath=$finalize_shlibpath test relink = "$opt_mode" || shlibpath=$compile_shlibpath$shlibpath if test -n "$shlibpath"; then eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" fi # Get the real and link names of the library. eval shared_ext=\"$shrext_cmds\" eval library_names=\"$library_names_spec\" set dummy $library_names shift realname=$1 shift if test -n "$soname_spec"; then eval soname=\"$soname_spec\" else soname=$realname fi if test -z "$dlname"; then dlname=$soname fi lib=$output_objdir/$realname linknames= for link do func_append linknames " $link" done # Use standard objects if they are pic test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` test "X$libobjs" = "X " && libobjs= delfiles= if test -n "$export_symbols" && test -n "$include_expsyms"; then $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" export_symbols=$output_objdir/$libname.uexp func_append delfiles " $export_symbols" fi orig_export_symbols= case $host_os in cygwin* | mingw* | cegcc*) if test -n "$export_symbols" && test -z "$export_symbols_regex"; then # exporting using user supplied symfile func_dll_def_p "$export_symbols" || { # and it's NOT already a .def file. Must figure out # which of the given symbols are data symbols and tag # them as such. So, trigger use of export_symbols_cmds. # export_symbols gets reassigned inside the "prepare # the list of exported symbols" if statement, so the # include_expsyms logic still works. orig_export_symbols=$export_symbols export_symbols= always_export_symbols=yes } fi ;; esac # Prepare the list of exported symbols if test -z "$export_symbols"; then if test yes = "$always_export_symbols" || test -n "$export_symbols_regex"; then func_verbose "generating symbol list for '$libname.la'" export_symbols=$output_objdir/$libname.exp $opt_dry_run || $RM $export_symbols cmds=$export_symbols_cmds save_ifs=$IFS; IFS='~' for cmd1 in $cmds; do IFS=$save_ifs # Take the normal branch if the nm_file_list_spec branch # doesn't work or if tool conversion is not needed. case $nm_file_list_spec~$to_tool_file_cmd in *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) try_normal_branch=yes eval cmd=\"$cmd1\" func_len " $cmd" len=$func_len_result ;; *) try_normal_branch=no ;; esac if test yes = "$try_normal_branch" \ && { test "$len" -lt "$max_cmd_len" \ || test "$max_cmd_len" -le -1; } then func_show_eval "$cmd" 'exit $?' skipped_export=false elif test -n "$nm_file_list_spec"; then func_basename "$output" output_la=$func_basename_result save_libobjs=$libobjs save_output=$output output=$output_objdir/$output_la.nm func_to_tool_file "$output" libobjs=$nm_file_list_spec$func_to_tool_file_result func_append delfiles " $output" func_verbose "creating $NM input file list: $output" for obj in $save_libobjs; do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" done > "$output" eval cmd=\"$cmd1\" func_show_eval "$cmd" 'exit $?' output=$save_output libobjs=$save_libobjs skipped_export=false else # The command line is too long to execute in one step. func_verbose "using reloadable object file for export list..." skipped_export=: # Break out early, otherwise skipped_export may be # set to false by a later but shorter cmd. break fi done IFS=$save_ifs if test -n "$export_symbols_regex" && test : != "$skipped_export"; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi fi fi if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols=$export_symbols test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi if test : != "$skipped_export" && test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. func_verbose "filter symbol list for '$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of # 's' commands, which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter func_append delfiles " $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi tmp_deplibs= for test_deplib in $deplibs; do case " $convenience " in *" $test_deplib "*) ;; *) func_append tmp_deplibs " $test_deplib" ;; esac done deplibs=$tmp_deplibs if test -n "$convenience"; then if test -n "$whole_archive_flag_spec" && test yes = "$compiler_needs_object" && test -z "$libobjs"; then # extract the archives, so we have objects to list. # TODO: could optimize this to just extract one archive. whole_archive_flag_spec= fi if test -n "$whole_archive_flag_spec"; then save_libobjs=$libobjs eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= else gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_extract_archives $gentop $convenience func_append libobjs " $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi fi if test yes = "$thread_safe" && test -n "$thread_safe_flag_spec"; then eval flag=\"$thread_safe_flag_spec\" func_append linker_flags " $flag" fi # Make a backup of the uninstalled library when relinking if test relink = "$opt_mode"; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? fi # Do each of the archive commands. if test yes = "$module" && test -n "$module_cmds"; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then eval test_cmds=\"$module_expsym_cmds\" cmds=$module_expsym_cmds else eval test_cmds=\"$module_cmds\" cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then eval test_cmds=\"$archive_expsym_cmds\" cmds=$archive_expsym_cmds else eval test_cmds=\"$archive_cmds\" cmds=$archive_cmds fi fi if test : != "$skipped_export" && func_len " $test_cmds" && len=$func_len_result && test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then : else # The command line is too long to link in one step, link piecewise # or, if using GNU ld and skipped_export is not :, use a linker # script. # Save the value of $output and $libobjs because we want to # use them later. If we have whole_archive_flag_spec, we # want to use save_libobjs as it was before # whole_archive_flag_spec was expanded, because we can't # assume the linker understands whole_archive_flag_spec. # This may have to be revisited, in case too many # convenience libraries get linked in and end up exceeding # the spec. if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then save_libobjs=$libobjs fi save_output=$output func_basename "$output" output_la=$func_basename_result # Clear the reloadable object creation command queue and # initialize k to one. test_cmds= concat_cmds= objlist= last_robj= k=1 if test -n "$save_libobjs" && test : != "$skipped_export" && test yes = "$with_gnu_ld"; then output=$output_objdir/$output_la.lnkscript func_verbose "creating GNU ld script: $output" echo 'INPUT (' > $output for obj in $save_libobjs do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" >> $output done echo ')' >> $output func_append delfiles " $output" func_to_tool_file "$output" output=$func_to_tool_file_result elif test -n "$save_libobjs" && test : != "$skipped_export" && test -n "$file_list_spec"; then output=$output_objdir/$output_la.lnk func_verbose "creating linker input file list: $output" : > $output set x $save_libobjs shift firstobj= if test yes = "$compiler_needs_object"; then firstobj="$1 " shift fi for obj do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" >> $output done func_append delfiles " $output" func_to_tool_file "$output" output=$firstobj\"$file_list_spec$func_to_tool_file_result\" else if test -n "$save_libobjs"; then func_verbose "creating reloadable object files..." output=$output_objdir/$output_la-$k.$objext eval test_cmds=\"$reload_cmds\" func_len " $test_cmds" len0=$func_len_result len=$len0 # Loop over the list of objects to be linked. for obj in $save_libobjs do func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result if test -z "$objlist" || test "$len" -lt "$max_cmd_len"; then func_append objlist " $obj" else # The command $test_cmds is almost too long, add a # command to the queue. if test 1 -eq "$k"; then # The first file doesn't have a previous command to add. reload_objs=$objlist eval concat_cmds=\"$reload_cmds\" else # All subsequent reloadable object files will link in # the last one created. reload_objs="$objlist $last_robj" eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" fi last_robj=$output_objdir/$output_la-$k.$objext func_arith $k + 1 k=$func_arith_result output=$output_objdir/$output_la-$k.$objext objlist=" $obj" func_len " $last_robj" func_arith $len0 + $func_len_result len=$func_arith_result fi done # Handle the remaining objects by creating one last # reloadable object file. All subsequent reloadable object # files will link in the last one created. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ reload_objs="$objlist $last_robj" eval concat_cmds=\"\$concat_cmds$reload_cmds\" if test -n "$last_robj"; then eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" fi func_append delfiles " $output" else output= fi ${skipped_export-false} && { func_verbose "generating symbol list for '$libname.la'" export_symbols=$output_objdir/$libname.exp $opt_dry_run || $RM $export_symbols libobjs=$output # Append the command to create the export file. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" if test -n "$last_robj"; then eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" fi } test -n "$save_libobjs" && func_verbose "creating a temporary reloadable object file: $output" # Loop through the commands generated above and execute them. save_ifs=$IFS; IFS='~' for cmd in $concat_cmds; do IFS=$save_ifs $opt_quiet || { func_quote_for_expand "$cmd" eval "func_echo $func_quote_for_expand_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test relink = "$opt_mode"; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) fi exit $lt_exit } done IFS=$save_ifs if test -n "$export_symbols_regex" && ${skipped_export-false}; then func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' func_show_eval '$MV "${export_symbols}T" "$export_symbols"' fi fi ${skipped_export-false} && { if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols=$export_symbols test -n "$orig_export_symbols" && tmp_export_symbols=$orig_export_symbols $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi if test -n "$orig_export_symbols"; then # The given exports_symbols file has to be filtered, so filter it. func_verbose "filter symbol list for '$libname.la' to tag DATA exports" # FIXME: $output_objdir/$libname.filter potentially contains lots of # 's' commands, which not all seds can handle. GNU sed should be fine # though. Also, the filter scales superlinearly with the number of # global variables. join(1) would be nice here, but unfortunately # isn't a blessed tool. $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter func_append delfiles " $export_symbols $output_objdir/$libname.filter" export_symbols=$output_objdir/$libname.def $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols fi } libobjs=$output # Restore the value of output. output=$save_output if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then eval libobjs=\"\$libobjs $whole_archive_flag_spec\" test "X$libobjs" = "X " && libobjs= fi # Expand the library linking commands again to reset the # value of $libobjs for piecewise linking. # Do each of the archive commands. if test yes = "$module" && test -n "$module_cmds"; then if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then cmds=$module_expsym_cmds else cmds=$module_cmds fi else if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then cmds=$archive_expsym_cmds else cmds=$archive_cmds fi fi fi if test -n "$delfiles"; then # Append the command to remove temporary files to $cmds. eval cmds=\"\$cmds~\$RM $delfiles\" fi # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_extract_archives $gentop $dlprefiles func_append libobjs " $func_extract_archives_result" test "X$libobjs" = "X " && libobjs= fi save_ifs=$IFS; IFS='~' for cmd in $cmds; do IFS=$sp$nl eval cmd=\"$cmd\" IFS=$save_ifs $opt_quiet || { func_quote_for_expand "$cmd" eval "func_echo $func_quote_for_expand_result" } $opt_dry_run || eval "$cmd" || { lt_exit=$? # Restore the uninstalled library and exit if test relink = "$opt_mode"; then ( cd "$output_objdir" && \ $RM "${realname}T" && \ $MV "${realname}U" "$realname" ) fi exit $lt_exit } done IFS=$save_ifs # Restore the uninstalled library and exit if test relink = "$opt_mode"; then $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? if test -n "$convenience"; then if test -z "$whole_archive_flag_spec"; then func_show_eval '${RM}r "$gentop"' fi fi exit $EXIT_SUCCESS fi # Create links to the real library. for linkname in $linknames; do if test "$realname" != "$linkname"; then func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' fi done # If -module or -export-dynamic was specified, set the dlname. if test yes = "$module" || test yes = "$export_dynamic"; then # On all known operating systems, these are identical. dlname=$soname fi fi ;; obj) if test -n "$dlfiles$dlprefiles" || test no != "$dlself"; then func_warning "'-dlopen' is ignored for objects" fi case " $deplibs" in *\ -l* | *\ -L*) func_warning "'-l' and '-L' are ignored for objects" ;; esac test -n "$rpath" && \ func_warning "'-rpath' is ignored for objects" test -n "$xrpath" && \ func_warning "'-R' is ignored for objects" test -n "$vinfo" && \ func_warning "'-version-info' is ignored for objects" test -n "$release" && \ func_warning "'-release' is ignored for objects" case $output in *.lo) test -n "$objs$old_deplibs" && \ func_fatal_error "cannot build library object '$output' from non-libtool objects" libobj=$output func_lo2o "$libobj" obj=$func_lo2o_result ;; *) libobj= obj=$output ;; esac # Delete the old objects. $opt_dry_run || $RM $obj $libobj # Objects from convenience libraries. This assumes # single-version convenience libraries. Whenever we create # different ones for PIC/non-PIC, this we'll have to duplicate # the extraction. reload_conv_objs= gentop= # if reload_cmds runs $LD directly, get rid of -Wl from # whole_archive_flag_spec and hope we can get by with turning comma # into space. case $reload_cmds in *\$LD[\ \$]*) wl= ;; esac if test -n "$convenience"; then if test -n "$whole_archive_flag_spec"; then eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" test -n "$wl" || tmp_whole_archive_flags=`$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` reload_conv_objs=$reload_objs\ $tmp_whole_archive_flags else gentop=$output_objdir/${obj}x func_append generated " $gentop" func_extract_archives $gentop $convenience reload_conv_objs="$reload_objs $func_extract_archives_result" fi fi # If we're not building shared, we need to use non_pic_objs test yes = "$build_libtool_libs" || libobjs=$non_pic_objects # Create the old-style object. reload_objs=$objs$old_deplibs' '`$ECHO "$libobjs" | $SP2NL | $SED "/\.$libext$/d; /\.lib$/d; $lo2o" | $NL2SP`' '$reload_conv_objs output=$obj func_execute_cmds "$reload_cmds" 'exit $?' # Exit if we aren't doing a library object file. if test -z "$libobj"; then if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi exit $EXIT_SUCCESS fi test yes = "$build_libtool_libs" || { if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi # Create an invalid libtool object if no PIC, so that we don't # accidentally link it into a program. # $show "echo timestamp > $libobj" # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? exit $EXIT_SUCCESS } if test -n "$pic_flag" || test default != "$pic_mode"; then # Only do commands if we really have different PIC objects. reload_objs="$libobjs $reload_conv_objs" output=$libobj func_execute_cmds "$reload_cmds" 'exit $?' fi if test -n "$gentop"; then func_show_eval '${RM}r "$gentop"' fi exit $EXIT_SUCCESS ;; prog) case $host in *cygwin*) func_stripname '' '.exe' "$output" output=$func_stripname_result.exe;; esac test -n "$vinfo" && \ func_warning "'-version-info' is ignored for programs" test -n "$release" && \ func_warning "'-release' is ignored for programs" $preload \ && test unknown,unknown,unknown = "$dlopen_support,$dlopen_self,$dlopen_self_static" \ && func_warning "'LT_INIT([dlopen])' not used. Assuming no dlopen support." case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library is the System framework compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` ;; esac case $host in *-*-darwin*) # Don't allow lazy linking, it breaks C++ global constructors # But is supposedly fixed on 10.4 or later (yay!). if test CXX = "$tagname"; then case ${MACOSX_DEPLOYMENT_TARGET-10.0} in 10.[0123]) func_append compile_command " $wl-bind_at_load" func_append finalize_command " $wl-bind_at_load" ;; esac fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac # move library search paths that coincide with paths to not yet # installed libraries to the beginning of the library search list new_libs= for path in $notinst_path; do case " $new_libs " in *" -L$path/$objdir "*) ;; *) case " $compile_deplibs " in *" -L$path/$objdir "*) func_append new_libs " -L$path/$objdir" ;; esac ;; esac done for deplib in $compile_deplibs; do case $deplib in -L*) case " $new_libs " in *" $deplib "*) ;; *) func_append new_libs " $deplib" ;; esac ;; *) func_append new_libs " $deplib" ;; esac done compile_deplibs=$new_libs func_append compile_command " $compile_deplibs" func_append finalize_command " $finalize_deplibs" if test -n "$rpath$xrpath"; then # If the user specified any rpath flags, then add them. for libdir in $rpath $xrpath; do # This is the magic to use -rpath. case "$finalize_rpath " in *" $libdir "*) ;; *) func_append finalize_rpath " $libdir" ;; esac done fi # Now hardcode the library paths rpath= hardcode_libdirs= for libdir in $compile_rpath $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs=$libdir else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append rpath " $flag" fi elif test -n "$runpath_var"; then case "$perm_rpath " in *" $libdir "*) ;; *) func_append perm_rpath " $libdir" ;; esac fi case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) testbindir=`$ECHO "$libdir" | $SED -e 's*/lib$*/bin*'` case :$dllsearchpath: in *":$libdir:"*) ;; ::) dllsearchpath=$libdir;; *) func_append dllsearchpath ":$libdir";; esac case :$dllsearchpath: in *":$testbindir:"*) ;; ::) dllsearchpath=$testbindir;; *) func_append dllsearchpath ":$testbindir";; esac ;; esac done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir=$hardcode_libdirs eval rpath=\" $hardcode_libdir_flag_spec\" fi compile_rpath=$rpath rpath= hardcode_libdirs= for libdir in $finalize_rpath; do if test -n "$hardcode_libdir_flag_spec"; then if test -n "$hardcode_libdir_separator"; then if test -z "$hardcode_libdirs"; then hardcode_libdirs=$libdir else # Just accumulate the unique libdirs. case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) ;; *) func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" ;; esac fi else eval flag=\"$hardcode_libdir_flag_spec\" func_append rpath " $flag" fi elif test -n "$runpath_var"; then case "$finalize_perm_rpath " in *" $libdir "*) ;; *) func_append finalize_perm_rpath " $libdir" ;; esac fi done # Substitute the hardcoded libdirs into the rpath. if test -n "$hardcode_libdir_separator" && test -n "$hardcode_libdirs"; then libdir=$hardcode_libdirs eval rpath=\" $hardcode_libdir_flag_spec\" fi finalize_rpath=$rpath if test -n "$libobjs" && test yes = "$build_old_libs"; then # Transform all the library objects into standard objects. compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` fi func_generate_dlsyms "$outputname" "@PROGRAM@" false # template prelinking step if test -n "$prelink_cmds"; then func_execute_cmds "$prelink_cmds" 'exit $?' fi wrappers_required=: case $host in *cegcc* | *mingw32ce*) # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. wrappers_required=false ;; *cygwin* | *mingw* ) test yes = "$build_libtool_libs" || wrappers_required=false ;; *) if test no = "$need_relink" || test yes != "$build_libtool_libs"; then wrappers_required=false fi ;; esac $wrappers_required || { # Replace the output file specification. compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` link_command=$compile_command$compile_rpath # We have no uninstalled library dependencies, so finalize right now. exit_status=0 func_show_eval "$link_command" 'exit_status=$?' if test -n "$postlink_cmds"; then func_to_tool_file "$output" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi # Delete the generated files. if test -f "$output_objdir/${outputname}S.$objext"; then func_show_eval '$RM "$output_objdir/${outputname}S.$objext"' fi exit $exit_status } if test -n "$compile_shlibpath$finalize_shlibpath"; then compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" fi if test -n "$finalize_shlibpath"; then finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" fi compile_var= finalize_var= if test -n "$runpath_var"; then if test -n "$perm_rpath"; then # We should set the runpath_var. rpath= for dir in $perm_rpath; do func_append rpath "$dir:" done compile_var="$runpath_var=\"$rpath\$$runpath_var\" " fi if test -n "$finalize_perm_rpath"; then # We should set the runpath_var. rpath= for dir in $finalize_perm_rpath; do func_append rpath "$dir:" done finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " fi fi if test yes = "$no_install"; then # We don't need to create a wrapper script. link_command=$compile_var$compile_command$compile_rpath # Replace the output file specification. link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` # Delete the old output file. $opt_dry_run || $RM $output # Link the executable and exit func_show_eval "$link_command" 'exit $?' if test -n "$postlink_cmds"; then func_to_tool_file "$output" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi exit $EXIT_SUCCESS fi case $hardcode_action,$fast_install in relink,*) # Fast installation is not supported link_command=$compile_var$compile_command$compile_rpath relink_command=$finalize_var$finalize_command$finalize_rpath func_warning "this platform does not like uninstalled shared libraries" func_warning "'$output' will be relinked during installation" ;; *,yes) link_command=$finalize_var$compile_command$finalize_rpath relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` ;; *,no) link_command=$compile_var$compile_command$compile_rpath relink_command=$finalize_var$finalize_command$finalize_rpath ;; *,needless) link_command=$finalize_var$compile_command$finalize_rpath relink_command= ;; esac # Replace the output file specification. link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` # Delete the old output files. $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname func_show_eval "$link_command" 'exit $?' if test -n "$postlink_cmds"; then func_to_tool_file "$output_objdir/$outputname" postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` func_execute_cmds "$postlink_cmds" 'exit $?' fi # Now create the wrapper script. func_verbose "creating $output" # Quote the relink command for shipping. if test -n "$relink_command"; then # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else func_quote_for_eval "$var_value" relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" fi done relink_command="(cd `pwd`; $relink_command)" relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` fi # Only actually do things if not in dry run mode. $opt_dry_run || { # win32 will think the script is a binary if it has # a .exe suffix, so we strip it off here. case $output in *.exe) func_stripname '' '.exe' "$output" output=$func_stripname_result ;; esac # test for cygwin because mv fails w/o .exe extensions case $host in *cygwin*) exeext=.exe func_stripname '' '.exe' "$outputname" outputname=$func_stripname_result ;; *) exeext= ;; esac case $host in *cygwin* | *mingw* ) func_dirname_and_basename "$output" "" "." output_name=$func_basename_result output_path=$func_dirname_result cwrappersource=$output_path/$objdir/lt-$output_name.c cwrapper=$output_path/$output_name.exe $RM $cwrappersource $cwrapper trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 func_emit_cwrapperexe_src > $cwrappersource # The wrapper executable is built using the $host compiler, # because it contains $host paths and files. If cross- # compiling, it, like the target executable, must be # executed on the $host or under an emulation environment. $opt_dry_run || { $LTCC $LTCFLAGS -o $cwrapper $cwrappersource $STRIP $cwrapper } # Now, create the wrapper script for func_source use: func_ltwrapper_scriptname $cwrapper $RM $func_ltwrapper_scriptname_result trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 $opt_dry_run || { # note: this script will not be executed, so do not chmod. if test "x$build" = "x$host"; then $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result else func_emit_wrapper no > $func_ltwrapper_scriptname_result fi } ;; * ) $RM $output trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 func_emit_wrapper no > $output chmod +x $output ;; esac } exit $EXIT_SUCCESS ;; esac # See if we need to build an old-fashioned archive. for oldlib in $oldlibs; do case $build_libtool_libs in convenience) oldobjs="$libobjs_save $symfileobj" addlibs=$convenience build_libtool_libs=no ;; module) oldobjs=$libobjs_save addlibs=$old_convenience build_libtool_libs=no ;; *) oldobjs="$old_deplibs $non_pic_objects" $preload && test -f "$symfileobj" \ && func_append oldobjs " $symfileobj" addlibs=$old_convenience ;; esac if test -n "$addlibs"; then gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_extract_archives $gentop $addlibs func_append oldobjs " $func_extract_archives_result" fi # Do each command in the archive commands. if test -n "$old_archive_from_new_cmds" && test yes = "$build_libtool_libs"; then cmds=$old_archive_from_new_cmds else # Add any objects from preloaded convenience libraries if test -n "$dlprefiles"; then gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_extract_archives $gentop $dlprefiles func_append oldobjs " $func_extract_archives_result" fi # POSIX demands no paths to be encoded in archives. We have # to avoid creating archives with duplicate basenames if we # might have to extract them afterwards, e.g., when creating a # static archive out of a convenience library, or when linking # the entirety of a libtool archive into another (currently # not supported by libtool). if (for obj in $oldobjs do func_basename "$obj" $ECHO "$func_basename_result" done | sort | sort -uc >/dev/null 2>&1); then : else echo "copying selected object files to avoid basename conflicts..." gentop=$output_objdir/${outputname}x func_append generated " $gentop" func_mkdir_p "$gentop" save_oldobjs=$oldobjs oldobjs= counter=1 for obj in $save_oldobjs do func_basename "$obj" objbase=$func_basename_result case " $oldobjs " in " ") oldobjs=$obj ;; *[\ /]"$objbase "*) while :; do # Make sure we don't pick an alternate name that also # overlaps. newobj=lt$counter-$objbase func_arith $counter + 1 counter=$func_arith_result case " $oldobjs " in *[\ /]"$newobj "*) ;; *) if test ! -f "$gentop/$newobj"; then break; fi ;; esac done func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" func_append oldobjs " $gentop/$newobj" ;; *) func_append oldobjs " $obj" ;; esac done fi func_to_tool_file "$oldlib" func_convert_file_msys_to_w32 tool_oldlib=$func_to_tool_file_result eval cmds=\"$old_archive_cmds\" func_len " $cmds" len=$func_len_result if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then cmds=$old_archive_cmds elif test -n "$archiver_list_spec"; then func_verbose "using command file archive linking..." for obj in $oldobjs do func_to_tool_file "$obj" $ECHO "$func_to_tool_file_result" done > $output_objdir/$libname.libcmd func_to_tool_file "$output_objdir/$libname.libcmd" oldobjs=" $archiver_list_spec$func_to_tool_file_result" cmds=$old_archive_cmds else # the command line is too long to link in one step, link in parts func_verbose "using piecewise archive linking..." save_RANLIB=$RANLIB RANLIB=: objlist= concat_cmds= save_oldobjs=$oldobjs oldobjs= # Is there a better way of finding the last object in the list? for obj in $save_oldobjs do last_oldobj=$obj done eval test_cmds=\"$old_archive_cmds\" func_len " $test_cmds" len0=$func_len_result len=$len0 for obj in $save_oldobjs do func_len " $obj" func_arith $len + $func_len_result len=$func_arith_result func_append objlist " $obj" if test "$len" -lt "$max_cmd_len"; then : else # the above command should be used before it gets too long oldobjs=$objlist if test "$obj" = "$last_oldobj"; then RANLIB=$save_RANLIB fi test -z "$concat_cmds" || concat_cmds=$concat_cmds~ eval concat_cmds=\"\$concat_cmds$old_archive_cmds\" objlist= len=$len0 fi done RANLIB=$save_RANLIB oldobjs=$objlist if test -z "$oldobjs"; then eval cmds=\"\$concat_cmds\" else eval cmds=\"\$concat_cmds~\$old_archive_cmds\" fi fi fi func_execute_cmds "$cmds" 'exit $?' done test -n "$generated" && \ func_show_eval "${RM}r$generated" # Now create the libtool archive. case $output in *.la) old_library= test yes = "$build_old_libs" && old_library=$libname.$libext func_verbose "creating $output" # Preserve any variables that may affect compiler behavior for var in $variables_saved_for_relink; do if eval test -z \"\${$var+set}\"; then relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" elif eval var_value=\$$var; test -z "$var_value"; then relink_command="$var=; export $var; $relink_command" else func_quote_for_eval "$var_value" relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" fi done # Quote the link command for shipping. relink_command="(cd `pwd`; $SHELL \"$progpath\" $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` if test yes = "$hardcode_automatic"; then relink_command= fi # Only create the output if not a dry run. $opt_dry_run || { for installed in no yes; do if test yes = "$installed"; then if test -z "$install_libdir"; then break fi output=$output_objdir/${outputname}i # Replace all uninstalled libtool libraries with the installed ones newdependency_libs= for deplib in $dependency_libs; do case $deplib in *.la) func_basename "$deplib" name=$func_basename_result func_resolve_sysroot "$deplib" eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $func_resolve_sysroot_result` test -z "$libdir" && \ func_fatal_error "'$deplib' is not a valid libtool archive" func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" ;; -L*) func_stripname -L '' "$deplib" func_replace_sysroot "$func_stripname_result" func_append newdependency_libs " -L$func_replace_sysroot_result" ;; -R*) func_stripname -R '' "$deplib" func_replace_sysroot "$func_stripname_result" func_append newdependency_libs " -R$func_replace_sysroot_result" ;; *) func_append newdependency_libs " $deplib" ;; esac done dependency_libs=$newdependency_libs newdlfiles= for lib in $dlfiles; do case $lib in *.la) func_basename "$lib" name=$func_basename_result eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "'$lib' is not a valid libtool archive" func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" ;; *) func_append newdlfiles " $lib" ;; esac done dlfiles=$newdlfiles newdlprefiles= for lib in $dlprefiles; do case $lib in *.la) # Only pass preopened files to the pseudo-archive (for # eventual linking with the app. that links it) if we # didn't already link the preopened objects directly into # the library: func_basename "$lib" name=$func_basename_result eval libdir=`$SED -n -e 's/^libdir=\(.*\)$/\1/p' $lib` test -z "$libdir" && \ func_fatal_error "'$lib' is not a valid libtool archive" func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" ;; esac done dlprefiles=$newdlprefiles else newdlfiles= for lib in $dlfiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; *) abs=`pwd`"/$lib" ;; esac func_append newdlfiles " $abs" done dlfiles=$newdlfiles newdlprefiles= for lib in $dlprefiles; do case $lib in [\\/]* | [A-Za-z]:[\\/]*) abs=$lib ;; *) abs=`pwd`"/$lib" ;; esac func_append newdlprefiles " $abs" done dlprefiles=$newdlprefiles fi $RM $output # place dlname in correct position for cygwin # In fact, it would be nice if we could use this code for all target # systems that can't hard-code library paths into their executables # and that have no shared library path variable independent of PATH, # but it turns out we can't easily determine that from inspecting # libtool variables, so we have to hard-code the OSs to which it # applies here; at the moment, that means platforms that use the PE # object format with DLL files. See the long comment at the top of # tests/bindir.at for full details. tdlname=$dlname case $host,$output,$installed,$module,$dlname in *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) # If a -bindir argument was supplied, place the dll there. if test -n "$bindir"; then func_relative_path "$install_libdir" "$bindir" tdlname=$func_relative_path_result/$dlname else # Otherwise fall back on heuristic. tdlname=../bin/$dlname fi ;; esac $ECHO > $output "\ # $outputname - a libtool library file # Generated by $PROGRAM (GNU $PACKAGE) $VERSION # # Please DO NOT delete this file! # It is necessary for linking the library. # The name that we can dlopen(3). dlname='$tdlname' # Names of this library. library_names='$library_names' # The name of the static archive. old_library='$old_library' # Linker flags that cannot go in dependency_libs. inherited_linker_flags='$new_inherited_linker_flags' # Libraries that this one depends upon. dependency_libs='$dependency_libs' # Names of additional weak libraries provided by this library weak_library_names='$weak_libs' # Version information for $libname. current=$current age=$age revision=$revision # Is this an already installed library? installed=$installed # Should we warn about portability when linking against -modules? shouldnotlink=$module # Files to dlopen/dlpreopen dlopen='$dlfiles' dlpreopen='$dlprefiles' # Directory that this library needs to be installed in: libdir='$install_libdir'" if test no,yes = "$installed,$need_relink"; then $ECHO >> $output "\ relink_command=\"$relink_command\"" fi done } # Do a symbolic link so that the libtool archive can be found in # LD_LIBRARY_PATH before the program is installed. func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' ;; esac exit $EXIT_SUCCESS } if test link = "$opt_mode" || test relink = "$opt_mode"; then func_mode_link ${1+"$@"} fi # func_mode_uninstall arg... func_mode_uninstall () { $debug_cmd RM=$nonopt files= rmforce=false exit_status=0 # This variable tells wrapper scripts just to set variables rather # than running their programs. libtool_install_magic=$magic for arg do case $arg in -f) func_append RM " $arg"; rmforce=: ;; -*) func_append RM " $arg" ;; *) func_append files " $arg" ;; esac done test -z "$RM" && \ func_fatal_help "you must specify an RM program" rmdirs= for file in $files; do func_dirname "$file" "" "." dir=$func_dirname_result if test . = "$dir"; then odir=$objdir else odir=$dir/$objdir fi func_basename "$file" name=$func_basename_result test uninstall = "$opt_mode" && odir=$dir # Remember odir for removal later, being careful to avoid duplicates if test clean = "$opt_mode"; then case " $rmdirs " in *" $odir "*) ;; *) func_append rmdirs " $odir" ;; esac fi # Don't error if the file doesn't exist and rm -f was used. if { test -L "$file"; } >/dev/null 2>&1 || { test -h "$file"; } >/dev/null 2>&1 || test -f "$file"; then : elif test -d "$file"; then exit_status=1 continue elif $rmforce; then continue fi rmfiles=$file case $name in *.la) # Possibly a libtool archive, so verify it. if func_lalib_p "$file"; then func_source $dir/$name # Delete the libtool libraries and symlinks. for n in $library_names; do func_append rmfiles " $odir/$n" done test -n "$old_library" && func_append rmfiles " $odir/$old_library" case $opt_mode in clean) case " $library_names " in *" $dlname "*) ;; *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; esac test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" ;; uninstall) if test -n "$library_names"; then # Do each command in the postuninstall commands. func_execute_cmds "$postuninstall_cmds" '$rmforce || exit_status=1' fi if test -n "$old_library"; then # Do each command in the old_postuninstall commands. func_execute_cmds "$old_postuninstall_cmds" '$rmforce || exit_status=1' fi # FIXME: should reinstall the best remaining shared library. ;; esac fi ;; *.lo) # Possibly a libtool object, so verify it. if func_lalib_p "$file"; then # Read the .lo file func_source $dir/$name # Add PIC object to the list of files to remove. if test -n "$pic_object" && test none != "$pic_object"; then func_append rmfiles " $dir/$pic_object" fi # Add non-PIC object to the list of files to remove. if test -n "$non_pic_object" && test none != "$non_pic_object"; then func_append rmfiles " $dir/$non_pic_object" fi fi ;; *) if test clean = "$opt_mode"; then noexename=$name case $file in *.exe) func_stripname '' '.exe' "$file" file=$func_stripname_result func_stripname '' '.exe' "$name" noexename=$func_stripname_result # $file with .exe has already been added to rmfiles, # add $file without .exe func_append rmfiles " $file" ;; esac # Do a test to see if this is a libtool program. if func_ltwrapper_p "$file"; then if func_ltwrapper_executable_p "$file"; then func_ltwrapper_scriptname "$file" relink_command= func_source $func_ltwrapper_scriptname_result func_append rmfiles " $func_ltwrapper_scriptname_result" else relink_command= func_source $dir/$noexename fi # note $name still contains .exe if it was in $file originally # as does the version of $file that was added into $rmfiles func_append rmfiles " $odir/$name $odir/${name}S.$objext" if test yes = "$fast_install" && test -n "$relink_command"; then func_append rmfiles " $odir/lt-$name" fi if test "X$noexename" != "X$name"; then func_append rmfiles " $odir/lt-$noexename.c" fi fi fi ;; esac func_show_eval "$RM $rmfiles" 'exit_status=1' done # Try to remove the $objdir's in the directories where we deleted files for dir in $rmdirs; do if test -d "$dir"; then func_show_eval "rmdir $dir >/dev/null 2>&1" fi done exit $exit_status } if test uninstall = "$opt_mode" || test clean = "$opt_mode"; then func_mode_uninstall ${1+"$@"} fi test -z "$opt_mode" && { help=$generic_help func_fatal_help "you must specify a MODE" } test -z "$exec_cmd" && \ func_fatal_help "invalid operation mode '$opt_mode'" if test -n "$exec_cmd"; then eval exec "$exec_cmd" exit $EXIT_FAILURE fi exit $exit_status # The TAGs below are defined such that we never get into a situation # where we disable both kinds of libraries. Given conflicting # choices, we go for a static library, that is the most portable, # since we can't tell whether shared libraries were disabled because # the user asked for that or because the platform doesn't support # them. This is particularly important on AIX, because we don't # support having both static and shared libraries enabled at the same # time on that platform, so we default to a shared-only configuration. # If a disable-shared tag is given, we'll fallback to a static-only # configuration. But we'll never go from static-only to shared-only. # ### BEGIN LIBTOOL TAG CONFIG: disable-shared build_libtool_libs=no build_old_libs=yes # ### END LIBTOOL TAG CONFIG: disable-shared # ### BEGIN LIBTOOL TAG CONFIG: disable-static build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` # ### END LIBTOOL TAG CONFIG: disable-static # Local Variables: # mode:shell-script # sh-indentation:2 # End: libinfinity-0.7.1/PaxHeaders.26529/ChangeLog0000644000000000000000000000013213055210724015354 xustar0030 mtime=1488261588.716139686 30 atime=1483909374.318682639 30 ctime=1488261588.768139572 libinfinity-0.7.1/ChangeLog0000644000175000017500000236513613055210724016126 0ustar00arminarmin00000000000000commit 9d828b4c8b8e64e33ebd8fffff1bf0b2b3fe35f0 Author: Armin Burgmeier Date: Mon Feb 27 21:51:03 2017 -0800 Release 0.7.1 NEWS | 6 ++++++ 1 file changed, 6 insertions(+) commit 67467468be4c8f44d54d69951bb9e5066e93db17 Author: Armin Burgmeier Date: Mon Feb 27 21:35:47 2017 -0800 Fix use-after-free in infinoted when uploading a document (gobby#142) libinfinity/server/infd-directory.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) commit 2929c31573d0c80456565983f20d492e14dbc673 Author: Armin Burgmeier Date: Wed Feb 15 22:19:56 2017 -0800 Add reference to the wiki on Github to the man page Thanks to Kardan for the patch. infinoted/infinoted-0.7.man | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) commit fdd7d51b04c4144630badb7eae90b306bfcd31bd Author: Armin Burgmeier Date: Thu Jan 12 21:43:36 2017 -0800 Fix two instances of possible format string injection (#17) infinoted/infinoted-config-reload.c | 2 +- test/inf-test-traffic-replay.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) commit 15721326e415264294466952e802bbe6a1ee2f68 Author: Armin Burgmeier Date: Thu Jan 12 21:43:11 2017 -0800 Post-release bump to 0.7.1 configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 9658eb6968a3161d6c752d5e2185dd24359af12a Author: Armin Burgmeier Date: Sat Jan 7 20:51:05 2017 -0800 Update NEWS for 0.7.0 NEWS | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) commit 39757f7bd82a48008b29dc8fd08937ebb6d40df9 Author: Armin Burgmeier Date: Sun Jan 8 11:35:05 2017 -0800 Various fixes to make building from distribution tarball work Mostly problems related to builddir != srcdir, `make distcheck` is happy now. infinoted/Makefile.am | 5 +++-- libinfgtk/Makefile.am | 10 ++++++++-- libinfinity/Makefile.am | 12 ++++++++++-- libinftext/Makefile.am | 2 ++ libinftextgtk/Makefile.am | 2 ++ test/Makefile.am | 3 +++ test/certs/Makefile.am | 2 +- test/inf-test-certificate-validate.c | 10 +++++++++- 8 files changed, 38 insertions(+), 8 deletions(-) commit 1bfb45c623fb310f4a3bb4bf981740654006242a Author: Armin Burgmeier Date: Sat Jan 7 20:33:39 2017 -0800 Update translations and po template po/POTFILES.in | 12 +- po/ca.po | 1018 ++++++++++++++++++++++++--------------------- po/de.po | 1019 +++++++++++++++++++++++++--------------------- po/libinfinity-0.7.pot | 1017 ++++++++++++++++++++++++--------------------- 4 files changed, 1650 insertions(+), 1416 deletions(-) commit 6c461a34568d40dc1cfcaa6863817e70101873c8 Author: Armin Burgmeier Date: Sun Jun 5 15:38:25 2016 -0700 Fix crash when disposing certificate manager while certificate dialog open libinfgtk/inf-gtk-certificate-manager.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) commit 76984a186ba62ad26a59328c80a7b68569ddd985 Author: Armin Burgmeier Date: Sat Jun 4 20:49:05 2016 -0700 InfGtkConnectionView: update view if TLS properties change Connection info might be displayed before the TLS handshake occurred, so we want to update the info display after the handshake. libinfgtk/inf-gtk-connection-view.c | 316 +++++++++++++++++++++------------- 1 file changed, 194 insertions(+), 122 deletions(-) commit 5091b1420ef0b48675a86f29fa3dadf82e12d8de Author: Armin Burgmeier Date: Mon May 30 17:26:16 2016 -0700 Simplify travis CI configuration .travis.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) commit 8eb9560de3ef5f0d7aa7f9f48ea9e3b55af24933 Author: Armin Burgmeier Date: Mon May 30 13:22:52 2016 -0700 Fix warning in usage of gtk_label_set_xalign libinfgtk/inf-gtk-certificate-manager.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 2c6ca5d6995e2464297f5fa45eca3ff441263785 Author: Armin Burgmeier Date: Mon May 30 13:22:41 2016 -0700 Add missing return type declaration infinoted/plugins/infinoted-plugin-dbus.c | 1 + 1 file changed, 1 insertion(+) commit ffbfe5b9422389af10ca8948684dc2e3afa1c219 Author: Hanno Heinrichs Date: Sun May 8 14:50:33 2016 +0200 Create private key file with restrictive permissions .../libinfinity/libinfinity-0.7-sections.txt | 1 + libinfinity/common/inf-cert-util.c | 5 +- libinfinity/common/inf-file-util.c | 72 +++++++++++++++++++++ libinfinity/common/inf-file-util.h | 6 ++ 4 files changed, 82 insertions(+), 2 deletions(-) commit 05dc6ef69a04199f5e385c574a736a04a61f92db Author: Armin Burgmeier Date: Tue May 10 22:04:58 2016 -0700 Fail config reload if listen address changes This is not so easy to support with the current mechanism because we open the new sockets before closing the old ones. infinoted/infinoted-config-reload.c | 43 +++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 5 deletions(-) commit 6822c4539ff7c4f67bb85aa106b42533a4ae7c33 Author: Armin Burgmeier Date: Tue May 10 22:04:50 2016 -0700 Add NULL check for freeing listen address infinoted/infinoted-options.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) commit 8f8c1611e6df3d5747e58c5c58efe416e9acc277 Author: Lukas Kupczyk Date: Sun May 1 13:11:38 2016 +0200 Add listen-address parameter .../libinfinoted-plugin-manager-0.7-sections.txt | 1 + infinoted/infinoted-0.7.man | 3 ++ infinoted/infinoted-options.c | 11 +++++ infinoted/infinoted-options.h | 1 + infinoted/infinoted-parameter.c | 46 +++++++++++++++++++++ infinoted/infinoted-parameter.h | 15 +++++-- infinoted/infinoted-run.c | 34 ++++++++++++--- 7 files changed, 102 insertions(+), 9 deletions(-) commit 594c44642730bb14448ced9b668ec6e8bc9bb7d5 Merge: 4f36255 ebe18aa Author: Armin Burgmeier Date: Mon Mar 21 20:40:29 2016 -0700 Merge remote-tracking branch 'hph86/rel-path-root' commit ebe18aa02d9238f47ee8ff9765db3d015765b3b7 Author: Hanno Heinrichs Date: Wed Mar 16 17:51:22 2016 +0100 Initialize root_directory with absolute path libinfinity/server/infd-filesystem-storage.c | 8 ++++++++ 1 file changed, 8 insertions(+) commit 4f3625534db3d7dbcfb8f4a40546444149641242 Author: Till Maas Date: Fri Mar 18 19:00:32 2016 +0100 Automatically select config files in travis .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit c074c317225f3a679c47562d5dc365ceb4dff5a5 Author: Armin Burgmeier Date: Tue Dec 8 22:24:53 2015 -0800 Fix g_return_val_if_fail on uninitialized memory libinfinity/server/infd-directory.c | 1 - 1 file changed, 1 deletion(-) commit b4924152a839012e0b0ed0f1107c33630b7bb6e7 Author: Armin Burgmeier Date: Mon Oct 12 21:21:20 2015 -0400 Remove duplicate certificate tests test/inf-test-certificate-validate.c | 20 -------------------- 1 file changed, 20 deletions(-) commit 21319ad8f2647081d6571981d4bb8935b4040dde Author: Armin Burgmeier Date: Mon Oct 12 21:20:04 2015 -0400 Fix certificate validation test One of the test certificates was issued for only 30 days when it should virtually never expire. Re-create the certificate with an expiration date in 3014. test/certs/test-expire-good-crt.pem | 56 +++++++++++++++++------------------ 1 file changed, 28 insertions(+), 28 deletions(-) commit 6721b411590488b5131264118dd47396413a31bd Author: Armin Burgmeier Date: Mon Oct 12 19:54:58 2015 -0400 Remove some unused variables in InfTextFixlineBuffer libinftext/inf-text-fixline-buffer.c | 3 --- 1 file changed, 3 deletions(-) commit 42064f3a4db4e42db68c222641dd117d8da371f3 Author: Armin Burgmeier Date: Mon Oct 12 19:51:50 2015 -0400 InfTextChunk: fix segment lookup for offset=0 (#10) This used to work with glib 2.42, but it seems that the semantics of g_sequence_search() have changed with respect to what item is returned when the comparison function returns 0. The behavior in that case is not documented. Fix this by passing a different comparison function that never returns 0, so that there is no ambiguity in which segment is returned. libinftext/inf-text-chunk.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) commit 669b3589760ea74312fa2ab7efbfcd4faed2c744 Author: Armin Burgmeier Date: Mon Oct 12 19:51:40 2015 -0400 Fix integrity check in inf_text_chunk_get_byte_index_utf8() libinftext/inf-text-chunk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 0d619e54bd8c351c7e6278bdab3e0cf4a57e8488 Author: Armin Burgmeier Date: Tue Jun 9 22:54:20 2015 -0400 Replace GtkBox by GtkGrid Where possible -- GtkDialog still has some internal GtkBox children libinfgtk/inf-gtk-acl-sheet-view.c | 2 +- libinfgtk/inf-gtk-acl-sheet-view.h | 4 +- libinfgtk/inf-gtk-certificate-manager.c | 7 ++ libinfgtk/inf-gtk-chat.c | 2 +- libinfgtk/inf-gtk-chat.h | 4 +- libinfgtk/inf-gtk-connection-view.c | 2 +- .../resources/ui/infgtkaccountcreationdialog.ui | 58 +++++++------- libinfgtk/resources/ui/infgtkaclsheetview.ui | 13 ++-- libinfgtk/resources/ui/infgtkcertificatedialog.ui | 61 ++++++++------- libinfgtk/resources/ui/infgtkchat.ui | 35 +++++---- libinfgtk/resources/ui/infgtkconnectionview.ui | 17 +++-- libinfgtk/resources/ui/infgtkpermissionsdialog.ui | 84 ++++++++++----------- 12 files changed, 148 insertions(+), 141 deletions(-) commit 4e3c752f1e3c2e1d8c61c22bf56657c3f34c517e Author: Armin Burgmeier Date: Tue Jun 9 21:23:01 2015 -0400 Remove some dead code in InfXmppManager libinfinity/common/inf-xmpp-manager.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) commit 869bf91b5e760eec12b21b0ac859acb164d1132b Author: Armin Burgmeier Date: Tue Jun 9 21:20:23 2015 -0400 Fix uninitialized variable when suggesting a SASL mechanism libinfinity/common/inf-xmpp-connection.c | 1 + 1 file changed, 1 insertion(+) commit f00d234951b61fac37873194cc58448fd5f65e17 Author: Armin Burgmeier Date: Sun Jun 7 21:33:13 2015 -0400 Update copyright years in source files for 2015 infinoted/infinoted-config-reload.c | 2 +- infinoted/infinoted-config-reload.h | 2 +- infinoted/infinoted-dh-params.c | 2 +- infinoted/infinoted-dh-params.h | 2 +- infinoted/infinoted-log.c | 2 +- infinoted/infinoted-log.h | 2 +- infinoted/infinoted-main.c | 2 +- infinoted/infinoted-options.c | 2 +- infinoted/infinoted-options.h | 2 +- infinoted/infinoted-pam.c | 2 +- infinoted/infinoted-pam.h | 2 +- infinoted/infinoted-parameter.c | 2 +- infinoted/infinoted-parameter.h | 2 +- infinoted/infinoted-plugin-manager.c | 2 +- infinoted/infinoted-plugin-manager.h | 2 +- infinoted/infinoted-run.c | 2 +- infinoted/infinoted-run.h | 2 +- infinoted/infinoted-signal.c | 2 +- infinoted/infinoted-signal.h | 2 +- infinoted/infinoted-startup.c | 2 +- infinoted/infinoted-startup.h | 2 +- infinoted/infinoted-util.c | 2 +- infinoted/infinoted-util.h | 2 +- infinoted/plugins/infinoted-plugin-autosave.c | 2 +- infinoted/plugins/infinoted-plugin-certificate-auth.c | 2 +- infinoted/plugins/infinoted-plugin-dbus.c | 2 +- infinoted/plugins/infinoted-plugin-directory-sync.c | 2 +- infinoted/plugins/infinoted-plugin-document-stream.c | 2 +- infinoted/plugins/infinoted-plugin-linekeeper.c | 2 +- infinoted/plugins/infinoted-plugin-logging.c | 2 +- infinoted/plugins/infinoted-plugin-note-chat.c | 2 +- infinoted/plugins/infinoted-plugin-note-text.c | 2 +- infinoted/plugins/infinoted-plugin-record.c | 2 +- infinoted/plugins/infinoted-plugin-traffic-logging.c | 2 +- infinoted/plugins/infinoted-plugin-transformation-protection.c | 2 +- infinoted/plugins/util/infinoted-plugin-util-navigate-browser.c | 2 +- infinoted/plugins/util/infinoted-plugin-util-navigate-browser.h | 2 +- libinfgtk/inf-gtk-account-creation-dialog.c | 2 +- libinfgtk/inf-gtk-account-creation-dialog.h | 2 +- libinfgtk/inf-gtk-acl-sheet-view.c | 2 +- libinfgtk/inf-gtk-acl-sheet-view.h | 2 +- libinfgtk/inf-gtk-browser-model-filter.c | 2 +- libinfgtk/inf-gtk-browser-model-filter.h | 2 +- libinfgtk/inf-gtk-browser-model-sort.c | 2 +- libinfgtk/inf-gtk-browser-model-sort.h | 2 +- libinfgtk/inf-gtk-browser-model.c | 2 +- libinfgtk/inf-gtk-browser-model.h | 2 +- libinfgtk/inf-gtk-browser-store.c | 2 +- libinfgtk/inf-gtk-browser-store.h | 2 +- libinfgtk/inf-gtk-browser-view.c | 2 +- libinfgtk/inf-gtk-browser-view.h | 2 +- libinfgtk/inf-gtk-certificate-dialog.c | 2 +- libinfgtk/inf-gtk-certificate-dialog.h | 2 +- libinfgtk/inf-gtk-certificate-manager.c | 2 +- libinfgtk/inf-gtk-certificate-manager.h | 2 +- libinfgtk/inf-gtk-certificate-view.c | 2 +- libinfgtk/inf-gtk-certificate-view.h | 2 +- libinfgtk/inf-gtk-chat.c | 2 +- libinfgtk/inf-gtk-chat.h | 2 +- libinfgtk/inf-gtk-connection-view.c | 2 +- libinfgtk/inf-gtk-connection-view.h | 2 +- libinfgtk/inf-gtk-io.c | 2 +- libinfgtk/inf-gtk-io.h | 2 +- libinfgtk/inf-gtk-permissions-dialog.c | 2 +- libinfgtk/inf-gtk-permissions-dialog.h | 2 +- libinfinity/adopted/inf-adopted-algorithm.c | 2 +- libinfinity/adopted/inf-adopted-algorithm.h | 2 +- libinfinity/adopted/inf-adopted-no-operation.c | 2 +- libinfinity/adopted/inf-adopted-no-operation.h | 2 +- libinfinity/adopted/inf-adopted-operation.c | 2 +- libinfinity/adopted/inf-adopted-operation.h | 2 +- libinfinity/adopted/inf-adopted-request-log.c | 2 +- libinfinity/adopted/inf-adopted-request-log.h | 2 +- libinfinity/adopted/inf-adopted-request.c | 2 +- libinfinity/adopted/inf-adopted-request.h | 2 +- libinfinity/adopted/inf-adopted-session-record.c | 2 +- libinfinity/adopted/inf-adopted-session-record.h | 2 +- libinfinity/adopted/inf-adopted-session-replay.c | 2 +- libinfinity/adopted/inf-adopted-session-replay.h | 2 +- libinfinity/adopted/inf-adopted-session.c | 2 +- libinfinity/adopted/inf-adopted-session.h | 2 +- libinfinity/adopted/inf-adopted-split-operation.c | 2 +- libinfinity/adopted/inf-adopted-split-operation.h | 2 +- libinfinity/adopted/inf-adopted-state-vector.c | 2 +- libinfinity/adopted/inf-adopted-state-vector.h | 2 +- libinfinity/adopted/inf-adopted-undo-grouping.c | 2 +- libinfinity/adopted/inf-adopted-undo-grouping.h | 2 +- libinfinity/adopted/inf-adopted-user.c | 2 +- libinfinity/adopted/inf-adopted-user.h | 2 +- libinfinity/client/infc-browser.c | 2 +- libinfinity/client/infc-browser.h | 2 +- libinfinity/client/infc-note-plugin.h | 2 +- libinfinity/client/infc-progress-request.c | 2 +- libinfinity/client/infc-progress-request.h | 2 +- libinfinity/client/infc-request-manager.c | 2 +- libinfinity/client/infc-request-manager.h | 2 +- libinfinity/client/infc-request.c | 2 +- libinfinity/client/infc-request.h | 2 +- libinfinity/client/infc-session-proxy.c | 2 +- libinfinity/client/infc-session-proxy.h | 2 +- libinfinity/common/inf-acl.c | 2 +- libinfinity/common/inf-acl.h | 2 +- libinfinity/common/inf-async-operation.c | 2 +- libinfinity/common/inf-async-operation.h | 2 +- libinfinity/common/inf-browser-iter.c | 2 +- libinfinity/common/inf-browser-iter.h | 2 +- libinfinity/common/inf-browser.c | 2 +- libinfinity/common/inf-browser.h | 2 +- libinfinity/common/inf-buffer.c | 2 +- libinfinity/common/inf-buffer.h | 2 +- libinfinity/common/inf-cert-util.c | 2 +- libinfinity/common/inf-cert-util.h | 2 +- libinfinity/common/inf-certificate-chain.c | 2 +- libinfinity/common/inf-certificate-chain.h | 2 +- libinfinity/common/inf-certificate-credentials.c | 2 +- libinfinity/common/inf-certificate-credentials.h | 2 +- libinfinity/common/inf-certificate-verify.c | 2 +- libinfinity/common/inf-certificate-verify.h | 2 +- libinfinity/common/inf-chat-buffer.c | 2 +- libinfinity/common/inf-chat-buffer.h | 2 +- libinfinity/common/inf-chat-session.c | 2 +- libinfinity/common/inf-chat-session.h | 2 +- libinfinity/common/inf-discovery-avahi.c | 2 +- libinfinity/common/inf-discovery-avahi.h | 2 +- libinfinity/common/inf-discovery.c | 2 +- libinfinity/common/inf-discovery.h | 2 +- libinfinity/common/inf-error.c | 2 +- libinfinity/common/inf-error.h | 2 +- libinfinity/common/inf-file-util.c | 2 +- libinfinity/common/inf-file-util.h | 2 +- libinfinity/common/inf-init.c | 2 +- libinfinity/common/inf-init.h | 2 +- libinfinity/common/inf-io.c | 2 +- libinfinity/common/inf-io.h | 2 +- libinfinity/common/inf-ip-address.c | 2 +- libinfinity/common/inf-ip-address.h | 2 +- libinfinity/common/inf-keepalive.c | 2 +- libinfinity/common/inf-keepalive.h | 2 +- libinfinity/common/inf-local-publisher.c | 2 +- libinfinity/common/inf-local-publisher.h | 2 +- libinfinity/common/inf-name-resolver.c | 2 +- libinfinity/common/inf-name-resolver.h | 2 +- libinfinity/common/inf-native-socket.c | 2 +- libinfinity/common/inf-native-socket.h | 2 +- libinfinity/common/inf-protocol.c | 2 +- libinfinity/common/inf-protocol.h | 2 +- libinfinity/common/inf-request-result.c | 2 +- libinfinity/common/inf-request-result.h | 2 +- libinfinity/common/inf-request.c | 2 +- libinfinity/common/inf-request.h | 2 +- libinfinity/common/inf-sasl-context.c | 2 +- libinfinity/common/inf-sasl-context.h | 2 +- libinfinity/common/inf-session-proxy.c | 2 +- libinfinity/common/inf-session-proxy.h | 2 +- libinfinity/common/inf-session.c | 2 +- libinfinity/common/inf-session.h | 2 +- libinfinity/common/inf-simulated-connection.c | 2 +- libinfinity/common/inf-simulated-connection.h | 2 +- libinfinity/common/inf-standalone-io.c | 2 +- libinfinity/common/inf-standalone-io.h | 2 +- libinfinity/common/inf-tcp-connection-private.h | 2 +- libinfinity/common/inf-tcp-connection.c | 2 +- libinfinity/common/inf-tcp-connection.h | 2 +- libinfinity/common/inf-user-table.c | 2 +- libinfinity/common/inf-user-table.h | 2 +- libinfinity/common/inf-user.c | 2 +- libinfinity/common/inf-user.h | 2 +- libinfinity/common/inf-xml-connection.c | 2 +- libinfinity/common/inf-xml-connection.h | 2 +- libinfinity/common/inf-xml-util.c | 2 +- libinfinity/common/inf-xml-util.h | 2 +- libinfinity/common/inf-xmpp-connection.c | 2 +- libinfinity/common/inf-xmpp-connection.h | 2 +- libinfinity/common/inf-xmpp-manager.c | 2 +- libinfinity/common/inf-xmpp-manager.h | 2 +- libinfinity/communication/inf-communication-central-factory.c | 2 +- libinfinity/communication/inf-communication-central-factory.h | 2 +- libinfinity/communication/inf-communication-central-method.c | 2 +- libinfinity/communication/inf-communication-central-method.h | 2 +- libinfinity/communication/inf-communication-factory.c | 2 +- libinfinity/communication/inf-communication-factory.h | 2 +- libinfinity/communication/inf-communication-group-private.h | 2 +- libinfinity/communication/inf-communication-group.c | 2 +- libinfinity/communication/inf-communication-group.h | 2 +- libinfinity/communication/inf-communication-hosted-group.c | 2 +- libinfinity/communication/inf-communication-hosted-group.h | 2 +- libinfinity/communication/inf-communication-joined-group.c | 2 +- libinfinity/communication/inf-communication-joined-group.h | 2 +- libinfinity/communication/inf-communication-manager.c | 2 +- libinfinity/communication/inf-communication-manager.h | 2 +- libinfinity/communication/inf-communication-method.c | 2 +- libinfinity/communication/inf-communication-method.h | 2 +- libinfinity/communication/inf-communication-object.c | 2 +- libinfinity/communication/inf-communication-object.h | 2 +- libinfinity/communication/inf-communication-registry.c | 2 +- libinfinity/communication/inf-communication-registry.h | 2 +- libinfinity/inf-config.h.in | 2 +- libinfinity/inf-define-enum.h | 2 +- libinfinity/inf-dll.c | 2 +- libinfinity/inf-dll.h | 2 +- libinfinity/inf-i18n.c | 2 +- libinfinity/inf-i18n.h | 2 +- libinfinity/inf-signals.c | 2 +- libinfinity/inf-signals.h | 2 +- libinfinity/server/infd-account-storage.c | 2 +- libinfinity/server/infd-account-storage.h | 2 +- libinfinity/server/infd-chat-filesystem-format.c | 2 +- libinfinity/server/infd-chat-filesystem-format.h | 2 +- libinfinity/server/infd-directory.c | 2 +- libinfinity/server/infd-directory.h | 2 +- libinfinity/server/infd-filesystem-account-storage.c | 2 +- libinfinity/server/infd-filesystem-account-storage.h | 2 +- libinfinity/server/infd-filesystem-storage.c | 2 +- libinfinity/server/infd-filesystem-storage.h | 2 +- libinfinity/server/infd-note-plugin.h | 2 +- libinfinity/server/infd-progress-request.c | 2 +- libinfinity/server/infd-progress-request.h | 2 +- libinfinity/server/infd-request.c | 2 +- libinfinity/server/infd-request.h | 2 +- libinfinity/server/infd-server-pool.c | 2 +- libinfinity/server/infd-server-pool.h | 2 +- libinfinity/server/infd-session-proxy.c | 2 +- libinfinity/server/infd-session-proxy.h | 2 +- libinfinity/server/infd-storage.c | 2 +- libinfinity/server/infd-storage.h | 2 +- libinfinity/server/infd-tcp-server.c | 2 +- libinfinity/server/infd-tcp-server.h | 2 +- libinfinity/server/infd-xml-server.c | 2 +- libinfinity/server/infd-xml-server.h | 2 +- libinfinity/server/infd-xmpp-server.c | 2 +- libinfinity/server/infd-xmpp-server.h | 2 +- libinftext/inf-text-buffer.c | 2 +- libinftext/inf-text-buffer.h | 2 +- libinftext/inf-text-chunk.c | 2 +- libinftext/inf-text-chunk.h | 2 +- libinftext/inf-text-default-buffer.c | 2 +- libinftext/inf-text-default-buffer.h | 2 +- libinftext/inf-text-default-delete-operation.c | 2 +- libinftext/inf-text-default-delete-operation.h | 2 +- libinftext/inf-text-default-insert-operation.c | 2 +- libinftext/inf-text-default-insert-operation.h | 2 +- libinftext/inf-text-delete-operation.c | 2 +- libinftext/inf-text-delete-operation.h | 2 +- libinftext/inf-text-filesystem-format.c | 2 +- libinftext/inf-text-filesystem-format.h | 2 +- libinftext/inf-text-fixline-buffer.c | 2 +- libinftext/inf-text-fixline-buffer.h | 2 +- libinftext/inf-text-insert-operation.c | 2 +- libinftext/inf-text-insert-operation.h | 2 +- libinftext/inf-text-move-operation.c | 2 +- libinftext/inf-text-move-operation.h | 2 +- libinftext/inf-text-operations.h | 2 +- libinftext/inf-text-remote-delete-operation.c | 2 +- libinftext/inf-text-remote-delete-operation.h | 2 +- libinftext/inf-text-session.c | 2 +- libinftext/inf-text-session.h | 2 +- libinftext/inf-text-undo-grouping.c | 2 +- libinftext/inf-text-undo-grouping.h | 2 +- libinftext/inf-text-user.c | 2 +- libinftext/inf-text-user.h | 2 +- libinftextgtk/inf-text-gtk-buffer.c | 2 +- libinftextgtk/inf-text-gtk-buffer.h | 2 +- libinftextgtk/inf-text-gtk-hue-chooser.c | 2 +- libinftextgtk/inf-text-gtk-hue-chooser.h | 2 +- libinftextgtk/inf-text-gtk-view.c | 2 +- libinftextgtk/inf-text-gtk-view.h | 2 +- libinftextgtk/inf-text-gtk-viewport.c | 2 +- libinftextgtk/inf-text-gtk-viewport.h | 2 +- test/inf-test-browser.c | 2 +- test/inf-test-certificate-request.c | 2 +- test/inf-test-certificate-validate.c | 2 +- test/inf-test-chat.c | 2 +- test/inf-test-chunk.c | 2 +- test/inf-test-daemon.c | 2 +- test/inf-test-gtk-browser.c | 2 +- test/inf-test-mass-join.c | 2 +- test/inf-test-reduce-replay.c | 2 +- test/inf-test-set-acl.c | 2 +- test/inf-test-state-vector.c | 2 +- test/inf-test-tcp-connection.c | 2 +- test/inf-test-tcp-server.c | 2 +- test/inf-test-text-cleanup.c | 2 +- test/inf-test-text-fixline.c | 2 +- test/inf-test-text-operations.c | 2 +- test/inf-test-text-quick-write.c | 2 +- test/inf-test-text-recover.c | 2 +- test/inf-test-text-replay.c | 2 +- test/inf-test-text-session.c | 2 +- test/inf-test-traffic-replay.c | 2 +- test/inf-test-xmpp-connection.c | 2 +- test/inf-test-xmpp-server.c | 2 +- test/util/inf-test-util.c | 2 +- test/util/inf-test-util.h | 2 +- 293 files changed, 293 insertions(+), 293 deletions(-) commit 7921fd451db3cce7fd962080bbedc7b8648be4e9 Author: Armin Burgmeier Date: Sun Jun 7 21:28:28 2015 -0400 Include pam_appl.h from security/ also on OS X Recent versions of OS X seem to have that header in security/ instead of pam/ infinoted/infinoted-pam.c | 4 ---- 1 file changed, 4 deletions(-) commit 2c96b4edf8c1a51c07b097e21f941bf7b040c42a Author: Armin Burgmeier Date: Sun Jun 7 21:27:23 2015 -0400 InfXmppConnection: Fix strncmp invocation when suggesting SASL mechanism libinfinity/common/inf-xmpp-connection.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 041b0839861de32774f15df6deeaaeb2bc484d98 Author: Armin Burgmeier Date: Sun Jun 7 21:25:58 2015 -0400 inf_keepalive_apply: fix parentheses in comparison of bitwise operation libinfinity/common/inf-keepalive.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 452c72aa9544199c51101d94e26e33e51ebc5bc2 Author: hgrundy Date: Sun Jun 7 11:34:04 2015 -0700 Update AUTHORS Touch years again. AUTHORS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit bef26888297375caac232fff244284cb0abfcdf2 Author: Armin Burgmeier Date: Wed Jun 3 21:51:17 2015 -0400 Add some spacing between "View certificate" expander and certificate list libinfgtk/resources/ui/infgtkcertificatedialog.ui | 1 + libinfgtk/resources/ui/infgtkconnectionview.ui | 1 + 2 files changed, 2 insertions(+) commit 817639b633e611ce04d8f42ed614408734b7427b Author: Armin Burgmeier Date: Sun May 31 19:14:07 2015 -0400 Make InfGtkChat expand horizontally and vertically This becomes relevant when the widget is attached to a GtkGrid. libinfgtk/resources/ui/infgtkchat.ui | 4 ++++ 1 file changed, 4 insertions(+) commit 11e7fb29eaded2748b739d290a5d26bb8e588e39 Author: Armin Burgmeier Date: Wed May 27 22:25:07 2015 -0400 inf-test-traffic-replay: Improve mismatch output format test/inf-test-traffic-replay.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 6d69aa5a97d72460cd6f0d9de866cfcb46230bb5 Author: Armin Burgmeier Date: Wed May 27 22:24:49 2015 -0400 inf-test-traffic-replay: Parse microseconds from replay test/inf-test-traffic-replay.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) commit 5914b9adf5c9aeb238c78669f2869f365c41c6b8 Author: Armin Burgmeier Date: Wed May 27 22:21:22 2015 -0400 Fix g_free / g_slice_free mismatch libinfinity/server/infd-directory.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) commit e55819bc7dd2a2b1581eaa01ba321de6a36956c4 Author: Armin Burgmeier Date: Wed May 27 21:12:28 2015 -0400 InfdDirectory: Fix error reply to client when session proxy cannot be created libinfinity/server/infd-directory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 42c55330a4c327e4db3c45a7c08cdd92068bdf9a Author: Armin Burgmeier Date: Sun May 24 13:11:02 2015 -0400 Make sure to prefer DHE-RSA over RSA Recent versions of GnuTLS prefer RSA over DHE-RSA for comatibility reasons. If a server negotiates a DH group with a low number of prime bits, the handshake will inevitably fial and there is no way to fall back to RSA. However, the DH groups that Gobby and infinoted generate have 2048 bits, so we don't expect this to be a problem in practise, and can therefore benefit from DHE-RSA. This might become a problem in the future, and we can re-visit then. Note that when Gobby and infinoted are used with recent versions of GnuTLS, they also prefer ECDHE over DHE, in which case this is not an issue anyway. This change basically fixes PFS when a client with a recent GnuTLS version connects to a server with a not-so-recent GnuTLS version (such as 2.12). We can do this because we know that the DH group that that server will have is strong enough. libinfinity/common/inf-xmpp-connection.c | 44 ++++++++---------------------- 1 file changed, 12 insertions(+), 32 deletions(-) commit 24b0ce6d986ad399b16ee695c8d15a1cd83e73de Author: Armin Burgmeier Date: Sat May 23 18:30:58 2015 -0400 Add InfGtkConnectionView docs/reference/libinfgtk/libinfgtk-0.7-docs.sgml | 1 + .../libinfgtk/libinfgtk-0.7-sections.txt | 21 + libinfgtk/Makefile.am | 3 + libinfgtk/inf-gtk-connection-view.c | 624 ++++++++++++++++++++ libinfgtk/inf-gtk-connection-view.h | 79 +++ libinfgtk/resources/infgtk.gresources.xml | 1 + libinfgtk/resources/ui/infgtkconnectionview.ui | 263 +++++++++ 7 files changed, 992 insertions(+) commit 32e7feba2be355a40287d410c3efe31a86ef3e32 Author: Armin Burgmeier Date: Sat May 23 22:07:44 2015 -0400 Add public API to obtain TLS parameters .../libinfinity/libinfinity-0.7-sections.txt | 5 + libinfinity/common/inf-xmpp-connection.c | 129 ++++++++++++++++++++ libinfinity/common/inf-xmpp-connection.h | 15 +++ 3 files changed, 149 insertions(+) commit 54a681d204036b8e263d672681b2f3d7a0b43707 Author: Armin Burgmeier Date: Sat May 23 18:30:29 2015 -0400 Small fixes to InfGtkCertificateDialog and InfGtkCertificateView libinfgtk/inf-gtk-certificate-dialog.h | 2 -- libinfgtk/inf-gtk-certificate-view.h | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) commit e4f2618d2d9c6e90c11b505182c8b79487fb47ca Author: Armin Burgmeier Date: Sat May 23 17:26:03 2015 -0400 Add signature algorithm information in certificate dialog libinfgtk/inf-gtk-certificate-view.c | 26 ++++++++++++++++ libinfgtk/resources/ui/infgtkcertificateview.ui | 38 +++++++++++++++++++++++ 2 files changed, 64 insertions(+) commit 5b88b02e379dd692b1ec85a787a1647fe21b19af Author: Armin Burgmeier Date: Sat May 23 16:52:12 2015 -0400 Add a test which writes text into an infinote document very quickly test/Makefile.am | 9 +- test/inf-test-text-quick-write.c | 644 +++++++++++++++++++++++++++++++++++++ 2 files changed, 652 insertions(+), 1 deletion(-) commit e2a25a38429bed21bcf7cdca25e3bce209eeb671 Author: Armin Burgmeier Date: Sat May 23 14:39:59 2015 -0400 Fix session becoming inconsistent with active local users during subscription When the server sends the vector time of local users during subscription, it now sends the last send vector instead of the real value of the user time, so that subsequent state vector diffs are consistent for the newly joined client. libinfinity/adopted/inf-adopted-session.c | 34 ++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) commit ea5b55f8e3e3d8478f91429b8ca2bd0cff21d9b4 Author: Armin Burgmeier Date: Fri May 22 19:22:26 2015 -0400 Fix a possible crash when removing a browser entry libinfgtk/inf-gtk-browser-store.c | 5 +++++ libinfgtk/inf-gtk-browser-view.c | 11 +++++++++++ 2 files changed, 16 insertions(+) commit a3dff98887c973d9452d0d97785a50fd7c20a60c Author: Armin Burgmeier Date: Mon May 18 21:08:37 2015 -0400 Initialize libinfinity in certificate validate test Otherwise GnuTLS will not work in old GnuTLS versions. test/inf-test-certificate-validate.c | 9 +++++++++ 1 file changed, 9 insertions(+) commit 5b2e89b98ca4887392f4ee36850225d316f0f32b Author: Armin Burgmeier Date: Sun May 17 22:57:42 2015 -0400 Fix variable initialization in inf-test-certificate-validate test/inf-test-certificate-validate.c | 1 + 1 file changed, 1 insertion(+) commit 1eda108268adb5cd5216f207be71675434e82cb1 Author: Armin Burgmeier Date: Sun May 17 22:56:20 2015 -0400 Fix buffer underrun in memrchr implementation libinfinity/common/inf-cert-util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 05f8baeab2f07de72648eeed00723890edd31d4e Author: Armin Burgmeier Date: Sun May 17 20:19:22 2015 -0400 Enhance the certificate verification unit test Check whether we would query the user or not, and whether the certificate would be pinned afterwards or not. test/certs/Makefile.am | 6 +- test/certs/test-expire-good-crt.pem | 32 +++ test/certs/test-expire-good-key.pem | 51 ++++ test/certs/test-good-crt.pem | 32 +++ test/certs/test-good-key.pem | 51 ++++ test/inf-test-certificate-validate.c | 432 +++++++++++++++++++++++++++++++-- 6 files changed, 577 insertions(+), 27 deletions(-) commit 254eaec3c6fadd63c0ffeeeedb11e11c786a4f1e Author: Armin Burgmeier Date: Sun May 17 18:36:43 2015 -0400 Make the certificate validation test not depend on GTK+ test/Makefile.am | 3 +-- test/inf-test-certificate-validate.c | 38 +++++++++++++++------------------- 2 files changed, 18 insertions(+), 23 deletions(-) commit ff46d6cda9b784bcf5c0243d031a0eb9b74a41d7 Author: Armin Burgmeier Date: Sun May 17 20:28:28 2015 -0400 Move the function to compare fingerprints to inf-cert-util .../libinfinity/libinfinity-0.7-sections.txt | 1 + libinfinity/common/inf-cert-util.c | 60 +++++++++++++++++++++ libinfinity/common/inf-cert-util.h | 13 +++-- libinfinity/common/inf-certificate-verify.c | 53 +----------------- 4 files changed, 72 insertions(+), 55 deletions(-) commit f31b75343c93bff1e14d87904c52d6a82a714f36 Author: Armin Burgmeier Date: Sun May 17 17:37:46 2015 -0400 Refactor certificate verification The non-UI dependent parts are now in the InfCertificateVerify class. .../libinfgtk/libinfgtk-0.7-sections.txt | 3 - .../libinfinity/libinfinity-0.7-docs.sgml | 1 + .../libinfinity/libinfinity-0.7-sections.txt | 20 + libinfgtk/inf-gtk-certificate-dialog.c | 144 +-- libinfgtk/inf-gtk-certificate-dialog.h | 31 +- libinfgtk/inf-gtk-certificate-manager.c | 836 ++++------------- libinfgtk/inf-gtk-certificate-manager.h | 6 +- libinfgtk/resources/ui/infgtkcertificatedialog.ui | 6 +- libinfinity/Makefile.am | 2 + libinfinity/common/inf-certificate-verify.c | 943 ++++++++++++++++++++ libinfinity/common/inf-certificate-verify.h | 110 +++ 11 files changed, 1325 insertions(+), 777 deletions(-) commit 080b0e992cc68d96e181f767e46db48bd962571d Author: Armin Burgmeier Date: Sun May 17 15:30:39 2015 -0400 Move writing of pinned certificates to inf-cert-util TODO | 8 +- .../libinfinity/libinfinity-0.7-sections.txt | 2 + libinfgtk/inf-gtk-certificate-manager.c | 255 +----------------- libinfinity/common/inf-cert-util.c | 274 +++++++++++++++++++- libinfinity/common/inf-cert-util.h | 9 + 5 files changed, 295 insertions(+), 253 deletions(-) commit 2e065b3cfd1769ae256573747ad4dbc1f5db2a59 Author: Armin Burgmeier Date: Tue May 12 20:55:41 2015 -0400 Fix make distcheck for recent automake versions Recent automake versions run with a more restrictive umask, so that the version.xml files are created with read-only permissions. This fails when trying to override them, so remove them explicitly before. docs/reference/Makefile.am | 2 ++ 1 file changed, 2 insertions(+) commit c97f870f5ae13112988d9f8ad464b4f679903706 Author: Armin Burgmeier Date: Mon May 11 22:59:34 2015 -0400 Fix expired certificate validation (gobby #61) libinfgtk/inf-gtk-certificate-manager.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) commit 3be299585a2fbf44811e27190435c87a4388c725 Author: Armin Burgmeier Date: Mon May 11 23:00:00 2015 -0400 Add a unit test for certicate validation At the moment this only includes one test that checks an expired certificate, but we should add more in the future. .gitignore | 1 - configure.ac | 1 + test/Makefile.am | 17 +- test/certs/Makefile.am | 5 + test/certs/ca-crt.pem | 34 +++ test/certs/ca-key.pem | 51 ++++ test/certs/test-expire-crt.pem | 32 +++ test/certs/test-expire-key.pem | 51 ++++ test/inf-test-certificate-validate.c | 428 +++++++++++++++++++++++++++++++++ 9 files changed, 616 insertions(+), 4 deletions(-) commit f321334dd28a23699069767c892811e5522f8e20 Author: Armin Burgmeier Date: Mon May 11 22:57:58 2015 -0400 InfdXmppServer: Unref own SASL context when setting a new connection The TODO comment above is valid no matter whether we do this or not, and this prevents an assertion to trigger in dispose() when unsetting the TCP connection and an own SASL context is in place. libinfinity/server/infd-xmpp-server.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit bdf0e9ccd914430e2eb835a3ffddd89eb3766a56 Author: Armin Burgmeier Date: Mon May 11 22:57:02 2015 -0400 Make inf_xmpp_connection_error_quark public .../libinfinity/libinfinity-0.7-sections.txt | 1 + libinfinity/common/inf-xmpp-connection.c | 38 +++++++++++++-------- libinfinity/common/inf-xmpp-connection.h | 3 ++ 3 files changed, 27 insertions(+), 15 deletions(-) commit 753bdcecf7e0a055c10a2cb0950ba8abb3953bf6 Author: Armin Burgmeier Date: Tue May 5 20:45:45 2015 -0400 Update caret position when only updating fixline state When the user inserts some newlines that are "swallowed" by the fixline buffer, then still advance the user's cursor such that newly to-be-written text is inserted after the imaginary newline. libinftext/inf-text-fixline-buffer.c | 54 ++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) commit 2bcf03391e626bb7b69ea1e2c50ea10f2a56eb22 Author: Armin Burgmeier Date: Wed May 6 18:22:55 2015 -0400 Allow multi-line chat messages (#gobby 58) libinfgtk/inf-gtk-chat.c | 45 ++++++++++++++++++++++++++++------ libinfgtk/resources/ui/infgtkchat.ui | 2 +- 2 files changed, 38 insertions(+), 9 deletions(-) commit 117bd0b4279ab3d4ac6d374e05d7d1edd65c3355 Author: Armin Burgmeier Date: Wed May 6 18:22:16 2015 -0400 InfGtkChat: Handle chat messages that are not null-terminated libinfgtk/inf-gtk-chat.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) commit ff6b3a23c15d426cdcb2a3d48df296f170adb9c9 Author: Armin Burgmeier Date: Mon May 4 20:31:12 2015 -0400 fixline buffer: Fix crash when iterating backwards through empty base buffer libinftext/inf-text-fixline-buffer.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) commit 7785d613a191a23f7e2340a372ed19862bde15de Author: Armin Burgmeier Date: Sun May 3 17:07:46 2015 -0400 Fix insert/erase notifications in InfTextFixlineBuffer The notifications were missing when the fixline buffer was modified directly with the API, and not in response to modifications to the underlying base buffer. libinftext/inf-text-fixline-buffer.c | 10 ++++++++++ 1 file changed, 10 insertions(+) commit c774fc97b5aa3414084f82e6d85faad60e23b2af Author: Armin Burgmeier Date: Thu Apr 30 21:37:23 2015 -0400 Fix create_end_iter() implementation in InfTextFixlineBuffer libinftext/inf-text-fixline-buffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit f8d3cf5049b2bf6dd75fb51398df4ba0bd96ec9a Author: Armin Burgmeier Date: Sat Apr 25 18:49:58 2015 -0400 Make Ctrl+C work in the chat box (gobby #53) We allow the chat box to receive focus, and the focus is directly transferred to the text entry. When Ctrl+C is pressed with the text entry focused, and no text selected in the entry, the selected text in the chat box is copied. libinfgtk/inf-gtk-chat.c | 70 ++++++++++++++++++++++++++++++++++ libinfgtk/resources/ui/infgtkchat.ui | 3 +- 2 files changed, 72 insertions(+), 1 deletion(-) commit a638bf48a01bf34660fa4b1eb29cbb922243eb01 Author: Armin Burgmeier Date: Fri Apr 3 13:32:01 2015 -0400 Fix crash after unloading dbus plugin Loading the dbus plugin also loads libgio-2.0.so, and when the plugin is unloaded, both are unloaded again. However, unloading libgio-2.0.so does not really work because it registers static memory with the gobject type system. Therefore, make sure that libgio stays loaded even after the dbus plugin gets unloaded. infinoted/plugins/infinoted-plugin-dbus.c | 42 +++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) commit ddd81af0933deab83c09c3d95a679489818053da Author: Armin Burgmeier Date: Fri Apr 3 13:05:29 2015 -0400 Add infinoted-plugin-dbus.c to POTFILES po/POTFILES.in | 1 + 1 file changed, 1 insertion(+) commit f2d8c87de90f3fa78baa71a65dd3349731b93c1e Author: Armin Burgmeier Date: Fri Apr 3 13:04:24 2015 -0400 Fix a crash when the server explicitly changes client account to default libinfinity/client/infc-browser.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) commit 4c5c4c62f57b3751042bddd8f662903b55babf56 Author: Jochen Müller Date: Wed Jan 28 15:46:10 2015 +0100 Fixed some minor mistakes in Windows-specific code for keepalives. libinfinity/common/inf-keepalive.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) commit c425b60d0549b898ce378db922d8926ddcffa044 Author: Armin Burgmeier Date: Wed Jan 14 15:28:16 2015 -0500 Check whether we need -lresolv for res_query() (gobby #23) Some systems such as FreeBSD have res_query() within libc, and passing -lresolv to the linker makes it fail because libresolv does not exist. configure.ac | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) commit d243a3cb81ad55ae2fca6625566dc0625301d38f Author: Philipp Kern Date: Wed Jan 7 00:09:55 2015 +0100 Travis CI: Ensure the presence of a current Ubuntu signing key. .travis.yml | 1 + 1 file changed, 1 insertion(+) commit a85ffdea80236172ece23b7ab6751b2e0e0a1a61 Author: Philipp Kern Date: Tue Jan 6 23:39:51 2015 +0100 Travis CI: Upgrade zlib to trusty due to libxml2. libxml2 in trusty seems to require trusty's zlib without declaring this dependency. Attempt to upgrade it first. .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 09531b5830ebad0d6fda82a91b4ad4a8df6b59ac Author: Philipp Kern Date: Tue Jan 6 23:39:01 2015 +0100 Revert "Travis CI: attempt a dist-upgrade first" This reverts commit 8231b949b4a41e420646a7d4e6a4e51af8516d3f. .travis.yml | 1 - 1 file changed, 1 deletion(-) commit d8d4d723a5f06f8288237990f0309c811d6de030 Author: Philipp Kern Date: Tue Jan 6 23:38:40 2015 +0100 Revert "Travis CI: handle conffile prompts on dist-upgrade correctly" This reverts commit 7fc1aa2454d46588d37596636fbe710bb01100da. .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 9acdde9b656110beb23aac72ef295f31121f8629 Author: Armin Burgmeier Date: Tue Jan 6 16:48:10 2015 +0100 Fix a crash when sending unsubscribe message causes connection failure libinfinity/client/infc-session-proxy.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) commit dd85786081ae65ea1afab3737076d5f1cbe2506d Author: Armin Burgmeier Date: Tue Jan 6 14:13:38 2015 +0100 InfdDirectory: Fail add-subdirectory request if name already exists libinfinity/server/infd-directory.c | 74 +++++++++++++++++++++-------------- 1 file changed, 45 insertions(+), 29 deletions(-) commit 847c089267494de8dcef304885094bea6c3226f5 Author: Armin Burgmeier Date: Tue Jan 6 13:30:37 2015 +0100 Fix assertion failure when directory without storage is disposed libinfinity/server/infd-directory.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) commit 7fc1aa2454d46588d37596636fbe710bb01100da Author: Philipp Kern Date: Tue Dec 23 13:32:41 2014 +0100 Travis CI: handle conffile prompts on dist-upgrade correctly .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 8231b949b4a41e420646a7d4e6a4e51af8516d3f Author: Philipp Kern Date: Tue Dec 23 13:18:08 2014 +0100 Travis CI: attempt a dist-upgrade first .travis.yml | 1 + 1 file changed, 1 insertion(+) commit 0469f348ae90922dd83e0998ad8b7a31895e9c1c Author: Philipp Kern Date: Tue Dec 23 13:03:08 2014 +0100 Travis CI: install libexpat1-dev as required by gtk+3.0 .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit fb4817ed8da337b79257d72ef186cfe66a81d9f0 Author: Philipp Kern Date: Tue Dec 23 12:56:41 2014 +0100 Travis CI: Pull build-dependencies from trusty. .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 29b58e0f9b0166be93b5878a530b3b2f7272b25c Author: Philipp Kern Date: Tue Dec 23 12:52:22 2014 +0100 Travis CI: install gobject-introspection .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit f17572de2cf601586ece6023d6c79267d85c2b6c Author: Philipp Kern Date: Tue Dec 23 12:46:15 2014 +0100 Travis CI: make trusty available .travis.yml | 1 + 1 file changed, 1 insertion(+) commit 8b8ba82b2d587adb2de73d7592eacfb4c3271840 Author: Armin Burgmeier Date: Tue Nov 25 10:48:10 2014 -0500 Add inf_io_add_watch_from_fd() (#8) This function is only available on Unix, and primarily intended for language bindings, since InfNativeSocket is not a managed type. .../libinfinity/libinfinity-0.7-sections.txt | 1 + libinfinity/common/inf-io.c | 64 +++++++++++++++++++++ libinfinity/common/inf-io.h | 12 +++- 3 files changed, 76 insertions(+), 1 deletion(-) commit 3048b6c3faf088787691501f112e883780395924 Author: Armin Burgmeier Date: Mon Oct 27 14:40:47 2014 -0400 Also support traffic replay on a server with the traffic replay tool test/inf-test-traffic-replay.c | 968 +++++++++++++++++++++++++++++++-------- 1 file changed, 781 insertions(+), 187 deletions(-) commit 050e26b7f6a15b616302942d34d2c35610815b13 Author: Armin Burgmeier Date: Tue Oct 28 13:40:42 2014 -0400 Fix a memory leak in the dbus plugin infinoted/plugins/infinoted-plugin-dbus.c | 2 ++ 1 file changed, 2 insertions(+) commit dd37b5a53f929565a785104c7a2de7f8da0df280 Author: Armin Burgmeier Date: Tue Oct 28 13:39:53 2014 -0400 Fix a memory leak in the plugin manager infinoted/infinoted-plugin-manager.c | 2 ++ 1 file changed, 2 insertions(+) commit cb63d072f30f3cb9768235a05d7f6f0b73501790 Author: Armin Burgmeier Date: Tue Oct 28 13:28:10 2014 -0400 Fix possible crash when a connection goes down while broadcasting data .../inf-communication-central-method.c | 167 ++++++++++---------- 1 file changed, 85 insertions(+), 82 deletions(-) commit 705844df34ae9afd4c2664f075e800862f689610 Author: Armin Burgmeier Date: Tue Oct 28 10:27:55 2014 -0400 Make sure messages are not attempted to be sent on closed connections .../inf-communication-central-method.c | 7 +++++- .../communication/inf-communication-registry.c | 24 +++++++++++++++------ 2 files changed, 24 insertions(+), 7 deletions(-) commit 09d040575ac650beee3eaf4d5107107fdb6fc16e Author: Armin Burgmeier Date: Tue Oct 28 10:27:21 2014 -0400 Add a missing status notify in InfXmppConnection libinfinity/common/inf-xmpp-connection.c | 3 +++ 1 file changed, 3 insertions(+) commit 631d0396631c4f155cfeddaa60f68fc5f96654d3 Author: Armin Burgmeier Date: Mon Oct 27 15:54:17 2014 -0400 Fix error message in server log when a client certificate is not trusted infinoted/plugins/infinoted-plugin-certificate-auth.c | 2 +- libinfinity/common/inf-error.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) commit 7fcb1435b7d241b37ba1a31d5cb3c56812f74f8c Author: Armin Burgmeier Date: Sun Oct 26 10:37:56 2014 -0400 Store timestamp of messages in microsecond resolution in traffic logs This will allow for a more accurate replay of multiple streams on the same server. infinoted/plugins/infinoted-plugin-traffic-logging.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) commit bcc3748742b8ba1c6bb0cd5487a0f5b3ef706287 Author: Armin Burgmeier Date: Wed Oct 22 13:44:03 2014 -0400 Fix possible memory corruption on insert in fixline buffer Also, add a test which reproduces this problem. While the test might well run through even with the buggy version, valgrind will uncover the memory corruption, and in some cases it can lead to a crash or otherwise undesired behaviour. libinftext/inf-text-fixline-buffer.c | 6 +++++- test/inf-test-text-fixline.c | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) commit 17d1c4ca5cd063f3dcbfb026dd282fc6aeae36e3 Author: Armin Burgmeier Date: Wed Oct 22 11:51:01 2014 -0400 Add a debug tool to replay a traffic log on a client test/Makefile.am | 9 +- test/inf-test-traffic-replay.c | 516 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 524 insertions(+), 1 deletion(-) commit 096634c70bf9bb0c466df2f4cd4fea02cf8f3c96 Author: Armin Burgmeier Date: Wed Oct 22 12:37:37 2014 -0400 Fix crash on an add-node request for a non-explored subdirectory libinfinity/client/infc-browser.c | 12 ++++++++++++ libinfinity/common/inf-error.c | 2 ++ libinfinity/common/inf-error.h | 3 +++ 3 files changed, 17 insertions(+) commit c361c7042732499b0cc39e9bbf1f5e331d0791a9 Author: Armin Burgmeier Date: Sat Oct 18 13:39:57 2014 -0400 infinoted-plugin-document-stream: Only use MSG_NOSIGNAL if available (#7) This is a build fix for Mac OS X. infinoted/plugins/infinoted-plugin-document-stream.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) commit addc7ea864f111837324805e41ec5efab7267532 Author: Armin Burgmeier Date: Sat Oct 18 13:39:06 2014 -0400 inf-name-resolver: Include and (#7) This fixes the build on Mac OS X. libinfinity/common/inf-name-resolver.c | 2 ++ 1 file changed, 2 insertions(+) commit 799dab8dea1bc6f267171b2f6b1b288bdb6cc419 Author: Armin Burgmeier Date: Thu Oct 9 13:19:14 2014 -0400 Use length-independent string compare for password check Thanks to Jann Horn for pointing this out. infinoted/infinoted-options.c | 4 ++++ infinoted/infinoted-options.h | 1 + infinoted/infinoted-startup.c | 20 +++++++++++++++++++- 3 files changed, 24 insertions(+), 1 deletion(-) commit d4a53299ee2fbc1ce65c0638a0945f84a75f9169 Author: Armin Burgmeier Date: Thu Oct 9 12:53:46 2014 -0400 Fix possible warning when session could not be created libinfinity/server/infd-directory.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) commit a32706cb48ab2237c1d31eda9207575898fb7833 Author: Armin Burgmeier Date: Thu Oct 9 12:53:32 2014 -0400 Fix sheet set verification when no account storage is set libinfinity/server/infd-directory.c | 48 ++++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 12 deletions(-) commit 9ef618ba96dd59a3c54bfc56eac2aa7fc6602085 Author: Armin Burgmeier Date: Thu Oct 9 12:51:49 2014 -0400 Fix possible deadlock in dbus plugin Apparently g_main_loop_quit() cannot be used from one thread to quit the main loop in another thread. Instead, an idle source is added now. Unfortunately, there is some strange crash happening inside a glib thread when the plugin is unloaded. That thread seems to do some more deinitialization, but we don't have a possibility to wait for it. We might need to use some more low-level dbus API to fix that properly. infinoted/plugins/infinoted-plugin-dbus.c | 45 +++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) commit e95c4668f539f3876889e47e26d42f1f164d7d90 Author: Armin Burgmeier Date: Thu Oct 9 11:16:39 2014 -0400 Fix check for empty path component in InfdFilesystemStorage Thanks to Jann Horn for reporting this. At the moment I don't think there are any security implications because of this. libinfinity/server/infd-directory.c | 17 ++++++++++++----- libinfinity/server/infd-filesystem-account-storage.c | 2 +- libinfinity/server/infd-filesystem-storage.c | 16 +++++++++++++--- 3 files changed, 26 insertions(+), 9 deletions(-) commit 84332bab84749f461d167e66f60cb892f3a83e41 Author: Armin Burgmeier Date: Mon Oct 6 18:05:52 2014 -0400 Change the mode parameter for directory creation to 0777 (#6) This especially affects the directory-sync plugin. If other modes are desired, the umask of the process should be set accordingly. This change allows the plugin to create directory that are readable or writable by other users than the process owner. infinoted/infinoted-util.c | 2 +- infinoted/plugins/infinoted-plugin-directory-sync.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) commit 8ee092630f84541f00b94bb71bbab45bbb6d8bdc Author: Armin Burgmeier Date: Sat Oct 4 20:49:28 2014 -0400 infinoted-plugin-document-stream: Don't join a user if username is empty infinoted/plugins/infinoted-plugin-document-stream.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) commit 3430961b51ea6ad75eea7302495d5c1a8d9b3292 Author: Armin Burgmeier Date: Wed Oct 1 14:39:53 2014 -0400 Add dbus API to explore, add and remove nodes infinoted/plugins/infinoted-plugin-dbus.c | 274 +++++++++++++++++++- .../plugins/infinoted-plugin-document-stream.c | 1 + .../util/infinoted-plugin-util-navigate-browser.c | 17 +- .../util/infinoted-plugin-util-navigate-browser.h | 1 + 4 files changed, 287 insertions(+), 6 deletions(-) commit c10300f6a4d24655c14bb230801baf897d349303 Author: Armin Burgmeier Date: Wed Oct 1 12:49:32 2014 -0400 dbus plugin: Fix missing variable initialization infinoted/plugins/infinoted-plugin-dbus.c | 2 ++ 1 file changed, 2 insertions(+) commit 920bbbafb5307d365d64ef6faf2bed50a2a23c7d Author: Armin Burgmeier Date: Sat Sep 20 22:02:24 2014 -0400 Make InfinotedLog thread-safe InfinotedPluginLogging should now be made thread-safe, too. infinoted/infinoted-log.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) commit 00d1c2f3a160ffb4b60b22c038cd1a3318f8ac2d Author: Armin Burgmeier Date: Sat Sep 20 17:44:26 2014 -0400 Add the dbus infinoted plugin This plugin can at some point export an extensive interface to the infinoted server via d-bus. At the moment, only three calls to query and set ACLs are provided. In the long term, this plugin can also replace the document-stream plugin, by serving a file-descriptor over d-bus which would then be used to stream the actual payload. configure.ac | 23 + infinoted/plugins/Makefile.am | 29 +- infinoted/plugins/infinoted-plugin-dbus.c | 889 ++++++++++++++++++++++++++++ 3 files changed, 939 insertions(+), 2 deletions(-) commit e43df07b37dc2a109cb476367173530e4b7917e9 Author: Armin Burgmeier Date: Sat Sep 20 17:41:49 2014 -0400 Write certificate to known hosts file also if it was not present before Regression caused by 37afb068e89fc1aed45f795581904c3aaec34e36. libinfgtk/inf-gtk-certificate-manager.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) commit 5004929579e2eae88294969bb72baa94fe9cbb9e Author: Armin Burgmeier Date: Sat Sep 20 17:35:22 2014 -0400 InfGtkAclSheetView: Fix crash when changing a permission to "No" This bug was introduced by the recent refactorings libinfgtk/inf-gtk-acl-sheet-view.c | 1 + 1 file changed, 1 insertion(+) commit 65c02c286a34c75112549566615d4484d4378590 Author: Armin Burgmeier Date: Sat Sep 20 17:34:36 2014 -0400 Check sheet set for invalid accounts on set-acl before writing to disk libinfinity/server/infd-directory.c | 86 +++++++++++++++++++++++++++++++++-- 1 file changed, 82 insertions(+), 4 deletions(-) commit fc691035f2fbe629b67ea4d1d8dc1d039f13a5c6 Author: Armin Burgmeier Date: Sat Sep 20 17:33:58 2014 -0400 Fix initialization of InfXmppConnection This is a bug introduced by changing constructor to constructed libinfinity/common/inf-xmpp-connection.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) commit e9cd4639c6f98b6f8c3244b2d8281fa487bf06d0 Author: Armin Burgmeier Date: Fri Sep 12 20:03:21 2014 -0400 Use g_get_real_time() and g_get_monotonic_time() where appropriate TODO | 5 ----- libinfinity/adopted/inf-adopted-algorithm.c | 20 ++++---------------- libinfinity/adopted/inf-adopted-session-record.c | 11 +---------- libinftext/inf-text-session.c | 15 +++------------ test/inf-test-text-replay.c | 18 ++---------------- 5 files changed, 10 insertions(+), 59 deletions(-) commit 3d616208ea4c505327a75a4f25b9ea22efeb658a Author: Armin Burgmeier Date: Fri Sep 12 19:46:33 2014 -0400 Use G_TYPE_ERROR and G_TYPE_ARRAY in signal definitions Before, we used G_TYPE_POINTER, for lack of a better GType. The above GTypes have been introduced in more recent glib versions. TODO | 2 -- libinfinity/adopted/inf-adopted-algorithm.c | 2 +- libinfinity/common/inf-browser.c | 4 ++-- libinfinity/common/inf-name-resolver.c | 4 ++-- libinfinity/common/inf-request.c | 2 +- libinfinity/common/inf-session.c | 4 ++-- libinfinity/common/inf-tcp-connection.c | 2 +- libinfinity/common/inf-xml-connection.c | 4 ++-- libinfinity/server/infd-session-proxy.c | 2 +- libinfinity/server/infd-tcp-server.c | 4 ++-- libinfinity/server/infd-xmpp-server.c | 4 ++-- 11 files changed, 16 insertions(+), 18 deletions(-) commit 23aec76417aef64318d560246149d1ba7949f0c9 Author: Armin Burgmeier Date: Fri Sep 12 18:56:36 2014 -0400 Don't remove InfGnutls-3.0.gir and InfGsasl-1.0.gir on make clean libinfinity/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit ae12ba76a5c67a8d6778e726d5f1db8dad93b8aa Author: Armin Burgmeier Date: Fri Sep 12 18:53:37 2014 -0400 Replace marshal generation by glib's generic marshaller TODO | 1 - infinoted/infinoted-log.c | 3 +-- libinfgtk/inf-gtk-account-creation-dialog.c | 3 +-- libinfgtk/inf-gtk-acl-sheet-view.c | 4 +-- libinfgtk/inf-gtk-browser-model.c | 3 +-- libinfgtk/inf-gtk-browser-store.c | 1 - libinfgtk/inf-gtk-browser-view.c | 7 +++-- libinfinity/Makefile.am | 18 +------------ libinfinity/adopted/inf-adopted-algorithm.c | 9 +++---- libinfinity/adopted/inf-adopted-request-log.c | 3 +-- libinfinity/adopted/inf-adopted-session.c | 3 +-- libinfinity/adopted/inf-adopted-undo-grouping.c | 3 +-- libinfinity/client/infc-browser.c | 1 - libinfinity/client/infc-request-manager.c | 5 ++-- libinfinity/common/inf-browser.c | 21 +++++++-------- libinfinity/common/inf-chat-buffer.c | 3 +-- libinfinity/common/inf-chat-session.c | 5 ++-- libinfinity/common/inf-discovery.c | 5 ++-- libinfinity/common/inf-name-resolver.c | 3 +-- libinfinity/common/inf-request.c | 3 +-- libinfinity/common/inf-session.c | 13 +++++---- libinfinity/common/inf-simulated-connection.c | 1 - libinfinity/common/inf-tcp-connection.c | 7 +++-- libinfinity/common/inf-user-table.c | 13 +++++---- libinfinity/common/inf-user.c | 3 +-- libinfinity/common/inf-xml-connection.c | 7 +++-- libinfinity/common/inf-xmpp-connection.c | 1 - libinfinity/common/inf-xmpp-manager.c | 5 ++-- .../communication/inf-communication-group.c | 5 ++-- .../communication/inf-communication-method.c | 6 ++--- libinfinity/inf-marshal.in | 30 --------------------- libinfinity/server/infd-account-storage.c | 5 ++-- libinfinity/server/infd-directory.c | 5 ++-- libinfinity/server/infd-session-proxy.c | 7 +++-- libinfinity/server/infd-tcp-server.c | 5 ++-- libinfinity/server/infd-xml-server.c | 3 +-- libinfinity/server/infd-xmpp-server.c | 3 +-- libinftext/inf-text-buffer.c | 5 ++-- libinftext/inf-text-user.c | 3 +-- libinftextgtk/inf-text-gtk-hue-chooser.c | 5 ++-- 40 files changed, 75 insertions(+), 161 deletions(-) commit 37afb068e89fc1aed45f795581904c3aaec34e36 Author: Armin Burgmeier Date: Fri Sep 12 15:02:29 2014 -0400 Fix a crash when a certificate is added into the known hosts file Typically this crash only happened at the point when the connection that presented that certificate was closed. libinfgtk/inf-gtk-certificate-manager.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 61f8eb8ce4a1da94b2e6d270d72ad56490d3e73b Author: Armin Burgmeier Date: Fri Sep 12 10:14:14 2014 -0400 Replace copied HSV/RGB conversions by GTK+ functions These have been added in GTK+ 2.14 and can be safely used now. TODO | 1 - libinftextgtk/inf-text-gtk-buffer.c | 81 +------------ libinftextgtk/inf-text-gtk-hue-chooser.c | 89 +------------- libinftextgtk/inf-text-gtk-view.c | 189 ++--------------------------- libinftextgtk/inf-text-gtk-viewport.c | 161 +----------------------- 5 files changed, 19 insertions(+), 502 deletions(-) commit 7b3862a4abdbc166c34c0053e7a2293fcadf527b Author: Armin Burgmeier Date: Thu Sep 11 18:54:40 2014 -0400 Replace g_set_error by g_set_error_literal where appropriate TODO | 1 - infinoted/infinoted-options.c | 15 ++-- infinoted/infinoted-pam.c | 4 +- infinoted/infinoted-parameter.c | 6 +- infinoted/infinoted-plugin-manager.c | 6 +- infinoted/infinoted-util.c | 3 +- .../plugins/infinoted-plugin-certificate-auth.c | 9 +-- .../plugins/infinoted-plugin-document-stream.c | 7 +- libinfinity/adopted/inf-adopted-session-record.c | 12 +-- libinfinity/adopted/inf-adopted-session-replay.c | 36 +++------ libinfinity/adopted/inf-adopted-session.c | 20 ++--- libinfinity/adopted/inf-adopted-state-vector.c | 5 +- libinfinity/client/infc-browser.c | 86 +++++++-------------- libinfinity/client/infc-request-manager.c | 19 ++--- libinfinity/client/infc-session-proxy.c | 9 +-- libinfinity/common/inf-acl.c | 3 +- libinfinity/common/inf-chat-session.c | 6 +- libinfinity/common/inf-discovery-avahi.c | 6 +- libinfinity/common/inf-file-util.c | 6 +- libinfinity/common/inf-init.c | 4 +- libinfinity/common/inf-name-resolver.c | 15 ++-- libinfinity/common/inf-native-socket.c | 6 +- libinfinity/common/inf-protocol.c | 12 +-- libinfinity/common/inf-session.c | 48 ++++-------- libinfinity/common/inf-xmpp-connection.c | 19 ++--- libinfinity/server/infd-account-storage.c | 21 ++--- libinfinity/server/infd-chat-filesystem-format.c | 3 +- libinfinity/server/infd-directory.c | 83 +++++++------------- .../server/infd-filesystem-account-storage.c | 9 +-- libinfinity/server/infd-filesystem-storage.c | 9 +-- libinfinity/server/infd-session-proxy.c | 26 +++---- libinftext/inf-text-default-delete-operation.c | 3 +- libinftext/inf-text-default-insert-operation.c | 3 +- libinftext/inf-text-filesystem-format.c | 3 +- libinftext/inf-text-move-operation.c | 3 +- libinftext/inf-text-remote-delete-operation.c | 3 +- libinftext/inf-text-session.c | 8 +- 37 files changed, 189 insertions(+), 348 deletions(-) commit 0b933ff98317fc1b1984dd5d8c38c52ee65ec07b Author: Armin Burgmeier Date: Thu Sep 11 18:18:48 2014 -0400 Replace calls to constructor by constructed TODO | 1 - libinfgtk/inf-gtk-account-creation-dialog.c | 18 ++++---------- libinfgtk/inf-gtk-browser-model-filter.c | 18 ++++---------- libinfgtk/inf-gtk-browser-model-sort.c | 18 ++++---------- libinfgtk/inf-gtk-permissions-dialog.c | 17 ++++--------- libinfinity/adopted/inf-adopted-algorithm.c | 27 ++++++--------------- libinfinity/adopted/inf-adopted-session.c | 21 +++++----------- libinfinity/adopted/inf-adopted-user.c | 16 +++--------- libinfinity/client/infc-browser.c | 25 ------------------- libinfinity/common/inf-chat-session.c | 22 +++++------------ libinfinity/common/inf-discovery-avahi.c | 16 +++--------- libinfinity/common/inf-session.c | 17 +++---------- libinfinity/common/inf-xmpp-connection.c | 18 ++++---------- .../inf-communication-joined-group.c | 27 +++++++++------------ libinfinity/server/infd-directory.c | 16 +++--------- libinfinity/server/infd-session-proxy.c | 19 ++++----------- libinfinity/server/infd-xmpp-server.c | 26 -------------------- libinftext/inf-text-session.c | 17 +++---------- 18 files changed, 82 insertions(+), 257 deletions(-) commit 463d7298eb26999c94193a5fc7a9285b28d090e1 Author: Armin Burgmeier Date: Thu Sep 11 14:30:59 2014 -0400 Enable TCP keepalives This commit also adds API to configure keepalive on a InfTcpConnection. In infinoted, the settings are set such that a keepalive probe is sent after 60s of inactivity, with an interval of 5s between probes. The number of probes sent before the connection is closed is system-dependent. TODO | 1 - .../libinfinity/libinfinity-0.7-docs.sgml | 1 + .../libinfinity/libinfinity-0.7-sections.txt | 22 + infinoted/infinoted-run.c | 2 + infinoted/infinoted-startup.c | 6 + infinoted/infinoted-startup.h | 2 + libinfinity/Makefile.am | 2 + libinfinity/common/inf-discovery-avahi.c | 74 ++- libinfinity/common/inf-discovery-avahi.h | 7 + libinfinity/common/inf-keepalive.c | 478 ++++++++++++++++++++ libinfinity/common/inf-keepalive.h | 106 +++++ libinfinity/common/inf-tcp-connection-private.h | 2 + libinfinity/common/inf-tcp-connection.c | 217 ++++++--- libinfinity/common/inf-tcp-connection.h | 9 + libinfinity/server/infd-tcp-server.c | 63 ++- libinfinity/server/infd-tcp-server.h | 7 + 16 files changed, 926 insertions(+), 73 deletions(-) commit 1f548d86f750794f222def5f69cdbc13a9b6a35e Author: Armin Burgmeier Date: Thu Sep 11 12:34:59 2014 -0400 Restore accidentally removed G_END_DECLS libinfinity/client/infc-note-plugin.h | 2 ++ 1 file changed, 2 insertions(+) commit 3401dede9e7e17f27f1289bbb0c0f4ff73696da2 Author: Armin Burgmeier Date: Thu Sep 11 12:28:12 2014 -0400 Fix installation path of header files libinfinity/Makefile.am | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) commit 9bee2543a503fdeee5cebb48d994f4d0bba6100f Author: Armin Burgmeier Date: Wed Sep 10 13:12:10 2014 -0400 Add some GObject introspection annotations Also, make the API a tiny bit more binding-friendly at some places. .gitignore | 3 +- .../libinfinity/libinfinity-0.7-sections.txt | 1 - .../libinfinoted-plugin-manager-0.7-sections.txt | 4 + .../libinftext/libinftext-0.7-sections.txt | 4 + infinoted/.gitignore | 1 + infinoted/infinoted-log.c | 12 +- infinoted/infinoted-parameter.c | 81 +++++-- infinoted/infinoted-parameter.h | 12 +- infinoted/infinoted-plugin-manager.c | 26 ++- infinoted/infinoted-startup.c | 3 +- infinoted/infinoted-util.c | 4 +- .../plugins/infinoted-plugin-certificate-auth.c | 4 +- libinfgtk/.gitignore | 1 + libinfgtk/Makefile.am | 3 +- libinfgtk/inf-gtk-account-creation-dialog.c | 6 +- libinfgtk/inf-gtk-acl-sheet-view.c | 15 +- libinfgtk/inf-gtk-browser-model-filter.c | 4 +- libinfgtk/inf-gtk-browser-model-sort.c | 4 +- libinfgtk/inf-gtk-browser-model.c | 4 +- libinfgtk/inf-gtk-browser-store.c | 236 ++++++++++---------- libinfgtk/inf-gtk-browser-view.c | 12 +- libinfgtk/inf-gtk-certificate-dialog.c | 7 +- libinfgtk/inf-gtk-certificate-manager.c | 11 +- libinfgtk/inf-gtk-certificate-view.c | 9 +- libinfgtk/inf-gtk-chat.c | 11 +- libinfgtk/inf-gtk-io.c | 5 +- libinfgtk/inf-gtk-permissions-dialog.c | 20 +- libinfinity/.gitignore | 3 + libinfinity/InfGnutls-3.0.gir | 31 +++ libinfinity/InfGsasl-1.0.gir | 21 ++ libinfinity/Makefile.am | 22 +- libinfinity/adopted/inf-adopted-algorithm.c | 29 +-- libinfinity/adopted/inf-adopted-no-operation.c | 4 +- libinfinity/adopted/inf-adopted-operation.c | 16 +- libinfinity/adopted/inf-adopted-operation.h | 4 +- libinfinity/adopted/inf-adopted-request-log.c | 43 ++-- libinfinity/adopted/inf-adopted-request-log.h | 2 +- libinfinity/adopted/inf-adopted-request.c | 31 +-- libinfinity/adopted/inf-adopted-session-record.c | 6 +- libinfinity/adopted/inf-adopted-session-replay.c | 10 +- libinfinity/adopted/inf-adopted-session.c | 16 +- libinfinity/adopted/inf-adopted-split-operation.c | 9 +- libinfinity/adopted/inf-adopted-state-vector.c | 28 +-- libinfinity/adopted/inf-adopted-undo-grouping.c | 7 +- libinfinity/adopted/inf-adopted-user.c | 4 +- libinfinity/client/infc-browser.c | 39 ++-- libinfinity/client/infc-note-plugin.h | 4 - libinfinity/client/infc-request-manager.c | 37 +-- libinfinity/client/infc-request-manager.h | 2 +- libinfinity/client/infc-session-proxy.c | 4 +- libinfinity/common/inf-acl.c | 3 +- libinfinity/common/inf-async-operation.c | 14 +- libinfinity/common/inf-async-operation.h | 2 +- libinfinity/common/inf-browser-iter.c | 2 +- libinfinity/common/inf-browser.c | 143 ++++++------ libinfinity/common/inf-cert-util.c | 140 ++++++------ libinfinity/common/inf-certificate-chain.c | 4 +- libinfinity/common/inf-chat-buffer.c | 10 +- libinfinity/common/inf-chat-session.c | 6 +- libinfinity/common/inf-discovery-avahi.c | 29 ++- libinfinity/common/inf-discovery.c | 20 +- libinfinity/common/inf-discovery.h | 19 +- libinfinity/common/inf-file-util.c | 18 +- libinfinity/common/inf-io.c | 10 +- libinfinity/common/inf-ip-address.c | 30 +-- libinfinity/common/inf-local-publisher.c | 4 +- libinfinity/common/inf-name-resolver.c | 17 +- libinfinity/common/inf-request-result.c | 156 ++++++++----- libinfinity/common/inf-request.c | 3 +- libinfinity/common/inf-sasl-context.c | 56 +++-- libinfinity/common/inf-sasl-context.h | 5 +- libinfinity/common/inf-session-proxy.c | 10 +- libinfinity/common/inf-session.c | 22 +- libinfinity/common/inf-simulated-connection.c | 8 +- libinfinity/common/inf-standalone-io.c | 6 +- libinfinity/common/inf-tcp-connection.c | 26 ++- libinfinity/common/inf-user-table.c | 12 +- libinfinity/common/inf-user.c | 14 +- libinfinity/common/inf-xml-connection.c | 7 +- libinfinity/common/inf-xml-util.c | 59 ++--- libinfinity/common/inf-xmpp-connection.c | 51 +++-- libinfinity/common/inf-xmpp-connection.h | 3 +- libinfinity/common/inf-xmpp-manager.c | 16 +- .../inf-communication-central-factory.c | 4 +- .../communication/inf-communication-factory.c | 2 +- .../communication/inf-communication-group.c | 8 +- .../inf-communication-joined-group.c | 2 +- .../communication/inf-communication-manager.c | 18 +- .../communication/inf-communication-method.c | 4 +- .../communication/inf-communication-registry.c | 2 +- libinfinity/server/infd-account-storage.c | 45 ++-- libinfinity/server/infd-account-storage.h | 4 +- libinfinity/server/infd-directory.c | 37 +-- libinfinity/server/infd-directory.h | 33 ++- .../server/infd-filesystem-account-storage.c | 4 +- libinfinity/server/infd-filesystem-storage.c | 18 +- libinfinity/server/infd-server-pool.c | 6 +- libinfinity/server/infd-server-pool.h | 21 ++ libinfinity/server/infd-storage.c | 29 +-- libinfinity/server/infd-storage.h | 4 +- libinfinity/server/infd-xmpp-server.c | 7 +- libinftext/.gitignore | 1 + libinftext/Makefile.am | 5 +- libinftext/inf-text-buffer.c | 43 ++-- libinftext/inf-text-buffer.h | 2 +- libinftext/inf-text-chunk.c | 78 +++++-- libinftext/inf-text-chunk.h | 10 + libinftext/inf-text-default-buffer.c | 4 +- libinftext/inf-text-default-delete-operation.c | 6 +- libinftext/inf-text-default-insert-operation.c | 6 +- libinftext/inf-text-delete-operation.c | 8 +- libinftext/inf-text-fixline-buffer.c | 4 +- libinftext/inf-text-fixline-buffer.h | 2 +- libinftext/inf-text-insert-operation.c | 8 +- libinftext/inf-text-move-operation.c | 22 +- libinftext/inf-text-remote-delete-operation.c | 4 +- libinftext/inf-text-session.c | 29 +-- libinftext/inf-text-undo-grouping.c | 5 +- libinftext/inf-text-user.c | 12 +- libinftextgtk/.gitignore | 1 + libinftextgtk/Makefile.am | 3 +- libinftextgtk/inf-text-gtk-buffer.c | 35 +-- libinftextgtk/inf-text-gtk-hue-chooser.c | 8 +- libinftextgtk/inf-text-gtk-view.c | 12 +- libinftextgtk/inf-text-gtk-viewport.c | 12 +- 125 files changed, 1375 insertions(+), 993 deletions(-) commit 4c3032c820b9cdb23c2fbb064a78f6b0be1d264a Author: Armin Burgmeier Date: Mon Sep 8 21:35:41 2014 -0400 Build gobject-introspection repositories .gitignore | 3 + configure.ac | 12 +- infinoted/Makefile.am | 44 +++++- libinfgtk/Makefile.am | 39 +++++ libinfinity/Makefile.am | 262 +++++++++++++++++++++++++++++++- libinfinity/adopted/Makefile.am | 36 ----- libinfinity/client/Makefile.am | 23 --- libinfinity/common/Makefile.am | 85 ----------- libinfinity/common/inf-acl.c | 84 +++++----- libinfinity/communication/Makefile.am | 36 ----- libinfinity/server/Makefile.am | 39 ----- libinftext/Makefile.am | 39 +++++ libinftextgtk/Makefile.am | 43 ++++++ 13 files changed, 470 insertions(+), 275 deletions(-) commit d1fa9e120bfce1b55f0ef949bfab3cc1e20aa4e5 Author: Armin Burgmeier Date: Mon Sep 8 16:56:45 2014 -0400 Fix compiler warnings and deprecations in tests test/inf-test-browser.c | 10 +++++++--- test/inf-test-chat.c | 10 +++++++--- test/inf-test-daemon.c | 10 +++++++--- test/inf-test-gtk-browser.c | 11 ++++++----- test/inf-test-mass-join.c | 1 + test/inf-test-reduce-replay.c | 1 + test/inf-test-state-vector.c | 2 -- test/inf-test-tcp-connection.c | 2 -- test/inf-test-tcp-server.c | 9 +++++++-- test/inf-test-text-cleanup.c | 11 ++++++++--- test/inf-test-text-operations.c | 2 -- test/inf-test-text-recover.c | 1 + test/inf-test-text-replay.c | 1 + test/inf-test-text-session.c | 9 +++++++-- test/inf-test-xmpp-connection.c | 11 +++++++---- test/inf-test-xmpp-server.c | 10 +++++++--- 16 files changed, 67 insertions(+), 34 deletions(-) commit 24fe1b32a69f72f5d781d84e845bba464f8f94af Author: Armin Burgmeier Date: Mon Sep 8 16:56:03 2014 -0400 Replace deprecated GTK+ API calls by non-deprecated API TODO | 3 -- libinfgtk/inf-gtk-browser-view.c | 2 +- libinftextgtk/inf-text-gtk-hue-chooser.c | 7 +-- libinftextgtk/inf-text-gtk-view.c | 72 +++++++++++++++++------------- libinftextgtk/inf-text-gtk-viewport.c | 27 ++++++----- 5 files changed, 61 insertions(+), 50 deletions(-) commit 42269d8860861cec557ff8a8bc9ca336713b5996 Author: Armin Burgmeier Date: Mon Sep 8 11:59:44 2014 -0400 Enable silent rules and quiet some automake compatibility warnings configure.ac | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) commit ccf903ad0f058a08ad4160c247c79d00c5019ba1 Author: Armin Burgmeier Date: Mon Sep 8 09:32:52 2014 -0400 Fix crash in inf_gtk_browser_store_tree_model_iter_has_child() (gobby #13) This happened if the browser was not open. libinfgtk/inf-gtk-browser-store.c | 5 +++++ 1 file changed, 5 insertions(+) commit fa03e5beab7a13950744a5c0d8177189d0128cd1 Author: Armin Burgmeier Date: Sun Sep 7 21:54:10 2014 -0400 Documentation fixes docs/reference/libinfgtk/Makefile.am | 2 +- docs/reference/libinfgtk/libinfgtk-0.7-docs.sgml | 4 ++++ docs/reference/libinfinity/Makefile.am | 4 ++-- .../libinfinity/libinfinity-0.7-docs.sgml | 4 ++++ .../libinfinity/libinfinity-0.7-sections.txt | 1 - .../libinfinoted-plugin-manager-0.7-docs.sgml | 4 ++++ .../reference/libinftext/libinftext-0.7-docs.sgml | 4 ++++ .../libinftextgtk/libinftextgtk-0.7-docs.sgml | 4 ++++ infinoted/infinoted-parameter.c | 2 +- infinoted/infinoted-util.c | 5 +++-- .../resources/ui/infgtkaccountcreationdialog.ui.h | 6 +++--- libinfgtk/resources/ui/infgtkaclsheetview.ui.h | 8 +++---- .../resources/ui/infgtkcertificatedialog.ui.h | 6 +++--- libinfgtk/resources/ui/infgtkcertificateview.ui.h | 24 ++++++++++----------- libinfgtk/resources/ui/infgtkchat.ui.h | 2 +- .../resources/ui/infgtkpermissionsdialog.ui.h | 2 +- libinfinity/adopted/inf-adopted-algorithm.c | 14 ++++++------ libinfinity/adopted/inf-adopted-request.c | 6 +++--- libinfinity/adopted/inf-adopted-session.c | 6 ++---- libinfinity/client/infc-browser.c | 14 ++++++------ libinfinity/common/inf-browser.c | 6 +++--- libinfinity/common/inf-protocol.c | 2 +- libinfinity/common/inf-session.c | 5 ++--- libinfinity/server/infd-storage.c | 2 +- update-potfiles | 3 ++- 25 files changed, 78 insertions(+), 62 deletions(-) commit 1150dfc5a69d931e7f796ea304a233501ed5eec6 Author: Armin Burgmeier Date: Sun Sep 7 20:42:34 2014 -0400 Add the verification-flags option for the certificate-auth plugin .../plugins/infinoted-plugin-certificate-auth.c | 69 +++++++++++++++++++-- 1 file changed, 64 insertions(+), 5 deletions(-) commit 42460de4e637aef690f534317924577aaab5f92b Author: Armin Burgmeier Date: Sun Sep 7 20:41:45 2014 -0400 Add infinoted_parameter_convert_flags() .../libinfinoted-plugin-manager-0.7-sections.txt | 1 + infinoted/infinoted-parameter.c | 76 +++++++++++++++++++++ infinoted/infinoted-parameter.h | 9 +++ 3 files changed, 86 insertions(+) commit 82a31180d770b2f1dd6601e49b90a33d4ccd52da Author: Armin Burgmeier Date: Sun Sep 7 18:43:56 2014 -0400 Update translations po/ca.po | 805 ++++++++++----------- po/de.po | 810 +++++++++++----------- po/{libinfinity-0.6.pot => libinfinity-0.7.pot} | 786 ++++++++++----------- 3 files changed, 1222 insertions(+), 1179 deletions(-) commit 193d576366a5efc2dd346bf213fd6c0fd182db2e Author: Armin Burgmeier Date: Sun Sep 7 18:43:12 2014 -0400 Make .ui files translatable TODO | 1 - libinfgtk/resources/ui/infgtkaccountcreationdialog.ui.h | 3 +++ libinfgtk/resources/ui/infgtkaclsheetview.ui.h | 4 ++++ libinfgtk/resources/ui/infgtkcertificatedialog.ui.h | 3 +++ libinfgtk/resources/ui/infgtkcertificateview.ui.h | 12 ++++++++++++ libinfgtk/resources/ui/infgtkchat.ui.h | 1 + libinfgtk/resources/ui/infgtkpermissionsdialog.ui.h | 1 + po/.gitignore | 1 + po/POTFILES.in | 7 +++++++ update-potfiles | 5 +++++ 10 files changed, 37 insertions(+), 1 deletion(-) commit f8a8edd17271d31aed357c418a02e152c722cf6b Author: Armin Burgmeier Date: Sun Sep 7 18:23:22 2014 -0400 Make InfGtkPermissionsDialog use a template libinfgtk/Makefile.am | 3 +- libinfgtk/inf-gtk-permissions-dialog.c | 462 +++++++------------- libinfgtk/resources/infgtk.gresources.xml | 1 + libinfgtk/resources/ui/infgtkcertificatedialog.ui | 2 +- libinfgtk/resources/ui/infgtkpermissionsdialog.ui | 232 ++++++++++ 5 files changed, 384 insertions(+), 316 deletions(-) commit c4132254be2f9b58e620dd277d0d5477d4fba7ca Author: Armin Burgmeier Date: Sun Sep 7 17:35:54 2014 -0400 Make InfGtkAclSheetView use a template libinfgtk/Makefile.am | 1 + libinfgtk/inf-gtk-acl-sheet-view.c | 283 +++++++++---------------- libinfgtk/resources/infgtk.gresources.xml | 1 + libinfgtk/resources/ui/infgtkaclsheetview.ui | 83 ++++++++ 4 files changed, 186 insertions(+), 182 deletions(-) commit caaddc3d32a062cd0e43f3df65a638dd6a3e2946 Author: Armin Burgmeier Date: Sat Sep 6 22:39:04 2014 -0400 Make InfGtkCertificateDialog use a template libinfgtk/Makefile.am | 1 + libinfgtk/inf-gtk-certificate-dialog.c | 302 +++++--------------- libinfgtk/inf-gtk-certificate-manager.c | 2 +- libinfgtk/resources/infgtk.gresources.xml | 1 + libinfgtk/resources/ui/infgtkcertificatedialog.ui | 198 +++++++++++++ libinfgtk/resources/ui/infgtkcertificateview.ui | 1 + 6 files changed, 277 insertions(+), 228 deletions(-) commit efa352f9715c1cbbb129c12b7ccc09c505a22ebb Author: Armin Burgmeier Date: Sat Sep 6 20:56:36 2014 -0400 Make InfGtkCertificateView use a template TODO | 1 + libinfgtk/Makefile.am | 1 + libinfgtk/inf-gtk-certificate-view.c | 287 ++++++------------- libinfgtk/resources/infgtk.gresources.xml | 3 +- libinfgtk/resources/ui/infgtkcertificateview.ui | 330 ++++++++++++++++++++++ 5 files changed, 423 insertions(+), 199 deletions(-) commit be3bdc117b3f15b84c6c7843a9731ab0d44e3791 Author: Armin Burgmeier Date: Fri Sep 5 20:12:11 2014 -0400 Create the account creation dialog from a template libinfgtk/Makefile.am | 1 + libinfgtk/inf-gtk-account-creation-dialog.c | 117 +++++---------- libinfgtk/resources/infgtk.gresources.xml | 1 + .../resources/ui/infgtkaccountcreationdialog.ui | 152 ++++++++++++++++++++ 4 files changed, 193 insertions(+), 78 deletions(-) commit cbd77892abd5a71bd904f93d3d8fc0171ea35fe0 Author: Armin Burgmeier Date: Fri Sep 5 15:26:25 2014 -0400 Construct InfGtkChat from a template This simplifies the widget construction code a lot. The other composite widgets will soon be migrated as well. This also raises the minimum GTK+ version required to 3.10. README.md | 4 +- configure.ac | 2 +- libinfgtk/.gitignore | 2 + libinfgtk/Makefile.am | 22 ++- libinfgtk/inf-gtk-chat.c | 275 +++++++++++++--------------- libinfgtk/resources/infgtk.gresources.xml | 5 + libinfgtk/resources/ui/infgtkchat.ui | 100 ++++++++++ 7 files changed, 255 insertions(+), 155 deletions(-) commit b34869b0f047a29b551027af3108ac892af076f1 Author: Armin Burgmeier Date: Fri Sep 5 15:17:39 2014 -0400 Clean up .gitignore in docs a bit docs/reference/libinfgtk/.gitignore | 1 + docs/reference/libinfgtk/libinfgtk-0.6-overrides.txt | 0 docs/reference/libinfinity/.gitignore | 1 + docs/reference/libinfinity/libinfinity-0.6-overrides.txt | 0 docs/reference/libinfinoted-plugin-manager/.gitignore | 1 + docs/reference/libinftext/.gitignore | 1 + docs/reference/libinftext/libinftext-0.6-overrides.txt | 0 docs/reference/libinftextgtk/.gitignore | 1 + docs/reference/libinftextgtk/libinftextgtk-0.6-overrides.txt | 0 9 files changed, 5 insertions(+) commit 5e8db2eb8599e67cd2ac46690535907e4c3ba09c Author: Armin Burgmeier Date: Fri Sep 5 14:20:42 2014 -0400 Raise required glib version to 2.38 This is needed for G_ADD_PRIVATE. README.md | 4 ++-- configure.ac | 6 +++--- libinfinity.pc.in | 2 +- libinfinity/common/inf-init.c | 3 --- libinfinity/inf-define-enum.h | 2 ++ 5 files changed, 8 insertions(+), 9 deletions(-) commit fa698233b88a081307e6dd9f5982c2cdf5a944ee Author: Armin Burgmeier Date: Wed Sep 3 11:10:59 2014 -0400 Use G_DEFINE_TYPE and friends to define GTypes This makes the _get_type() functions threadsafe. TODO | 4 +- .../libinfgtk/libinfgtk-0.7-sections.txt | 2 +- .../libinfinity/libinfinity-0.7-sections.txt | 30 +- .../libinftext/libinftext-0.7-sections.txt | 6 +- infinoted/infinoted-log.c | 54 +- infinoted/infinoted-plugin-manager.c | 53 +- libinfgtk/inf-gtk-account-creation-dialog.c | 63 +- libinfgtk/inf-gtk-acl-sheet-view.c | 55 +- libinfgtk/inf-gtk-browser-model-filter.c | 83 +-- libinfgtk/inf-gtk-browser-model-sort.c | 81 +-- libinfgtk/inf-gtk-browser-model.c | 187 ++---- libinfgtk/inf-gtk-browser-model.h | 8 +- libinfgtk/inf-gtk-browser-store.c | 94 +-- libinfgtk/inf-gtk-browser-view.c | 92 +-- libinfgtk/inf-gtk-certificate-dialog.c | 120 +--- libinfgtk/inf-gtk-certificate-manager.c | 58 +- libinfgtk/inf-gtk-certificate-view.c | 51 +- libinfgtk/inf-gtk-chat.c | 51 +- libinfgtk/inf-gtk-io.c | 70 +- libinfgtk/inf-gtk-permissions-dialog.c | 54 +- libinfinity/Makefile.am | 1 + libinfinity/adopted/inf-adopted-algorithm.c | 57 +- libinfinity/adopted/inf-adopted-no-operation.c | 64 +- libinfinity/adopted/inf-adopted-operation.c | 158 ++--- libinfinity/adopted/inf-adopted-operation.h | 8 +- libinfinity/adopted/inf-adopted-request-log.c | 67 +- libinfinity/adopted/inf-adopted-request.c | 114 +--- libinfinity/adopted/inf-adopted-session-record.c | 74 +-- libinfinity/adopted/inf-adopted-session-replay.c | 76 +-- libinfinity/adopted/inf-adopted-session.c | 181 ++---- libinfinity/adopted/inf-adopted-split-operation.c | 84 +-- libinfinity/adopted/inf-adopted-state-vector.c | 21 +- libinfinity/adopted/inf-adopted-undo-grouping.c | 57 +- libinfinity/adopted/inf-adopted-user.c | 58 +- libinfinity/client/infc-browser.c | 96 +-- libinfinity/client/infc-progress-request.c | 54 +- libinfinity/client/infc-request-manager.c | 58 +- libinfinity/client/infc-request.c | 71 +- libinfinity/client/infc-session-proxy.c | 100 +-- libinfinity/common/inf-acl.c | 211 ++---- libinfinity/common/inf-browser-iter.c | 17 +- libinfinity/common/inf-browser.c | 684 +++++++++----------- libinfinity/common/inf-browser.h | 8 +- libinfinity/common/inf-buffer.c | 68 +- libinfinity/common/inf-buffer.h | 8 +- libinfinity/common/inf-certificate-chain.c | 19 +- libinfinity/common/inf-certificate-credentials.c | 19 +- libinfinity/common/inf-chat-buffer.c | 199 ++---- libinfinity/common/inf-chat-session.c | 71 +- libinfinity/common/inf-discovery-avahi.c | 99 +-- libinfinity/common/inf-discovery.c | 144 ++--- libinfinity/common/inf-discovery.h | 8 +- libinfinity/common/inf-io.c | 98 +-- libinfinity/common/inf-io.h | 8 +- libinfinity/common/inf-ip-address.c | 69 +- libinfinity/common/inf-local-publisher.c | 46 +- libinfinity/common/inf-local-publisher.h | 8 +- libinfinity/common/inf-name-resolver.c | 70 +- libinfinity/common/inf-request-result.c | 19 +- libinfinity/common/inf-request.c | 136 ++-- libinfinity/common/inf-request.h | 8 +- libinfinity/common/inf-sasl-context.c | 19 +- libinfinity/common/inf-session-proxy.c | 66 +- libinfinity/common/inf-session-proxy.h | 8 +- libinfinity/common/inf-session.c | 145 ++--- libinfinity/common/inf-simulated-connection.c | 138 ++-- libinfinity/common/inf-standalone-io.c | 69 +- libinfinity/common/inf-tcp-connection.c | 114 +--- libinfinity/common/inf-user-table.c | 56 +- libinfinity/common/inf-user.c | 154 ++--- libinfinity/common/inf-xml-connection.c | 374 +++++------ libinfinity/common/inf-xml-connection.h | 8 +- libinfinity/common/inf-xmpp-connection.c | 197 ++---- libinfinity/common/inf-xmpp-manager.c | 54 +- .../inf-communication-central-factory.c | 67 +- .../inf-communication-central-method.c | 75 +-- .../communication/inf-communication-factory.c | 42 +- .../communication/inf-communication-factory.h | 8 +- .../communication/inf-communication-group.c | 56 +- .../inf-communication-hosted-group.c | 57 +- .../inf-communication-joined-group.c | 61 +- .../communication/inf-communication-manager.c | 59 +- .../communication/inf-communication-method.c | 137 ++-- .../communication/inf-communication-method.h | 8 +- .../communication/inf-communication-object.c | 86 +-- .../communication/inf-communication-object.h | 8 +- .../communication/inf-communication-registry.c | 59 +- libinfinity/inf-define-enum.h | 59 ++ libinfinity/server/infd-account-storage.c | 252 +++----- libinfinity/server/infd-account-storage.h | 8 +- libinfinity/server/infd-directory.c | 103 +-- .../server/infd-filesystem-account-storage.c | 82 +-- libinfinity/server/infd-filesystem-storage.c | 75 +-- libinfinity/server/infd-progress-request.c | 54 +- libinfinity/server/infd-request.c | 75 +-- libinfinity/server/infd-server-pool.c | 52 +- libinfinity/server/infd-session-proxy.c | 97 +-- libinfinity/server/infd-storage.c | 122 +--- libinfinity/server/infd-storage.h | 6 +- libinfinity/server/infd-tcp-server.c | 106 +-- libinfinity/server/infd-xml-server.c | 156 ++--- libinfinity/server/infd-xml-server.h | 6 +- libinfinity/server/infd-xmpp-server.c | 78 +-- libinftext/inf-text-buffer.c | 128 ++-- libinftext/inf-text-buffer.h | 8 +- libinftext/inf-text-chunk.c | 19 +- libinftext/inf-text-default-buffer.c | 93 +-- libinftext/inf-text-default-delete-operation.c | 94 +-- libinftext/inf-text-default-insert-operation.c | 97 +-- libinftext/inf-text-delete-operation.c | 54 +- libinftext/inf-text-delete-operation.h | 8 +- libinftext/inf-text-fixline-buffer.c | 93 +-- libinftext/inf-text-insert-operation.c | 54 +- libinftext/inf-text-insert-operation.h | 6 +- libinftext/inf-text-move-operation.c | 70 +- libinftext/inf-text-remote-delete-operation.c | 93 +-- libinftext/inf-text-session.c | 104 +-- libinftext/inf-text-undo-grouping.c | 68 +- libinftext/inf-text-user.c | 52 +- libinftextgtk/inf-text-gtk-buffer.c | 93 +-- libinftextgtk/inf-text-gtk-hue-chooser.c | 84 +-- libinftextgtk/inf-text-gtk-view.c | 50 +- libinftextgtk/inf-text-gtk-viewport.c | 50 +- 123 files changed, 2454 insertions(+), 6952 deletions(-) commit 604241c4fbc385191743b8646d53f9383271ff3b Author: Armin Burgmeier Date: Wed Sep 3 18:34:13 2014 -0400 Use new threading API in InfNameResolver libinfinity/common/inf-name-resolver.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) commit 69bb095ae3f07f384838fcf8699a7f2024e06a65 Author: Armin Burgmeier Date: Wed Sep 3 18:29:58 2014 -0400 Switch to non-deprecated threading API in InfStandaloneIo and InfGtkIo libinfgtk/inf-gtk-io.c | 115 +++++++++++++++---------------- libinfinity/common/inf-standalone-io.c | 104 ++++++++++++++-------------- 2 files changed, 109 insertions(+), 110 deletions(-) commit d3b14a40cd1f38f1455f7f0fa6da006aa83bb8cc Author: Armin Burgmeier Date: Wed Sep 3 11:10:25 2014 -0400 Fix a typo in InfAsyncOperation libinfinity/common/inf-async-operation.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit f709632c87d29c934c5c0a7159c7e2f4e565e699 Author: Armin Burgmeier Date: Wed Sep 3 11:09:50 2014 -0400 Fix a crash when a TCP connection while a hostname is being resolved libinfinity/common/inf-tcp-connection.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) commit 514c3cbc0731f14ea72359c3407bed86b24dfdc0 Author: Armin Burgmeier Date: Wed Sep 3 09:24:41 2014 -0400 Reduce the glib dependency to 2.32 This allows libinfinity to be built still with ubuntu precise. The call to g_type_init() is put back for glib versions below 2.36. README.md | 4 ++-- configure.ac | 6 +++--- libinfinity.pc.in | 2 +- libinfinity/common/inf-init.c | 3 +++ 4 files changed, 9 insertions(+), 6 deletions(-) commit 986046339109346739362702ae5ce4219b4cac35 Author: Armin Burgmeier Date: Tue Sep 2 22:28:19 2014 -0400 travis CI: Install more recent version of glib So that travis has a chance to meet the new glib dependency. .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 68b67a9aa19014e9cfc50342a3532d3a31a19e7f Author: Armin Burgmeier Date: Tue Sep 2 22:20:23 2014 -0400 Remove use of stock icons in favor of icon names Stock icons have been deprecated by GTK+ TODO | 2 +- libinfgtk/inf-gtk-browser-view.c | 86 +++++++++---------------------- libinfgtk/inf-gtk-certificate-dialog.c | 4 +- libinfgtk/inf-gtk-certificate-manager.c | 16 +----- libinfgtk/inf-gtk-chat.c | 2 +- libinfgtk/inf-gtk-permissions-dialog.c | 61 +++------------------- 6 files changed, 36 insertions(+), 135 deletions(-) commit 576ff061faec3b82c12c2c155116403be937a4ec Author: Armin Burgmeier Date: Tue Sep 2 21:47:20 2014 -0400 Replace use of deprecated GThread API Also remove the call to g_type_init(), which is deprecated and no longer needed since glib 2.36. The thread functions have been deprecated in glib 2.32. We therefore raise the required glib version to 2.36. README.md | 5 +- configure.ac | 6 +- libinfinity.pc.in | 2 +- libinfinity/common/inf-async-operation.c | 47 +++++++--------- libinfinity/common/inf-init.c | 5 +- libinfinity/common/inf-sasl-context.c | 88 +++++++++++++++--------------- 6 files changed, 72 insertions(+), 81 deletions(-) commit 6a0791cfcf0ff8a91f12b76a02f090c3b0da625c Author: Armin Burgmeier Date: Tue Sep 2 21:22:04 2014 -0400 Update the requirements in the README.md file README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit 59e6cf736d34088a544be141f0edad15473caf33 Author: Armin Burgmeier Date: Tue Sep 2 21:18:38 2014 -0400 Remove the background parameter in inf_text_gtk_buffer_set_fade() Instead, we just set the alpha value of the GdkRGBA object. This simplifies the code and it possible because we now depend on GTK+ > 3.2. TODO | 2 +- configure.ac | 2 +- libinftextgtk/inf-text-gtk-buffer.c | 73 ++++++----------------------------- libinftextgtk/inf-text-gtk-buffer.h | 3 +- 4 files changed, 15 insertions(+), 65 deletions(-) commit d04e500795f787445f0bdbdd9d8c8825acd1cc93 Merge: 100254e 22be6f9 Author: Armin Burgmeier Date: Mon Sep 1 20:03:35 2014 -0400 Merge pull request #5 from dev-zero/master Build documentation conditionally commit 22be6f9d57d6476c7407007ccccc1702936fb53b Author: Tiziano Müller Date: Mon Sep 1 17:55:37 2014 +0200 Build documentation conditionally Building documentation for disabled libraries fails with the following error: ``` libtool: link: cannot find the library `../../../libinfgtk/libinfgtk-0.6.la' or unhandled argument `../../../libinfgtk/libinfgtk-0.6.la' Linking of scanner failed: Makefile:609: recipe for target 'scan-build.stamp' failed ``` docs/reference/Makefile.am | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) commit 100254ecbfc5cea4363829b6eeb2d348149942c5 Author: Sven Brauch Date: Sat Aug 31 14:01:15 2013 +0200 Provide the node path to session_new infinoted/plugins/infinoted-plugin-note-chat.c | 1 + infinoted/plugins/infinoted-plugin-note-text.c | 1 + libinfinity/adopted/inf-adopted-session-replay.c | 1 + libinfinity/client/infc-browser.c | 8 +++++++ libinfinity/client/infc-note-plugin.h | 1 + libinfinity/server/infd-directory.c | 28 ++++++++++++++++++---- libinfinity/server/infd-note-plugin.h | 1 + 7 files changed, 37 insertions(+), 4 deletions(-) commit e234f8dfdc2c1f704ea8f23bb6545d011b591b7d Author: Armin Burgmeier Date: Fri Aug 29 10:43:37 2014 -0400 Update .gitignore .gitignore | 2 ++ test/.gitignore | 5 +++++ 2 files changed, 7 insertions(+) commit 4a5bd2c22458240b9be99e363fc407bf7600054f Author: Armin Burgmeier Date: Fri Aug 29 10:02:15 2014 -0400 Add two items to the TODO list TODO | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) commit 70948c67290736cd217353cde27db7d247a2afe0 Merge: 7a34a42 1e54001 Author: Armin Burgmeier Date: Fri Aug 29 09:46:13 2014 -0400 Merge pull request #4 from pkern/master infinoted man page: correct the usage of --plugins commit 1e540018518dd37db55ac5189112131603121c9c Author: Philipp Kern Date: Thu Aug 28 22:08:35 2014 +0200 infinoted man page: correct the usage of --plugins infinoted/infinoted-0.7.man | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit 7a34a422cb477c2efcfcf0c09b5faeae2bee0b5d Author: Armin Burgmeier Date: Tue Aug 26 22:26:30 2014 -0400 infinoted: Load default account storage only after loading plugins This allows a plugin to override the account storage without the default account storage having been loaded first, wasting resources and potentially removing permissions for non-matching users. infinoted/infinoted-run.c | 69 ++++++++++++++++++++++++++++----------------- 1 file changed, 43 insertions(+), 26 deletions(-) commit 4f9dc2f47987bd2739e59c2f1e82ef8816fabec1 Author: Philipp Kern Date: Wed Aug 27 01:11:12 2014 +0200 infinoted/infinoted-options.c: Fix a grammar mistake. infinoted/infinoted-options.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit ec57016a31e99d9065afbc77e9575cfdd9411185 Author: Philipp Kern Date: Wed Aug 27 00:57:01 2014 +0200 infinoted man page: correct a grammar mistake, escape hyphens infinoted/infinoted-0.7.man | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) commit eae469370dcefdc5be0f08b3c083a5d5b79bfb77 Author: Philipp Kern Date: Mon Aug 25 04:43:13 2014 +0200 Makefile.am: ship the new markdown formatted README Makefile.am | 2 ++ 1 file changed, 2 insertions(+) commit 23afbe1e3d8a6692b4cf962d384ff2ee98b4d42e Author: Armin Burgmeier Date: Sun Aug 24 12:31:36 2014 -0400 Remove support for GTK+ 2.x Makefile.am | 4 +- TODO | 3 +- configure.ac | 33 +---- docs/reference/libinfgtk/Makefile.am | 2 +- docs/reference/libinftextgtk/Makefile.am | 4 +- libinfgtk.pc.in | 6 +- libinfgtk/Makefile.am | 14 -- libinfgtk/inf-gtk-account-creation-dialog.c | 13 -- libinfgtk/inf-gtk-browser-view.c | 31 +--- libinfgtk/inf-gtk-certificate-dialog.c | 11 -- libinfgtk/inf-gtk-certificate-manager.c | 9 -- libinfgtk/inf-gtk-chat.c | 8 - libinfgtk/inf-gtk-permissions-dialog.c | 40 +---- libinftextgtk.pc.in | 6 +- libinftextgtk/Makefile.am | 14 -- libinftextgtk/inf-text-gtk-hue-chooser.c | 201 +------------------------- libinftextgtk/inf-text-gtk-view.c | 126 +--------------- libinftextgtk/inf-text-gtk-viewport.c | 54 ------- test/Makefile.am | 4 +- 19 files changed, 25 insertions(+), 558 deletions(-) commit b79893e2186046e5e92f875e9d3b7ebc8300e918 Author: Armin Burgmeier Date: Sun Aug 24 09:57:21 2014 -0400 Explicitly link against libresolv (libinfinity #3) configure.ac | 2 ++ 1 file changed, 2 insertions(+) commit a114b6590d2511bd994ed3e7b1c8e44f059c98c1 Author: Armin Burgmeier Date: Sat Aug 23 13:40:08 2014 -0400 Post-release bump to 0.7.0 configure.ac | 4 +-- docs/reference/libinfgtk/.gitignore | 20 +++++++-------- ...fgtk-0.6-docs.sgml => libinfgtk-0.7-docs.sgml} | 0 ....6-sections.txt => libinfgtk-0.7-sections.txt} | 0 docs/reference/libinfinity/.gitignore | 20 +++++++-------- ...ty-0.6-docs.sgml => libinfinity-0.7-docs.sgml} | 0 ...-sections.txt => libinfinity-0.7-sections.txt} | 0 .../libinfinoted-plugin-manager/.gitignore | 22 ++++++++-------- ... => libinfinoted-plugin-manager-0.7-docs.sgml} | 0 ... libinfinoted-plugin-manager-0.7-sections.txt} | 0 docs/reference/libinftext/.gitignore | 20 +++++++-------- ...ext-0.6-docs.sgml => libinftext-0.7-docs.sgml} | 0 ...6-sections.txt => libinftext-0.7-sections.txt} | 0 docs/reference/libinftextgtk/.gitignore | 20 +++++++-------- ...-0.6-docs.sgml => libinftextgtk-0.7-docs.sgml} | 0 ...ections.txt => libinftextgtk-0.7-sections.txt} | 0 infinoted/.gitignore | 2 +- infinoted/Makefile.am | 24 +++++++++--------- .../{infinoted-0.6.man => infinoted-0.7.man} | 0 libinfgtk/Makefile.am | 28 ++++++++++----------- libinfinity/Makefile.am | 14 +++++------ libinftext/Makefile.am | 14 +++++------ libinftextgtk/Makefile.am | 28 ++++++++++----------- po/libinfinity-0.6.pot | 8 +++--- 24 files changed, 112 insertions(+), 112 deletions(-) commit 9952497a8d6ce591cc77cc7cc9a3f8e350870a30 Author: Armin Burgmeier Date: Sat Aug 23 13:06:03 2014 -0400 Release libinfinity 0.6.0 NEWS | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) commit 85dbbc473ce05f4c2c13b7baff33fc46e1458afe Author: Armin Burgmeier Date: Sat Aug 23 13:05:31 2014 -0400 Fix compilation with GTK+ versions below 2.18 libinfgtk/inf-gtk-account-creation-dialog.c | 4 ++++ 1 file changed, 4 insertions(+) commit 1cfaa3085a3029b7ae46de407bc2fd2474c964cb Author: Armin Burgmeier Date: Sat Aug 23 13:05:09 2014 -0400 Fix GError pointer error in infinoted-plugin-traffic-logging infinoted/plugins/infinoted-plugin-traffic-logging.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 7fb92feac55fa14a606c80fe9f8bbe408eed0cd5 Author: Armin Burgmeier Date: Fri Aug 22 15:15:17 2014 -0400 Add some compatibility fixes for older systems configure.ac | 13 +++++++++++++ infinoted/infinoted-plugin-manager.c | 7 ++++--- libinfinity/common/inf-file-util.c | 4 ++++ test/inf-test-text-replay.c | 18 ++++++++++++++++-- 4 files changed, 37 insertions(+), 5 deletions(-) commit b2bd6fc0f93b609e16be6d9b24c5d58691bba7dd Author: Armin Burgmeier Date: Fri Aug 22 12:58:37 2014 -0400 Fixes for "make dist" configure.ac | 2 +- infinoted/plugins/Makefile.am | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) commit 416d010b9ed29bf034164d31f2f7a77c2d73608a Author: Armin Burgmeier Date: Fri Aug 22 11:40:06 2014 -0400 Update translations for 0.6 release po/POTFILES.in | 37 +- po/ca.po | 2097 +++++++++++++++++++++++++++++++++--------- po/de.po | 2277 +++++++++++++++++++++++++++++++++++----------- po/libinfinity-0.6.pot | 2070 ++++++++++++++++++++++++++++++++--------- 4 files changed, 5085 insertions(+), 1396 deletions(-) commit 34232a2c4c597c94d715aa0c39666d205a71464d Author: Armin Burgmeier Date: Thu Aug 21 22:10:27 2014 -0400 Fix several undeclared functions infinoted/infinoted-log.c | 5 +++++ infinoted/infinoted-parameter.c | 2 ++ infinoted/infinoted-plugin-manager.c | 1 + infinoted/infinoted-util.c | 2 +- infinoted/plugins/infinoted-plugin-autosave.c | 1 + infinoted/plugins/infinoted-plugin-certificate-auth.c | 6 ++++-- infinoted/plugins/infinoted-plugin-directory-sync.c | 2 ++ infinoted/plugins/infinoted-plugin-document-stream.c | 8 +++++--- infinoted/plugins/infinoted-plugin-linekeeper.c | 2 ++ infinoted/plugins/infinoted-plugin-logging.c | 1 + infinoted/plugins/infinoted-plugin-record.c | 1 + infinoted/plugins/infinoted-plugin-traffic-logging.c | 3 +++ .../plugins/infinoted-plugin-transformation-protection.c | 1 + .../plugins/util/infinoted-plugin-util-navigate-browser.c | 4 ++++ libinfgtk/inf-gtk-account-creation-dialog.c | 3 +++ libinfgtk/inf-gtk-certificate-manager.c | 6 ++++-- libinfgtk/inf-gtk-permissions-dialog.c | 3 +++ libinfinity/server/infd-filesystem-account-storage.c | 1 + libinftext/inf-text-filesystem-format.c | 2 ++ libinftext/inf-text-fixline-buffer.c | 1 + test/inf-test-certificate-request.c | 2 ++ test/inf-test-chat.c | 1 + test/inf-test-gtk-browser.c | 3 ++- test/inf-test-mass-join.c | 5 ++++- test/inf-test-set-acl.c | 2 ++ test/inf-test-tcp-connection.c | 3 ++- test/inf-test-text-recover.c | 12 ++++++------ 27 files changed, 66 insertions(+), 17 deletions(-) commit c89bcafccf5a971e8435b5d65167dc6bf4f25205 Author: Armin Burgmeier Date: Thu Aug 21 20:27:50 2014 -0400 Various small build fixes libinfinity/common/inf-file-util.c | 3 +++ libinfinity/common/inf-tcp-connection.c | 1 + libinfinity/common/inf-xmpp-manager.c | 6 +++--- libinfinity/server/infd-chat-filesystem-format.c | 2 ++ libinfinity/server/infd-directory.c | 12 ++++++------ 5 files changed, 15 insertions(+), 9 deletions(-) commit 1604ff38b5fd64394c0264fa7af45a6594c696c4 Author: Armin Burgmeier Date: Thu Aug 21 18:41:11 2014 -0400 Fix use-after-free in Win32 implementation of InfStandaloneIo libinfinity/common/inf-standalone-io.c | 34 ++++++++++++++++---------------- 1 file changed, 17 insertions(+), 17 deletions(-) commit a87f0ed6fc5b423e55f725d44791376588d653fb Author: Armin Burgmeier Date: Thu Aug 21 18:29:06 2014 -0400 Fix infinoted shutdown procedure on Windows It is run concurrently with the program, so instead of just shutting infinoted down (which did not seem to be a problem when InfStandaloneIo could not handle calls from another thread), now we dispatch a message to the main thread, to shut infinoted down. infinoted/infinoted-signal.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) commit 00c4322842600f429c74eddfde2c36ef9f014d04 Author: Armin Burgmeier Date: Thu Aug 21 17:58:45 2014 -0400 Fix infinoted not starting when accounts file is not available libinfinity/server/infd-filesystem-account-storage.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit b6b0b404480fd7610fb24a728ec5d513b1af911b Author: Armin Burgmeier Date: Thu Aug 21 16:30:37 2014 -0400 Initialize libinfinity in inf-test-tcp-connection So that on Windows WinSock is initialized test/inf-test-tcp-connection.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) commit 365fa90ab4b9ff7698b11455c60859f3368663ea Author: Armin Burgmeier Date: Thu Aug 21 16:30:21 2014 -0400 Fix compilation of InfGtkPermissionsDialog with GTK+ 2 libinfgtk/inf-gtk-permissions-dialog.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) commit 943254a96d448d2faa43cebc037c0dbc99868ce2 Author: Armin Burgmeier Date: Thu Aug 21 16:29:05 2014 -0400 Fix a small typo when creating the serial number of a certificate libinfinity/common/inf-cert-util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit a81a5b5cf93e323721e6054c593d8e67ae91bef7 Author: Armin Burgmeier Date: Wed Aug 20 14:28:17 2014 -0400 Fix a memory leak in InfTextUndoGrouping The behaviour was also not correct, since the function took the position from the original request, and not from the translated one. libinftext/inf-text-undo-grouping.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) commit 7873c4f019b5a81ad088997e04ce34e5d75f6884 Author: Armin Burgmeier Date: Wed Aug 20 14:13:36 2014 -0400 Fix a memory leak in InfAdoptedUndoGrouping libinfinity/adopted/inf-adopted-undo-grouping.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) commit 56d6c679c4bb737ea1dedc29a35cca3d659be4ef Author: Armin Burgmeier Date: Wed Aug 20 13:27:33 2014 -0400 InfGtkCertificateManager: Read known hosts file correctly with IPv6 addresses libinfgtk/inf-gtk-certificate-manager.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) commit 5257f0f9f8dc80f8f9eb6397d843cc95ce313082 Author: Armin Burgmeier Date: Wed Aug 20 13:27:07 2014 -0400 Fix a resource leak in InfUser The connection object was not released. libinfinity/common/inf-user.c | 9 +++++++++ 1 file changed, 9 insertions(+) commit b40d04d93fd7c94eb52c2553f07e384ae7fa4220 Author: Armin Burgmeier Date: Wed Aug 20 11:54:44 2014 -0400 Fix a memory leak in InfGtkBrowserView The browser variable could be leaked in inf_gtk_browser_view_progress_data_func(). libinfgtk/inf-gtk-browser-view.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) commit c290f6d8e84654e3826f75337279a47013cc33c4 Author: Armin Burgmeier Date: Wed Aug 20 09:58:37 2014 -0400 Add support to InfXmppManager for hostname-based TCP connections .../libinfinity/libinfinity-0.6-sections.txt | 4 + libinfgtk/inf-gtk-certificate-manager.c | 10 +- libinfinity/common/inf-name-resolver.c | 45 + libinfinity/common/inf-name-resolver.h | 9 + libinfinity/common/inf-xmpp-manager.c | 873 +++++++++++++++----- libinfinity/common/inf-xmpp-manager.h | 25 +- 6 files changed, 743 insertions(+), 223 deletions(-) commit 8401d29051448f4f2590d5d691bd15906f800356 Author: Armin Burgmeier Date: Mon Aug 18 22:25:06 2014 -0400 Add the resolver property to InfTcpConnection This allows InfTcpConnection to resolve a hostname by itself before it connects to it, with the advantage that it can try all available addresses for the hostname in question. .../libinfinity/libinfinity-0.6-sections.txt | 1 + libinfinity/common/inf-tcp-connection.c | 753 ++++++++++++++------ libinfinity/common/inf-tcp-connection.h | 5 + test/inf-test-tcp-connection.c | 114 ++- 4 files changed, 651 insertions(+), 222 deletions(-) commit ee3e24849ef65f658fddf45f16bdef104544937d Author: Armin Burgmeier Date: Mon Aug 18 22:23:52 2014 -0400 Add the InfNameResolver class This class allows to do asynchronous host name lookups with support for SRV records. SRV lookups are only implemented on Linux at the moment. configure.ac | 2 +- .../libinfinity/libinfinity-0.6-docs.sgml | 1 + .../libinfinity/libinfinity-0.6-sections.txt | 22 + libinfinity/common/Makefile.am | 2 + libinfinity/common/inf-name-resolver.c | 1444 +++++++++++++++++++ libinfinity/common/inf-name-resolver.h | 104 ++ 6 files changed, 1574 insertions(+), 1 deletion(-) commit 0fe67f9b9be5ed9fa5918ee9cd324894bd8aedf3 Author: Armin Burgmeier Date: Tue Aug 19 11:08:05 2014 -0400 InfXmppConnection: Make notification callbacks when properties can be changed libinfinity/common/inf-xmpp-connection.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) commit 1bb4690ab9061e1c8cd128ce14414f1ccad00017 Author: Armin Burgmeier Date: Mon Aug 18 22:24:38 2014 -0400 Fix a typo in the documentation libinfinity/server/infd-filesystem-account-storage.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 0cb6099eb0601edc8dd8160635cf4ab9585ae8d1 Author: Armin Burgmeier Date: Mon Aug 18 18:10:59 2014 -0400 Make InfdDirectory use the InfdAccountStorage interface .../libinfinity/libinfinity-0.6-docs.sgml | 3 +- .../libinfinity/libinfinity-0.6-sections.txt | 23 +- infinoted/infinoted-config-reload.c | 131 +- infinoted/infinoted-run.c | 28 +- .../plugins/infinoted-plugin-certificate-auth.c | 18 +- libinfinity/common/inf-acl.c | 17 + libinfinity/common/inf-acl.h | 4 + libinfinity/server/Makefile.am | 2 - libinfinity/server/infd-acl-account-info.c | 686 ---- libinfinity/server/infd-acl-account-info.h | 105 - libinfinity/server/infd-directory.c | 3560 +++++++++++++------ libinfinity/server/infd-directory.h | 14 +- libinfinity/server/infd-filesystem-storage.c | 126 - libinfinity/server/infd-storage.c | 61 - libinfinity/server/infd-storage.h | 23 - 15 files changed, 2574 insertions(+), 2227 deletions(-) commit 0f5c5a88bf35113035fafee5b33f64fb8a46f2c4 Author: Armin Burgmeier Date: Mon Aug 18 18:10:34 2014 -0400 infinoted: Fix crash when reloading options without command line args infinoted/infinoted-options.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) commit 2dc5846b243b10cb556ab5a6a6858ba7c755916a Author: Armin Burgmeier Date: Mon Aug 18 17:25:33 2014 -0400 Fix delicate warnings and crashes in InfGtkPermissionsDialog libinfgtk/inf-gtk-permissions-dialog.c | 68 ++++++++++++++++++++++++++------ 1 file changed, 56 insertions(+), 12 deletions(-) commit 01eb49a842d5e3fb292c1b51cb71a0bb0573648c Author: Armin Burgmeier Date: Mon Aug 18 15:59:04 2014 -0400 Don't remove ACL-queried flag when query-account-list permission was dropped The can-query-acl-account-list permission is no longer required to query the ACL of a node. libinfinity/client/infc-browser.c | 11 ++--------- libinfinity/server/infd-directory.c | 14 -------------- 2 files changed, 2 insertions(+), 23 deletions(-) commit c666b95a8e4c8f124291c9f8f83321a80ac81cc7 Author: Armin Burgmeier Date: Mon Aug 18 15:58:02 2014 -0400 Permissions dialog: Lookup account names after query-acl-account-list This updates the dialog when the query-acl-account-list permission has been granted while the dialog is open, and some un-lookupped names are lingering in the list. libinfgtk/inf-gtk-permissions-dialog.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) commit 45449b2931861e67695a2d8ad1d1e046394222ef Author: Armin Burgmeier Date: Mon Aug 18 15:29:40 2014 -0400 Permissions dialog: Lookup unknown accounts from cache before querying browser libinfgtk/inf-gtk-permissions-dialog.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) commit 6c7f4017adab1fb4b605f4b416f25983f4fc48fa Author: Armin Burgmeier Date: Mon Aug 18 15:28:51 2014 -0400 Correctly remove outdated user accounts when client updates account list libinfinity/client/infc-browser.c | 104 ++++++++++++++++++++++++++++++++++-- 1 file changed, 101 insertions(+), 3 deletions(-) commit e07d9978e89b7da673ebf8b3265f6a5d8cc5808b Author: Armin Burgmeier Date: Mon Aug 18 11:38:49 2014 -0400 Don't require client certificates to be signed by a CA The server only requires that it is signed by one of the certificates in its list. The client does not verify the signer of the retrieved client certificate, since it has to trust the server anyway. .../plugins/infinoted-plugin-certificate-auth.c | 6 +- libinfinity/client/infc-browser.c | 107 +++++++++++--------- libinfinity/server/infd-directory.c | 37 +++---- 3 files changed, 82 insertions(+), 68 deletions(-) commit fdc74988a414e526c7065574fcd2e06a86288b62 Author: Armin Burgmeier Date: Mon Aug 18 12:49:56 2014 -0400 Don't trust every certificate where the issuer is not found The code was written under the assumption that when asking GnuTLS to verify a certificate, it always fills the verification result fully. However, when the issuer is not found, it immediately returns and does not report other reasons why the certificate might be invalid. However, we need to do at least a certificate verification even if the signer of the certificate is not found, because in the latter case, we use trust-on-first-use, and if the user decides so, still accept the certificate. This is now fixed by running the certificate validation a second time when the signer is not found, where we explicitly provide the signer sent by the server. libinfgtk/inf-gtk-certificate-dialog.c | 2 +- libinfgtk/inf-gtk-certificate-manager.c | 44 ++++++++++++++++++++++--------- 2 files changed, 33 insertions(+), 13 deletions(-) commit 742ff4e1a9cf1337701c13a18b9d9c989252a063 Author: Armin Burgmeier Date: Mon Aug 18 12:49:32 2014 -0400 Set a title for the account creation window libinfgtk/inf-gtk-account-creation-dialog.c | 2 ++ 1 file changed, 2 insertions(+) commit 3c6c896fd0d1341ad4d7b3ad4932dce41246d8a9 Author: Armin Burgmeier Date: Mon Aug 18 11:37:29 2014 -0400 Add inf_cert_util_write_certificate_mem() This also changes the internal certificate writing proceduces from GIOchannel to GString, which allows to write the files with g_file_set_contents(). This has better error checking, and more importantly, it writes files atomically. .../libinfinity/libinfinity-0.6-sections.txt | 1 + libinfinity/common/inf-cert-util.c | 150 +++++++++++++------- libinfinity/common/inf-cert-util.h | 5 + 3 files changed, 104 insertions(+), 52 deletions(-) commit 569ad7d5efc7e43bbcc0ea9659b078929431e2ee Author: Armin Burgmeier Date: Mon Aug 18 10:11:36 2014 -0400 infinoted: Make sure startup errors also show in log file This allows system administrators to only filter the log file for errors, and they don't have to keep also an eye on stderr. However, early startup errors are still only logged to stderr, in case they happen before the log file could be opened, for example when the configuration file is incorrectly formatted. infinoted/infinoted-main.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) commit c0d104245c0585a22e6ebc3f0d6b9c2e0d540d2b Author: Armin Burgmeier Date: Fri Aug 15 16:43:46 2014 -0400 Update button sensitivity after pending realization in permissions dialog libinfgtk/inf-gtk-permissions-dialog.c | 4 ++++ 1 file changed, 4 insertions(+) commit 7e6b3b17c8f5f7e6cf38b1b090beea0f78e8f18b Author: Armin Burgmeier Date: Fri Aug 15 16:42:54 2014 -0400 Fix a warning in the permissions dialog This could happen when the default sheet of a node was empty and a new account was added to the sheet in the dialog. libinfgtk/inf-gtk-permissions-dialog.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) commit e687fd618f0dda417560ab5da2cb5fb03b49d194 Author: Armin Burgmeier Date: Fri Aug 15 16:24:28 2014 -0400 Fix a possible warning when the permissions dialog is closed It can happen that dispose() is called twice. libinfgtk/inf-gtk-permissions-dialog.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) commit efed7ba453e652d300545b0aee2d377d0ca8d2b6 Author: Armin Burgmeier Date: Fri Aug 15 16:24:14 2014 -0400 Add inf_acl_sheet_set_sink() .../libinfinity/libinfinity-0.6-sections.txt | 1 + libinfinity/common/inf-acl.c | 28 +++++++++++++++++++++ libinfinity/common/inf-acl.h | 3 +++ 3 files changed, 32 insertions(+) commit c98ebb4086ef09203308a5da383b98a71f71b89e Author: Armin Burgmeier Date: Fri Aug 15 15:01:46 2014 -0400 Implement InfdFilesystemAccountStorage .../libinfinity/libinfinity-0.6-docs.sgml | 1 + .../libinfinity/libinfinity-0.6-sections.txt | 19 +- libinfinity/server/Makefile.am | 2 + libinfinity/server/infd-account-storage.c | 4 +- .../server/infd-filesystem-account-storage.c | 1771 +++++++++++++++++++ .../server/infd-filesystem-account-storage.h | 101 ++ libinfinity/server/infd-filesystem-storage.c | 36 +- libinfinity/server/infd-filesystem-storage.h | 2 - 8 files changed, 1917 insertions(+), 19 deletions(-) commit c68194a97d5ddb45aff01cb2d9f7011f3a7eadeb Author: Armin Burgmeier Date: Fri Aug 15 13:09:57 2014 -0400 InfdFilesystemStorage: Make the XML reading/writing functions public This can help to simplify InfChatFilesystemFormat and InfTextFilesystemFormat, and it allows external code to alter XML files in the storage. .../libinfinity/libinfinity-0.6-sections.txt | 2 + libinfinity/server/infd-filesystem-storage.c | 469 +++++++++++--------- libinfinity/server/infd-filesystem-storage.h | 16 + 3 files changed, 284 insertions(+), 203 deletions(-) commit c8a0358d529b8a99168703bb37496212341c262e Author: Armin Burgmeier Date: Mon Aug 11 21:50:33 2014 -0400 Add the InfdAccountStorage interface .../libinfinity/libinfinity-0.6-docs.sgml | 1 + .../libinfinity/libinfinity-0.6-sections.txt | 28 + libinfinity/common/inf-acl.h | 1 + libinfinity/server/Makefile.am | 2 + libinfinity/server/infd-account-storage.c | 742 ++++++++++++++++++++ libinfinity/server/infd-account-storage.h | 251 +++++++ 6 files changed, 1025 insertions(+) commit 0dbaea2420ee278fd4b63e93720b20c1cfb2acaa Author: Armin Burgmeier Date: Thu Aug 14 23:07:37 2014 -0400 InfGtkPermissionsDialog: Skip warning account listing is unsupported libinfgtk/inf-gtk-permissions-dialog.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) commit 8c04cf744e1b54d6a3a50ea44d6850461b57fd6f Author: Armin Burgmeier Date: Wed Aug 13 21:54:48 2014 -0400 Fix certificate-auth plugin loading failure On success, gnutls_certificate_set_x509_trust() returns the number of added certificates instead of 0 in some gnutls versions. infinoted/plugins/infinoted-plugin-certificate-auth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 58d9a57fa27356b124bb714a81eb893884025c2c Author: Armin Burgmeier Date: Wed Aug 13 21:45:24 2014 -0400 Impose fewer constraints on the server, protocol-wise For example, the server does no longer need to be able to provide a full list of accounts, or to provide notifications when accounts are added or removed. This is preparation work for a new interface that allows to provide the user accounts from an external source such as a database, LDAP, pam, or other means. .../libinfinity/libinfinity-0.6-sections.txt | 15 +- .../plugins/infinoted-plugin-certificate-auth.c | 18 +- libinfgtk/inf-gtk-account-creation-dialog.c | 5 +- libinfgtk/inf-gtk-acl-sheet-view.c | 1 + libinfgtk/inf-gtk-browser-view.c | 36 +- libinfgtk/inf-gtk-permissions-dialog.c | 1981 ++++++++++++++++--- libinfinity/client/infc-browser.c | 1098 +++++++--- libinfinity/common/inf-acl.c | 98 +- libinfinity/common/inf-acl.h | 64 +- libinfinity/common/inf-browser.c | 218 +- libinfinity/common/inf-browser.h | 66 +- libinfinity/common/inf-request-result.c | 96 +- libinfinity/common/inf-request-result.h | 21 +- libinfinity/server/infd-acl-account-info.c | 7 +- libinfinity/server/infd-acl-account-info.h | 2 +- libinfinity/server/infd-directory.c | 796 +++++--- libinfinity/server/infd-directory.h | 2 +- libinfinity/server/infd-filesystem-storage.c | 2 +- test/inf-test-set-acl.c | 55 +- 19 files changed, 3541 insertions(+), 1040 deletions(-) commit b83655140face899a87287f47af9284a5c4e4fbb Author: Armin Burgmeier Date: Wed Aug 13 10:51:24 2014 -0400 Fix a crash when there is an empty directory and a plugin is unloaded infinoted/infinoted-plugin-manager.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) commit 650a6207ee994b464f710ea28beda6d3ffa4d2f7 Author: Armin Burgmeier Date: Tue Aug 12 21:11:00 2014 -0400 inf-test-set-acl: Bail out if file does not contain a certificate Instead of crashing. test/inf-test-set-acl.c | 6 ++++++ 1 file changed, 6 insertions(+) commit b96eef880fe8a98d551c46607a05675ed20ef40e Author: Armin Burgmeier Date: Sat Aug 9 23:01:51 2014 -0400 Update infinoted man page infinoted/infinoted-0.6.man | 45 ++++++++++++++++--------------------------- 1 file changed, 17 insertions(+), 28 deletions(-) commit 12e9a8e6274f386cffb147a35b1b560d52ac530c Author: Armin Burgmeier Date: Sat Aug 9 12:10:37 2014 -0400 Print the final buffer in inf-test-text-replay to stdout test/inf-test-text-replay.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 200840eb93229aa2e6b5be3de29bdcd3108519d1 Author: Armin Burgmeier Date: Fri Aug 8 22:52:12 2014 -0400 Add a TODO comment about smarter transformation of text with newlines TODO | 13 +++++++++++++ 1 file changed, 13 insertions(+) commit 82f991d26f15d644720d512b3949af1439168919 Author: Armin Burgmeier Date: Thu Aug 7 18:33:32 2014 -0400 Complete libinfinoted-plugin-manager documentation .../libinfinoted-plugin-manager-0.6-sections.txt | 45 ++++---- infinoted/infinoted-log.c | 10 +- infinoted/infinoted-parameter.c | 18 ++++ infinoted/infinoted-parameter.h | 107 ++++++++++++++++++-- infinoted/infinoted-plugin-manager.h | 65 +++++++++++- infinoted/infinoted-util.c | 29 ++++-- infinoted/infinoted-util.h | 2 - 7 files changed, 227 insertions(+), 49 deletions(-) commit b3035a108ebb6db7e224c2604fc6215a2e25eb7b Author: Armin Burgmeier Date: Thu Aug 7 17:26:57 2014 -0400 Build documentation for libinfinoted-plugin-manager configure.ac | 1 + docs/reference/Makefile.am | 2 +- .../libinfinoted-plugin-manager/.gitignore | 13 +++ .../libinfinoted-plugin-manager/Makefile.am | 110 ++++++++++++++++++++ .../libinfinoted-plugin-manager-0.6-docs.sgml | 25 +++++ .../libinfinoted-plugin-manager-0.6-sections.txt | 79 ++++++++++++++ 6 files changed, 229 insertions(+), 1 deletion(-) commit ba2f8635767671ebaa29377e988c2ce9a5ec22a4 Author: Armin Burgmeier Date: Thu Aug 7 17:04:54 2014 -0400 Turn InfinotedPluginManager into a GObject infinoted/infinoted-config-reload.c | 13 +- infinoted/infinoted-plugin-manager.c | 656 +++++++++++++++++++++++++-------- infinoted/infinoted-plugin-manager.h | 61 ++- infinoted/infinoted-run.c | 12 +- 4 files changed, 569 insertions(+), 173 deletions(-) commit 086fc2f4f0265760e1db94f6ceb4ba4a014e7f39 Author: Armin Burgmeier Date: Thu Aug 7 15:03:41 2014 -0400 Move chat filesystem format from infinoted plugin to libinfinity This way other note plugins can share the code. .../libinfinity/libinfinity-0.6-docs.sgml | 1 + .../libinfinity/libinfinity-0.6-sections.txt | 7 + infinoted/plugins/infinoted-plugin-note-chat.c | 149 ++---------- libinfinity/client/infc-browser.c | 7 +- libinfinity/common/inf-chat-session.c | 21 +- libinfinity/common/inf-chat-session.h | 2 +- libinfinity/server/Makefile.am | 2 + libinfinity/server/infd-chat-filesystem-format.c | 255 ++++++++++++++++++++ libinfinity/server/infd-chat-filesystem-format.h | 58 +++++ libinfinity/server/infd-directory.c | 7 +- libinftext/inf-text-filesystem-format.c | 10 +- 11 files changed, 366 insertions(+), 153 deletions(-) commit 66360a1e45eeb3930988ba44f21f2bab2e903c6f Author: Armin Burgmeier Date: Thu Aug 7 14:31:49 2014 -0400 Provide functions to operate on InfdFilesystemStorage-provided stream This avoids potential problems when the the stream is opened in a DLL that uses a different C runtime library than the code that is trying to read from it or close it. This can especially happen on Windows. .../libinfinity/libinfinity-0.6-sections.txt | 3 ++ infinoted/plugins/infinoted-plugin-note-chat.c | 19 ++++--- libinfinity/server/infd-filesystem-storage.c | 59 +++++++++++++++++++++ libinfinity/server/infd-filesystem-storage.h | 13 +++++ libinftext/inf-text-filesystem-format.c | 17 +++--- 5 files changed, 96 insertions(+), 15 deletions(-) commit fb4ba8d7fee8d0466b209809e32c11773363b815 Author: Armin Burgmeier Date: Thu Aug 7 14:12:16 2014 -0400 Add infd_filesystem_storage_get_path() .../libinfinity/libinfinity-0.6-sections.txt | 1 + libinfinity/server/infd-filesystem-storage.c | 62 ++++++++++++++++----- libinfinity/server/infd-filesystem-storage.h | 6 ++ 3 files changed, 55 insertions(+), 14 deletions(-) commit 95ad52800ada168f818210664e04e34bde6265cf Author: Armin Burgmeier Date: Thu Aug 7 11:24:06 2014 -0400 Don't require a "seq" attribute for set-acl requests The client handling of set-acl was incorrect; if no "seq" attribute was provided it set an error but never actually checked for the error. libinfinity/client/infc-browser.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) commit 684bdf5ee8b003f0c4a12149446858b378cdec1f Author: Armin Burgmeier Date: Thu Aug 7 11:23:13 2014 -0400 Avoid crash on destruction when non-fatal error is set in InfGtkBrowserStore libinfgtk/inf-gtk-browser-store.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) commit 2cf867636d684b00493bdfa4b006cd9922fd7854 Author: Armin Burgmeier Date: Wed Aug 6 21:20:02 2014 -0400 Emit "subscribe-session" when enabling the server chat The same for "unsubscribe-session" when the chat is disabled libinfinity/server/infd-directory.c | 160 +++++++++++++++++++--------------- 1 file changed, 92 insertions(+), 68 deletions(-) commit f90baa048556c8dbfcb9c07cb110cfe00b951c06 Author: Armin Burgmeier Date: Tue Aug 5 22:25:56 2014 -0400 Several documentation fixes .../libinfgtk/libinfgtk-0.6-sections.txt | 4 +- docs/reference/libinfinity/Makefile.am | 4 +- .../libinfinity/libinfinity-0.6-sections.txt | 111 +++++------ .../libinftext/libinftext-0.6-sections.txt | 2 - libinfgtk/inf-gtk-account-creation-dialog.c | 22 +-- libinfgtk/inf-gtk-account-creation-dialog.h | 5 +- libinfinity/adopted/inf-adopted-algorithm.h | 8 +- libinfinity/adopted/inf-adopted-request-log.c | 6 +- libinfinity/adopted/inf-adopted-user.c | 2 +- libinfinity/client/infc-request-manager.c | 42 ++++- libinfinity/client/infc-request-manager.h | 32 +++- libinfinity/client/infc-session-proxy.c | 2 +- libinfinity/common/inf-acl.c | 4 +- libinfinity/common/inf-acl.h | 5 +- libinfinity/common/inf-browser-iter.h | 8 + libinfinity/common/inf-browser.c | 42 ++--- libinfinity/common/inf-browser.h | 8 +- libinfinity/common/inf-cert-util.h | 2 +- libinfinity/common/inf-certificate-chain.c | 2 +- libinfinity/common/inf-error.h | 3 + libinfinity/common/inf-file-util.h | 2 + libinfinity/common/inf-io.h | 23 +++ libinfinity/common/inf-native-socket.c | 6 + libinfinity/common/inf-request-result.c | 8 +- libinfinity/common/inf-request.c | 2 +- libinfinity/common/inf-sasl-context.c | 5 +- libinfinity/common/inf-session-proxy.c | 2 +- libinfinity/common/inf-session.c | 8 +- libinfinity/common/inf-session.h | 1 + libinfinity/common/inf-tcp-connection.c | 42 ++++- libinfinity/common/inf-tcp-connection.h | 31 +++ libinfinity/common/inf-user.h | 4 +- libinfinity/common/inf-xmpp-connection.c | 24 ++- libinfinity/common/inf-xmpp-connection.h | 198 ++++++++++++++++++-- .../inf-communication-group-private.h | 2 +- libinfinity/server/infd-acl-account-info.c | 7 +- libinfinity/server/infd-acl-account-info.h | 4 +- libinfinity/server/infd-directory.c | 2 +- libinfinity/server/infd-progress-request.c | 2 +- libinfinity/server/infd-server-pool.c | 2 +- libinfinity/server/infd-storage.c | 6 +- libinftext/inf-text-buffer.h | 8 +- libinftext/inf-text-filesystem-format.h | 2 +- libinftextgtk/inf-text-gtk-hue-chooser.c | 27 +++ libinftextgtk/inf-text-gtk-hue-chooser.h | 18 ++ 45 files changed, 574 insertions(+), 176 deletions(-) commit 571df75d2ae995983984214d1588cab80eddd339 Author: Armin Burgmeier Date: Mon Aug 4 22:23:47 2014 -0400 Remove outdated HACKING file HACKING | 10 ---------- 1 file changed, 10 deletions(-) commit 7fccfd56a7816dc488e354f0d852e5d5652e3800 Author: Armin Burgmeier Date: Mon Aug 4 22:23:02 2014 -0400 Add libinfinoted-plugin-manager to README.md README.md | 2 ++ 1 file changed, 2 insertions(+) commit 921fd26e896b225034296732f8db485ffcec4fac Author: Philipp Kern Date: Sun Jul 20 22:15:41 2014 +0200 Ignore missing README. Not shipping with a README does not comply with GNU standards. But that's ok, we ship with a README.md. Tell autoconf that the package is foreign to GNU. configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 8154fa4a2020843ed397b4b29f17f4dfd47c1d14 Author: Philipp Kern Date: Sun Jul 20 22:09:35 2014 +0200 Convert the README to Markdown and update it. Markdown is rendered as HTML on GitHub. Add build status from Travis CI. Reference the GitHub issue tracker instead of the old Trac. Update dependencies using the actual checks in configure.ac. README | 56 ---------------------------------------------------- README.md | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 56 deletions(-) commit 04c3483b5088e9acbf1c288b2c43872b1bd2243b Author: Philipp Kern Date: Sun Jul 20 21:56:08 2014 +0200 Use g_return_val_if_fail in inf_sasl_context_session_is_processing. Fixes a build failure with clang because an empty return is invalid in a non-void function. libinfinity/common/inf-sasl-context.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 67a08838002bf6b490d9156e9b90d54799f54bea Author: Armin Burgmeier Date: Wed Jul 16 16:55:06 2014 +0200 InfGtkBrowserView: Redraw also recursively on ACL change This is necessary since when for example the "can-subscribe-session" ACL is changed on a subdirectory, the icons for many nodes within the subdirectory might need to be changed. libinfgtk/inf-gtk-browser-view.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) commit c55870103984ff3800c29e56dc3f740c78678cf6 Author: Armin Burgmeier Date: Wed Jul 16 16:38:39 2014 +0200 InfXmppConnection: Allow to change credentials after construction But only as long as the credentials are not in use. libinfinity/common/inf-xmpp-connection.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) commit 29fe913257c1ec4c1c53b509b4e0f89cb2c0e6f5 Author: Armin Burgmeier Date: Wed Jul 16 16:09:59 2014 +0200 Fix a warning when the root ACL sheetset is empty libinfinity/server/infd-directory.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) commit a32f2da88f15d0dae6132f6d6410410daf345eed Author: Armin Burgmeier Date: Wed Jul 16 16:02:34 2014 +0200 Associate certificates to users by DN instead of by key fingerprint This allows easier transition when a user gets a new certificate, without serious security degradations. libinfinity/server/infd-acl-account-info.c | 22 ++++----- libinfinity/server/infd-directory.c | 72 +++++++++++++++++++++------- 2 files changed, 67 insertions(+), 27 deletions(-) commit 5b2ae5bff7bbb031d7c58b25cc40d62cc8c16eb5 Author: Armin Burgmeier Date: Wed Jul 16 15:37:50 2014 +0200 Add the gnutls_x509_crt_get_dn() function .../libinfinity/libinfinity-0.6-sections.txt | 1 + libinfinity/common/inf-cert-util.c | 36 +++++++++++++++++++++ libinfinity/common/inf-cert-util.h | 3 ++ 3 files changed, 40 insertions(+) commit c6c7dc67fa27905a26e2ec54e943a5f2defed75f Author: Armin Burgmeier Date: Mon Jul 14 18:42:47 2014 +0200 Don't show subdirectory-only ACLs for leaf node in permissions dialog libinfgtk/inf-gtk-permissions-dialog.c | 33 +++++++++++++++++++------------- libinfinity/common/inf-acl.c | 19 ++++++++++++++++++ libinfinity/common/inf-acl.h | 4 +++- 3 files changed, 42 insertions(+), 14 deletions(-) commit 3a612c3ce077cf2f49b1f5c51416d308e9c4a0f8 Author: Armin Burgmeier Date: Mon Jul 14 18:14:59 2014 +0200 Don't allow the CAN_CREATE_ACCOUNT permission when server has no private key In this situation, the server does not support creating accounts, because it cannot generate client certificates. libinfinity/server/infd-directory.c | 170 +++++++++++++++++++++++++++++++++- 1 file changed, 168 insertions(+), 2 deletions(-) commit a4e9db590f2dd94db6eaaecbea1977adbe402c05 Author: Armin Burgmeier Date: Sun Jul 13 17:18:21 2014 +0200 Fix plugin manager cleanup when unloading a plugin causes unsubscriptions The connection to the "unsubscribe-session" signal was removed too early, so that the cleanup of the plugin manager session hash table was not properly performed when a plugin's on_deinitialize() callback causes sessions to be unsubscribed. This can happen when the "note-text" plugin is deinitialized on server shutdown, and lead to an assertion failure at time of plugin manager destruction. infinoted/infinoted-plugin-manager.c | 38 +++++++++++++++++----------------- 1 file changed, 19 insertions(+), 19 deletions(-) commit fc6b7bcf57701cb7ae2fb4aec133fb97fe72a891 Author: Armin Burgmeier Date: Sun Jul 13 17:10:35 2014 +0200 Fix assertion failure when removing a note plugin while a session is weak-refed libinfinity/server/infd-directory.c | 1 + 1 file changed, 1 insertion(+) commit 135ac641c2a2d0e500f69294666ec1579588adea Author: Armin Burgmeier Date: Sun Jul 13 16:46:36 2014 +0200 Don't create InfTextSession object in InfTextFilesystemFormat This allows to re-use the filesystem format functions when inheriting a class from InfTextSession. infinoted/plugins/infinoted-plugin-note-text.c | 25 ++++++++-- libinftext/inf-text-filesystem-format.c | 63 ++++++++---------------- libinftext/inf-text-filesystem-format.h | 7 ++- 3 files changed, 44 insertions(+), 51 deletions(-) commit fd249542ebe7d07784301bccef16d0006d3b07c4 Author: Armin Burgmeier Date: Sun Jul 13 13:31:28 2014 +0200 Install header and pkg-config files for infinoted-plugin-manager This allows developing infinoted plugins outside of the libinfinity tree. Makefile.am | 1 + configure.ac | 1 + infinoted/Makefile.am | 13 +++++++++---- libinfinoted-plugin-manager.pc.in | 11 +++++++++++ 4 files changed, 22 insertions(+), 4 deletions(-) commit 581a8b4377f0d3e73a5def62b60805137b0bbdca Author: Armin Burgmeier Date: Sat Jul 12 21:24:08 2014 +0200 Fix g_return_if_fail usage in inf_async_operation_start() libinfinity/common/inf-async-operation.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) commit c1a24fb73b2fe0cc3e79207e21e13d48ac54ab8f Author: Armin Burgmeier Date: Sat Jul 5 22:53:18 2014 +0200 Add InfGtkAccountCreationDialog docs/reference/libinfgtk/libinfgtk-0.6-docs.sgml | 1 + .../libinfgtk/libinfgtk-0.6-sections.txt | 17 + libinfgtk/Makefile.am | 2 + libinfgtk/inf-gtk-account-creation-dialog.c | 949 ++++++++++++++++++++ libinfgtk/inf-gtk-account-creation-dialog.h | 86 ++ libinfinity/inf-marshal.in | 1 + 6 files changed, 1056 insertions(+) commit cad668dd5b51bddc7d84fd07cd94650eb43fd370 Author: Armin Burgmeier Date: Thu Jul 3 17:27:06 2014 +0200 Add framework to run simple tasks asynchronously in a worker thread .../libinfinity/libinfinity-0.6-docs.sgml | 1 + .../libinfinity/libinfinity-0.6-sections.txt | 11 + libinfinity/common/Makefile.am | 2 + libinfinity/common/inf-async-operation.c | 301 ++++++++++++++++++++ libinfinity/common/inf-async-operation.h | 80 ++++++ 5 files changed, 395 insertions(+) commit 4bef6174b6801a02e5997577fb983801f08d299d Author: Armin Burgmeier Date: Sat Jul 5 22:30:48 2014 +0200 InfcBrowser: reset account-list-queried flag on disconnection libinfinity/client/infc-browser.c | 1 + 1 file changed, 1 insertion(+) commit ca3eb03e1caa2ad9efb817eca6ab0b08e2938316 Author: Armin Burgmeier Date: Sat Jul 5 22:30:20 2014 +0200 InfcBrowser: report error properly when sheet set could not be decoded libinfinity/client/infc-browser.c | 3 +++ 1 file changed, 3 insertions(+) commit 08e06015be1d76304f80dd12028ed93619d47c7d Author: Armin Burgmeier Date: Sat Jul 5 22:07:41 2014 +0200 Fix crash when changing ACL on unknown note type libinfinity/server/infd-directory.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) commit 29e5351cbcacb0a0469e97d4f92fa03c2157ac0e Author: Armin Burgmeier Date: Sat Jul 5 21:59:47 2014 +0200 Update TODO statements TODO | 2 +- libinfinity/server/infd-directory.c | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) commit 8bbb19df0bb5eb1c75a07377729439fb6d21f657 Author: Armin Burgmeier Date: Sat Jul 5 21:59:17 2014 +0200 Fix a crash when certificate-auth plugin fails to initialize infinoted/plugins/infinoted-plugin-certificate-auth.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) commit 3f776966a1ef79c206b5e44b3b59910c02fa6d72 Author: Armin Burgmeier Date: Thu Jul 3 14:38:31 2014 +0200 InfGtkBrowserView: Allow initial root expansion in multiple views With the change that initial root expansion is performed by default in commit ef1ccbe5492e0d086e618ce323f3910b837bcf60, the current assumption that there is at most one view per request that expands the root node after initial exploration is no longer valid. The code is now changed such that the root node can be expanded in multiple views at the same time. libinfgtk/inf-gtk-browser-view.c | 48 ++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 18 deletions(-) commit 7bb34e741a4d8c4d88530331db7714384fe5fcc7 Author: Armin Burgmeier Date: Wed Jul 2 14:56:12 2014 +0200 Replace InfStandaloneIo by GAsyncQueue in InfSaslContext This simplifies the code a bit, and probably involves less overhead in the message passing. libinfinity/common/inf-error.h | 2 +- libinfinity/common/inf-sasl-context.c | 61 +++++++++++++++++++-------------- 2 files changed, 36 insertions(+), 27 deletions(-) commit 5da56cc674dc2a43c32d83e5becb5407b0345ec8 Author: Armin Burgmeier Date: Wed Jul 2 14:52:35 2014 +0200 Fix assertion failure on double-challenge in SASL authentication This can not normally happen, however if a client sends a response before the server having asked for it, an assertion was hit in InfSaslContext. This behaviour is not allowed by SASL which follows a strict challenge -> response -> challenge -> response etc. pattern. Therefore, in this case the authentication is aborted now. .../libinfinity/libinfinity-0.6-sections.txt | 1 + libinfinity/common/inf-sasl-context.c | 26 ++++++++++++++++++ libinfinity/common/inf-sasl-context.h | 3 +++ libinfinity/common/inf-xmpp-connection.c | 30 ++++++++++++++++----- 4 files changed, 53 insertions(+), 7 deletions(-) commit 5e9fdc5c9a79cd455618d336a33d67af81d3afca Merge: 687617b 27ef5d4 Author: Armin Burgmeier Date: Mon Jun 30 19:46:14 2014 +0200 Merge remote-tracking branch 'polarina/master' commit 687617baa4fbdb79d599a993183686ce09b2fd7b Author: Armin Burgmeier Date: Mon Jun 30 19:42:24 2014 +0200 Fix g_return_val_if_fail in infd_directory_remove_plugin() libinfinity/server/infd-directory.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit 27ef5d4a8e0c5be5899155f56374cd2988f93b35 Author: Gabríel Arthúr Pétursson Date: Mon Jun 23 13:04:09 2014 +0000 Implement inf_gtk_browser_store_remove_browser .../libinfgtk/libinfgtk-0.6-sections.txt | 1 + libinfgtk/inf-gtk-browser-store.c | 22 +++++++++++++++++++++ libinfgtk/inf-gtk-browser-store.h | 4 ++++ 3 files changed, 27 insertions(+) commit ef1ccbe5492e0d086e618ce323f3910b837bcf60 Author: Gabríel Arthúr Pétursson Date: Fri Jun 13 22:45:39 2014 +0000 Expand server's document list on connect libinfgtk/inf-gtk-browser-view.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 2f9298920a647d671db59c9bce6149f27fad3db9 Author: Gabríel Arthúr Pétursson Date: Thu Jun 12 21:10:26 2014 +0000 Fix use of uninitialized variable in inf_text_gtk_view_user_invalidate_user_area The bug manifests itself when show_remote_cursors and show_remote_selections evaluate to FALSE and show_remote_current_lines evaluates to TRUE. Usual symptoms are crashes. libinftextgtk/inf-text-gtk-view.c | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) commit 6bcf72500046a5f7c11f83e256cf534a56e70058 Author: Armin Burgmeier Date: Sun Jun 29 14:11:57 2014 +0200 Turn note plugins into regular plugins configure.ac | 3 - infinoted/Makefile.am | 7 +- infinoted/infinoted-note-plugin.c | 208 ------------ infinoted/infinoted-note-plugin.h | 49 --- infinoted/infinoted-options.c | 6 +- infinoted/infinoted-plugin-manager.c | 16 +- infinoted/infinoted-run.c | 35 -- infinoted/note-plugins/Makefile.am | 1 - infinoted/note-plugins/chat/Makefile.am | 20 -- .../note-plugins/chat/infd-note-plugin-chat.c | 235 -------------- infinoted/note-plugins/text/Makefile.am | 23 -- .../note-plugins/text/infd-note-plugin-text.c | 116 ------- infinoted/plugins/Makefile.am | 22 ++ infinoted/plugins/infinoted-plugin-note-chat.c | 333 ++++++++++++++++++++ infinoted/plugins/infinoted-plugin-note-text.c | 214 +++++++++++++ libinfinity/common/inf-error.c | 2 + libinfinity/common/inf-error.h | 3 + libinfinity/server/infd-directory.c | 10 +- 18 files changed, 601 insertions(+), 702 deletions(-) commit 9c6504ba5ae13d5b5a29608e4342dfda4714df9d Author: Armin Burgmeier Date: Sun Jun 29 13:50:13 2014 +0200 Add infd_directory_remove_plugin() function .../libinfinity/libinfinity-0.6-sections.txt | 1 + libinfinity/server/infd-directory.c | 119 +++++++++++++++++++- libinfinity/server/infd-directory.h | 4 + 3 files changed, 122 insertions(+), 2 deletions(-) commit 9fd77a7295e5395ec02118971937e8fd28266839 Author: Armin Burgmeier Date: Sun Jun 29 13:20:58 2014 +0200 Add support for unknown notes in InfdDirectory libinfinity/server/infd-directory.c | 267 +++++++++++++++++++++++++--------- 1 file changed, 196 insertions(+), 71 deletions(-) commit 6401fb586ec9102287e350880ea678ed23a5990b Author: Armin Burgmeier Date: Fri Jun 27 14:30:04 2014 +0200 Fix erase-text propagation in InfTextFixlineBuffer libinftext/inf-text-fixline-buffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 208c40e6d8f21007f113932030fbbc44bb29ab35 Author: Gabríel Arthúr Pétursson Date: Mon Jun 9 16:18:42 2014 +0000 Include GDK headers in inf-gtk-permissions-dialog.c libinfgtk/inf-gtk-permissions-dialog.c | 3 +++ 1 file changed, 3 insertions(+) commit e43c20849d4c9a1397ff60d3c3b7ab9ac95e74b2 Author: Armin Burgmeier Date: Tue Jun 3 21:42:40 2014 +0200 Add missing include file This fixes the build on Windows libinfgtk/inf-gtk-permissions-dialog.c | 1 + 1 file changed, 1 insertion(+) commit 1288cdf8f8a16f31689977e4cf70f54fc1a9520e Author: Armin Burgmeier Date: Mon Jun 2 21:28:11 2014 +0200 Fix a crash when server does not support a permission that the client does The client would then mask out the root node permission of the "default account", which is not allowed: the default account needs to have the full mask set on the root node. This patch fixes the problem by making sure the full mask is set in handle_set_acl. Unsupported permissions are then assumed to correspond to the default ones. libinfinity/client/infc-browser.c | 52 ++++++++++++++++++++++++++++++++----- 1 file changed, 46 insertions(+), 6 deletions(-) commit 8b9df18a3a49ccedce26ffa6b81339964aa78625 Author: Armin Burgmeier Date: Fri May 16 16:09:01 2014 +0200 Add functionality in InfGtkPermissionDialog to remove accounts libinfgtk/inf-gtk-permissions-dialog.c | 442 +++++++++++++++++++++++++++++++ 1 file changed, 442 insertions(+) commit 0b35ee51e0d808c956420cea9f8061218a449e4a Author: Armin Burgmeier Date: Fri May 16 16:07:19 2014 +0200 Fix authorization check in infd_directory_handle_query_acl() libinfinity/server/infd-directory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit b344804d3584bc860d60431142b6453505ec8ac7 Author: Armin Burgmeier Date: Thu May 15 19:32:39 2014 +0200 Implement remaining ACL permissions libinfinity/common/inf-acl.c | 43 ++++++++- libinfinity/common/inf-acl.h | 23 +++++ libinfinity/server/infd-directory.c | 174 +++++++++++++++++++++++++++------- 3 files changed, 207 insertions(+), 33 deletions(-) commit adb4cb3c8045e5784b38dcfa0926dcdfd1d110fd Author: Armin Burgmeier Date: Thu May 15 16:41:31 2014 +0200 Fix the cleanup tests This change involves making the function inf_adopted_algorithm_cleanup() public, so that it can be called by InfAdoptedSession at the appropriate time. Another nice benefit of this is that now it is up to the user of InfAdoptedAlgorithm to decide when to remove no longer used requests. This can for example be used to keep a full history by not calling the function at all, or to cleanup in regular intervals. .../libinfinity/libinfinity-0.6-sections.txt | 1 + libinfinity/adopted/inf-adopted-algorithm.c | 252 ++++++++++---------- libinfinity/adopted/inf-adopted-algorithm.h | 3 + libinfinity/adopted/inf-adopted-session.c | 22 +- 4 files changed, 154 insertions(+), 124 deletions(-) commit 30af3fc4b0c57cce4f349cfd80d1f216fe1eb8b0 Author: Armin Burgmeier Date: Wed May 14 17:42:33 2014 +0200 Fix possible memory leak in inf_session_communication_object_received() libinfinity/common/inf-session.c | 2 ++ 1 file changed, 2 insertions(+) commit 6be10da6ac0f130deff03a3e85d3a651f97b1e17 Author: Armin Burgmeier Date: Wed May 14 17:38:41 2014 +0200 Improve error messages in inf-test-text-cleanup test/inf-test-text-cleanup.c | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) commit d7d5c6cdf0ed5f890d5eb14c13be4d466b615f29 Author: Philipp Kern Date: Sun May 11 12:33:48 2014 +0200 Travis CI: Do not call configure twice. .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit e6919ac6b4246e964a5648e1bc24e5955e1e8b20 Author: Philipp Kern Date: Sun May 11 12:24:03 2014 +0200 Add Travis CI support. .travis.yml | 8 ++++++++ 1 file changed, 8 insertions(+) commit 3ca30b3e2bd8881368c586a7dfa828251c39a1ab Author: Armin Burgmeier Date: Fri May 9 16:18:26 2014 +0200 Change logic of certificate checking to be SSH-like The "known hosts" file is changed to contain mappings from hostname to certificate. This technique is also known as "certificate pinnng". The certificate check is then performed as follows: If the certificate is valid, then connect, and remove any entry in the known hosts file. If the certificate is invalid for a reason other than a hostname mismatch or the CA not being trusted, then disconnect. Otherwise, look up the name of the host in the "known hosts" file: * If the certificate that is saved for this host is equal to the one that was presented, then proceed. * If there is no entry, or if the certificate saved in the known hosts file is expired or revoked, then show a dialog asking whether to trust the connection (showing what the problem is (either hostname or CA untrusted)), and if yes, add it to the known hosts file * If the stored certificate is not the same as the one presented, then also show a dialog with a "this is strange, please make sure you only proceed if you expect this message otherwise contact the server administrator". Replace the certificate in the known hosts file if proceeding. If the hostname matches the one in the certificate and if the certificate is issued by a trusted CA, then proceed with the connection. If the certificate is invalid libinfgtk/inf-gtk-certificate-dialog.c | 160 ++---- libinfgtk/inf-gtk-certificate-dialog.h | 30 +- libinfgtk/inf-gtk-certificate-manager.c | 840 +++++++++++++++++++----------- 3 files changed, 613 insertions(+), 417 deletions(-) commit 9879d21e64d73d007b56e75a4cbcac9eadac33e0 Author: Armin Burgmeier Date: Tue May 6 21:17:52 2014 +0200 Allow to specify reason for certificate rejection .../plugins/infinoted-plugin-certificate-auth.c | 17 +++++- libinfgtk/inf-gtk-certificate-manager.c | 9 ++- libinfinity/common/inf-xmpp-connection.c | 61 ++++++++++++++++----- libinfinity/common/inf-xmpp-connection.h | 3 +- 4 files changed, 70 insertions(+), 20 deletions(-) commit 4ea815cccb2b3388a5f33d72b42ba47a93038c80 Author: Armin Burgmeier Date: Tue May 6 21:02:41 2014 +0200 Add INF_GNUTLS_CERTIFICATE_VERIFICATION_ERROR domain .../libinfinity/libinfinity-0.6-sections.txt | 2 + libinfinity/common/inf-error.c | 57 +++++++++++++++++++++ libinfinity/common/inf-error.h | 7 +++ 3 files changed, 66 insertions(+) commit 1e2edf642135ee87ec0cbb582d3763b17086548b Author: Armin Burgmeier Date: Tue May 6 16:17:18 2014 +0200 Add additional assert statements These avoid false positives of the clang static analyzer. libinfinity/adopted/inf-adopted-state-vector.c | 8 +++++--- test/inf-test-reduce-replay.c | 5 +++++ 2 files changed, 10 insertions(+), 3 deletions(-) commit 67be1478d72b139937d95098326ce31ba2e99dd5 Author: Armin Burgmeier Date: Tue May 6 16:54:36 2014 +0200 Fix missing return values in infinoted_plugin_document_stream_io_in() infinoted/plugins/infinoted-plugin-document-stream.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) commit 2d907b7eea831a4d79095cee03d62a7bfd8d8d43 Author: Armin Burgmeier Date: Tue May 6 16:41:45 2014 +0200 Fix cleanup order of InfdDirectory libinfinity/server/infd-directory.c | 101 ++++++++++++++++++++-------------- 1 file changed, 59 insertions(+), 42 deletions(-) commit 33b90bf92d17d121cf9cac5a829f7e0f20446be0 Author: Armin Burgmeier Date: Tue May 6 16:16:35 2014 +0200 Fix an invalid pointer dereference in inf_text_chunk_get_segment() libinftext/inf-text-chunk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 8ab8c9bd841011ef7c7b119a27743b1ffe1f4800 Author: Armin Burgmeier Date: Tue May 6 14:18:10 2014 +0200 Fix g_return_if_fail / g_return_val_if_fail occurences libinfgtk/inf-gtk-browser-store.c | 4 ++-- libinfgtk/inf-gtk-certificate-manager.c | 2 +- libinfinity/adopted/inf-adopted-algorithm.c | 19 +++++++++++-------- libinfinity/adopted/inf-adopted-operation.c | 10 +++++----- libinfinity/common/inf-acl.c | 2 +- libinfinity/server/infd-directory.c | 6 +++--- 6 files changed, 23 insertions(+), 20 deletions(-) commit 7bdda5389027559f10c708aa68e35a755b7a7b68 Author: Armin Burgmeier Date: Sun May 4 19:31:44 2014 +0200 Add the certificate-auth plugin This plugin enables client authentification with client certificates. The functionality has already been available in the infinoted server itself and is now moved into a plugin. The has additional features compared to the previous functionality, including the accept-unauthenticated-clients option and the feature to create a short-lived super account that can be used to set up the initial permissions. infinoted/infinoted-options.c | 12 - infinoted/infinoted-options.h | 1 - infinoted/infinoted-run.c | 87 --- infinoted/infinoted-startup.c | 47 -- infinoted/infinoted-startup.h | 3 - infinoted/plugins/Makefile.am | 10 + .../plugins/infinoted-plugin-certificate-auth.c | 602 ++++++++++++++++++++ 7 files changed, 612 insertions(+), 150 deletions(-) commit 4d8093bad8c3bf526e6c7f93483f69eae71c4b88 Author: Armin Burgmeier Date: Sun May 4 19:31:13 2014 +0200 Remove an outdated assertion that is no longer true with transient accounts libinfinity/server/infd-directory.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) commit af92d0d91e4cf692bb2ed6db4d88f7239605b753 Author: Armin Burgmeier Date: Sun May 4 19:20:45 2014 +0200 Fix two memory leaks in infinoted infinoted/infinoted-log.c | 2 ++ infinoted/infinoted-parameter.c | 3 +++ 2 files changed, 5 insertions(+) commit 85bffce83cfe8880dbc1febf4c4af31c6ac107ed Author: Armin Burgmeier Date: Sun May 4 19:19:30 2014 +0200 Fix assertion failure when browser is disconnected while waiting for welcome libinfinity/client/infc-browser.c | 6 ++++++ 1 file changed, 6 insertions(+) commit 53ebb250c396ad4a0de492fdd34c933459f33bb8 Author: Armin Burgmeier Date: Sun May 4 17:24:55 2014 +0200 Remove an obsolete TODO item libinfinity/server/infd-directory.c | 4 ---- 1 file changed, 4 deletions(-) commit 54e839839f2caa165edd58585c56da26c28254c2 Author: Armin Burgmeier Date: Sun May 4 16:56:49 2014 +0200 InfXmppConnection: Allow to specify gnutls_certificate_request_t This allows to reject clients that do not present a certificate already on the TLS level. infinoted/infinoted-run.c | 1 + libinfgtk/inf-gtk-certificate-manager.c | 1 + libinfinity/common/inf-xmpp-connection.c | 7 ++++++- libinfinity/common/inf-xmpp-connection.h | 1 + 4 files changed, 9 insertions(+), 1 deletion(-) commit d8a306e8cbc0a5028a7950efb4f1e196ed9fc314 Author: Armin Burgmeier Date: Sun May 4 16:43:42 2014 +0200 Add certificate credentials to the plugin manager This allows plugin to access the credentials and to possibly alter them. The upcoming certificate authentication plugin needs to do this in order to set the trusted CA certificates that client certificates need to be signed with. infinoted/infinoted-config-reload.c | 1 + infinoted/infinoted-plugin-manager.c | 27 ++++++++++++++++++++++++++- infinoted/infinoted-plugin-manager.h | 5 +++++ infinoted/infinoted-run.c | 1 + 4 files changed, 33 insertions(+), 1 deletion(-) commit e95548e32d86c4769a19b860138d5f54ae539280 Author: Armin Burgmeier Date: Sun May 4 15:05:26 2014 +0200 infinoted plugin manager: Call on_deinitalize if on_initialize fails This simplifies makes the cleanup routines in the plugins. infinoted/infinoted-plugin-manager.c | 3 +++ infinoted/plugins/infinoted-plugin-directory-sync.c | 4 ---- infinoted/plugins/infinoted-plugin-document-stream.c | 8 -------- 3 files changed, 3 insertions(+), 12 deletions(-) commit 02ca7b677894164ca1c202b164797402d1445727 Author: Armin Burgmeier Date: Sun May 4 13:58:08 2014 +0200 Raise key strength when creating private key with --create-key Going up from 2048 bit to 4096 bit. infinoted/infinoted-startup.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit 054a6d88054e04185dcce1d8c332b1f6c811f5b4 Author: Armin Burgmeier Date: Sun May 4 13:45:35 2014 +0200 Rename inf_cert_util_check_certificate_signature to _check_certificate_key docs/reference/libinfinity/libinfinity-0.6-sections.txt | 2 +- libinfinity/common/inf-cert-util.c | 10 +++++----- libinfinity/common/inf-cert-util.h | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) commit fbfc23a38364417c48db36c92f8b0f4c0ba3c66a Author: Armin Burgmeier Date: Sun May 4 13:42:59 2014 +0200 Add more flexibility when creating certificates with inf-cert-util .../libinfinity/libinfinity-0.6-sections.txt | 3 + infinoted/infinoted-startup.c | 8 +- libinfinity/common/inf-cert-util.c | 176 +++++++++++++++----- libinfinity/common/inf-cert-util.h | 34 ++++ 4 files changed, 180 insertions(+), 41 deletions(-) commit 8b781bcf8511d6e7107fcd6e0e1b8a8c6e39e065 Author: Armin Burgmeier Date: Sat May 3 21:20:35 2014 +0200 Add API and protocol handling for creating and removing ACL accounts .../libinfinity/libinfinity-0.6-sections.txt | 18 +- libinfinity/client/infc-browser.c | 705 +++++++++------- libinfinity/client/infc-browser.h | 8 - libinfinity/common/inf-browser.c | 73 ++ libinfinity/common/inf-browser.h | 28 + libinfinity/common/inf-error.c | 2 + libinfinity/common/inf-error.h | 3 + libinfinity/common/inf-request-result.c | 190 +++-- libinfinity/common/inf-request-result.h | 29 +- libinfinity/server/infd-acl-account-info.c | 10 +- libinfinity/server/infd-acl-account-info.h | 6 +- libinfinity/server/infd-directory.c | 849 ++++++++++++++------ libinfinity/server/infd-directory.h | 9 + test/inf-test-certificate-request.c | 19 +- 14 files changed, 1308 insertions(+), 641 deletions(-) commit c187c67d86449688b61fa2c1ffd4e763876c9037 Author: Armin Burgmeier Date: Sat May 3 20:35:00 2014 +0200 Fix PEM output in inf-test-certificate-request.c test/inf-test-certificate-request.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) commit f8edd98b0984ccc870d04b2ad7f6ef29d690d13c Author: Armin Burgmeier Date: Sat May 3 20:34:35 2014 +0200 Fix a memory leak in infc_request_manager_get_request_by_xml() libinfinity/client/infc-request-manager.c | 1 + 1 file changed, 1 insertion(+) commit 287c722099e8a9d44381ed6516eca477f18f7dc8 Author: Armin Burgmeier Date: Fri May 2 12:23:33 2014 +0200 Add possibility to the protocol to remove ACL accounts libinfinity/client/infc-browser.c | 163 +++++++++++++++++++++++++++ libinfinity/common/inf-error.c | 2 + libinfinity/common/inf-error.h | 3 + libinfinity/server/infd-directory.c | 206 +++++++++++++++++++++++++++++++++- 4 files changed, 371 insertions(+), 3 deletions(-) commit ea3893a6b73ea4d4dbf06c8f4eacbb22a67d51b2 Author: Armin Burgmeier Date: Fri May 2 11:18:39 2014 +0200 Bail if an inconsistent change-acl-account message arrives libinfinity/client/infc-browser.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) commit 3cbe8c6b6113f92213800d1777599c237174ecc8 Author: Armin Burgmeier Date: Thu May 1 21:15:49 2014 +0200 Fix possible read-after-end in inf_text_fixline_buffer_buffer_insert_text() libinftext/inf-text-fixline-buffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 5a7157e75e583bce88a1805be7cae63da0bb5810 Author: Armin Burgmeier Date: Thu May 1 21:15:12 2014 +0200 Fix an allocation problem in inf_text_fixline_buffer_buffer_insert_text() libinftext/inf-text-fixline-buffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit e1fdb9c87e1db1f6df18dc0897657ab651b9e9dd Author: Armin Burgmeier Date: Thu May 1 20:15:38 2014 +0200 Fix build of inf-native-socket.c on Windows libinfinity/common/inf-native-socket.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) commit c49d3e29c538030179eeb494732e4f185d72cd0a Author: Armin Burgmeier Date: Wed Apr 30 23:18:25 2014 +0200 Re-use some low level socket code in inf-native-socket.[hc] .../libinfinity/libinfinity-0.6-docs.sgml | 1 + .../libinfinity/libinfinity-0.6-sections.txt | 8 ++ libinfinity/common/Makefile.am | 2 + libinfinity/common/inf-io.h | 18 +-- libinfinity/common/inf-native-socket.c | 97 +++++++++++++++ libinfinity/common/inf-native-socket.h | 72 ++++++++++++ libinfinity/common/inf-tcp-connection.c | 123 +++++--------------- libinfinity/server/infd-tcp-server.c | 71 +++-------- 8 files changed, 227 insertions(+), 165 deletions(-) commit f0d448a8807af1d7814a537a7a404ea104cdf211 Author: Armin Burgmeier Date: Sun Apr 27 23:12:38 2014 +0200 Allow the account of a client to be changed at runtime .../libinfinity/libinfinity-0.6-sections.txt | 5 +- libinfinity/client/infc-browser.c | 192 ++++++++++++++++---- libinfinity/common/inf-acl.c | 23 +++ libinfinity/common/inf-acl.h | 3 + libinfinity/common/inf-browser.c | 52 ++++++ libinfinity/common/inf-browser.h | 9 + libinfinity/server/infd-directory.c | 100 +++++++++- libinfinity/server/infd-directory.h | 5 + 8 files changed, 348 insertions(+), 41 deletions(-) commit d1a7c0852b6f723cc943bf98deb1d0e098b54fc1 Author: Armin Burgmeier Date: Sun Apr 27 20:42:24 2014 +0200 Support can-subscribe-session and can-explore-nodes in InfGtkBrowserView libinfgtk/inf-gtk-browser-view.c | 148 ++++++++++++++++++++++++++++++++----- 1 file changed, 129 insertions(+), 19 deletions(-) commit a717abf035ffc06de3389f060b8f1bb9651b28fe Author: Armin Burgmeier Date: Sun Apr 27 19:52:52 2014 +0200 Add INF_ACL_CAN_EXPLORE_NODE permission libinfinity/client/infc-browser.c | 4 ++-- libinfinity/common/inf-acl.c | 5 +++++ libinfinity/common/inf-acl.h | 3 +++ libinfinity/server/infd-directory.c | 9 +++++++-- 4 files changed, 17 insertions(+), 4 deletions(-) commit 9f0236e5e4a8447e977470bcbfdf5295df4cf1db Author: Armin Burgmeier Date: Sun Apr 27 20:52:41 2014 +0200 Fix return value of infd_directory_enforce_single_acl() libinfinity/server/infd-directory.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) commit f946a63a101743c6b29d8ba3ca9ebe1f275ed3f2 Author: Armin Burgmeier Date: Sun Apr 27 20:44:44 2014 +0200 Fix a crash when enforcing ACL on the server side libinfinity/server/infd-directory.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) commit 3395af5ca3c68bd81479d3597f9c3bd92ed0acb6 Author: Armin Burgmeier Date: Sat Apr 26 21:57:41 2014 +0200 Enforce ACLs on all connections on ACL change .../libinfinity/libinfinity-0.6-sections.txt | 3 +- libinfgtk/inf-gtk-acl-sheet-view.c | 2 +- libinfgtk/inf-gtk-permissions-dialog.c | 77 +++- libinfinity/client/infc-browser.c | 349 +++++++++++++++ libinfinity/common/inf-browser.c | 55 ++- libinfinity/common/inf-browser.h | 9 + libinfinity/server/infd-directory.c | 451 ++++++++++++++++++-- 7 files changed, 904 insertions(+), 42 deletions(-) commit e940fcbc46f3b400ecb2265bc83a79da54930235 Author: Armin Burgmeier Date: Sat Apr 26 21:31:26 2014 +0200 Update autogen.sh to latest version of gnome-common This enables running it with the latest automake INSTALL | 12 ++-- autogen.sh | 184 ++++++++++++++--------------------------------------------- 2 files changed, 48 insertions(+), 148 deletions(-) commit a50ed511c754c5d23cca185eb54548dd9176b080 Author: Armin Burgmeier Date: Sat Apr 26 20:26:29 2014 +0200 Fix crash in inf_acl_sheet_set_from_xml when account id cannot be found libinfinity/common/inf-acl.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) commit 5ca0e84462bbe471d91eee00660a28a60a500b29 Author: Armin Burgmeier Date: Sat Apr 26 10:09:24 2014 +0200 Remove ACLs from disk when removing a node libinfinity/server/infd-filesystem-storage.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) commit 61fc849a575bb93a3fecc70478c98b3f80e6a5a1 Author: Armin Burgmeier Date: Sat Apr 19 19:26:23 2014 +0200 Add two-way chat support to document-stream .../plugins/infinoted-plugin-document-stream.c | 379 +++++++++++++++++--- 1 file changed, 335 insertions(+), 44 deletions(-) commit 598ed69384c91e4636c9bbb649d1b4ff8ea4f558 Author: Armin Burgmeier Date: Sat Apr 19 19:24:45 2014 +0200 Fix resurrection of weak-refed session in InfdDirectory libinfinity/server/infd-directory.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) commit 1171093ea96156d092a45924635b3cd7769d1ec6 Author: Armin Burgmeier Date: Thu Apr 10 17:16:06 2014 +0200 infinoted: Also log CN of certificate at connection attempts and errors infinoted/plugins/infinoted-plugin-logging.c | 179 +++++++++++++++++++++---- libinfinity/common/inf-xmpp-connection.c | 40 +++++- 2 files changed, 191 insertions(+), 28 deletions(-) commit ff19814b2a91e3442f3f536978dfc65e5132ffc6 Author: Armin Burgmeier Date: Wed Apr 9 19:32:00 2014 +0200 Send a "request-invalid" back to the remote site if execute-request failed This is currently not handled, but can help to diagnose problems libinfinity/adopted/inf-adopted-session.c | 80 ++++++++++++++++++++++++++--- 1 file changed, 72 insertions(+), 8 deletions(-) commit ce068a20618772726ccc20f3751f04114307f474 Author: Armin Burgmeier Date: Sat Apr 5 23:04:17 2014 +0200 Add document-stream infinoted plugin configure.ac | 4 +- infinoted/infinoted-plugin-manager.c | 14 + infinoted/infinoted-plugin-manager.h | 3 + infinoted/plugins/Makefile.am | 23 +- .../plugins/infinoted-plugin-document-stream.c | 1215 +++++++++++++++++++ .../util/infinoted-plugin-util-navigate-browser.c | 310 +++++ .../util/infinoted-plugin-util-navigate-browser.h | 60 + 7 files changed, 1627 insertions(+), 2 deletions(-) commit e49eb90e6f53ffb96c54d2fa2c98b7e4ff6254e7 Author: Armin Burgmeier Date: Sat Apr 5 23:03:41 2014 +0200 Fix win32 build failure in directory-sync infinoted plugin infinoted/plugins/infinoted-plugin-directory-sync.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) commit 0cf4bd7934024673dbd4ebc4490889432b27fb84 Author: Armin Burgmeier Date: Fri Feb 28 16:02:13 2014 +0100 Simplify the request API Instead of having many classes and interfaces for the different parameter types of request results, we have now one new type, InfRequestResult, which combines the various signatures of a request result. This allows to keep only one interface, InfRequest, which provides the "finished" signal itself. There are four implementations, two on the client and two on the server side. One is the basic "request" object, and the other is a request object with progress information for node exploration and user list query. .../libinfinity/libinfinity-0.6-docs.sgml | 19 +- .../libinfinity/libinfinity-0.6-sections.txt | 262 ++----- .../plugins/infinoted-plugin-directory-sync.c | 2 +- infinoted/plugins/infinoted-plugin-linekeeper.c | 11 +- libinfgtk/inf-gtk-browser-store.c | 44 +- libinfgtk/inf-gtk-browser-view.c | 74 +- libinfgtk/inf-gtk-permissions-dialog.c | 44 +- libinfinity/client/Makefile.am | 18 +- .../client/infc-acl-account-list-request.c | 357 --------- .../client/infc-acl-account-list-request.h | 75 -- libinfinity/client/infc-browser.c | 603 ++++++++------- libinfinity/client/infc-browser.h | 17 +- libinfinity/client/infc-certificate-request.c | 312 -------- libinfinity/client/infc-certificate-request.h | 98 --- libinfinity/client/infc-chat-request.c | 305 -------- libinfinity/client/infc-chat-request.h | 90 --- libinfinity/client/infc-explore-request.c | 273 ------- libinfinity/client/infc-explore-request.h | 76 -- libinfinity/client/infc-node-request.c | 314 -------- libinfinity/client/infc-node-request.h | 66 -- libinfinity/client/infc-progress-request.c | 286 +++++++ libinfinity/client/infc-progress-request.h | 76 ++ libinfinity/client/infc-request-manager.c | 24 + libinfinity/client/infc-request-manager.h | 6 + libinfinity/client/infc-request.c | 255 +++++- libinfinity/client/infc-request.h | 20 +- libinfinity/client/infc-session-proxy.c | 25 +- libinfinity/client/infc-user-request.c | 272 ------- libinfinity/client/infc-user-request.h | 64 -- libinfinity/common/Makefile.am | 10 +- libinfinity/common/inf-acl-account-list-request.c | 164 ---- libinfinity/common/inf-acl-account-list-request.h | 82 -- libinfinity/common/inf-browser.c | 125 ++- libinfinity/common/inf-browser.h | 136 ++-- libinfinity/common/inf-explore-request.c | 117 --- libinfinity/common/inf-explore-request.h | 58 -- libinfinity/common/inf-node-request.c | 141 ---- libinfinity/common/inf-node-request.h | 87 --- libinfinity/common/inf-request-result.c | 808 ++++++++++++++++++++ libinfinity/common/inf-request-result.h | 157 ++++ libinfinity/common/inf-request.c | 94 ++- libinfinity/common/inf-request.h | 36 +- libinfinity/common/inf-session-proxy.c | 10 +- libinfinity/common/inf-session-proxy.h | 16 +- libinfinity/common/inf-user-request.c | 143 ---- libinfinity/common/inf-user-request.h | 87 --- libinfinity/server/Makefile.am | 10 +- libinfinity/server/infd-directory.c | 260 ++++--- libinfinity/server/infd-explore-request.c | 258 ------- libinfinity/server/infd-explore-request.h | 73 -- libinfinity/server/infd-node-request.c | 310 -------- libinfinity/server/infd-progress-request.c | 272 +++++++ libinfinity/server/infd-progress-request.h | 73 ++ libinfinity/server/infd-request.c | 302 ++++++++ .../{infd-node-request.h => infd-request.h} | 34 +- libinfinity/server/infd-session-proxy.c | 26 +- libinfinity/server/infd-user-request.c | 242 ------ libinfinity/server/infd-user-request.h | 64 -- libinftext/inf-text-session.c | 8 +- libinftext/inf-text-session.h | 4 +- test/inf-test-certificate-request.c | 8 +- test/inf-test-chat.c | 12 +- test/inf-test-gtk-browser.c | 32 +- test/inf-test-mass-join.c | 14 +- test/inf-test-set-acl.c | 16 +- 65 files changed, 3227 insertions(+), 5150 deletions(-) commit 1e7fabfa776854711035825271e06f5c6ce4a52d Author: Armin Burgmeier Date: Mon Feb 24 22:15:14 2014 +0100 infinoted: Set umask to system value instead of 0077 This is only relevant when infinoted is started in daemonized mode. libdaemon resets the umask, but we don't want that, so that the system administrator can specify the permissions to use for the root directory with the umask. See #617. infinoted/infinoted-main.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) commit 12d4e363692fa352d31aee65143af885a61da90f Author: Armin Burgmeier Date: Mon Feb 24 22:12:47 2014 +0100 Allow group and other access to files created in the storage If this is not wanted, it can be prevented by setting the umask appropriately. libinfinity/server/infd-filesystem-storage.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit cecf5112459ce7f93c354b9f80831720e31d88f6 Author: Armin Burgmeier Date: Mon Feb 24 21:55:59 2014 +0100 Make sure infinoted properly depends on infinoted-plugin-manager It looks like the dependency tracking works when specifying the relative path in infinoted_0_6_LDADD, but not the absolute path based on ${top_srcdir}. It seems strange to me, but it seems to work. infinoted/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit af955a3e1ef7cd7753b594e72bd5446a25d1ef61 Author: Armin Burgmeier Date: Sun Feb 23 22:25:02 2014 +0100 Add missing LIBADD to infinoted-plugin-traffic-logging infinoted/plugins/Makefile.am | 8 ++++++++ 1 file changed, 8 insertions(+) commit bb7e1741413a97c30359d0aeee32b83f3ef5d438 Author: Armin Burgmeier Date: Sat Feb 22 22:30:22 2014 +0100 Add workaround for inconsistent cursor position with InfTextFixlineBuffer This should be treated as a temporary solution until a proper propagation of cursor position and selection through the InfTextBuffer interface is in place. libinftext/inf-text-session.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) commit 264b71eac40d00ab3643060b77a71f3d216181eb Author: Armin Burgmeier Date: Mon Feb 17 22:42:43 2014 +0100 infinoted: flush the log file after writing to it infinoted/infinoted-log.c | 1 + 1 file changed, 1 insertion(+) commit a8fea1c61cf03e994b3bff072ef1a8d3ba019650 Author: Armin Burgmeier Date: Fri Feb 14 19:18:24 2014 +0100 Fix return value check of gnutls_certificate_set_x509_trust() Since some version of gnutls, this function seems to return the number of read certificates instead of 0, in case of success. infinoted/infinoted-startup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 687fb2556da44926a7a4051131f53861faea278f Author: Armin Burgmeier Date: Fri Feb 14 19:00:40 2014 +0100 Add missing include file to inf-file-util.c libinfinity/common/inf-file-util.c | 1 + 1 file changed, 1 insertion(+) commit 8e5854b462001e3ca2501b3402df466bee942ba9 Author: Armin Burgmeier Date: Fri Feb 14 15:52:10 2014 +0100 Fix iter_get_length implementation in InfTextGtkBuffer The problem was that the begin and end iterators were swapped. libinftextgtk/inf-text-gtk-buffer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit 5356b8395e1333b628017c2f102f97e2332dfccc Author: Armin Burgmeier Date: Fri Feb 14 15:51:51 2014 +0100 Fix an off-by-one assertion in InfTextFixlineBuffer libinftext/inf-text-fixline-buffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 9addbcbda6660c72377513535699a764decb5f24 Author: Armin Burgmeier Date: Sat Feb 8 23:21:14 2014 +0100 Add InfTextFixlineBuffer This class allows to keep a fixed number of empty trailing lines on the client side, without making any change to the actual document that is kept synchronized in the session. .../reference/libinftext/libinftext-0.6-docs.sgml | 1 + .../libinftext/libinftext-0.6-sections.txt | 16 + libinftext/Makefile.am | 2 + libinftext/inf-text-fixline-buffer.c | 1831 +++++++++++++++++++ libinftext/inf-text-fixline-buffer.h | 72 + test/Makefile.am | 12 +- test/inf-test-text-fixline.c | 310 ++++ 7 files changed, 2243 insertions(+), 1 deletion(-) commit 6902b68b49a94681d380d56abd18993e09ae131e Author: Armin Burgmeier Date: Thu Feb 6 18:18:26 2014 +0100 Fix two minor documentation issues libinftext/inf-text-buffer.c | 2 +- libinftext/inf-text-filesystem-format.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) commit 4f03719e33e988d86e4c7482e4ca14f21532940b Author: Armin Burgmeier Date: Thu Feb 6 15:32:49 2014 +0100 Add inf_text_buffer_iter_get_offset() .../libinftext/libinftext-0.6-sections.txt | 2 ++ libinftext/inf-text-buffer.c | 26 +++++++++++++++++++++ libinftext/inf-text-buffer.h | 9 +++++++ libinftext/inf-text-chunk.c | 20 ++++++++++++++++ libinftext/inf-text-chunk.h | 3 +++ libinftext/inf-text-default-buffer.c | 8 +++++++ libinftextgtk/inf-text-gtk-buffer.c | 8 +++++++ 7 files changed, 76 insertions(+) commit 21bbc30c617425fe4c2f488c760af2529bf02f15 Author: Armin Burgmeier Date: Wed Jan 29 16:11:09 2014 +0100 Add inf_cert_util_write_certificate_with_key() .../libinfinity/libinfinity-0.6-sections.txt | 1 + libinfinity/common/inf-cert-util.c | 252 ++++++++++++++------ libinfinity/common/inf-cert-util.h | 7 + 3 files changed, 184 insertions(+), 76 deletions(-) commit 69da25cd114438a478ce6d9c66fe84a014a3c957 Author: Armin Burgmeier Date: Mon Jan 27 23:15:21 2014 +0100 Convert the infinoted traffic logger into a plugin infinoted/Makefile.am | 6 +- infinoted/infinoted-config-reload.c | 35 -- infinoted/infinoted-options.c | 15 - infinoted/infinoted-options.h | 2 - infinoted/infinoted-run.c | 16 - infinoted/infinoted-run.h | 3 - infinoted/infinoted-traffic-logger.c | 357 -------------------- infinoted/infinoted-traffic-logger.h | 52 --- infinoted/plugins/Makefile.am | 4 + .../plugins/infinoted-plugin-traffic-logging.c | 351 +++++++++++++++++++ 10 files changed, 357 insertions(+), 484 deletions(-) commit 8931c8b560af87c3ed11472f1c09d5074f0303a2 Author: Armin Burgmeier Date: Mon Jan 27 11:15:30 2014 +0100 Turn the session recording functionality into a infinoted plugin infinoted/Makefile.am | 2 - infinoted/infinoted-record.c | 283 -------------------------- infinoted/infinoted-record.h | 50 ----- infinoted/infinoted-run.c | 5 - infinoted/infinoted-run.h | 3 - infinoted/plugins/Makefile.am | 12 ++ infinoted/plugins/infinoted-plugin-record.c | 236 +++++++++++++++++++++ 7 files changed, 248 insertions(+), 343 deletions(-) commit 9fcac38543d6f58829309608c3ad5dc3671479e8 Author: Armin Burgmeier Date: Mon Jan 27 10:40:16 2014 +0100 linekeeper plugin: Only join local user if other users are available This allows to session to go idle when no remote users are connected, so that InfdDirectory unloads the session into the background storage. infinoted/plugins/infinoted-plugin-linekeeper.c | 241 +++++++++++++++++++--- 1 file changed, 212 insertions(+), 29 deletions(-) commit 46d69bbad760689fa6df0f224fbdc3d2df98f7f9 Author: Armin Burgmeier Date: Mon Jan 27 10:40:01 2014 +0100 Add the add-available-user and remove-available-user signals to InfUserTable libinfinity/common/inf-user-table.c | 144 +++++++++++++++++++++++++++++++--- libinfinity/common/inf-user-table.h | 10 +++ 2 files changed, 141 insertions(+), 13 deletions(-) commit 6983bf41ccc35ff0b1adce211ad1ba45dbb18eff Author: Armin Burgmeier Date: Mon Jan 27 09:35:35 2014 +0100 Keep the session subscribed to the directory if it has local users libinfinity/server/infd-session-proxy.c | 39 +++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) commit f5411ac85be89c6ff62f62e8877c8dfc9ead930e Author: Armin Burgmeier Date: Mon Jan 27 09:07:29 2014 +0100 Add request parameter for the InfBrowser::unsubscribe-session signal TODO | 5 ---- infinoted/infinoted-plugin-manager.c | 1 + infinoted/infinoted-record.c | 1 + libinfinity/client/infc-browser.c | 27 ++++++++++++++------- libinfinity/common/inf-browser.c | 20 +++++++++++----- libinfinity/common/inf-browser.h | 6 +++-- libinfinity/server/infd-directory.c | 43 +++++++++++++++++++++++++++------- 7 files changed, 72 insertions(+), 31 deletions(-) commit 5c6096c612214685fed13afa5b772152571fa391 Author: Armin Burgmeier Date: Sun Jan 26 21:36:59 2014 +0100 Fix notification order on node removal in InfcBrowser Make sure that "unsubscribe-session" is emitted before "node-removed" libinfinity/client/infc-browser.c | 46 +++++++++++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 5 deletions(-) commit c7c5a5d2c86f34bc1e9557e85d47a8368aeadd0b Author: Armin Burgmeier Date: Sun Jan 26 12:43:06 2014 +0100 Fix InfChatBuffer structure when prepending a message This caused an entry to be overwritten and an invalid entry at the end to be used. This typically lead to a crash on destruction of the chat buffer. libinfinity/common/inf-chat-buffer.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) commit 9faedb7ccf0a00849b077febda9521a68718aa19 Author: Armin Burgmeier Date: Fri Jan 24 21:06:01 2014 +0100 Fix an uninitialized variable in InfGtkPermissionsDialog This can happen when the root node is being displayed and the selection is reset, so that no entry is selected. In that case the account variable was uninitialized but still used. libinfgtk/inf-gtk-permissions-dialog.c | 2 ++ 1 file changed, 2 insertions(+) commit 945f60127a1c05ef48c4f62e3996e50d2450ffaf Author: Armin Burgmeier Date: Fri Jan 24 12:06:09 2014 +0100 Make local users unavailable in InfdSessionProxy when session is closed TODO | 5 +++++ libinfinity/client/infc-session-proxy.c | 3 ++- libinfinity/server/infd-session-proxy.c | 10 ++++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) commit 7aae6e67a8c7e93a588c157c10a51bdac0fd8dc5 Author: Armin Burgmeier Date: Fri Jan 24 10:47:49 2014 +0100 Keep communication method alive in inf_communication_central_method_received() This fixes a problem when the inf_communication_object_received() callback would delete the method, since afterwards the method checks whether the message needs to be forwarded to the other group members. .../communication/inf-communication-central-method.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) commit 74ffdc70417721a587a90868323868ef8063a0a0 Author: Armin Burgmeier Date: Thu Jan 23 17:29:38 2014 +0100 Fix inf_browser_add_note implementation in InfdDirectory with nonzero session libinfinity/server/infd-directory.c | 44 +++++++++++------------------------ 1 file changed, 13 insertions(+), 31 deletions(-) commit c2c8b645f970b1507e9b70b74eb3420dc70a8616 Author: Armin Burgmeier Date: Tue Jan 21 21:04:32 2014 +0100 inf_gtk_io_io_watch_free(): Do not use the watch after it is destroyed libinfgtk/inf-gtk-io.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) commit b8340029bdd95a9535bc7264d5a9c09784f29251 Author: Armin Burgmeier Date: Mon Jan 20 22:18:49 2014 +0100 Make sure that sessions are running when "subscribe-session" is emitted Before the InfdDirectory would emit the subscribe-session signal for a synced-in session before the session status was changed to RUNNING. This makes infinoted plugin development easier, since plugins do not need to wait for the session to switch to the running state before for example a InfAdoptedAlgorithm becomes available. libinfinity/server/infd-directory.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) commit f3eb7a88b54a1077d618738b2c6a3d748f68e8c6 Author: Armin Burgmeier Date: Mon Jan 20 20:36:49 2014 +0100 Fix some warnings during destruction in InfTextGtkView and InfTextGtkViewport libinftextgtk/inf-text-gtk-view.c | 2 +- libinftextgtk/inf-text-gtk-viewport.c | 25 +++++++++++++++++-------- 2 files changed, 18 insertions(+), 9 deletions(-) commit 37ec211d0fe9694d9cad1e62823ce6b7b32e6a30 Author: Armin Burgmeier Date: Mon Jan 20 17:11:53 2014 +0100 Add is_local vfunc for InfRequest This allows to check whether the request was made by a local API call or by a remote user over the network. .../client/infc-acl-account-list-request.c | 12 ++++++++ libinfinity/client/infc-certificate-request.c | 14 ++++++++- libinfinity/client/infc-chat-request.c | 12 ++++++++ libinfinity/client/infc-node-request.c | 14 ++++++++- libinfinity/client/infc-user-request.c | 12 ++++++++ libinfinity/common/inf-request.c | 33 +++++++++++++++++---- libinfinity/common/inf-request.h | 10 ++++++- libinfinity/server/infd-node-request.c | 12 ++++++++ libinfinity/server/infd-user-request.c | 12 ++++++++ 9 files changed, 123 insertions(+), 8 deletions(-) commit 5d22c0e3bc563c395203a02d8863a91bd8496a3b Author: Armin Burgmeier Date: Sun Jan 19 22:54:59 2014 +0100 Add request parameters to most InfBrowser signals This is basically to provide more convenience in the API. One could always subscribe to the "begin-request" signal, and then connect to the "finished" signal of the newly started request. The request parameter can for instance be used to check whether the action was due to some local request. In InfcBrowser this would basically be all actions that have a request set. In InfdDirectory, this would be all actions whose request does have the "requestor" property set to NULL. A future commit will introduce a convenience API call for this check. TODO | 4 + infinoted/infinoted-plugin-manager.c | 1 + infinoted/infinoted-record.c | 1 + .../plugins/infinoted-plugin-directory-sync.c | 1 + libinfgtk/inf-gtk-browser-store.c | 4 + libinfgtk/inf-gtk-browser-view.c | 1 + libinfgtk/inf-gtk-permissions-dialog.c | 3 + libinfinity/client/infc-browser.c | 110 +++++++--- libinfinity/common/inf-browser.c | 92 +++++--- libinfinity/common/inf-browser.h | 30 ++- libinfinity/inf-marshal.in | 3 +- libinfinity/server/infd-directory.c | 226 +++++++++++--------- test/inf-test-gtk-browser.c | 1 + 13 files changed, 307 insertions(+), 170 deletions(-) commit 55657f00ab027cf45798f77f747acb455b6f7339 Author: Armin Burgmeier Date: Sun Jan 19 18:23:01 2014 +0100 Allow to specify external user table for inf_text_filesystem_format_read() This allows to use buffer implementations that need a user table, such as InfTextGtkBuffer. infinoted/note-plugins/text/infd-note-plugin-text.c | 5 +++++ libinftext/inf-text-filesystem-format.c | 19 ++++++++----------- libinftext/inf-text-filesystem-format.h | 1 + 3 files changed, 14 insertions(+), 11 deletions(-) commit fb49eccb5a02c4cb5f4aa85ce31c47caf75bcba0 Author: Armin Burgmeier Date: Sun Jan 19 18:21:25 2014 +0100 Set the type of the synchronization group in the note plugins to the base type This way the same function can be used for InfcNotePlugin::session_new and InfdNotePlugin::session_new. infinoted/note-plugins/chat/infd-note-plugin-chat.c | 2 +- infinoted/note-plugins/text/infd-note-plugin-text.c | 5 +++-- libinfinity/adopted/inf-adopted-session-replay.c | 2 +- libinfinity/client/infc-browser.c | 2 +- libinfinity/client/infc-note-plugin.h | 2 +- libinfinity/server/infd-directory.c | 2 +- libinfinity/server/infd-note-plugin.h | 2 +- test/inf-test-gtk-browser.c | 4 ++-- test/inf-test-mass-join.c | 4 ++-- test/inf-test-reduce-replay.c | 4 ++-- test/inf-test-text-replay.c | 4 ++-- 11 files changed, 17 insertions(+), 16 deletions(-) commit 104c7233aff6061ffb596d47f9def8238feb9813 Author: Armin Burgmeier Date: Sun Jan 19 01:16:52 2014 +0100 Move filesystem storage code for text sessions to libinftext .../reference/libinftext/libinftext-0.6-docs.sgml | 1 + .../libinftext/libinftext-0.6-sections.txt | 7 + .../note-plugins/text/infd-note-plugin-text.c | 458 +------------- libinftext/Makefile.am | 2 + libinftext/inf-text-filesystem-format.c | 623 ++++++++++++++++++++ libinftext/inf-text-filesystem-format.h | 66 +++ 6 files changed, 716 insertions(+), 441 deletions(-) commit 505d78c5e7bb197fffdea9052f9cd9329801e468 Author: Armin Burgmeier Date: Sat Jan 18 12:42:54 2014 +0100 Add full_path output parameter to infd_filesystem_storage_open() infinoted/note-plugins/chat/infd-note-plugin-chat.c | 2 ++ infinoted/note-plugins/text/infd-note-plugin-text.c | 2 ++ libinfinity/server/infd-filesystem-storage.c | 18 ++++++++++++++---- libinfinity/server/infd-filesystem-storage.h | 1 + 4 files changed, 19 insertions(+), 4 deletions(-) commit e9d692ea2708dfc51ee3f29fd7980d49c56c1986 Author: Armin Burgmeier Date: Fri Jan 17 21:15:56 2014 +0100 Fix small issues when using InfdDirectory in a InfGtkBrowserStore libinfgtk/inf-gtk-browser-model.c | 2 +- libinfgtk/inf-gtk-browser-store.c | 2 +- libinfgtk/inf-gtk-browser-view.c | 26 +++++++++++++++++++------- 3 files changed, 21 insertions(+), 9 deletions(-) commit aa3f1a6dc368fa260b64aeda2f64743773afed45 Author: Armin Burgmeier Date: Fri Jan 17 23:37:15 2014 +0100 Set node explored flag before announcing nodes in InfdDirectory This allows to iterate through the node already in the handler of the node-added signal. libinfinity/server/infd-directory.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) commit 57d29a48259e96e121f38659036f55573dc982ad Author: Armin Burgmeier Date: Fri Jan 17 23:15:17 2014 +0100 Emit row-has-child-toggled for the root node if it has children libinfgtk/inf-gtk-browser-store.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) commit db2e520d0138c400c41b7edbe517ae9897a25b88 Author: Armin Burgmeier Date: Fri Jan 17 22:36:27 2014 +0100 Allow the account parameter in inf_browser_check_acl to be NULL. libinfinity/common/inf-browser.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) commit 21a6106cddc8340962ce94c377232072396114eb Author: Armin Burgmeier Date: Fri Jan 17 22:22:02 2014 +0100 Handle name collisions in inf_discovery_avahi_entry_group_add_service This can happen when two services with the same name are being published on the same host. In this case we catch the error and use an alternative name. libinfinity/common/inf-discovery-avahi.c | 47 +++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 14 deletions(-) commit 3ba66e643d470c7973f729fc78a71c3b29403bf0 Author: Armin Burgmeier Date: Fri Jan 17 20:03:53 2014 +0100 Fix an uninitialized variable in infd_directory_browser_list_pending_requests libinfinity/server/infd-directory.c | 1 + 1 file changed, 1 insertion(+) commit de433fe31e320ca546279acc10110b0bfecb2b6f Author: Armin Burgmeier Date: Thu Jan 16 19:37:09 2014 +0100 Make sure that browser is set when emitting "browser-set" signal This affects InfGtkBrowserModelFilter and InfGtkBrowserModelSort. We now connect to the browser-set signal of the child model after its default handler is run, so that when we emit our own browser-set signal the browser is actually accessible via the GtkTreeModel API. The InfGtkBrowserView implementation is now also changed such that it is no longer required that before the default handler run the old browser is still available in the model. Before, it assumed that after the default handler ran the new browser would be available, which was not true for InfGtkBrowserModelFilter and InfGtkBrowserModelSort. The semantic now is that, when connecting after the default handler of the set-browser signal, the browser is set in the model. When connecting before the default handler, the old or the new browser might be set in the model. In order to make sure that both the old and the new browser are available at all times both browsers are now parameters of the signal. libinfgtk/inf-gtk-browser-model-filter.c | 8 ++-- libinfgtk/inf-gtk-browser-model-sort.c | 8 ++-- libinfgtk/inf-gtk-browser-model.c | 36 +++++++++------ libinfgtk/inf-gtk-browser-model.h | 6 ++- libinfgtk/inf-gtk-browser-store.c | 13 +++--- libinfgtk/inf-gtk-browser-view.c | 72 +++++++++--------------------- libinfinity/inf-marshal.in | 2 +- 7 files changed, 68 insertions(+), 77 deletions(-) commit dd3919c8b54e1ab44aca3a1a53bc7dc244c97ccf Author: Armin Burgmeier Date: Thu Jan 16 19:09:11 2014 +0100 Add the inf_gtk_browser_store_add_browser() function .../libinfgtk/libinfgtk-0.6-sections.txt | 1 + libinfgtk/inf-gtk-browser-store.c | 120 +++++++++++++++----- libinfgtk/inf-gtk-browser-store.h | 5 + 3 files changed, 99 insertions(+), 27 deletions(-) commit 52c7b6e0f9ee80743cdf18f02f4b37e6ab0d572e Author: Armin Burgmeier Date: Thu Jan 16 17:41:54 2014 +0100 InfDiscoveryAvahi: Do not discover what we published ourselves libinfinity/common/inf-discovery-avahi.c | 31 +++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) commit 67b7aaf13b708f90ada9d41e2b133bfa0a3e8e32 Author: Armin Burgmeier Date: Thu Jan 16 12:45:45 2014 +0100 Allow to add and remove connections in infd_directory_foreach_connection libinfinity/server/infd-directory.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) commit ecc63ecec84d3a8a7bacbdece8e0f587de32603c Author: Armin Burgmeier Date: Thu Jan 16 12:20:44 2014 +0100 Fix warnings when changing a directory's storage The semantics are also slightly changed now, so that when a directory had a storage set and the storage is removed without setting a new one, then the directory keeps all nodes intact until another storage is set. libinfinity/server/infd-directory.c | 57 +++++++++++++++++++++++------------ 1 file changed, 38 insertions(+), 19 deletions(-) commit fc08baf7a4d8f2bcbd108eacffadcb06dbd8ac5b Author: Armin Burgmeier Date: Tue Jan 14 17:03:31 2014 +0100 Add inf_cert_util_check_certificate_signature() function .../libinfinity/libinfinity-0.6-sections.txt | 1 + libinfinity/common/inf-cert-util.c | 36 +++++++++++++++++++++ libinfinity/common/inf-cert-util.h | 4 +++ 3 files changed, 41 insertions(+) commit 5b9ad636f4e63ff5e042546b9a0b4b0e3ec3c10e Author: Armin Burgmeier Date: Mon Jan 13 14:07:11 2014 +0100 Fix a crash when accepted connection is immediately closed by remote In this case, getpeername() would fail, with an error of ENOTCONN. However, the code assumed getpeername() would never fail. This has been fixed in two ways now. First, the result of getpeername() is checked for errors. Second, in the case of accepting a connection, we use the result from accept() to find the peer's address, and no longer call getpeername(). This way, we avoid an error during getpeername() failing, and should receive a proper socket closure with the normal mechanism of send() or recv() returning 0. This bug was trigged by nmap scanning the infinoted port. Thanks to Rainer Rehak for spotting this! libinfinity/common/inf-tcp-connection-private.h | 2 + libinfinity/common/inf-tcp-connection.c | 126 ++++++++++++++-------- libinfinity/server/infd-tcp-server.c | 25 ++++- 3 files changed, 108 insertions(+), 45 deletions(-) commit d9d279084ce54c6491590f5990a0aa8e642a37d7 Author: Armin Burgmeier Date: Sun Jan 12 22:11:55 2014 +0100 Fix return value on success in inf_file_util_delete_single_directory() libinfinity/common/inf-file-util.c | 3 +++ 1 file changed, 3 insertions(+) commit 08e62706db5bfad35f26b09458c78f68e325f030 Author: Armin Burgmeier Date: Sun Jan 12 16:34:11 2014 +0100 Move infinoted-directory-sync into a plugin In addition, the plugin now also handles documents or directories removed on the server. Such files are now also removed from the sync-directory (#608). infinoted/Makefile.am | 3 - infinoted/infinoted-config-reload.c | 31 - infinoted/infinoted-directory-sync.c | 571 ----------------- infinoted/infinoted-directory-sync.h | 63 -- infinoted/infinoted-options.c | 90 --- infinoted/infinoted-options.h | 6 - infinoted/infinoted-run.c | 19 - infinoted/infinoted-run.h | 2 - infinoted/plugins/Makefile.am | 14 +- .../plugins/infinoted-plugin-directory-sync.c | 651 ++++++++++++++++++++ 10 files changed, 664 insertions(+), 786 deletions(-) commit dacaafd736f4e6c5f4630cbd462cc99a6b1b239e Author: Armin Burgmeier Date: Sat Jan 11 21:18:20 2014 +0100 Add file utility functions in inf-file-util These provide a platform abstraction for common file and directory operations, with convenient GError-based error reporting. .../libinfinity/libinfinity-0.6-docs.sgml | 3 +- .../libinfinity/libinfinity-0.6-sections.txt | 14 + infinoted/infinoted-util.c | 24 +- libinfinity/common/Makefile.am | 2 + libinfinity/common/inf-file-util.c | 511 ++++++++++++++++++++ libinfinity/common/inf-file-util.h | 99 ++++ libinfinity/server/infd-filesystem-storage.c | 363 +++----------- 7 files changed, 705 insertions(+), 311 deletions(-) commit 440356d89938ae028b221e8b1fdeeb49206df2ee Author: Armin Burgmeier Date: Sun Jan 12 15:08:19 2014 +0100 Remove an entry from the TODO list This has been implemented by now. TODO | 3 --- 1 file changed, 3 deletions(-) commit bd3be83625164fdd84f82d57a4384193d9a9fb21 Author: Armin Burgmeier Date: Sat Jan 11 21:18:32 2014 +0100 Fix missing return value in infinoted plugin initialize functions infinoted/plugins/infinoted-plugin-autosave.c | 4 +++- infinoted/plugins/infinoted-plugin-linekeeper.c | 2 ++ infinoted/plugins/infinoted-plugin-logging.c | 2 ++ infinoted/plugins/infinoted-plugin-transformation-protection.c | 2 ++ 4 files changed, 9 insertions(+), 1 deletion(-) commit 1982804c22d53a58f19d64be5768ae7b9bf4456f Author: Armin Burgmeier Date: Thu Jan 9 15:47:49 2014 +0100 Fix a crash when receiving cursor updates in quick succession In this case InfTextGtkView would install an idle handler for actual determination of the new cursor and selection areas without checking whether there was already an idle handler installed, leading to a possible crash on the second occasion when the user has been set inactive meanwhile, for example by the server unsubscribing the client. This can be artifically provoked by Ctrl+Zing infinoted with enabled transformation-protection plugin, making a couple of edits or cursor movements in a 2nd gobby, then making another edit in the first gobby, and then reviving the infinoted, so that it sends all updates immediately to the first gobby and unsubscribing it directly afterwirds because its own request exceeds the vdiff threshold of the transformation-protection plugin. libinftextgtk/inf-text-gtk-view.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) commit 027d4227963f014f8be841c1e9b5ff1f588649c2 Author: Armin Burgmeier Date: Thu Jan 9 15:05:08 2014 +0100 Turn the infinoted transformation protector into a plugin infinoted/Makefile.am | 6 +- infinoted/infinoted-config-reload.c | 26 -- infinoted/infinoted-options.c | 15 - infinoted/infinoted-options.h | 1 - infinoted/infinoted-run.c | 16 - infinoted/infinoted-run.h | 2 - infinoted/infinoted-transformation-protector.c | 334 -------------------- infinoted/infinoted-transformation-protector.h | 56 ---- infinoted/plugins/Makefile.am | 14 +- .../infinoted-plugin-transformation-protection.c | 251 +++++++++++++++ 10 files changed, 266 insertions(+), 455 deletions(-) commit 69ce937baff1860de371fd1bac099c595f097eab Author: Armin Burgmeier Date: Tue Jan 7 22:00:25 2014 +0100 Handle errors in input requests gracefully This handles the case when we receive an undo or redo request on the network without any request to be undone or redone, or if we receive a request which after transformation cannot be applied to the buffer, for example writing past the end of the document. .../libinfinity/libinfinity-0.6-sections.txt | 1 + .../libinftext/libinftext-0.6-sections.txt | 1 + libinfinity/adopted/inf-adopted-algorithm.c | 236 +++++++++++++++++--- libinfinity/adopted/inf-adopted-algorithm.h | 23 +- libinfinity/adopted/inf-adopted-no-operation.c | 6 +- libinfinity/adopted/inf-adopted-operation.c | 49 ++-- libinfinity/adopted/inf-adopted-operation.h | 18 +- libinfinity/adopted/inf-adopted-session.c | 152 +++++++++---- libinfinity/adopted/inf-adopted-split-operation.c | 60 +++-- libinftext/inf-text-default-delete-operation.c | 36 ++- libinftext/inf-text-default-insert-operation.c | 35 ++- libinftext/inf-text-move-operation.c | 39 +++- libinftext/inf-text-operations.h | 21 ++ libinftext/inf-text-remote-delete-operation.c | 54 +++-- libinftext/inf-text-session.c | 11 +- test/inf-test-text-operations.c | 135 ++++++++--- test/inf-test-text-replay.c | 4 +- 17 files changed, 678 insertions(+), 203 deletions(-) commit 20ceb27ad613c7cc3d4611a8b244bd76f20b4cd2 Author: Armin Burgmeier Date: Tue Jan 7 22:23:39 2014 +0100 Add some notes into the TODO file and InfTextChunk TODO | 1 + libinftext/inf-text-chunk.c | 9 ++++++--- 2 files changed, 7 insertions(+), 3 deletions(-) commit 6c282aa94e40f6606ba64454163c12c8d9a8d895 Author: Armin Burgmeier Date: Mon Jan 6 22:55:20 2014 +0100 Change InfAdoptedAlgorithm API such that execute_request is public This commit also gets rid of the obsolete "backward translation" option in InfAdoptedAlgorithm. .../libinfinity/libinfinity-0.6-sections.txt | 6 +- libinfinity/adopted/inf-adopted-algorithm.c | 970 +++++--------------- libinfinity/adopted/inf-adopted-algorithm.h | 19 +- libinfinity/adopted/inf-adopted-session.c | 194 +++- libinftext/inf-text-session.c | 15 +- 5 files changed, 423 insertions(+), 781 deletions(-) commit d4f209dff4208ea990acbd683772939825cb59fe Author: Armin Burgmeier Date: Tue Jan 7 10:30:14 2014 +0100 Fix a missing '\' in infinoted/Makefile.am infinoted/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 11f43d660095f58255ee999f9849bb4452fc9d80 Author: Armin Burgmeier Date: Sun Jan 5 15:02:30 2014 +0100 Replace execute-request by begin-execute-request and end-execute-request This allows to run the request execution not in the default signal handler of the execute-request signal, which we need for error reporting from request exeuction. However, we still need a possibility to hook into request execution both before and after the request was transformed. Therefore the two new signals have been introduced. This also allows to provide a different set of parameters for the two; in end-execute-request we now provide the result of the request execution, and also the reversible original request. There is also an error parameter already which will be used later when error reporting is implemented. infinoted/plugins/infinoted-plugin-logging.c | 95 ++-- libinfinity/adopted/inf-adopted-algorithm.c | 508 +++++++++++---------- libinfinity/adopted/inf-adopted-algorithm.h | 18 +- libinfinity/adopted/inf-adopted-session-record.c | 29 +- libinfinity/adopted/inf-adopted-session.c | 69 +-- libinfinity/adopted/inf-adopted-undo-grouping.c | 26 +- libinfinity/inf-marshal.in | 1 + test/inf-test-text-replay.c | 78 ++-- 8 files changed, 446 insertions(+), 378 deletions(-) commit bf7733152505e8b64ec3779b1508f1fada328c5c Author: Armin Burgmeier Date: Sun Jan 5 13:34:32 2014 +0100 Remove the InfAdoptedAlgorithm::apply-request signal This is a first step for proper error reporting from the algorithm. The resulting operation might not be applicable to the buffer if the input was invalid, and in order to report this the function should eventually be able to report the error. However, this is problematic if it only runs as a signal handler. Therefore, the signal has been removed. The signal was used in three places. In InfTextSession it was used to detect whether a buffer change was caused by an executed request or externally. This use has been replaced by the new inf_adopted_algorithm_get_execute_request() function. inf_adopted_algorithm_execute_request() is not re-entrant anyway, so that the introduction of this function does not cause a loss of generality. The other two cases are in the libinfinity test suite where they can easily be replaced by connecting to text-inserted and text-erased of the underlying buffer instead. libinfinity/adopted/inf-adopted-algorithm.c | 224 ++++++++++++-------------- libinfinity/adopted/inf-adopted-algorithm.h | 3 + libinftext/inf-text-session.c | 112 +++---------- test/inf-test-text-recover.c | 67 ++++---- test/inf-test-text-replay.c | 172 ++++++-------------- 5 files changed, 212 insertions(+), 366 deletions(-) commit c0e42798c7cae2802ec17de5b461adf78a2aecf6 Author: Armin Burgmeier Date: Mon Jan 6 21:15:35 2014 +0100 Make the infinoted plugin building work on Windows Unfortunately LIBADD does not seem to cause proper linking for all targets. Therefore, duplicate some code with the correct linking flags for each target until we find a better solution. infinoted/plugins/Makefile.am | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) commit e6a8723811525a43b2d12b85df06ce6b57fdf5b1 Author: Armin Burgmeier Date: Mon Jan 6 21:15:06 2014 +0100 Add infinoted-util to libinfinoted-plugin-manager infinoted/Makefile.am | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) commit 91e86f0e57e3c9c955bbd52979ad0b1c471197a4 Author: Armin Burgmeier Date: Mon Jan 6 21:14:37 2014 +0100 Fix the build without libdaemon infinoted/infinoted-options.c | 4 ++++ 1 file changed, 4 insertions(+) commit fbb0bb5f96d211cf38d6149589bab4f8d92c34fa Author: Armin Burgmeier Date: Sun Jan 5 12:50:33 2014 +0100 Make infinoted-transformation-protector use the check-request signal This avoids using the g_signal_stop_emission_by_name(), which is a rather rough method, and interferes with other users of the signal which rely on both the before and after handlers to run, such as InfinotedPluginLogging. infinoted/infinoted-transformation-protector.c | 43 ++++++++++-------------- 1 file changed, 18 insertions(+), 25 deletions(-) commit bc2fd7ec1de1862ae178b5094881e94d6e6d40d9 Author: Armin Burgmeier Date: Sun Jan 5 12:41:17 2014 +0100 Add the InfAdoptedSession::check-request signal libinfinity/adopted/inf-adopted-session.c | 92 ++++++++++++++++++++++++++++- libinfinity/adopted/inf-adopted-session.h | 10 +++- 2 files changed, 98 insertions(+), 4 deletions(-) commit 7fe494a28fbb34d3a8424face7c5cc216a4b5507 Author: Armin Burgmeier Date: Sun Jan 5 12:18:35 2014 +0100 Document the by_request parameter of inf_text_user_set_selection() libinftext/inf-text-user.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) commit 8c283cb64598ef7164b0b613a8379b1f7c0e6e6f Author: Armin Burgmeier Date: Sat Jan 4 17:43:19 2014 +0100 Add 2014 to copyright years AUTHORS | 2 +- infinoted/infinoted-config-reload.c | 2 +- infinoted/infinoted-config-reload.h | 2 +- infinoted/infinoted-dh-params.c | 2 +- infinoted/infinoted-dh-params.h | 2 +- infinoted/infinoted-directory-sync.c | 2 +- infinoted/infinoted-directory-sync.h | 2 +- infinoted/infinoted-log.c | 2 +- infinoted/infinoted-log.h | 2 +- infinoted/infinoted-main.c | 2 +- infinoted/infinoted-note-plugin.c | 2 +- infinoted/infinoted-note-plugin.h | 2 +- infinoted/infinoted-options.c | 2 +- infinoted/infinoted-options.h | 2 +- infinoted/infinoted-pam.c | 2 +- infinoted/infinoted-pam.h | 2 +- infinoted/infinoted-parameter.c | 2 +- infinoted/infinoted-parameter.h | 2 +- infinoted/infinoted-plugin-manager.c | 2 +- infinoted/infinoted-plugin-manager.h | 2 +- infinoted/infinoted-record.c | 2 +- infinoted/infinoted-record.h | 2 +- infinoted/infinoted-run.c | 2 +- infinoted/infinoted-run.h | 2 +- infinoted/infinoted-signal.c | 2 +- infinoted/infinoted-signal.h | 2 +- infinoted/infinoted-startup.c | 2 +- infinoted/infinoted-startup.h | 2 +- infinoted/infinoted-traffic-logger.c | 2 +- infinoted/infinoted-traffic-logger.h | 2 +- infinoted/infinoted-transformation-protector.c | 2 +- infinoted/infinoted-transformation-protector.h | 2 +- infinoted/infinoted-util.c | 2 +- infinoted/infinoted-util.h | 2 +- infinoted/note-plugins/chat/infd-note-plugin-chat.c | 2 +- infinoted/note-plugins/text/infd-note-plugin-text.c | 2 +- infinoted/plugins/infinoted-plugin-autosave.c | 2 +- infinoted/plugins/infinoted-plugin-linekeeper.c | 2 +- infinoted/plugins/infinoted-plugin-logging.c | 2 +- libinfgtk/inf-gtk-acl-sheet-view.c | 2 +- libinfgtk/inf-gtk-acl-sheet-view.h | 2 +- libinfgtk/inf-gtk-browser-model-filter.c | 2 +- libinfgtk/inf-gtk-browser-model-filter.h | 2 +- libinfgtk/inf-gtk-browser-model-sort.c | 2 +- libinfgtk/inf-gtk-browser-model-sort.h | 2 +- libinfgtk/inf-gtk-browser-model.c | 2 +- libinfgtk/inf-gtk-browser-model.h | 2 +- libinfgtk/inf-gtk-browser-store.c | 2 +- libinfgtk/inf-gtk-browser-store.h | 2 +- libinfgtk/inf-gtk-browser-view.c | 2 +- libinfgtk/inf-gtk-browser-view.h | 2 +- libinfgtk/inf-gtk-certificate-dialog.c | 2 +- libinfgtk/inf-gtk-certificate-dialog.h | 2 +- libinfgtk/inf-gtk-certificate-manager.c | 2 +- libinfgtk/inf-gtk-certificate-manager.h | 2 +- libinfgtk/inf-gtk-certificate-view.c | 2 +- libinfgtk/inf-gtk-certificate-view.h | 2 +- libinfgtk/inf-gtk-chat.c | 2 +- libinfgtk/inf-gtk-chat.h | 2 +- libinfgtk/inf-gtk-io.c | 2 +- libinfgtk/inf-gtk-io.h | 2 +- libinfgtk/inf-gtk-permissions-dialog.c | 2 +- libinfgtk/inf-gtk-permissions-dialog.h | 2 +- libinfinity/adopted/inf-adopted-algorithm.c | 2 +- libinfinity/adopted/inf-adopted-algorithm.h | 2 +- libinfinity/adopted/inf-adopted-no-operation.c | 2 +- libinfinity/adopted/inf-adopted-no-operation.h | 2 +- libinfinity/adopted/inf-adopted-operation.c | 2 +- libinfinity/adopted/inf-adopted-operation.h | 2 +- libinfinity/adopted/inf-adopted-request-log.c | 2 +- libinfinity/adopted/inf-adopted-request-log.h | 2 +- libinfinity/adopted/inf-adopted-request.c | 2 +- libinfinity/adopted/inf-adopted-request.h | 2 +- libinfinity/adopted/inf-adopted-session-record.c | 2 +- libinfinity/adopted/inf-adopted-session-record.h | 2 +- libinfinity/adopted/inf-adopted-session-replay.c | 2 +- libinfinity/adopted/inf-adopted-session-replay.h | 2 +- libinfinity/adopted/inf-adopted-session.c | 2 +- libinfinity/adopted/inf-adopted-session.h | 2 +- libinfinity/adopted/inf-adopted-split-operation.c | 2 +- libinfinity/adopted/inf-adopted-split-operation.h | 2 +- libinfinity/adopted/inf-adopted-state-vector.c | 2 +- libinfinity/adopted/inf-adopted-state-vector.h | 2 +- libinfinity/adopted/inf-adopted-undo-grouping.c | 2 +- libinfinity/adopted/inf-adopted-undo-grouping.h | 2 +- libinfinity/adopted/inf-adopted-user.c | 2 +- libinfinity/adopted/inf-adopted-user.h | 2 +- libinfinity/client/infc-acl-account-list-request.c | 2 +- libinfinity/client/infc-acl-account-list-request.h | 2 +- libinfinity/client/infc-browser.c | 2 +- libinfinity/client/infc-browser.h | 2 +- libinfinity/client/infc-certificate-request.c | 2 +- libinfinity/client/infc-certificate-request.h | 2 +- libinfinity/client/infc-chat-request.c | 2 +- libinfinity/client/infc-chat-request.h | 2 +- libinfinity/client/infc-explore-request.c | 2 +- libinfinity/client/infc-explore-request.h | 2 +- libinfinity/client/infc-node-request.c | 2 +- libinfinity/client/infc-node-request.h | 2 +- libinfinity/client/infc-note-plugin.h | 2 +- libinfinity/client/infc-request-manager.c | 2 +- libinfinity/client/infc-request-manager.h | 2 +- libinfinity/client/infc-request.c | 2 +- libinfinity/client/infc-request.h | 2 +- libinfinity/client/infc-session-proxy.c | 2 +- libinfinity/client/infc-session-proxy.h | 2 +- libinfinity/client/infc-user-request.c | 2 +- libinfinity/client/infc-user-request.h | 2 +- libinfinity/common/inf-acl-account-list-request.c | 2 +- libinfinity/common/inf-acl-account-list-request.h | 2 +- libinfinity/common/inf-acl.c | 2 +- libinfinity/common/inf-acl.h | 2 +- libinfinity/common/inf-browser-iter.c | 2 +- libinfinity/common/inf-browser-iter.h | 2 +- libinfinity/common/inf-browser.c | 2 +- libinfinity/common/inf-browser.h | 2 +- libinfinity/common/inf-buffer.c | 2 +- libinfinity/common/inf-buffer.h | 2 +- libinfinity/common/inf-cert-util.c | 2 +- libinfinity/common/inf-cert-util.h | 2 +- libinfinity/common/inf-certificate-chain.c | 2 +- libinfinity/common/inf-certificate-chain.h | 2 +- libinfinity/common/inf-certificate-credentials.c | 2 +- libinfinity/common/inf-certificate-credentials.h | 2 +- libinfinity/common/inf-chat-buffer.c | 2 +- libinfinity/common/inf-chat-buffer.h | 2 +- libinfinity/common/inf-chat-session.c | 2 +- libinfinity/common/inf-chat-session.h | 2 +- libinfinity/common/inf-discovery-avahi.c | 2 +- libinfinity/common/inf-discovery-avahi.h | 2 +- libinfinity/common/inf-discovery.c | 2 +- libinfinity/common/inf-discovery.h | 2 +- libinfinity/common/inf-error.c | 2 +- libinfinity/common/inf-error.h | 2 +- libinfinity/common/inf-explore-request.c | 2 +- libinfinity/common/inf-explore-request.h | 2 +- libinfinity/common/inf-init.c | 2 +- libinfinity/common/inf-init.h | 2 +- libinfinity/common/inf-io.c | 2 +- libinfinity/common/inf-io.h | 2 +- libinfinity/common/inf-ip-address.c | 2 +- libinfinity/common/inf-ip-address.h | 2 +- libinfinity/common/inf-local-publisher.c | 2 +- libinfinity/common/inf-local-publisher.h | 2 +- libinfinity/common/inf-node-request.c | 2 +- libinfinity/common/inf-node-request.h | 2 +- libinfinity/common/inf-protocol.c | 2 +- libinfinity/common/inf-protocol.h | 2 +- libinfinity/common/inf-request.c | 2 +- libinfinity/common/inf-request.h | 2 +- libinfinity/common/inf-sasl-context.c | 2 +- libinfinity/common/inf-sasl-context.h | 2 +- libinfinity/common/inf-session-proxy.c | 2 +- libinfinity/common/inf-session-proxy.h | 2 +- libinfinity/common/inf-session.c | 2 +- libinfinity/common/inf-session.h | 2 +- libinfinity/common/inf-simulated-connection.c | 2 +- libinfinity/common/inf-simulated-connection.h | 2 +- libinfinity/common/inf-standalone-io.c | 2 +- libinfinity/common/inf-standalone-io.h | 2 +- libinfinity/common/inf-tcp-connection-private.h | 2 +- libinfinity/common/inf-tcp-connection.c | 2 +- libinfinity/common/inf-tcp-connection.h | 2 +- libinfinity/common/inf-user-request.c | 2 +- libinfinity/common/inf-user-request.h | 2 +- libinfinity/common/inf-user-table.c | 2 +- libinfinity/common/inf-user-table.h | 2 +- libinfinity/common/inf-user.c | 2 +- libinfinity/common/inf-user.h | 2 +- libinfinity/common/inf-xml-connection.c | 2 +- libinfinity/common/inf-xml-connection.h | 2 +- libinfinity/common/inf-xml-util.c | 2 +- libinfinity/common/inf-xml-util.h | 2 +- libinfinity/common/inf-xmpp-connection.c | 2 +- libinfinity/common/inf-xmpp-connection.h | 2 +- libinfinity/common/inf-xmpp-manager.c | 2 +- libinfinity/common/inf-xmpp-manager.h | 2 +- libinfinity/communication/inf-communication-central-factory.c | 2 +- libinfinity/communication/inf-communication-central-factory.h | 2 +- libinfinity/communication/inf-communication-central-method.c | 2 +- libinfinity/communication/inf-communication-central-method.h | 2 +- libinfinity/communication/inf-communication-factory.c | 2 +- libinfinity/communication/inf-communication-factory.h | 2 +- libinfinity/communication/inf-communication-group-private.h | 2 +- libinfinity/communication/inf-communication-group.c | 2 +- libinfinity/communication/inf-communication-group.h | 2 +- libinfinity/communication/inf-communication-hosted-group.c | 2 +- libinfinity/communication/inf-communication-hosted-group.h | 2 +- libinfinity/communication/inf-communication-joined-group.c | 2 +- libinfinity/communication/inf-communication-joined-group.h | 2 +- libinfinity/communication/inf-communication-manager.c | 2 +- libinfinity/communication/inf-communication-manager.h | 2 +- libinfinity/communication/inf-communication-method.c | 2 +- libinfinity/communication/inf-communication-method.h | 2 +- libinfinity/communication/inf-communication-object.c | 2 +- libinfinity/communication/inf-communication-object.h | 2 +- libinfinity/communication/inf-communication-registry.c | 2 +- libinfinity/communication/inf-communication-registry.h | 2 +- libinfinity/inf-dll.c | 2 +- libinfinity/inf-dll.h | 2 +- libinfinity/inf-i18n.c | 2 +- libinfinity/inf-i18n.h | 2 +- libinfinity/inf-signals.c | 2 +- libinfinity/inf-signals.h | 2 +- libinfinity/server/infd-acl-account-info.c | 2 +- libinfinity/server/infd-acl-account-info.h | 2 +- libinfinity/server/infd-directory.c | 2 +- libinfinity/server/infd-directory.h | 2 +- libinfinity/server/infd-explore-request.c | 2 +- libinfinity/server/infd-explore-request.h | 2 +- libinfinity/server/infd-filesystem-storage.c | 2 +- libinfinity/server/infd-filesystem-storage.h | 2 +- libinfinity/server/infd-node-request.c | 2 +- libinfinity/server/infd-node-request.h | 2 +- libinfinity/server/infd-note-plugin.h | 2 +- libinfinity/server/infd-server-pool.c | 2 +- libinfinity/server/infd-server-pool.h | 2 +- libinfinity/server/infd-session-proxy.c | 2 +- libinfinity/server/infd-session-proxy.h | 2 +- libinfinity/server/infd-storage.c | 2 +- libinfinity/server/infd-storage.h | 2 +- libinfinity/server/infd-tcp-server.c | 2 +- libinfinity/server/infd-tcp-server.h | 2 +- libinfinity/server/infd-user-request.c | 2 +- libinfinity/server/infd-user-request.h | 2 +- libinfinity/server/infd-xml-server.c | 2 +- libinfinity/server/infd-xml-server.h | 2 +- libinfinity/server/infd-xmpp-server.c | 2 +- libinfinity/server/infd-xmpp-server.h | 2 +- libinftext/inf-text-buffer.c | 2 +- libinftext/inf-text-buffer.h | 2 +- libinftext/inf-text-chunk.c | 2 +- libinftext/inf-text-chunk.h | 2 +- libinftext/inf-text-default-buffer.c | 2 +- libinftext/inf-text-default-buffer.h | 2 +- libinftext/inf-text-default-delete-operation.c | 2 +- libinftext/inf-text-default-delete-operation.h | 2 +- libinftext/inf-text-default-insert-operation.c | 2 +- libinftext/inf-text-default-insert-operation.h | 2 +- libinftext/inf-text-delete-operation.c | 2 +- libinftext/inf-text-delete-operation.h | 2 +- libinftext/inf-text-insert-operation.c | 2 +- libinftext/inf-text-insert-operation.h | 2 +- libinftext/inf-text-move-operation.c | 2 +- libinftext/inf-text-move-operation.h | 2 +- libinftext/inf-text-operations.h | 2 +- libinftext/inf-text-remote-delete-operation.c | 2 +- libinftext/inf-text-remote-delete-operation.h | 2 +- libinftext/inf-text-session.c | 2 +- libinftext/inf-text-session.h | 2 +- libinftext/inf-text-undo-grouping.c | 2 +- libinftext/inf-text-undo-grouping.h | 2 +- libinftext/inf-text-user.c | 2 +- libinftext/inf-text-user.h | 2 +- libinftextgtk/inf-text-gtk-buffer.c | 2 +- libinftextgtk/inf-text-gtk-buffer.h | 2 +- libinftextgtk/inf-text-gtk-hue-chooser.c | 2 +- libinftextgtk/inf-text-gtk-hue-chooser.h | 2 +- libinftextgtk/inf-text-gtk-view.c | 2 +- libinftextgtk/inf-text-gtk-view.h | 2 +- libinftextgtk/inf-text-gtk-viewport.c | 2 +- libinftextgtk/inf-text-gtk-viewport.h | 2 +- test/inf-test-browser.c | 2 +- test/inf-test-certificate-request.c | 2 +- test/inf-test-chat.c | 2 +- test/inf-test-chunk.c | 2 +- test/inf-test-daemon.c | 2 +- test/inf-test-gtk-browser.c | 2 +- test/inf-test-mass-join.c | 2 +- test/inf-test-reduce-replay.c | 2 +- test/inf-test-set-acl.c | 2 +- test/inf-test-state-vector.c | 2 +- test/inf-test-tcp-connection.c | 2 +- test/inf-test-tcp-server.c | 2 +- test/inf-test-text-cleanup.c | 2 +- test/inf-test-text-operations.c | 2 +- test/inf-test-text-recover.c | 2 +- test/inf-test-text-replay.c | 2 +- test/inf-test-text-session.c | 2 +- test/inf-test-xmpp-connection.c | 2 +- test/inf-test-xmpp-server.c | 2 +- test/util/inf-test-util.c | 2 +- test/util/inf-test-util.h | 2 +- 283 files changed, 283 insertions(+), 283 deletions(-) commit 85ff3057f03a3106095ef5bc7fa7a0c328e68294 Author: Armin Burgmeier Date: Sat Jan 4 17:38:34 2014 +0100 Simplify plugin initialize function Only pass the plugin manager itself to the initialize function, and add functions in the plugin manager to retrieve the InfinotedLog and the InfdDirectory. This way plugins only need to store one pointer to access all functionality. infinoted/infinoted-plugin-manager.c | 37 ++++++++++++++++++----- infinoted/infinoted-plugin-manager.h | 8 +++-- infinoted/plugins/infinoted-plugin-autosave.c | 30 ++++++++---------- infinoted/plugins/infinoted-plugin-linekeeper.c | 32 +++++++++++--------- infinoted/plugins/infinoted-plugin-logging.c | 28 ++++++----------- 5 files changed, 74 insertions(+), 61 deletions(-) commit bf5d68e03ed84a8886b2619e4b20c6284e041195 Author: Armin Burgmeier Date: Sat Jan 4 17:12:56 2014 +0100 Add logging plugin This adds back the functionality removed when InfinotedLog was refactored, as a plugin. infinoted/infinoted-record.c | 2 + infinoted/plugins/Makefile.am | 13 +- infinoted/plugins/infinoted-plugin-logging.c | 645 +++++++++++++++++++++++++ 3 files changed, 657 insertions(+), 3 deletions(-) commit 7a4f805e3e1781222756dff0fb2421121f7f5af9 Author: Armin Burgmeier Date: Sat Jan 4 17:25:08 2014 +0100 Fix a typo in infinoted_plugin_manager_get_session_info() infinoted/infinoted-plugin-manager.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit b59fda0f3da2d764c76b6e681ff4967dacb89a20 Author: Armin Burgmeier Date: Sat Jan 4 16:30:03 2014 +0100 Add boolean type for InfinotedParameterInfo infinoted/infinoted-options.c | 53 +++++++++++++++++++++++++++++++++++++++ infinoted/infinoted-options.h | 1 + infinoted/infinoted-parameter.c | 36 ++++++++++++++++++++++++++ infinoted/infinoted-parameter.h | 7 ++++++ 4 files changed, 97 insertions(+) commit 8a9cebbe4865f027229119135e67da744cba12c7 Author: Armin Burgmeier Date: Sat Jan 4 16:29:54 2014 +0100 Add generic infinoted_log_log function infinoted/infinoted-log.c | 35 ++++++++++++++++++++++++++++++++--- infinoted/infinoted-log.h | 6 ++++++ 2 files changed, 38 insertions(+), 3 deletions(-) commit 2a87f288d0ee45b4da3fa932d85a90dcc4566b4e Author: Armin Burgmeier Date: Fri Jan 3 23:51:54 2014 +0100 Use InfinotedLog for logging messages from plugins infinoted/infinoted-config-reload.c | 1 + infinoted/infinoted-plugin-manager.c | 6 ++++++ infinoted/infinoted-plugin-manager.h | 10 +++++++--- infinoted/infinoted-run.c | 1 + infinoted/plugins/infinoted-plugin-autosave.c | 16 ++++++++++++---- infinoted/plugins/infinoted-plugin-linekeeper.c | 11 ++++++++--- 6 files changed, 35 insertions(+), 10 deletions(-) commit 7c7a99494eee88a93f841de3d0d7c2378ca89a0c Author: Armin Burgmeier Date: Fri Jan 3 23:41:49 2014 +0100 Build InfinotedLog as part of libinfinoted-plugin-manager So that plugins are able to use InfinotedLog infinoted/Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit 64fa02f0dd84ba6a727daf62c8497bb7df2379a5 Author: Armin Burgmeier Date: Fri Jan 3 22:27:19 2014 +0100 Turn InfinotedLog into a GObject with only basic functionality The plan is to add the additional functionality (logging when connections come in and on connection and session errors) as plugins. infinoted/infinoted-config-reload.c | 4 - infinoted/infinoted-log.c | 1009 +++++++--------------- infinoted/infinoted-log.h | 87 +- infinoted/infinoted-run.c | 10 - infinoted/infinoted-startup.c | 6 +- infinoted/infinoted-transformation-protector.c | 4 + libinfinity/common/inf-session.c | 2 +- libinfinity/inf-marshal.in | 1 + 8 files changed, 381 insertions(+), 742 deletions(-) commit b3b9d9c86eccd51b0722c584be0d93dfb3181912 Author: Armin Burgmeier Date: Mon Dec 30 22:31:28 2013 +0100 Move infinoted autosave support into a plugin infinoted/Makefile.am | 2 - infinoted/infinoted-autosave.c | 475 ------------------------ infinoted/infinoted-autosave.h | 52 --- infinoted/infinoted-config-reload.c | 22 -- infinoted/infinoted-options.c | 39 -- infinoted/infinoted-options.h | 2 - infinoted/infinoted-run.c | 15 - infinoted/infinoted-run.h | 2 - infinoted/plugins/Makefile.am | 11 +- infinoted/plugins/infinoted-plugin-autosave.c | 364 ++++++++++++++++++ 10 files changed, 371 insertions(+), 613 deletions(-) commit 7f3023a36586c155df63f2fb312d67235bf4b606 Author: Armin Burgmeier Date: Mon Dec 30 22:12:25 2013 +0100 Rename "interval" convert func to "nonnegative", add "positive" infinoted/infinoted-options.c | 6 +-- infinoted/infinoted-parameter.c | 48 +++++++++++++++++++++-- infinoted/infinoted-parameter.h | 7 +++- infinoted/plugins/infinoted-plugin-linekeeper.c | 2 +- 4 files changed, 54 insertions(+), 9 deletions(-) commit d80defa2fb532fd2d4fe83ad41990bb11cdeecd1 Author: Armin Burgmeier Date: Mon Dec 30 21:40:50 2013 +0100 Add InfBrowserIter parameter to session callbacks in infinoted plugins infinoted/infinoted-plugin-manager.c | 25 ++++++++++++++++++++--- infinoted/infinoted-plugin-manager.h | 6 ++++-- infinoted/plugins/infinoted-plugin-linekeeper.c | 6 ++++-- 3 files changed, 30 insertions(+), 7 deletions(-) commit 914595e2096196522c76a0c7c94124265e82c325 Author: Armin Burgmeier Date: Sat Dec 28 23:30:31 2013 +0100 Add the "linekeeper" infinoted plugin This plugin makes sure that at the end of the document there is always a fixed number of empty lines. configure.ac | 1 + infinoted/Makefile.am | 2 +- infinoted/plugins/Makefile.am | 22 ++ infinoted/plugins/infinoted-plugin-linekeeper.c | 379 ++++++++++++++++++++++ 4 files changed, 403 insertions(+), 1 deletion(-) commit 1b1ff9424bba1b58dba6a4f8ebbd8d943fb62f60 Author: Armin Burgmeier Date: Sat Dec 28 21:48:28 2013 +0100 Add the possibility to get an iterator at the end of the buffer .../libinftext/libinftext-0.6-sections.txt | 6 ++-- .../note-plugins/text/infd-note-plugin-text.c | 2 +- libinftext/inf-text-buffer.c | 39 ++++++++++++++++++--- libinftext/inf-text-buffer.h | 9 +++-- libinftext/inf-text-chunk.c | 37 +++++++++++++++++-- libinftext/inf-text-chunk.h | 14 +++++--- libinftext/inf-text-default-buffer.c | 27 ++++++++++++-- libinftext/inf-text-session.c | 6 ++-- libinftext/inf-text-undo-grouping.c | 2 +- libinftextgtk/inf-text-gtk-buffer.c | 35 ++++++++++++++++-- test/inf-test-text-replay.c | 4 +-- 11 files changed, 151 insertions(+), 30 deletions(-) commit c13c9d9a65e25257615b0912e3006a4894bcad35 Author: Armin Burgmeier Date: Sat Dec 28 21:47:49 2013 +0100 Fix a crash when checking can-join-user ACL for local user join libinfinity/server/infd-directory.c | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) commit c167cda81ec35cf57bfac5dea6e430bec0f04ad3 Author: Armin Burgmeier Date: Sat Dec 28 16:35:21 2013 +0100 Fix a stray reference in InfSession This would add an extra reference that is never unreferenced if the communication manager was set after sync connection and sync group, which practically never happens. Basically it was a bug in dead code. libinfinity/common/inf-session.c | 20 -------------------- 1 file changed, 20 deletions(-) commit 4892fb8d20262ce5e6f0e9fe82c1ed72c8dc7875 Author: Armin Burgmeier Date: Wed Dec 18 16:51:35 2013 +0100 Move infinoted-parameter.c to libinfinoted-plugin-manager This allows plugins to use parameter parsing. Also, add a flags field for InfinotedParameterInfo, allowing individual options to be required, i.e. error out on loading if the parameter is not specified. infinoted/Makefile.am | 4 ++-- infinoted/infinoted-options.c | 24 +++++++++++++++++++- infinoted/infinoted-parameter.c | 31 +++++++++++++++++++------- infinoted/infinoted-parameter.h | 11 +++++++--- infinoted/infinoted-plugin-manager.c | 40 ++++++++++++++++++++++++++++++++-- infinoted/infinoted-plugin-manager.h | 15 +++++++++++-- 6 files changed, 107 insertions(+), 18 deletions(-) commit d3a56cbbb63e339de77615aa72c594630eb40784 Author: Armin Burgmeier Date: Wed Dec 18 15:28:13 2013 +0100 Add generic plugin system This allows to implement some special not-so-common functions as plugins, mostly helping in keeping the core infinoted code clean and maintainable. Features I have in mind for changing into a plugin are: autosave, directory-sync, transformation-protector, session recording, directory logging, traffic logging, and maybe also password, PAM and/or certificate authentication. infinoted/Makefile.am | 35 +- infinoted/infinoted-config-reload.c | 46 +++ infinoted/infinoted-options.c | 127 +++++- infinoted/infinoted-options.h | 9 + infinoted/infinoted-plugin-manager.c | 696 +++++++++++++++++++++++++++++++++ infinoted/infinoted-plugin-manager.h | 115 ++++++ infinoted/infinoted-run.c | 45 ++- infinoted/infinoted-run.h | 3 + 8 files changed, 1064 insertions(+), 12 deletions(-) commit ee7284589a1c7701093a67a98a8b0b75753c3526 Author: Armin Burgmeier Date: Thu Dec 19 12:05:54 2013 +0100 Allow request functions to finish synchronously This adds two additional arguments to all functions, which is the callback function for the finished signal. The functions now work such that they either return a request object with the given function connected to the finished handler, or they return NULL in which case they must have called the given function during their invocation. This simplifies the implementation on the server side a lot, since requests do not need to be artificially delayed any longer. Also, using the API is a a bit simpler since in many cases one does not need to use the request object anymore at all. libinfgtk/inf-gtk-browser-view.c | 59 +- libinfgtk/inf-gtk-permissions-dialog.c | 86 +- libinfinity/client/infc-browser.c | 88 +- libinfinity/client/infc-browser.h | 10 +- libinfinity/client/infc-certificate-request.c | 2 +- libinfinity/client/infc-certificate-request.h | 14 + libinfinity/client/infc-chat-request.h | 12 + libinfinity/client/infc-request-manager.c | 30 +- libinfinity/client/infc-request-manager.h | 4 + libinfinity/client/infc-session-proxy.c | 6 +- libinfinity/common/inf-acl-account-list-request.h | 12 + libinfinity/common/inf-browser.c | 115 +- libinfinity/common/inf-browser.h | 65 +- libinfinity/common/inf-node-request.c | 2 +- libinfinity/common/inf-node-request.h | 18 +- libinfinity/common/inf-session-proxy.c | 16 +- libinfinity/common/inf-session-proxy.h | 8 +- libinfinity/common/inf-user-request.h | 14 + libinfinity/server/infd-directory.c | 1392 ++++++------------- libinfinity/server/infd-session-proxy.c | 212 +-- libinftext/inf-text-session.c | 14 +- libinftext/inf-text-session.h | 4 +- test/inf-test-browser.c | 15 +- test/inf-test-certificate-request.c | 15 +- test/inf-test-chat.c | 36 +- test/inf-test-gtk-browser.c | 85 +- test/inf-test-mass-join.c | 48 +- test/inf-test-set-acl.c | 31 +- 28 files changed, 1050 insertions(+), 1363 deletions(-) commit dde5cc2ae929f148d38834cd4d48e0ac11c597e2 Author: Armin Burgmeier Date: Tue Dec 17 15:56:46 2013 +0100 Update autogen.sh from current gnome-autogen.sh autogen.sh | 97 ++++++++++++++++++++++++++++++++++++++-------------------- configure.ac | 1 + 2 files changed, 65 insertions(+), 33 deletions(-) commit 1abf4945a9309b4ee896f604e78a47e7abd4708e Author: Armin Burgmeier Date: Tue Dec 17 15:54:27 2013 +0100 Factor out some common API from InfinotedOptions to InfinotedParameter This is another preparation step for the plugin system. This provides a common API for plugins to read their configuration values from the infinoted configuration file. infinoted/Makefile.am | 2 + infinoted/infinoted-options.c | 555 +++++++------------------------------- infinoted/infinoted-options.h | 3 - infinoted/infinoted-parameter.c | 508 ++++++++++++++++++++++++++++++++++ infinoted/infinoted-parameter.h | 126 +++++++++ 5 files changed, 731 insertions(+), 463 deletions(-) commit ea3daa87be97aa2cbabb5e28911c96326e5dd18b Author: Armin Burgmeier Date: Tue Dec 17 14:11:14 2013 +0100 Refactor infinoted option parsing This was made having in mind introduction of generic infinoted plugins. The parsing is now arranged such that in the end there is one GKeyFile from which all options are read. Also, the configuration file to load can now be specified on the command line, and the --help output is more useful. infinoted/infinoted-options.c | 1532 ++++++++++++++++++++++++--------------- infinoted/infinoted-options.h | 7 +- infinoted/infinoted-run.h | 1 + infinoted/infinoted-startup.c | 4 +- 4 files changed, 935 insertions(+), 609 deletions(-) commit 7472ca0763386af8d6ebc38cfd8d377be7ec64c3 Author: Armin Burgmeier Date: Wed Dec 11 11:54:41 2013 +0100 Fix restoring of ACLs after server restart libinfinity/server/infd-directory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 2a872f06e336a707e48b999ed85bff902aea6d79 Author: Armin Burgmeier Date: Wed Dec 11 11:35:33 2013 +0100 Do not evaluate account and ACL files when reading subdirectory from disk libinfinity/server/infd-filesystem-storage.c | 42 ++++++++++++++++---------- 1 file changed, 26 insertions(+), 16 deletions(-) commit b1eb1dc5113e3f7c9cfd0ceae749b09a25781e02 Author: Armin Burgmeier Date: Sun Nov 17 15:39:46 2013 +0100 inf_adopted_request_log_original_request: Return given request for DO requests This fixes transforming the move request that InfTextUndoGrouping uses to determine whether to group two requests or not with the new algorithm. libinfinity/adopted/inf-adopted-request-log.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) commit d1ded09f5c266f18ddfffcc678c0fc878e5c369d Author: Armin Burgmeier Date: Sun Nov 17 16:03:26 2013 +0100 Use "forward translation" in InfAdoptedAlgorithm This makes it possible to apply the mirror operation as late as possible during a translation. Also, add a test case which failed before due to this not being the case (test-55.xml). This also simplifies the implementation of the adOPTed algorithm quite a bit. At the moment the old implementation is still available and can be switched back on. This is mostly for reference -- one of the new tests will fail with the old implementation. Unfortunately, there is also a performance impact with the new algorithm. inf-test-text-session runs 30-40% slower. I hope this can be optimized more later, and is another reason to keep the old algorithm still in place, so that the two can easily be benchmarked against each other. Also, replay-09.xml has been removed. This replay will fail with the new algorithm. However, this is not an issue of the new algorithm, but rather that the record was taken with the old algorithm, and therefore transformations have been carried out incorrectly. The new algorithm carries them out correctly, ends up in a different document state, and cannot play the rest of the record. libinfinity/adopted/inf-adopted-algorithm.c | 181 +- test/replay/replay-09.record.xml | 26366 ------------------------ test/session/test-55.xml | 34 + test/session/test-56.xml | 34 + test/session/test-57.xml | 24 + 5 files changed, 271 insertions(+), 26368 deletions(-) commit 68c9d3c6aad7f3ce106211253dc2e92b83e36e00 Author: Armin Burgmeier Date: Sun Nov 17 15:39:20 2013 +0100 Use inf_adopted_request_get_index() in InfTextUndoGrouping It makes the code a bit more readable. libinftext/inf-text-undo-grouping.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 0a9981042cd494b982982a65db528fef788cd20f Author: Armin Burgmeier Date: Sun Nov 17 12:32:11 2013 +0100 inf-test-reduce-replay: also catch SIGTRAP of the child process test/inf-test-reduce-replay.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) commit 562e3fcacb3e44d6aa47aa714a9be62d56a29379 Author: Armin Burgmeier Date: Sun Nov 17 12:03:33 2013 +0100 Don't assert at unknown operation type in inf_test_util_print_operation() test/util/inf-test-util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 5e6ad16039595d1062e6c04b044ed500adafc1a6 Author: Armin Burgmeier Date: Sun Nov 17 12:01:13 2013 +0100 Fix a typo in documentation of inf_adopted_request_log_prev_associated() libinfinity/adopted/inf-adopted-request-log.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 3aa1e7d3b9be3c7fe81eff66bb3520588b57890c Author: Armin Burgmeier Date: Fri Aug 30 16:43:02 2013 +0200 Make InfAdoptedSplitOperation fulfill the C2 transformation property libinfinity/adopted/Makefile.am | 4 - libinfinity/adopted/inf-adopted-algorithm.c | 20 +- .../adopted/inf-adopted-concurrency-warning.c | 41 --- .../adopted/inf-adopted-concurrency-warning.h | 35 --- libinfinity/adopted/inf-adopted-no-operation.c | 12 +- libinfinity/adopted/inf-adopted-operation.c | 102 +++----- libinfinity/adopted/inf-adopted-operation.h | 12 +- libinfinity/adopted/inf-adopted-request.c | 161 +++++------- libinfinity/adopted/inf-adopted-request.h | 7 +- libinfinity/adopted/inf-adopted-split-operation.c | 160 +++++++++--- libinfinity/adopted/inf-adopted-split-operation.h | 2 + libinftext/inf-text-default-delete-operation.c | 23 +- libinftext/inf-text-default-insert-operation.c | 28 +- libinftext/inf-text-delete-operation.c | 37 +-- libinftext/inf-text-delete-operation.h | 10 +- libinftext/inf-text-insert-operation.c | 98 +++---- libinftext/inf-text-insert-operation.h | 9 +- libinftext/inf-text-move-operation.c | 13 +- libinftext/inf-text-remote-delete-operation.c | 23 +- test/inf-test-text-operations.c | 272 +++++--------------- 20 files changed, 373 insertions(+), 696 deletions(-) commit 2fe9d50775196be4152460678d745637957ca76c Author: Armin Burgmeier Date: Wed Aug 21 17:28:13 2013 +0200 Operations in InfAdoptedSplitOperation are now one after each other This defines the two operations in an InfAdoptedSplitOperation to be executed one after each other, not anymore both operations at the same state. This makes applying the split operation to the buffer straight forward, and no internal concurrency ID would be needed to decide what to do when there are two insert operations at the same position. This fixes #610. Also, add a test and a replay reproducing the problem. libinfinity/adopted/inf-adopted-split-operation.c | 87 +- libinftext/inf-text-default-delete-operation.c | 2 +- libinftext/inf-text-remote-delete-operation.c | 12 +- test/inf-test-text-operations.c | 37 +- test/inf-test-text-replay.c | 10 +- test/replay/replay-13.record.xml | 6916 +++++++++++++++++++ test/session/test-54.xml | 37 + 7 files changed, 7040 insertions(+), 61 deletions(-) commit d346e7af637892bb7f1bf72b40424b3c3347e512 Author: Armin Burgmeier Date: Fri Aug 23 12:57:16 2013 +0200 Replace make_reversible vfunc by apply_transformed vfunc This is another step for fixing #610. The two proceduces of making an operation reversible and applying it to the buffer are now performed by a single function, inf_adopted_operation_apply_transformed(). libinfinity/adopted/inf-adopted-algorithm.c | 34 ++--- libinfinity/adopted/inf-adopted-no-operation.c | 4 +- libinfinity/adopted/inf-adopted-operation.c | 133 +++++++++++++------- libinfinity/adopted/inf-adopted-operation.h | 34 ++--- libinfinity/adopted/inf-adopted-split-operation.c | 108 +++++++++++----- libinftext/inf-text-default-delete-operation.c | 3 +- libinftext/inf-text-default-insert-operation.c | 3 +- libinftext/inf-text-move-operation.c | 22 +--- libinftext/inf-text-remote-delete-operation.c | 27 ++-- 9 files changed, 215 insertions(+), 153 deletions(-) commit 4f666fee58db3fa2463d16aa62aac2214058965d Author: Armin Burgmeier Date: Thu Aug 22 16:01:49 2013 +0200 Make the original operation reversible inside apply-request This is a first step to fix #610. For the fix I have in mind we will need to create the reversible operation when applying the operation to the buffer. libinfinity/adopted/inf-adopted-algorithm.c | 183 ++++++++++++++++---------- libinfinity/adopted/inf-adopted-algorithm.h | 3 +- libinfinity/inf-marshal.in | 1 + libinftext/inf-text-session.c | 2 + test/inf-test-text-recover.c | 7 +- test/inf-test-text-replay.c | 2 + 6 files changed, 128 insertions(+), 70 deletions(-) commit a89ea37e3520207035a4030ffee1a6a4feee61da Author: Armin Burgmeier Date: Wed Aug 21 16:58:52 2013 +0200 Test split operations explicitely in inf-test-text-operations Right now, one of them fails the undo test, and another one causes a crash. test/inf-test-text-operations.c | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) commit 8bd3e23d0bde5b054e3956b8121c7774d79edb10 Author: Armin Burgmeier Date: Wed Aug 21 16:58:14 2013 +0200 Perform a basic Undo test in inf-test-text-operations This checks whether the example document remains the same when applying the operation and its inverse consecutively. test/inf-test-text-operations.c | 103 +++++++++++++++++++++++++++++++++++++- 1 file changed, 101 insertions(+), 2 deletions(-) commit 60c42982bd04ecc0d53fbc00b4f84aa280ce5945 Author: Armin Burgmeier Date: Wed Aug 21 11:54:41 2013 +0200 Validate correctly concurrency situations in inf-test-reduce-replay Since we are deleting all sync requests, it can happen that remaining session requests would depend on deleted ones in concurrent situations. This situation is now detected as invalid. test/inf-test-reduce-replay.c | 264 ++++++++++++++++++++++++++++++++++------ 1 file changed, 224 insertions(+), 40 deletions(-) commit dca689aeadf0b18c1d09d14df95d66cb0d49a59d Author: Armin Burgmeier Date: Tue Aug 20 12:14:14 2013 +0200 Add some more TODO notes TODO | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) commit a8719920ce827361f1f8a118ac79ee6fc13ee02d Author: Armin Burgmeier Date: Tue Aug 20 12:13:21 2013 +0200 Break the codeflow when a server sent a certificate the client did not request libinfinity/client/infc-browser.c | 2 ++ 1 file changed, 2 insertions(+) commit 57b19fcd016e6b385314a302936f61e225cb7be5 Author: Armin Burgmeier Date: Tue Aug 20 12:08:22 2013 +0200 Fix possible undefined behaviour in inf_cert_util_copy_certificate() libinfinity/common/inf-cert-util.c | 1 + 1 file changed, 1 insertion(+) commit 58f0f1b8f9e37be5e60cf20a794cdcd96c287058 Author: Armin Burgmeier Date: Sun Aug 18 21:31:54 2013 +0200 Set the activation time of newly generated certificate a bit in the past This is so that if the client verifies the certificate immediately and has its clock slightly offset it does not find the certificate invalid because its activation time has not started yet. libinfinity/server/infd-directory.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) commit 4ae6d7267075e52a82dceb022da38d8b90175398 Author: Armin Burgmeier Date: Sun Aug 18 13:33:43 2013 +0200 Document InfAdoptedUser and InfStandaloneIo libinfinity/adopted/inf-adopted-user.c | 17 +++++++++++++++++ libinfinity/common/inf-standalone-io.c | 22 ++++++++++++++++++++++ libinfinity/common/inf-standalone-io.h | 13 +++++++++++++ libinfinity/common/inf-user.c | 1 - 4 files changed, 52 insertions(+), 1 deletion(-) commit 210a7ade528e0ec119bf4c740ab3989e00f69b35 Author: Armin Burgmeier Date: Sun Aug 18 13:17:17 2013 +0200 Fix uninitialized variables in infinote server code infinoted/note-plugins/chat/infd-note-plugin-chat.c | 2 ++ libinfinity/server/infd-directory.c | 1 + 2 files changed, 3 insertions(+) commit 380beb0c5700c031f554e750816c220ccc8f41a3 Author: Armin Burgmeier Date: Mon Aug 12 12:06:14 2013 +0200 Watch notify::subscription-group instead of close for session detach The reason is that when the session is closed, the subscription group is reset as well in any case. This is being done by the default handler of the InfSession::close signal. However, there are other occurences where the subscription can be lost, for example if the server forcibly removes the subscription with infd_session_proxy_unsubscribe(). If that happens, we also want to detach the session from the browser, so that the client can try to re-subscribe. The old session with lost subscription is kep alive, however, so that it can be used for other purposes, such as for a sync-in on another node. The documentation of the InfBrowser::unsubscribe-session has also been changed to describe its meaning more explicitly. libinfinity/client/infc-browser.c | 125 +++++++++++++++++++----------------- libinfinity/common/inf-browser.c | 16 ++++- 2 files changed, 80 insertions(+), 61 deletions(-) commit ccb2a691554741f92951762f23aeb14f7e5ffd26 Author: Armin Burgmeier Date: Mon Aug 12 12:05:10 2013 +0200 Keep the InfcSessionProxy object always consistent when releasing connection libinfinity/client/infc-session-proxy.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) commit 511a81f3f81ed5dffbc447dffec17c0cd8b20cf9 Author: Armin Burgmeier Date: Sun Aug 11 22:25:58 2013 +0200 Fix a memory leak when reading text sessions from disk The buffer and user table were not unref'ed either at failure or at success. Even at success the session makes a new reference on the objects, so we have to unref them for the buffer and user table to be finalized eventually. infinoted/note-plugins/text/infd-note-plugin-text.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) commit 7ed7f593f5db2a6e5c0cccefee26e8aebfa7fc02 Author: Armin Burgmeier Date: Sun Aug 11 22:20:45 2013 +0200 Fix a couple of compiler warnings infinoted/infinoted-run.c | 3 +-- libinfinity/adopted/inf-adopted-request.c | 2 +- libinfinity/common/inf-browser.c | 2 ++ libinfinity/communication/inf-communication-registry.c | 1 + 4 files changed, 5 insertions(+), 3 deletions(-) commit 5ff938541b828de03fa37032eac06020669d168b Author: Armin Burgmeier Date: Sun Aug 11 22:10:37 2013 +0200 Add InfChat note plugin for infinoted configure.ac | 1 + infinoted/note-plugins/Makefile.am | 2 +- infinoted/note-plugins/chat/Makefile.am | 20 ++ .../note-plugins/chat/infd-note-plugin-chat.c | 231 ++++++++++++++++++++ 4 files changed, 253 insertions(+), 1 deletion(-) commit 0af3d3d83a3031cff71eecfe91b33e678aed6530 Author: Armin Burgmeier Date: Sun Aug 11 15:57:27 2013 +0200 Rework the ACL implementation It is now possible to associate more than one certificate to an account, and some basic functionality for other login procedures, such as password-based authentication. There are also some other internal reworkings. .../libinfinity/libinfinity-0.6-docs.sgml | 7 +- .../libinfinity/libinfinity-0.6-sections.txt | 109 +- libinfgtk/inf-gtk-acl-sheet-view.c | 92 +- libinfgtk/inf-gtk-acl-sheet-view.h | 6 +- libinfgtk/inf-gtk-permissions-dialog.c | 150 +-- libinfinity/client/Makefile.am | 4 +- .../client/infc-acl-account-list-request.c | 345 +++++ .../client/infc-acl-account-list-request.h | 75 ++ libinfinity/client/infc-acl-user-list-request.c | 344 ----- libinfinity/client/infc-acl-user-list-request.h | 74 -- libinfinity/client/infc-browser.c | 396 +++--- libinfinity/common/Makefile.am | 10 +- ...t-request.c => inf-acl-account-list-request.c} | 84 +- libinfinity/common/inf-acl-account-list-request.h | 70 + libinfinity/common/inf-acl-sheet.c | 701 ---------- libinfinity/common/inf-acl-sheet.h | 209 --- libinfinity/common/inf-acl-table.c | 901 ------------- libinfinity/common/inf-acl-table.h | 146 --- libinfinity/common/inf-acl-user-list-request.h | 70 - libinfinity/common/inf-acl.c | 1282 +++++++++++++++++++ libinfinity/common/inf-acl.h | 289 +++++ libinfinity/common/inf-browser.c | 240 ++-- libinfinity/common/inf-browser.h | 70 +- libinfinity/common/inf-error.c | 6 +- libinfinity/common/inf-error.h | 9 +- libinfinity/server/Makefile.am | 2 + libinfinity/server/infd-acl-account-info.c | 680 ++++++++++ libinfinity/server/infd-acl-account-info.h | 101 ++ libinfinity/server/infd-directory.c | 915 ++++++++----- libinfinity/server/infd-directory.h | 7 +- libinfinity/server/infd-filesystem-storage.c | 93 +- libinfinity/server/infd-storage.c | 57 +- libinfinity/server/infd-storage.h | 42 +- test/inf-test-set-acl.c | 62 +- 34 files changed, 4205 insertions(+), 3443 deletions(-) commit bc1b8f41cc3b8d3e26681e9f86240248a71337be Author: Armin Burgmeier Date: Sun Aug 11 13:59:57 2013 +0200 Ignore everything the remote side sends while waiting for Since the communication channel is full-duplex, it can happen that the remote side sends more data before it receives our request to close the connection and eventually acknowledges it. libinfinity/common/inf-xmpp-connection.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) commit 5b68ef7efd453670435739c997af3cd50ea89e99 Author: Armin Burgmeier Date: Tue Aug 6 09:27:35 2013 +0200 Add INF_ACL_CAN_JOIN_USER permission libinfinity/adopted/inf-adopted-session-replay.c | 13 ++- libinfinity/client/infc-session-proxy.c | 16 ++- libinfinity/common/inf-acl-sheet.c | 4 + libinfinity/common/inf-acl-sheet.h | 8 +- libinfinity/common/inf-session.c | 37 +++---- libinfinity/common/inf-session.h | 3 +- libinfinity/inf-marshal.in | 1 + libinfinity/server/infd-directory.c | 55 +++++++++++ libinfinity/server/infd-session-proxy.c | 108 +++++++++++++++++---- libinfinity/server/infd-session-proxy.h | 7 ++ 10 files changed, 205 insertions(+), 47 deletions(-) commit e0e2cb1c3243f52767bd9a7ba9b1389d416e38e4 Author: Armin Burgmeier Date: Mon Aug 5 17:38:40 2013 +0200 Add documentation for InfcSessionProxy and InfdSessionProxy libinfinity/client/infc-session-proxy.c | 21 +++++++++++++++++++++ libinfinity/client/infc-session-proxy.h | 20 ++++++++++++++++++++ libinfinity/server/infd-session-proxy.c | 22 ++++++++++++++++++++++ libinfinity/server/infd-session-proxy.h | 20 ++++++++++++++++++++ 4 files changed, 83 insertions(+) commit 4b4df45bd24d6b3136702f1e20b05a157b618e20 Author: Armin Burgmeier Date: Mon Aug 5 15:58:26 2013 +0200 Add InfcChatRequest to libinfinity-0.6-sections.txt .../reference/libinfinity/libinfinity-0.6-sections.txt | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) commit b0b628fbd6de907ebd2c751334f91d214ee7a823 Author: Armin Burgmeier Date: Mon Aug 5 15:16:18 2013 +0200 Move the NOT_AUTHORIZED error from directory to the request domain libinfinity/common/inf-error.c | 4 ++-- libinfinity/common/inf-error.h | 6 +++--- libinfinity/server/infd-directory.c | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) commit 6a5f7a42436fa04f1544af59ee837fb74389a2c9 Author: Armin Burgmeier Date: Sat Aug 3 19:10:49 2013 +0200 Remove two unused marshallers libinfinity/inf-marshal.in | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) commit 9219688f98c1c84e515fd5ef456057f57b378b6c Author: Armin Burgmeier Date: Thu Aug 1 12:30:23 2013 +0200 Make key algorithm and length parameters of inf_cert_util_create_private_key() infinoted/infinoted-startup.c | 2 +- libinfinity/common/inf-cert-util.c | 12 +++++++++--- libinfinity/common/inf-cert-util.h | 4 +++- 3 files changed, 13 insertions(+), 5 deletions(-) commit 62fea70e983e8ac4a937a57a84cb147c88409404 Author: Armin Burgmeier Date: Wed Jul 31 19:15:50 2013 +0200 Add infd_directory_get_acl_user_for_connection() .../libinfinity/libinfinity-0.6-sections.txt | 1 + libinfinity/server/infd-directory.c | 32 +++++++++++++++++++++ libinfinity/server/infd-directory.h | 4 +++ 3 files changed, 37 insertions(+) commit 014da3537e2fd7c740e2e9348f728f290ae32858 Author: Armin Burgmeier Date: Wed Jul 31 15:46:44 2013 +0200 Change INF_ACL_CAN_SET_ACL so it works on the node rather than its children libinfgtk/inf-gtk-permissions-dialog.c | 34 ++++++++++-------------------- libinfinity/common/inf-acl-sheet.h | 4 ++-- libinfinity/server/infd-directory.c | 36 +++++++++++++++----------------- 3 files changed, 30 insertions(+), 44 deletions(-) commit 3f34da0256495a5f435eecc6e00cdc217c4cfa39 Author: Armin Burgmeier Date: Wed Jul 31 15:37:50 2013 +0200 InfGtkPermissionsDialog: Apply line wrap to the status label libinfgtk/inf-gtk-permissions-dialog.c | 3 +++ 1 file changed, 3 insertions(+) commit bf767b90abe607c7a0c1263dddfb382465165eb2 Author: Armin Burgmeier Date: Wed Jul 31 14:11:44 2013 +0200 Use the new InfGtkAclSheetView properties in InfGtkPermissionsDialog libinfgtk/inf-gtk-permissions-dialog.c | 50 ++++++++++++++++++++++++++++++-- libinfinity/common/inf-acl-sheet.h | 6 ++++ 2 files changed, 54 insertions(+), 2 deletions(-) commit 4ece31ca272992c7234341912895fa6c183374ad Author: Armin Burgmeier Date: Wed Jul 31 13:54:58 2013 +0200 Add "show-default" and "permission-mask" properties to InfGtkAclSheetView .../libinfgtk/libinfgtk-0.6-sections.txt | 4 + libinfgtk/inf-gtk-acl-sheet-view.c | 218 ++++++++++++++++++-- libinfgtk/inf-gtk-acl-sheet-view.h | 14 ++ 3 files changed, 219 insertions(+), 17 deletions(-) commit e24b4ac5b691066a191c92a7733799ed0188ca5d Author: Armin Burgmeier Date: Wed Jul 31 11:30:37 2013 +0200 Some more cosmetics to the InfGtkPermissionsDialog Add two images, and show some informational text when no node is selected. libinfgtk/inf-gtk-permissions-dialog.c | 108 ++++++++++++++++++++++++------- 1 file changed, 83 insertions(+), 25 deletions(-) commit a4b56505a5ea3471b70822354d89c388f5d5d0ae Author: Armin Burgmeier Date: Wed Jul 31 11:01:38 2013 +0200 Fix double slash in inf_browser_get_path() inf_browser_get_path() was returning paths beginning with two slashes for non-root nodes. libinfinity/common/inf-browser.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) commit bac7c1367f36422f596d72ba31f5902d1f993027 Author: Armin Burgmeier Date: Wed Jul 31 08:40:20 2013 +0200 Fix masking logic in inf_browser_check_acl It was wrong in the sense that all masked permissions were revoked, instead of being left untouched. libinfinity/common/inf-browser.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit 6e1f7f0276b4bfe88cf5994b3e48284ea5541135 Author: Armin Burgmeier Date: Wed Jul 31 08:04:59 2013 +0200 Fix a server crash when announcing non-root ACL libinfinity/server/infd-directory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 146050dceccc9245b778c0be3836883c2f293308 Author: Armin Burgmeier Date: Wed Jul 31 08:04:09 2013 +0200 InfGtkPermissionsDialog: Fix a warning when connection drops while changing ACL libinfgtk/inf-gtk-permissions-dialog.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) commit b2893f118fca6fdb14132d362620563ab5a890bf Author: Armin Burgmeier Date: Wed Jul 31 08:03:46 2013 +0200 InfGtkAclSheetView: Sort ACLs in ascending order, not descending libinfgtk/inf-gtk-acl-sheet-view.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 71f8057dee37081cc09ef6df4b0f12ab9d7f95eb Author: Armin Burgmeier Date: Tue Jul 30 17:56:49 2013 +0200 Add the InfGtkPermissionsDialog widget TODO | 2 + docs/reference/libinfgtk/libinfgtk-0.6-docs.sgml | 1 + .../libinfgtk/libinfgtk-0.6-sections.txt | 17 + libinfgtk/Makefile.am | 6 +- libinfgtk/inf-gtk-permissions-dialog.c | 1246 +++++++++++++++++++ libinfgtk/inf-gtk-permissions-dialog.h | 80 ++ 6 files changed, 1350 insertions(+), 2 deletions(-) commit 341ee453b8d58a19153796ebfe1065ad0baa400d Author: Armin Burgmeier Date: Mon Jul 29 21:20:20 2013 +0200 Add the inf_browser_is_ancestor() function .../libinfinity/libinfinity-0.6-sections.txt | 1 + libinfinity/common/inf-browser.c | 34 +++++++++++++++++++++ libinfinity/common/inf-browser.h | 5 +++ 3 files changed, 40 insertions(+) commit 8ae97cb6997b83351977c9d6cb0a0b19c525d645 Author: Armin Burgmeier Date: Sun Jul 28 21:52:25 2013 +0200 Add INF_ACL_CAN_QUERY_USER_LIST and INF_ACL_CAN_QUERY_ACL permissions libinfinity/common/inf-acl-sheet.c | 8 ++++++++ libinfinity/common/inf-acl-sheet.h | 10 ++++++++-- libinfinity/server/infd-directory.c | 12 ++++++++++-- 3 files changed, 26 insertions(+), 4 deletions(-) commit 29e50230fe0f471c69f2851472c7b1d55f454c01 Author: Armin Burgmeier Date: Mon Jul 22 21:41:11 2013 +0200 Add the InfGtkAclSheetView widget docs/reference/libinfgtk/libinfgtk-0.6-docs.sgml | 1 + .../libinfgtk/libinfgtk-0.6-sections.txt | 20 + libinfgtk/Makefile.am | 2 + libinfgtk/inf-gtk-acl-sheet-view.c | 775 ++++++++++++++++++++ libinfgtk/inf-gtk-acl-sheet-view.h | 92 +++ 5 files changed, 890 insertions(+) commit b3b600717b4902e42e805b828745094262aa2ff0 Author: Armin Burgmeier Date: Mon Jul 22 21:51:33 2013 +0200 Document InfTextGtkView and InfTextGtkViewport libinftextgtk/inf-text-gtk-view.c | 31 ++++++++++++++++++++++++++++++- libinftextgtk/inf-text-gtk-view.h | 13 +++++++++++++ libinftextgtk/inf-text-gtk-viewport.c | 20 ++++++++++++++++++++ libinftextgtk/inf-text-gtk-viewport.h | 13 +++++++++++++ 4 files changed, 76 insertions(+), 1 deletion(-) commit 4f254e05c114f0f6e4835f7c7d475d8b9a3f8c75 Author: Armin Burgmeier Date: Sun Jul 21 21:36:50 2013 +0200 InfGtkBrowserStore: Handle correctly when the missing node is a root node libinfgtk/inf-gtk-browser-store.c | 55 +++++++++++++++++++++++++++++++++---- 1 file changed, 49 insertions(+), 6 deletions(-) commit d17cacbd8a30c99dea25af3e926a2f7237cc8b66 Author: Armin Burgmeier Date: Sun Jul 21 21:22:01 2013 +0200 Fix a warning in infinoted when a document is being synced in This causes a session to be created but the InfAdoptedAlgorithm does not exist yet, so the signal handlers cannot be installed. Instead, wait for the synchronization to finish before installing the signal handlers on the algorithm. infinoted/infinoted-log.c | 87 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 72 insertions(+), 15 deletions(-) commit 33985ea64af638f22c6478437f9d8c90b01caf0f Author: Armin Burgmeier Date: Sun Jul 21 21:21:30 2013 +0200 Fix crashes when creating a node with empty ACL Due to missing NULL checks for the ACL sheet set. libinfinity/server/infd-directory.c | 68 ++++++++++++++++++++--------------- 1 file changed, 40 insertions(+), 28 deletions(-) commit ef3472ebb546e1648932574e7a7747a8c7cdf84b Author: Armin Burgmeier Date: Sun Jul 21 21:20:01 2013 +0200 Make sure adOPTed algorithm is available at session status notify This makes the two events "synchronization complete" and "notify::status" atomic in the sense that when one happens in any signal handler the other one will have changed, too, and the adOPTed algorithm is created in every case. libinfinity/adopted/inf-adopted-session.c | 4 ++++ 1 file changed, 4 insertions(+) commit 2c7e860872b6fc3bbc8e76a83c1bd301452c1051 Author: Armin Burgmeier Date: Sun Jul 21 17:51:42 2013 +0200 Only declare protocol versions incompatible if the major number changes The current version is perfectly capable to talk to a 0.5 infinoted. It will even handle replies to ACL-related messages gracefully. libinfinity/client/infc-browser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit d11e38b6ee66644bff67f4c0e3fc6302c1afb8f7 Author: Armin Burgmeier Date: Sun Jul 21 17:43:50 2013 +0200 Allow iter to be NULL in inf_gtk_browser_model_browser_iter_to_tree_iter() This is necessary to since now the root iterator is not always available, namely for non-open browsers. In that case one can call the function with a NULL iterator to obtain the toplevel item. libinfgtk/inf-gtk-browser-model.c | 8 +++++--- libinfgtk/inf-gtk-browser-store.c | 17 ++++++++++++----- 2 files changed, 17 insertions(+), 8 deletions(-) commit c5b04ebca407cbdbd0f60d6ab1c43f3bb352ab9b Author: Armin Burgmeier Date: Sun Jul 21 12:12:24 2013 +0200 Make the inf_tcp_connection_new*() functions take a const InfIpAddress libinfinity/common/inf-tcp-connection.c | 4 ++-- libinfinity/common/inf-tcp-connection.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) commit 63c939f88dc1e2921ae07540f98ee521f541d29b Author: Armin Burgmeier Date: Sun Jul 21 12:10:00 2013 +0200 Make inf_xmpp_manager_lookup_connection_by_address() take a const InfIpAddress libinfinity/common/inf-xmpp-manager.c | 6 +++--- libinfinity/common/inf-xmpp-manager.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) commit a6130fc6caef93a65c051e036f8ce159f0b93d34 Author: Armin Burgmeier Date: Sun Jul 21 12:06:49 2013 +0200 Make inf_gtk_browser_store_add_connection() return a InfBrowser libinfgtk/inf-gtk-browser-store.c | 14 +++++++++++--- libinfgtk/inf-gtk-browser-store.h | 2 +- 2 files changed, 12 insertions(+), 4 deletions(-) commit 7107d534107bcdc5b4cdf1cf5af35733e0e4f5fc Author: Armin Burgmeier Date: Sat Jul 20 23:33:35 2013 +0200 Document the InfTextGtkBuffer class libinftextgtk/inf-text-gtk-buffer.c | 33 +++++++++++++++++++++++++++++++++ libinftextgtk/inf-text-gtk-buffer.h | 13 +++++++++++++ 2 files changed, 46 insertions(+) commit effd8971f72e73dba248749634ee581490f17ca1 Author: Armin Burgmeier Date: Fri Jul 19 16:37:53 2013 +0200 Do not return a group that is larger than what can be undone in UndoGrouping This could lead to submission of too many undo or redo requests if one would blindly generate as many undo or redo requests as the size of the corresponding undo group. Since it is not trivial to figure out the number of requests allowed before no more requests can be made due to an excess of the max total log size, this functionality has been added to InfAdoptedUndoGrouping. This would also lead to a crash in the server which cannot handle invalid undo requests gracefully at the moment. libinfinity/adopted/inf-adopted-undo-grouping.c | 58 ++++++++++++++++++++++- 1 file changed, 56 insertions(+), 2 deletions(-) commit 781a9f540e1cb8e15d6ad55b895305d38d2d4269 Author: Armin Burgmeier Date: Thu Jul 18 23:44:08 2013 +0200 inf_adopted_request_log_upper_related(): Allow n to be anywhere in the set Also, add inf_adopted_request_log_lower_related(), which comes for free with the new implementation .../libinfinity/libinfinity-0.6-sections.txt | 1 + libinfinity/adopted/inf-adopted-request-log.c | 194 +++++++++++++------- libinfinity/adopted/inf-adopted-request-log.h | 4 + 3 files changed, 135 insertions(+), 64 deletions(-) commit d0b540a1ffdd4c74133d09651d3ffefcd17848c7 Author: Armin Burgmeier Date: Thu Jul 18 23:38:11 2013 +0200 Add inf_adopted_request_get_index() This function returns the vector time component of the user that issued the request itself. This value is needed often, and should allow to simplify more code through libinfinity's adOPTed implementation. It could later also be optimized by caching that quantity. .../libinfinity/libinfinity-0.6-sections.txt | 1 + libinfinity/adopted/inf-adopted-request.c | 20 ++++++++++++++++++++ libinfinity/adopted/inf-adopted-request.h | 3 +++ 3 files changed, 24 insertions(+) commit 930367a41762c454819596bac419a72d0ca87290 Author: Armin Burgmeier Date: Thu Jul 18 20:02:47 2013 +0200 Keep a reference to requests in the undo grouper Otherwise requests could be removed before the cleanup would happen. Also, add a replay which exhibits the problem. libinfinity/adopted/inf-adopted-undo-grouping.c | 6 + test/replay/replay-12.record.xml | 6599 +++++++++++++++++++++ 2 files changed, 6605 insertions(+) commit cdf4f978df6275c9228c87cb765d30c36f81fee1 Author: Armin Burgmeier Date: Wed Jul 17 12:02:21 2013 +0200 Remove the trust-file property from InfGtkCertificateManager Instead, give the gnutls_session_t to the certificate callback. The callback can then call gnutls_certificate_verify_peers2() in order to check the certificate with the trusted CAs stored in the certificate credentials. infinoted/infinoted-run.c | 1 + libinfgtk/inf-gtk-certificate-manager.c | 86 +++--------------------------- libinfgtk/inf-gtk-certificate-manager.h | 1 - libinfinity/common/inf-xmpp-connection.c | 1 + libinfinity/common/inf-xmpp-connection.h | 1 + 5 files changed, 10 insertions(+), 80 deletions(-) commit 2c6ccbd4b7a03176b188da2e41c5e1b38fde6596 Author: Armin Burgmeier Date: Tue Jul 16 19:42:14 2013 +0200 Fix FSF address in COPYING file Bug report #609, http://gobby.0x539.de/trac/ticket/609 COPYING | 68 ++++++++++++++++++++++++++++----------------------------------- 1 file changed, 30 insertions(+), 38 deletions(-) commit cab8f0779006d86a4931ed6762bcfba326c6e765 Author: Armin Burgmeier Date: Tue Jul 16 17:37:14 2013 +0200 Fix a crash in infd_directory_handle_subscribe_session() Due to two uninitialized pointers. libinfinity/server/infd-directory.c | 3 +++ 1 file changed, 3 insertions(+) commit de9cf1d34a75bb511e4dff85d82ea7f192d7fa84 Author: Armin Burgmeier Date: Tue Jul 16 17:25:39 2013 +0200 Fix inf_browser_check_acl() for non-root nodes The tree was correctly propagated, but the ACL sheet was only queried from the original (bottommost) node. libinfinity/common/inf-browser.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit 0ae099912608da1d24c95c0310bdde1af421f899 Author: Armin Burgmeier Date: Tue Jul 16 17:25:00 2013 +0200 Fix a warning when receiving an add_node request by the server If the request has no ACL sheets set, a inf_acl_sheet_set_free() was attempted on a NULL variable. libinfinity/client/infc-browser.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) commit 25058fafbcd28c53daa62b3674382f8510183620 Author: Armin Burgmeier Date: Tue Jul 16 17:19:51 2013 +0200 Avoid a warning when adding a note without ACL sheets Due to a missing NULL check in infc_browser_node_new_common() libinfinity/client/infc-browser.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) commit 7b0034e3f7fb663f86ebb8f8eb4767e17383cda7 Author: Armin Burgmeier Date: Tue Jul 16 17:16:50 2013 +0200 Fix a crash when sending explored nodes to a client There was a NULL check missing when adding the ACL sheets of the explored nodes to the server reply. libinfinity/server/infd-directory.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) commit e1039666e8cc35af6967087a5ee82277cf6ae256 Author: Armin Burgmeier Date: Tue Jul 16 17:16:31 2013 +0200 Fix a crash when exploring nodes from background storage Due to an uninitialized variable libinfinity/server/infd-directory.c | 2 ++ 1 file changed, 2 insertions(+) commit 60c9b1172ca3ea5b13652266ab3beb8789b32d6d Author: Armin Burgmeier Date: Tue Jul 16 17:16:00 2013 +0200 Add g_return_if_fail() checks into InfdExploreRequest public functions libinfinity/server/infd-explore-request.c | 6 ++++++ 1 file changed, 6 insertions(+) commit 3dc6cb3a5cbdb85f7735e0655e16d014b71096a1 Author: Armin Burgmeier Date: Tue Jul 16 17:07:37 2013 +0200 Fix a crash when exploring nodes in the background storage libinfinity/server/infd-directory.c | 2 ++ 1 file changed, 2 insertions(+) commit 514ee584b700da5ab1ee12b2495e47b5bdac485b Author: Armin Burgmeier Date: Tue Jul 16 17:07:08 2013 +0200 Adapt InfGtkBrowserStore to modified root node handling in InfcBrowser The root node is now only available when the browser is open. libinfgtk/inf-gtk-browser-store.c | 172 ++++++++++++++++++++++-------------- 1 file changed, 105 insertions(+), 67 deletions(-) commit d2e0e937a5c19af22731b26ca8636389ec7f2433 Author: Armin Burgmeier Date: Tue Jul 16 15:56:29 2013 +0200 Add 2013 to copyright years AUTHORS | 2 +- infinoted/infinoted-autosave.c | 2 +- infinoted/infinoted-autosave.h | 2 +- infinoted/infinoted-config-reload.c | 2 +- infinoted/infinoted-config-reload.h | 2 +- infinoted/infinoted-dh-params.c | 2 +- infinoted/infinoted-dh-params.h | 2 +- infinoted/infinoted-directory-sync.c | 2 +- infinoted/infinoted-directory-sync.h | 2 +- infinoted/infinoted-log.c | 2 +- infinoted/infinoted-log.h | 2 +- infinoted/infinoted-main.c | 2 +- infinoted/infinoted-note-plugin.c | 2 +- infinoted/infinoted-note-plugin.h | 2 +- infinoted/infinoted-options.c | 2 +- infinoted/infinoted-options.h | 2 +- infinoted/infinoted-pam.c | 2 +- infinoted/infinoted-pam.h | 2 +- infinoted/infinoted-record.c | 2 +- infinoted/infinoted-record.h | 2 +- infinoted/infinoted-run.c | 2 +- infinoted/infinoted-run.h | 2 +- infinoted/infinoted-signal.c | 2 +- infinoted/infinoted-signal.h | 2 +- infinoted/infinoted-startup.c | 2 +- infinoted/infinoted-startup.h | 2 +- infinoted/infinoted-traffic-logger.c | 2 +- infinoted/infinoted-traffic-logger.h | 2 +- infinoted/infinoted-transformation-protector.c | 2 +- infinoted/infinoted-transformation-protector.h | 2 +- infinoted/infinoted-util.c | 2 +- infinoted/infinoted-util.h | 2 +- infinoted/note-plugins/text/infd-note-plugin-text.c | 2 +- libinfgtk/inf-gtk-browser-model-filter.c | 2 +- libinfgtk/inf-gtk-browser-model-filter.h | 2 +- libinfgtk/inf-gtk-browser-model-sort.c | 2 +- libinfgtk/inf-gtk-browser-model-sort.h | 2 +- libinfgtk/inf-gtk-browser-model.c | 2 +- libinfgtk/inf-gtk-browser-model.h | 2 +- libinfgtk/inf-gtk-browser-store.c | 2 +- libinfgtk/inf-gtk-browser-store.h | 2 +- libinfgtk/inf-gtk-browser-view.c | 2 +- libinfgtk/inf-gtk-browser-view.h | 2 +- libinfgtk/inf-gtk-certificate-dialog.c | 2 +- libinfgtk/inf-gtk-certificate-dialog.h | 2 +- libinfgtk/inf-gtk-certificate-manager.c | 2 +- libinfgtk/inf-gtk-certificate-manager.h | 2 +- libinfgtk/inf-gtk-certificate-view.c | 2 +- libinfgtk/inf-gtk-certificate-view.h | 2 +- libinfgtk/inf-gtk-chat.c | 2 +- libinfgtk/inf-gtk-chat.h | 2 +- libinfgtk/inf-gtk-io.c | 2 +- libinfgtk/inf-gtk-io.h | 2 +- libinfinity/adopted/inf-adopted-algorithm.c | 2 +- libinfinity/adopted/inf-adopted-algorithm.h | 2 +- libinfinity/adopted/inf-adopted-concurrency-warning.c | 2 +- libinfinity/adopted/inf-adopted-concurrency-warning.h | 2 +- libinfinity/adopted/inf-adopted-no-operation.c | 2 +- libinfinity/adopted/inf-adopted-no-operation.h | 2 +- libinfinity/adopted/inf-adopted-operation.c | 2 +- libinfinity/adopted/inf-adopted-operation.h | 2 +- libinfinity/adopted/inf-adopted-request-log.c | 2 +- libinfinity/adopted/inf-adopted-request-log.h | 2 +- libinfinity/adopted/inf-adopted-request.c | 2 +- libinfinity/adopted/inf-adopted-request.h | 2 +- libinfinity/adopted/inf-adopted-session-record.c | 2 +- libinfinity/adopted/inf-adopted-session-record.h | 2 +- libinfinity/adopted/inf-adopted-session-replay.c | 2 +- libinfinity/adopted/inf-adopted-session-replay.h | 2 +- libinfinity/adopted/inf-adopted-session.c | 2 +- libinfinity/adopted/inf-adopted-session.h | 2 +- libinfinity/adopted/inf-adopted-split-operation.c | 2 +- libinfinity/adopted/inf-adopted-split-operation.h | 2 +- libinfinity/adopted/inf-adopted-state-vector.c | 2 +- libinfinity/adopted/inf-adopted-state-vector.h | 2 +- libinfinity/adopted/inf-adopted-undo-grouping.c | 2 +- libinfinity/adopted/inf-adopted-undo-grouping.h | 2 +- libinfinity/adopted/inf-adopted-user.c | 2 +- libinfinity/adopted/inf-adopted-user.h | 2 +- libinfinity/client/infc-acl-user-list-request.c | 2 +- libinfinity/client/infc-acl-user-list-request.h | 2 +- libinfinity/client/infc-browser.c | 2 +- libinfinity/client/infc-browser.h | 2 +- libinfinity/client/infc-certificate-request.c | 2 +- libinfinity/client/infc-certificate-request.h | 2 +- libinfinity/client/infc-chat-request.c | 2 +- libinfinity/client/infc-chat-request.h | 2 +- libinfinity/client/infc-explore-request.c | 2 +- libinfinity/client/infc-explore-request.h | 2 +- libinfinity/client/infc-node-request.c | 2 +- libinfinity/client/infc-node-request.h | 2 +- libinfinity/client/infc-note-plugin.h | 2 +- libinfinity/client/infc-request-manager.c | 2 +- libinfinity/client/infc-request-manager.h | 2 +- libinfinity/client/infc-request.c | 2 +- libinfinity/client/infc-request.h | 2 +- libinfinity/client/infc-session-proxy.c | 2 +- libinfinity/client/infc-session-proxy.h | 2 +- libinfinity/client/infc-user-request.c | 2 +- libinfinity/client/infc-user-request.h | 2 +- libinfinity/common/inf-acl-sheet.c | 2 +- libinfinity/common/inf-acl-sheet.h | 2 +- libinfinity/common/inf-acl-table.c | 2 +- libinfinity/common/inf-acl-table.h | 2 +- libinfinity/common/inf-acl-user-list-request.c | 2 +- libinfinity/common/inf-acl-user-list-request.h | 2 +- libinfinity/common/inf-browser-iter.c | 2 +- libinfinity/common/inf-browser-iter.h | 2 +- libinfinity/common/inf-browser.c | 2 +- libinfinity/common/inf-browser.h | 2 +- libinfinity/common/inf-buffer.c | 2 +- libinfinity/common/inf-buffer.h | 2 +- libinfinity/common/inf-cert-util.c | 2 +- libinfinity/common/inf-cert-util.h | 2 +- libinfinity/common/inf-certificate-chain.c | 2 +- libinfinity/common/inf-certificate-chain.h | 2 +- libinfinity/common/inf-certificate-credentials.c | 2 +- libinfinity/common/inf-certificate-credentials.h | 2 +- libinfinity/common/inf-chat-buffer.c | 2 +- libinfinity/common/inf-chat-buffer.h | 2 +- libinfinity/common/inf-chat-session.c | 2 +- libinfinity/common/inf-chat-session.h | 2 +- libinfinity/common/inf-discovery-avahi.c | 2 +- libinfinity/common/inf-discovery-avahi.h | 2 +- libinfinity/common/inf-discovery.c | 2 +- libinfinity/common/inf-discovery.h | 2 +- libinfinity/common/inf-error.c | 2 +- libinfinity/common/inf-error.h | 2 +- libinfinity/common/inf-explore-request.c | 2 +- libinfinity/common/inf-explore-request.h | 2 +- libinfinity/common/inf-init.c | 2 +- libinfinity/common/inf-init.h | 2 +- libinfinity/common/inf-io.c | 2 +- libinfinity/common/inf-io.h | 2 +- libinfinity/common/inf-ip-address.c | 2 +- libinfinity/common/inf-ip-address.h | 2 +- libinfinity/common/inf-local-publisher.c | 2 +- libinfinity/common/inf-local-publisher.h | 2 +- libinfinity/common/inf-node-request.c | 2 +- libinfinity/common/inf-node-request.h | 2 +- libinfinity/common/inf-protocol.c | 2 +- libinfinity/common/inf-protocol.h | 2 +- libinfinity/common/inf-request.c | 2 +- libinfinity/common/inf-request.h | 2 +- libinfinity/common/inf-sasl-context.c | 2 +- libinfinity/common/inf-sasl-context.h | 2 +- libinfinity/common/inf-session-proxy.c | 2 +- libinfinity/common/inf-session-proxy.h | 2 +- libinfinity/common/inf-session.c | 2 +- libinfinity/common/inf-session.h | 2 +- libinfinity/common/inf-simulated-connection.c | 2 +- libinfinity/common/inf-simulated-connection.h | 2 +- libinfinity/common/inf-standalone-io.c | 2 +- libinfinity/common/inf-standalone-io.h | 2 +- libinfinity/common/inf-tcp-connection-private.h | 2 +- libinfinity/common/inf-tcp-connection.c | 2 +- libinfinity/common/inf-tcp-connection.h | 2 +- libinfinity/common/inf-user-request.c | 2 +- libinfinity/common/inf-user-request.h | 2 +- libinfinity/common/inf-user-table.c | 2 +- libinfinity/common/inf-user-table.h | 2 +- libinfinity/common/inf-user.c | 2 +- libinfinity/common/inf-user.h | 2 +- libinfinity/common/inf-xml-connection.c | 2 +- libinfinity/common/inf-xml-connection.h | 2 +- libinfinity/common/inf-xml-util.c | 2 +- libinfinity/common/inf-xml-util.h | 2 +- libinfinity/common/inf-xmpp-connection.c | 2 +- libinfinity/common/inf-xmpp-connection.h | 2 +- libinfinity/common/inf-xmpp-manager.c | 2 +- libinfinity/common/inf-xmpp-manager.h | 2 +- libinfinity/communication/inf-communication-central-factory.c | 2 +- libinfinity/communication/inf-communication-central-factory.h | 2 +- libinfinity/communication/inf-communication-central-method.c | 2 +- libinfinity/communication/inf-communication-central-method.h | 2 +- libinfinity/communication/inf-communication-factory.c | 2 +- libinfinity/communication/inf-communication-factory.h | 2 +- libinfinity/communication/inf-communication-group-private.h | 2 +- libinfinity/communication/inf-communication-group.c | 2 +- libinfinity/communication/inf-communication-group.h | 2 +- libinfinity/communication/inf-communication-hosted-group.c | 2 +- libinfinity/communication/inf-communication-hosted-group.h | 2 +- libinfinity/communication/inf-communication-joined-group.c | 2 +- libinfinity/communication/inf-communication-joined-group.h | 2 +- libinfinity/communication/inf-communication-manager.c | 2 +- libinfinity/communication/inf-communication-manager.h | 2 +- libinfinity/communication/inf-communication-method.c | 2 +- libinfinity/communication/inf-communication-method.h | 2 +- libinfinity/communication/inf-communication-object.c | 2 +- libinfinity/communication/inf-communication-object.h | 2 +- libinfinity/communication/inf-communication-registry.c | 2 +- libinfinity/communication/inf-communication-registry.h | 2 +- libinfinity/inf-dll.c | 2 +- libinfinity/inf-dll.h | 2 +- libinfinity/inf-i18n.c | 2 +- libinfinity/inf-i18n.h | 2 +- libinfinity/inf-signals.c | 2 +- libinfinity/inf-signals.h | 2 +- libinfinity/server/infd-directory.c | 2 +- libinfinity/server/infd-directory.h | 2 +- libinfinity/server/infd-explore-request.c | 2 +- libinfinity/server/infd-explore-request.h | 2 +- libinfinity/server/infd-filesystem-storage.c | 2 +- libinfinity/server/infd-filesystem-storage.h | 2 +- libinfinity/server/infd-node-request.c | 2 +- libinfinity/server/infd-node-request.h | 2 +- libinfinity/server/infd-note-plugin.h | 2 +- libinfinity/server/infd-server-pool.c | 2 +- libinfinity/server/infd-server-pool.h | 2 +- libinfinity/server/infd-session-proxy.c | 2 +- libinfinity/server/infd-session-proxy.h | 2 +- libinfinity/server/infd-storage.c | 2 +- libinfinity/server/infd-storage.h | 2 +- libinfinity/server/infd-tcp-server.c | 2 +- libinfinity/server/infd-tcp-server.h | 2 +- libinfinity/server/infd-user-request.c | 2 +- libinfinity/server/infd-user-request.h | 2 +- libinfinity/server/infd-xml-server.c | 2 +- libinfinity/server/infd-xml-server.h | 2 +- libinfinity/server/infd-xmpp-server.c | 2 +- libinfinity/server/infd-xmpp-server.h | 2 +- libinftext/inf-text-buffer.c | 2 +- libinftext/inf-text-buffer.h | 2 +- libinftext/inf-text-chunk.c | 2 +- libinftext/inf-text-chunk.h | 2 +- libinftext/inf-text-default-buffer.c | 2 +- libinftext/inf-text-default-buffer.h | 2 +- libinftext/inf-text-default-delete-operation.c | 2 +- libinftext/inf-text-default-delete-operation.h | 2 +- libinftext/inf-text-default-insert-operation.c | 2 +- libinftext/inf-text-default-insert-operation.h | 2 +- libinftext/inf-text-delete-operation.c | 2 +- libinftext/inf-text-delete-operation.h | 2 +- libinftext/inf-text-insert-operation.c | 2 +- libinftext/inf-text-insert-operation.h | 2 +- libinftext/inf-text-move-operation.c | 2 +- libinftext/inf-text-move-operation.h | 2 +- libinftext/inf-text-operations.h | 2 +- libinftext/inf-text-remote-delete-operation.c | 2 +- libinftext/inf-text-remote-delete-operation.h | 2 +- libinftext/inf-text-session.c | 2 +- libinftext/inf-text-session.h | 2 +- libinftext/inf-text-undo-grouping.c | 2 +- libinftext/inf-text-undo-grouping.h | 2 +- libinftext/inf-text-user.c | 2 +- libinftext/inf-text-user.h | 2 +- libinftextgtk/inf-text-gtk-buffer.c | 2 +- libinftextgtk/inf-text-gtk-buffer.h | 2 +- libinftextgtk/inf-text-gtk-hue-chooser.c | 2 +- libinftextgtk/inf-text-gtk-hue-chooser.h | 2 +- libinftextgtk/inf-text-gtk-view.c | 2 +- libinftextgtk/inf-text-gtk-view.h | 2 +- libinftextgtk/inf-text-gtk-viewport.c | 2 +- libinftextgtk/inf-text-gtk-viewport.h | 2 +- test/inf-test-browser.c | 2 +- test/inf-test-certificate-request.c | 2 +- test/inf-test-chat.c | 2 +- test/inf-test-chunk.c | 2 +- test/inf-test-daemon.c | 2 +- test/inf-test-gtk-browser.c | 2 +- test/inf-test-mass-join.c | 2 +- test/inf-test-reduce-replay.c | 2 +- test/inf-test-set-acl.c | 2 +- test/inf-test-state-vector.c | 2 +- test/inf-test-tcp-connection.c | 2 +- test/inf-test-tcp-server.c | 2 +- test/inf-test-text-cleanup.c | 2 +- test/inf-test-text-operations.c | 2 +- test/inf-test-text-recover.c | 2 +- test/inf-test-text-replay.c | 2 +- test/inf-test-text-session.c | 2 +- test/inf-test-xmpp-connection.c | 2 +- test/inf-test-xmpp-server.c | 2 +- test/util/inf-test-util.c | 2 +- test/util/inf-test-util.h | 2 +- 275 files changed, 275 insertions(+), 275 deletions(-) commit 0c304bcc6e9d57f0e6fd13fe2201866313a368c3 Author: Armin Burgmeier Date: Tue Jul 16 15:04:25 2013 +0200 Increase protocol version to 1.1 The support for Access Control Lists adds new functionality to the protoc,l however backwards compatibility is preserved. The new protocol version can be used by clients to find out whether a server supports ACLs or not. If a client does not check explicitely, corresponding requests would either fail (e.g. query-user-list) or silently be ignored (e.g. initial ACL for new nodes) by a server which does not support ACLs. libinfinity/common/inf-protocol.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit d24be134740bbfabba275a9c4bd77a38e916ff90 Author: Armin Burgmeier Date: Tue Jul 16 15:07:19 2013 +0200 Implement support for Access Control Lists (ACL) This feature allows apply sets of permissions for different users on individual nodes. Nodes which don't have an explicit setting for a permission inherit the setting from their parent node. The default user for the root node must have all permissions defined for the default user. The user authentication currently works only with client side certificates. This requires to run infinoted with the --ca-list-file option, since otherwise clients are not requested to send a certificate. This behaviour needs yet to be documented. Users are identified by the SHA256 fingerprint of their certificate. This means that, currently, a new certificate for a user would lead to a different user account. This is not optimal. There should be fixed accounts to which one or more certificates can be mapped, and which should also be able to be associated to a SASL username, so that after successful SASL authentication one has access to the account, without requiring client side certificates. Right now, only two permissions are implemented, can-subscribe-session and can-set-acl. With the can-subscribe-session permission certain users can be allowed or denied to subscribe to particular sessions in the tree, and with can-set-acl they can be allowed or denied to change the ACL for nodes. Of course, more permissions will be added in the future. This commit is mostly meant to provide the basic ACL framework, including ACL storage on the server side, the API and the protocol layer to query, change and check ACLs. .../libinfinity/libinfinity-0.6-docs.sgml | 3 + .../libinfinity/libinfinity-0.6-sections.txt | 90 + libinfinity/client/Makefile.am | 2 + libinfinity/client/infc-acl-user-list-request.c | 344 ++++ libinfinity/client/infc-acl-user-list-request.h | 74 + libinfinity/client/infc-browser.c | 1027 ++++++++-- libinfinity/common/Makefile.am | 6 + libinfinity/common/inf-acl-sheet.c | 689 +++++++ libinfinity/common/inf-acl-sheet.h | 191 ++ libinfinity/common/inf-acl-table.c | 901 +++++++++ libinfinity/common/inf-acl-table.h | 146 ++ libinfinity/common/inf-acl-user-list-request.c | 164 ++ libinfinity/common/inf-acl-user-list-request.h | 70 + libinfinity/common/inf-browser.c | 437 ++++- libinfinity/common/inf-browser.h | 124 +- libinfinity/common/inf-error.c | 8 + libinfinity/common/inf-error.h | 14 + libinfinity/inf-marshal.in | 1 + libinfinity/server/infd-directory.c | 1902 +++++++++++++++++-- libinfinity/server/infd-filesystem-storage.c | 537 ++++++ libinfinity/server/infd-filesystem-storage.h | 2 + libinfinity/server/infd-storage.c | 212 ++- libinfinity/server/infd-storage.h | 63 +- test/Makefile.am | 15 +- test/inf-test-browser.c | 2 +- test/inf-test-set-acl.c | 343 ++++ 26 files changed, 7016 insertions(+), 351 deletions(-) commit 84a7fc87acfda9225f07662612e16b4ae5e37dbc Author: Armin Burgmeier Date: Tue Jul 16 15:01:28 2013 +0200 Run the callback last in infc_request_manager_fail_request Otherwise it can happen that the callback deletes the request manager itself, and the following attempt to remove the request from the manager would fail. libinfinity/client/infc-request-manager.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) commit 88960c34bcff2781282d51f2292874c523941bb0 Author: Armin Burgmeier Date: Tue Jul 16 15:00:00 2013 +0200 Some cosmetic improvements to InfcExploreRequest libinfinity/client/infc-explore-request.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) commit 477337982cb7d9bf9780314302bae9172ea4ffa0 Author: Armin Burgmeier Date: Tue Jul 16 14:47:06 2013 +0200 Update the TODO list TODO | 44 +++++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 21 deletions(-) commit 05e0f3384518ecac69a4333c3aa085fc8d2ab78e Author: Armin Burgmeier Date: Tue Jul 16 14:12:26 2013 +0200 Add a general inf_browser_get_pending_request() function This function replaces inf_browser_get_pending_explore_request() and inf_browser_get_pending_subscribe_request(). The rationale for this change is that more similar requests might be introduced shortly, and one helper function for each request type would be a bit too much code duplication. .../libinfinity/libinfinity-0.6-sections.txt | 3 +- libinfgtk/inf-gtk-browser-view.c | 46 +++++++----- libinfinity/client/infc-browser.c | 10 ++- libinfinity/common/inf-browser.c | 78 ++++++--------------- libinfinity/common/inf-browser.h | 12 ++-- test/inf-test-gtk-browser.c | 10 ++- 6 files changed, 68 insertions(+), 91 deletions(-) commit e04e2b3a11a753b855a263f44c167531fe779be0 Author: Armin Burgmeier Date: Tue Jul 16 14:03:23 2013 +0200 Fix a parameter name in InfNodeRequest::finished documentation libinfinity/common/inf-node-request.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit e95a83f8160a9901054150ab3942e6e3118cb94c Author: Armin Burgmeier Date: Tue Jul 2 11:15:36 2013 +0200 Add certificate properties to InfXmlConnection This allows InfcBrowser and InfdDirectory to access the certificates in a generic way, without making assumptions about whether the connection at hand is a InfXmppConnection or not. InfSimulatedConnection always returns NULL at this point for the certificates, but API could be added later to supply proper certificates. libinfinity/client/infc-browser.c | 20 +------- libinfinity/common/inf-simulated-connection.c | 22 ++++++++- libinfinity/common/inf-xml-connection.c | 22 +++++++++ libinfinity/common/inf-xmpp-connection.c | 62 ++++++++++--------------- libinfinity/server/infd-directory.c | 15 ------ 5 files changed, 70 insertions(+), 71 deletions(-) commit 5dd52dd9494fafb696dd9fe15a0a334d82c8fe8f Author: Armin Burgmeier Date: Wed Jun 26 16:46:33 2013 +0200 infinoted: Add --ca-list-file option to check client certificates This option allows infinoted to request clients to send a certificate. If no certificate is sent or the certificate is not issued by one of the CAs in the given list the connection is rejected. infinoted/infinoted-0.6.man | 12 +++-- infinoted/infinoted-options.c | 17 ++++++- infinoted/infinoted-options.h | 1 + infinoted/infinoted-run.c | 80 ++++++++++++++++++++++++++++++ infinoted/infinoted-startup.c | 51 ++++++++++++++++++- infinoted/infinoted-startup.h | 3 ++ libinfinity/common/inf-xmpp-connection.c | 10 ++++ 7 files changed, 168 insertions(+), 6 deletions(-) commit fdce67d94c5112fe503bd9edecffa5abe4bbc9c7 Author: Armin Burgmeier Date: Wed Jun 26 18:07:18 2013 +0200 Also call the certificate callback when no certificate was sent This allows the user to choose whether to accept or reject the connection in case it does not have a certificate. For example, the connection might be temporarily accepted and further authentication being performed at a different layer of the protocol. libinfinity/common/inf-xmpp-connection.c | 39 +++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 11 deletions(-) commit e1cc01a950f69cea73d23b995524c63430f5a94c Author: Armin Burgmeier Date: Wed Jun 26 16:29:12 2013 +0200 Add functionality for the client to ask for a certificate signed by the server The client will reject the generated certificate if the server certificate is not a CA. This also increases the required GnuTLS version to 2.12.0. This makes sure that all the functions we use are available, especially gnutls_x509_crq_verify is only available since 2.12.0. configure.ac | 2 +- .../libinfinity/libinfinity-0.6-docs.sgml | 1 + .../libinfinity/libinfinity-0.6-sections.txt | 17 ++ libinfinity/client/Makefile.am | 2 + libinfinity/client/infc-browser.c | 283 +++++++++++++++++- libinfinity/client/infc-browser.h | 9 + libinfinity/client/infc-certificate-request.c | 300 ++++++++++++++++++++ libinfinity/client/infc-certificate-request.h | 84 ++++++ libinfinity/common/inf-error.c | 6 + libinfinity/common/inf-error.h | 7 + libinfinity/server/infd-directory.c | 270 ++++++++++++++++++ test/Makefile.am | 16 +- test/inf-test-certificate-request.c | 282 ++++++++++++++++++ 13 files changed, 1273 insertions(+), 6 deletions(-) commit 2d60f182f48c873122cdd27992206b045c315595 Author: Armin Burgmeier Date: Tue Jun 25 13:26:28 2013 +0200 infinoted: Set the server certificate as the directory certificate infinoted/infinoted-run.c | 6 ++++++ infinoted/infinoted-startup.c | 23 +++++++++++------------ infinoted/infinoted-startup.h | 3 +-- 3 files changed, 18 insertions(+), 14 deletions(-) commit abaaa91c0efb2a78ba085a6233fda4291aa0b68b Author: Armin Burgmeier Date: Tue Jun 25 13:23:26 2013 +0200 Add infd_directory_set_certificate This will be used for issuing certificates signed with the directory certificate, in response to a new request-certificate message. .../libinfinity/libinfinity-0.6-sections.txt | 1 + libinfinity/server/infd-directory.c | 91 +++++++++++++++++++++ libinfinity/server/infd-directory.h | 8 ++ 3 files changed, 100 insertions(+) commit 01106696ac768a49ad173a40433ffa55f23a9d0d Author: Armin Burgmeier Date: Fri Jun 21 14:39:31 2013 +0200 Don't require an InfNodeRequest in inf_browser_begin_request() This fixes the precondition in inf_browser_begin_request() and makes use of it with chat subscription in InfcBrowser. libinfinity/client/infc-browser.c | 4 +--- libinfinity/common/inf-browser.c | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) commit be886df7763e99d744f578a688884e5f1e143ba1 Author: Armin Burgmeier Date: Fri Jun 21 14:38:12 2013 +0200 Add API to query certificates from InfXmppConnection This allows to ask both for the local certificate that was presented to the peer and to ask for the certificate of the peer itself. .../libinfinity/libinfinity-0.6-sections.txt | 2 + libinfinity/common/inf-xmpp-connection.c | 262 +++++++++++++++++--- libinfinity/common/inf-xmpp-connection.h | 6 + 3 files changed, 230 insertions(+), 40 deletions(-) commit 9e78707f9a48092a70483c5ba4a556e3b70df3f0 Author: Armin Burgmeier Date: Sun Jul 14 21:32:46 2013 +0200 Document the InfTextDeleteOperation interface .../libinfgtk/libinfgtk-0.6-sections.txt | 20 ++++++++--------- .../reference/libinftext/libinftext-0.6-docs.sgml | 1 - .../libinftext/libinftext-0.6-sections.txt | 24 +++++++++------------ .../libinftextgtk/libinftextgtk-0.6-sections.txt | 8 +++---- libinftext/inf-text-delete-operation.c | 20 +++++++++++++++++ libinftext/inf-text-delete-operation.h | 19 ++++++++++++++++ libinftext/inf-text-operations.h | 14 ++++++++++++ 7 files changed, 77 insertions(+), 29 deletions(-) commit 05cc23f6051fc9c408e636a9261343b72bbe78ea Author: Armin Burgmeier Date: Sun Jul 14 20:52:59 2013 +0200 Fix a warning in case the connection goes down at sending This is a similar fix to the previous one: The connection can go down in , and then gnutls_bye would try to send more data on a closed connection. libinfinity/common/inf-xmpp-connection.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) commit e0ce7364cfaf7ad5c1f202850f6d6a4b6ee17cfe Author: Armin Burgmeier Date: Sun Jul 14 17:40:01 2013 +0200 Fix a runtime warning when connection goes down during gnutls_bye() If that happens the XMPP status would have been "revived" from CLOSED to CLOSING, since the code didn't handle the case that the connection could go down during gnutls_bye(). libinfinity/common/inf-xmpp-connection.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) commit bed81c1bab1e161a5ac715b719c36411810de877 Author: Armin Burgmeier Date: Mon Jul 1 22:16:05 2013 +0200 More documentation fixes and updates libinfinity/common/inf-protocol.c | 2 +- libinfinity/common/inf-session.c | 8 +++---- libinfinity/common/inf-user.c | 2 +- libinfinity/common/inf-xml-connection.c | 40 +++++++++++++++++++++++++++++++ libinfinity/common/inf-xml-connection.h | 32 +++++++++++++++++++++++++ libinfinity/server/infd-directory.c | 2 +- 6 files changed, 79 insertions(+), 7 deletions(-) commit 5242b2f332cf25069328b9abd5c67cb365f35a8e Author: Armin Burgmeier Date: Tue Jul 2 21:39:51 2013 +0200 Add the InfdDirectory implementation of InfBrowser This was supposed to included already in the original merge, b7f4ae3d3a50664bfdb16e403ccc1675139475cc, but went missing somehow. libinfinity/server/infd-directory.c | 404 ++++++++++++++++++++++++++++++---- 1 file changed, 364 insertions(+), 40 deletions(-) commit 568c89e3a68266ad5c9991cfda7c6347c1b23fcc Author: Armin Burgmeier Date: Sun Jun 30 22:33:40 2013 +0200 Miscellaneous documentation fixes and updates .../libinfgtk/libinfgtk-0.6-sections.txt | 2 +- .../libinfinity/libinfinity-0.6-sections.txt | 2 +- libinfgtk/inf-gtk-browser-model.c | 20 ++++++ libinfgtk/inf-gtk-browser-model.h | 69 +++++++++++++++++++-- libinfgtk/inf-gtk-certificate-dialog.c | 19 +++++- libinfgtk/inf-gtk-certificate-dialog.h | 36 +++++++++++ libinfgtk/inf-gtk-chat.c | 3 +- libinfgtk/inf-gtk-chat.h | 2 - libinfinity/common/inf-user.c | 14 +++++ libinfinity/common/inf-user.h | 31 +++++++++ libinftext/inf-text-buffer.c | 21 +++++++ libinftext/inf-text-buffer.h | 48 ++++++++++++++ libinftext/inf-text-chunk.c | 28 +++++++++ libinftext/inf-text-chunk.h | 29 +++++---- libinftextgtk/inf-text-gtk-buffer.c | 8 +-- libinftextgtk/inf-text-gtk-view.c | 4 +- libinftextgtk/inf-text-gtk-viewport.c | 2 +- 17 files changed, 308 insertions(+), 30 deletions(-) commit 0d5bf73be3a4a460404cf52881fadbb8853e72e5 Author: Armin Burgmeier Date: Fri Jun 28 19:52:39 2013 +0200 Terminate connection gracefully when rejecting a certificate Instead of brutally closing the TCP connection, terminate it properly by sending a before. libinfinity/common/inf-xmpp-connection.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 635d7e77f4d80baf864dbc0f216356512f91f8f0 Author: Armin Burgmeier Date: Fri Jun 28 19:51:15 2013 +0200 Fix a crash when data was received immediately after the TLS handshake InfXmppConnection expected the data to arrive in another bunch, i.e. in a separate call of the IO function. libinfinity/common/inf-xmpp-connection.c | 39 +++++++++++++++--------------- 1 file changed, 20 insertions(+), 19 deletions(-) commit a14f6fa51f5ac9c6a24f62e84b49dd5cdcf79473 Author: Armin Burgmeier Date: Tue Jun 25 09:40:09 2013 +0200 Properly quote XML in documentation comments libinfinity/common/inf-error.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit c34f4fdf9656460c60ca9f94bbd1a35671d8f684 Author: Armin Burgmeier Date: Mon Jun 24 17:18:47 2013 +0200 Add missing files for infinoted-traffic-logger infinoted/infinoted-traffic-logger.c | 357 +++++++++++++++++++++++++++++++++ infinoted/infinoted-traffic-logger.h | 52 +++++ 2 files changed, 409 insertions(+) commit c402de91beb688413967d725df6eb1facf27ef4e Author: Armin Burgmeier Date: Sun Apr 28 22:58:41 2013 +0200 Move functions from infinoted-creds.c to inf-cert-util.c Conflicts: infinoted/infinoted-startup.c .../libinfinity/libinfinity-0.6-sections.txt | 17 +- infinoted/Makefile.am | 2 - infinoted/infinoted-creds.c | 416 ------------ infinoted/infinoted-creds.h | 69 -- infinoted/infinoted-dh-params.c | 8 +- infinoted/infinoted-run.c | 1 - infinoted/infinoted-startup.c | 34 +- libinfgtk/inf-gtk-certificate-manager.c | 14 +- libinfinity/common/inf-cert-util.c | 670 ++++++++++++++++++-- libinfinity/common/inf-cert-util.h | 50 +- libinfinity/common/inf-xml-util.c | 2 +- 11 files changed, 698 insertions(+), 585 deletions(-) commit 629a5c091c876b8ea9fa30c920181d43f5858ff6 Author: Armin Burgmeier Date: Fri Jun 21 15:23:52 2013 +0200 Improve infinoted man pages a bit After suggestions from Rainer Rehak: http://permalink.gmane.org/gmane.network.obby.user/407 infinoted/infinoted-0.6.man | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) commit 6e6d99d5eddc4779ffd9a37b6cd6043da3677b60 Author: Armin Burgmeier Date: Wed Jun 19 15:21:01 2013 +0200 Fix a warning when the browser is disconnected in the explore request callback libinfinity/client/infc-browser.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) commit b7f4ae3d3a50664bfdb16e403ccc1675139475cc Merge: 8838bf2 706fb1a Author: Armin Burgmeier Date: Tue Jun 18 09:25:52 2013 +0200 Add InfBrowser interface, implemented by InfcBrowser and InfdDirectory This is a merge of a rather old branch that I have finished working on recently. The idea is to unify the interface of InfcBrowser and InfdDirectory, getting rid of some duplicate code and eventually allowing handling them as interchangeably as possible, and as transparently as possible for a user. The interface now allows to do most operations of InfcBrowser or InfdDirectory in a unified way, so that it is not necessary to know whether one is working locally on a directory or remotely on a server. I feel this branch is ready to merge now, even though the new possibilities have not yet been fully exploited. What is yet to come is full support for InfdDirectory browsers in InfGtkBrowserStore/InfGtkBrowserView. This would allow easy combination of working with both local and remote documents and is a step toward self-hosting support in Gobby. Merge branch 'inf-browser' Conflicts: ChangeLog.manual infinoted/infinoted-record.c libinfinity/client/infc-browser.c libinfinity/inf-marshal.in libinfinity/server/infd-directory.c libinfinity/server/infd-directory.h commit 8838bf272946116372272e4740593c5330b842ef Author: Armin Burgmeier Date: Fri Jun 14 18:08:41 2013 +0200 infinoted: Add --traffic-log-directory option This allows to specify a directory into which infinoted will write all network traffic, with one file per connection. This is mainly meant for debugging purposes. infinoted/Makefile.am | 2 ++ infinoted/infinoted-config-reload.c | 35 ++++++++++++++++++++++++++++ infinoted/infinoted-options.c | 43 +++++++++++++++++++++++------------ infinoted/infinoted-options.h | 1 + infinoted/infinoted-run.c | 16 +++++++++++++ infinoted/infinoted-run.h | 2 ++ 6 files changed, 85 insertions(+), 14 deletions(-) commit 535e36654ad3f20a12fdda8ba9494725d8641861 Author: Armin Burgmeier Date: Fri Jun 14 18:07:29 2013 +0200 Communication registry: Handle received and sent signals after default handler This allows other signal handlers to reliably run before libinfinity actually handles the signal, for example to stop the signal emission, or to write sent and/or received messages into a log. libinfinity/communication/inf-communication-registry.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) commit f94c882be6405ec47ab8b3c4a85c2cb94947405b Author: Armin Burgmeier Date: Thu Jun 6 22:03:13 2013 +0200 Generate ChangeLog from git log ChangeLog => ChangeLog.manual | 0 Makefile.am | 25 +++++++++++++++++++++++++ 2 files changed, 25 insertions(+) commit 7fd13237ea7cfbe2ea3ea57a8e008e836dd67fbe Author: Armin Burgmeier Date: Thu Jun 6 21:28:00 2013 +0200 Move transformation cache into InfAdoptedRequestLog This is mainly an optimization of the algorithm cleanup routine. Until now, every request made would trigger a traverse through the whole request cache in order to see whether a request needs to be cleaned up or not. This is optimized by instead of maintaining one big cache, maintain for each user which only contains requests made by that user. The requests are primarily sorted by the vector component of that user. The actual cleanup is then done only when requests are removed from the request log itself, instead of for processed request. Also, the tree is only traversed until the first request is found that does not need to be removed -- since the requests are sorted by the user component all other requests would not be removed either. .../libinfinity/libinfinity-0.6-sections.txt | 2 + libinfinity/adopted/inf-adopted-algorithm.c | 182 ++---------------- libinfinity/adopted/inf-adopted-request-log.c | 202 +++++++++++++++++++- libinfinity/adopted/inf-adopted-request-log.h | 8 + 4 files changed, 228 insertions(+), 166 deletions(-) commit d4b8c608e5a7527253e663e55f0b707523c2bccf Author: Armin Burgmeier Date: Thu Jun 6 21:26:55 2013 +0200 Make InfAdoptedStateVector const-correct libinfinity/adopted/inf-adopted-state-vector.c | 37 ++++++++++++------------ libinfinity/adopted/inf-adopted-state-vector.h | 31 ++++++++++---------- 2 files changed, 35 insertions(+), 33 deletions(-) commit 68c65807482ec5465f71c7cbbcda373c5daac9fb Author: Armin Burgmeier Date: Tue Jun 4 16:56:51 2013 +0200 Add InfinotedTransformationProtector This is a utility for infinoted that rejects requests that would require transformation over many requests by other users. This allows to protect the infinoted from users that are many requests behind and keep sending own requests which would put a heavy load on the server. The implementation is a bit hacky at this point. A cleaner solution would be to add a query-execute-request signal to InfAdoptedAlgorithm, or to reject the request on a lower level before execute-request is actually called. infinoted/Makefile.am | 2 + infinoted/infinoted-config-reload.c | 26 ++ infinoted/infinoted-options.c | 32 ++- infinoted/infinoted-options.h | 5 +- infinoted/infinoted-run.c | 16 ++ infinoted/infinoted-run.h | 2 + infinoted/infinoted-transformation-protector.c | 319 +++++++++++++++++++++++ infinoted/infinoted-transformation-protector.h | 56 ++++ 8 files changed, 454 insertions(+), 4 deletions(-) commit 6abb08e27276e6b6549b1fdb2bb87bc97c190ba1 Author: Armin Burgmeier Date: Tue Jun 4 16:51:30 2013 +0200 Add infd_session_proxy_unsubscribe() .../libinfinity/libinfinity-0.6-sections.txt | 1 + libinfinity/server/infd-session-proxy.c | 103 ++++++++++++++------ libinfinity/server/infd-session-proxy.h | 4 + 3 files changed, 77 insertions(+), 31 deletions(-) commit c986056a8c793063370c372f9d2f12202c96ed81 Author: Armin Burgmeier Date: Tue Jun 4 16:45:37 2013 +0200 Add inf_session_cancel_synchronization() .../libinfinity/libinfinity-0.6-sections.txt | 1 + libinfinity/common/inf-session.c | 173 ++++++++++++-------- libinfinity/common/inf-session.h | 4 + 3 files changed, 114 insertions(+), 64 deletions(-) commit 26870147969794199aba23ec863682bec5c2cbb5 Author: Armin Burgmeier Date: Mon Jun 3 14:38:38 2013 +0200 infinoted: Log session errors into log file infinoted/infinoted-log.c | 296 ++++++++++++++++++++++++++++++++------------ 1 file changed, 218 insertions(+), 78 deletions(-) commit e4a978e2c94942556d98fd60c4ef50de64eaef7d Author: Armin Burgmeier Date: Mon Jun 3 14:38:25 2013 +0200 Remove unused includes and variables in inf-communication-central-method.c libinfinity/communication/inf-communication-central-method.c | 4 ---- 1 file changed, 4 deletions(-) commit 65e8f0f271705849b8133be2adc66459d65175d4 Author: Armin Burgmeier Date: Sun Jun 2 22:35:06 2013 +0200 Remove error parameter from inf_communication_object_received() Implement this by adding the InfSession::error signal in InfSession. This allows client code to handle the error in whatever way is approriate, instead of just logging it to stderr. InfSession itself does not know about the nature of the error, or whether it is fatal or not. For example, if a request cannot be processed it would be fatal for a client (or a peer-to-peer participant) but not for a server (infinoted). In the server case, it would simply ignore the request, not forward it to the other clients, keeping the session consistent for everyone but the client sending the erroneous request. libinfinity/client/infc-browser.c | 7 +- libinfinity/client/infc-session-proxy.c | 13 ++- libinfinity/common/inf-session.c | 88 +++++++++++++++++++-- libinfinity/common/inf-session.h | 4 + .../inf-communication-central-method.c | 37 +-------- .../communication/inf-communication-object.c | 6 +- .../communication/inf-communication-object.h | 6 +- libinfinity/inf-marshal.in | 1 + libinfinity/server/infd-directory.c | 5 +- libinfinity/server/infd-session-proxy.c | 11 +-- test/inf-test-text-cleanup.c | 6 +- test/inf-test-text-session.c | 4 +- 12 files changed, 108 insertions(+), 80 deletions(-) commit 61011af0388de99e9a38bfb71aecd0f0b3b16141 Author: Armin Burgmeier Date: Sun Jun 2 22:34:56 2013 +0200 Fix return value in infc_session_proxy_communication_object_received() libinfinity/client/infc-session-proxy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit e940f939d71efe74924371858d82882314583dce Author: Armin Burgmeier Date: Sun Jun 2 17:26:54 2013 +0200 Add timestamps into records for when a request was received end executed libinfinity/adopted/inf-adopted-session-record.c | 33 ++++++++++++++++++++++ 1 file changed, 33 insertions(+) commit 792af0c44b5f81a4e92ae045b12e3983737cc739 Author: Armin Burgmeier Date: Sun Jun 2 17:26:31 2013 +0200 Add reception and execution times times to InfAdoptedRequest .../libinfinity/libinfinity-0.6-sections.txt | 3 + libinfinity/adopted/inf-adopted-algorithm.c | 44 +++++- libinfinity/adopted/inf-adopted-request.c | 163 +++++++++++++++++++- libinfinity/adopted/inf-adopted-request.h | 19 ++- libinftext/inf-text-session.c | 28 +++- libinftext/inf-text-undo-grouping.c | 7 +- 6 files changed, 243 insertions(+), 21 deletions(-) commit 9035666dfce4a8466c8545cbde2c66ab20c6bcc0 Author: Armin Burgmeier Date: Sun Jun 2 17:21:50 2013 +0200 inf_adopted_request_fold(): Fix missing NULL terminator to g_object_new libinfinity/adopted/inf-adopted-request.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) commit 827a5f09eaa29b0601c835faa02413e9183db03d Author: Armin Burgmeier Date: Thu May 30 17:19:40 2013 +0200 inf-test-text-replay: Print warnings before making large transformations Also, warn if executing a specific request has taken very long. This can help in finding problematic requests in a record, or point out when something is worthwhile to optimize. test/inf-test-text-replay.c | 123 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) commit 189d9d11893f519ca87e3ea5c068304ac83ed5a5 Author: Armin Burgmeier Date: Thu May 30 17:17:18 2013 +0200 InfTextUndoGrouping: Don't get stuck with transforming too old requests It could happen that a request was transformed over tens of thousands of other requests if a user waits a long time between two keystrokes, and there was much activity by others between the two keystrokes. In such a case, simply do not group two requests which are very far apart from each other. libinftext/inf-text-undo-grouping.c | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) commit 55a9a324a6c4a78a592ad5d0d521c78d2e6e68fd Author: Armin Burgmeier Date: Thu May 30 12:13:09 2013 +0200 Implement skip parameter for inf-test-reduce-replay this allows, instead of going forward one-by-one, to go in steps of more than one request. This is useful for very big records, where one first needs to get close to where the problem is and then one can carry on in smaller steps to get the most minimal record possible. test/inf-test-reduce-replay.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) commit 949264595f1622a948e8d46e15fc8d53f0c477cd Author: Armin Burgmeier Date: Tue May 28 20:57:10 2013 +0200 Add inf_text_gtk_buffer_set_fade() along with the "alpha" and "background" properties .../libinftextgtk/libinftextgtk-0.6-sections.txt | 1 + libinftextgtk/inf-text-gtk-buffer.c | 140 ++++++++++++++++++-- libinftextgtk/inf-text-gtk-buffer.h | 5 + 3 files changed, 138 insertions(+), 8 deletions(-) commit dc63ce63d82be5442822b54bf1c9146bfd6360e4 Author: Armin Burgmeier Date: Thu May 9 15:55:43 2013 +0200 infinoted: Log extra information during InfAdoptedAlgorithm execute infinoted/infinoted-log.c | 301 +++++++++++++++++++++++++++++++++++++++++ infinoted/infinoted-log.h | 13 ++ infinoted/infinoted-record.c | 34 ++++- infinoted/infinoted-record.h | 5 + infinoted/infinoted-run.c | 10 +- 5 files changed, 359 insertions(+), 4 deletions(-) commit 5837910c043dc77a567648cc84471303a273325f Author: Armin Burgmeier Date: Thu May 9 15:55:32 2013 +0200 Add "filename" property to InfAdoptedSessionRecord libinfinity/adopted/inf-adopted-session-record.c | 23 +++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) commit 706fb1a98d0dc9cda1d0635b7f5a15749a7a5c30 Author: Armin Burgmeier Date: Fri Apr 19 00:55:55 2013 +0200 Implement the InfBrowser interface in InfdDirectory .../libinfinity/libinfinity-0.6-docs.sgml | 2 + .../libinfinity/libinfinity-0.6-sections.txt | 54 +- infinoted/infinoted-autosave.c | 75 +- infinoted/infinoted-directory-sync.c | 84 +- infinoted/infinoted-record.c | 30 +- libinfinity/server/Makefile.am | 4 + libinfinity/server/infd-directory.c | 3113 +++++++++++-------- libinfinity/server/infd-directory.h | 67 +- libinfinity/server/infd-explore-request.c | 252 ++ libinfinity/server/infd-explore-request.h | 73 + libinfinity/server/infd-node-request.h | 66 + 11 files changed, 2432 insertions(+), 1388 deletions(-) commit 72e1d9d7725fe638b096596b4b3258e1df201bd8 Author: Armin Burgmeier Date: Fri Apr 19 00:55:39 2013 +0200 Add a requestor property to InfdNodeRequest libinfinity/server/infd-node-request.c | 298 +++++++++++++++++++++++++++++++ 1 file changed, 298 insertions(+) commit 73e605a34c0b44bb65ad7c04a60b216584cb04bb Author: Armin Burgmeier Date: Fri Apr 19 00:54:09 2013 +0200 Add INF_DIRECTORY_ERROR_SUBSCRIPTION_REJECTED error libinfinity/common/inf-error.c | 2 ++ libinfinity/common/inf-error.h | 3 +++ 2 files changed, 5 insertions(+) commit 991f5e61a3f227cafd1e0d86500cfec5789e6dc0 Author: Armin Burgmeier Date: Fri Apr 19 00:53:36 2013 +0200 Fix signature of inf_browser_(un)subscribe_session() libinfinity/client/infc-browser.c | 14 +++++++++----- libinfinity/common/inf-browser.c | 4 ++-- libinfinity/common/inf-browser.h | 4 ++-- 3 files changed, 13 insertions(+), 9 deletions(-) commit 587e14df08878164b06d831ddaa654651e93c9e1 Author: Armin Burgmeier Date: Mon Apr 15 21:48:04 2013 +0200 Initialize node_id variable in infc_node_request_init() libinfinity/client/infc-node-request.c | 1 + 1 file changed, 1 insertion(+) commit 83b1de1efb199552ee2f8fae8791ae4f63e4d2c7 Author: Armin Burgmeier Date: Mon Apr 15 21:47:39 2013 +0200 Add missing declaration of infc_explore_request_get_initiated() libinfinity/client/infc-explore-request.h | 3 +++ 1 file changed, 3 insertions(+) commit 204a552875adae2a4644ce3333dcf595942baa94 Author: Armin Burgmeier Date: Mon Apr 15 21:46:53 2013 +0200 Fix a typo in InfcExploreRequest documentation libinfinity/client/infc-explore-request.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit d19d7f343b56bd35b11c170b08c853549d92d2ae Author: Armin Burgmeier Date: Sun Apr 14 20:13:48 2013 +0200 Make InfdSessionProxy implement InfSessionProxy .../libinfinity/libinfinity-0.6-docs.sgml | 1 + .../libinfinity/libinfinity-0.6-sections.txt | 16 ++ infinoted/infinoted-autosave.c | 99 ++++--- infinoted/infinoted-directory-sync.c | 92 +++--- infinoted/infinoted-record.c | 18 +- libinfinity/client/infc-user-request.c | 4 +- libinfinity/server/Makefile.am | 2 + libinfinity/server/infd-directory.c | 95 +++++-- libinfinity/server/infd-session-proxy.c | 292 +++++++++++++++----- libinfinity/server/infd-session-proxy.h | 9 - libinfinity/server/infd-user-request.c | 230 +++++++++++++++ libinfinity/server/infd-user-request.h | 64 +++++ 12 files changed, 740 insertions(+), 182 deletions(-) commit 20ad04f34c3fd09395462077490e2d12339f8be2 Author: Armin Burgmeier Date: Sun Apr 14 17:50:40 2013 +0200 Make InfBrowser use InfSessionProxy instead of GObject libinfgtk/inf-gtk-browser-view.c | 45 ++++++++++++++----------------------- libinfinity/client/infc-browser.c | 7 +++--- libinfinity/common/inf-browser.c | 7 +++--- libinfinity/common/inf-browser.h | 11 ++++----- 4 files changed, 30 insertions(+), 40 deletions(-) commit 9b607bf5daaccf6442a32740a0dd077cbdd756ae Author: Armin Burgmeier Date: Sun Apr 14 17:21:37 2013 +0200 Implement InfSessionProxy interface in InfcSessionProxy libinfgtk/inf-gtk-browser-view.c | 51 ++++----- libinfinity/client/infc-browser.c | 63 ++++++++--- libinfinity/client/infc-session-proxy.c | 171 ++++++++++++++---------------- libinfinity/client/infc-session-proxy.h | 11 -- libinftext/inf-text-session.c | 39 +++---- libinftext/inf-text-session.h | 10 +- test/inf-test-chat.c | 22 ++-- test/inf-test-gtk-browser.c | 144 +++++++++++++------------ 8 files changed, 256 insertions(+), 255 deletions(-) commit 9f57d335ac7d2f6759be3793041da4261ff3219e Author: Armin Burgmeier Date: Sun Apr 14 16:15:15 2013 +0200 Add InfSessionProxy interface .../libinfinity/libinfinity-0.6-docs.sgml | 1 + .../libinfinity/libinfinity-0.6-sections.txt | 14 +++ libinfinity/common/Makefile.am | 2 + libinfinity/common/inf-session-proxy.c | 127 ++++++++++++++++++++ libinfinity/common/inf-session-proxy.h | 75 ++++++++++++ 5 files changed, 219 insertions(+) commit 27ba6a2520f542b29f8b7327780c0b1ecfa3b279 Author: Armin Burgmeier Date: Sun Apr 14 15:34:33 2013 +0200 Remove the infc_browser_get_status() function If anything it belongs to InfBrowser. For now, simply ask people to query the "status" property of the browser instead. .../libinfinity/libinfinity-0.6-sections.txt | 1 - libinfinity/client/infc-browser.c | 18 ------------------ libinfinity/client/infc-browser.h | 3 --- test/inf-test-gtk-browser.c | 9 +++++++-- 4 files changed, 7 insertions(+), 24 deletions(-) commit 92f00f5fa337c432660309645b12d3f7e66f17e3 Author: Armin Burgmeier Date: Sun Apr 14 15:31:18 2013 +0200 Add InfUserRequest interface .../libinfinity/libinfinity-0.6-docs.sgml | 1 + .../libinfinity/libinfinity-0.6-sections.txt | 14 ++ libinfinity/client/infc-session-proxy.c | 9 +- libinfinity/client/infc-user-request.c | 82 ++++------- libinfinity/client/infc-user-request.h | 18 +-- libinfinity/common/Makefile.am | 2 + libinfinity/common/inf-user-request.c | 143 ++++++++++++++++++++ libinfinity/common/inf-user-request.h | 73 ++++++++++ 8 files changed, 262 insertions(+), 80 deletions(-) commit 689ee214c855c6b259362cc40e2104abd1cf2a51 Author: Armin Burgmeier Date: Sun Apr 14 13:54:01 2013 +0200 Add InfExploreRequest interface .../libinfinity/libinfinity-0.6-docs.sgml | 3 +- .../libinfinity/libinfinity-0.6-sections.txt | 13 ++ libinfgtk/inf-gtk-browser-view.c | 102 ++++++------ libinfinity/client/infc-browser.c | 9 +- libinfinity/client/infc-explore-request.c | 163 +++++--------------- libinfinity/client/infc-explore-request.h | 13 +- libinfinity/client/infc-node-request.c | 14 +- libinfinity/common/Makefile.am | 2 + libinfinity/common/inf-browser.c | 14 +- libinfinity/common/inf-browser.h | 13 +- libinfinity/common/inf-explore-request.c | 117 ++++++++++++++ libinfinity/common/inf-explore-request.h | 58 +++++++ libinfinity/common/inf-node-request.c | 20 +-- 13 files changed, 294 insertions(+), 247 deletions(-) commit 28bb206521cd4ec8c20239faaf81ac34aa9d1276 Author: Armin Burgmeier Date: Sun Apr 14 11:48:48 2013 +0200 Make iter argument of inf_gtk_browser_model_browser_iter_to_tree_iter const libinfgtk/inf-gtk-browser-model-filter.c | 4 ++-- libinfgtk/inf-gtk-browser-model-sort.c | 4 ++-- libinfgtk/inf-gtk-browser-model.c | 13 ++++--------- libinfgtk/inf-gtk-browser-model.h | 4 ++-- libinfgtk/inf-gtk-browser-store.c | 10 +++++----- 5 files changed, 15 insertions(+), 20 deletions(-) commit 83018965592d093992c378220cabeed730f2686f Author: Armin Burgmeier Date: Sat Apr 13 21:31:41 2013 +0200 Rename InfBrowserRequest to InfNodeRequest TODO | 1 - .../libinfinity/libinfinity-0.6-docs.sgml | 2 +- .../libinfinity/libinfinity-0.6-sections.txt | 20 +++--- libinfgtk/inf-gtk-browser-store.c | 20 +++--- libinfgtk/inf-gtk-browser-view.c | 10 +-- libinfinity/client/infc-browser.c | 42 +++++------ libinfinity/client/infc-node-request.c | 28 ++++---- libinfinity/common/Makefile.am | 4 +- libinfinity/common/inf-browser.c | 46 ++++++------ libinfinity/common/inf-browser.h | 30 ++++---- .../{inf-browser-request.c => inf-node-request.c} | 78 ++++++++++----------- .../{inf-browser-request.h => inf-node-request.h} | 40 +++++------ 12 files changed, 159 insertions(+), 162 deletions(-) commit 6fd14122a7502cfc46331a60f28e0acd0e78395d Author: Armin Burgmeier Date: Sat Apr 13 21:11:04 2013 +0200 Make InfcBrowser implement InfBrowser TODO | 27 +- .../libinfinity/libinfinity-0.6-docs.sgml | 4 +- libinfgtk/inf-gtk-browser-model-filter.c | 6 +- libinfgtk/inf-gtk-browser-model-sort.c | 6 +- libinfgtk/inf-gtk-browser-model.c | 14 +- libinfgtk/inf-gtk-browser-model.h | 12 +- libinfgtk/inf-gtk-browser-store.c | 423 ++-- libinfgtk/inf-gtk-browser-view.c | 377 +-- libinfinity/client/Makefile.am | 4 +- libinfinity/client/infc-browser-iter.c | 98 - libinfinity/client/infc-browser-iter.h | 49 - libinfinity/client/infc-browser.c | 2346 ++++++++----------- libinfinity/client/infc-browser.h | 201 +- libinfinity/client/infc-chat-request.c | 293 +++ libinfinity/client/infc-chat-request.h | 78 + libinfinity/client/infc-explore-request.c | 293 +-- libinfinity/client/infc-explore-request.h | 29 +- libinfinity/client/infc-node-request.c | 193 +- libinfinity/client/infc-node-request.h | 26 +- libinfinity/client/infc-request-manager.c | 45 +- libinfinity/client/infc-request.c | 283 +-- libinfinity/client/infc-request.h | 44 +- libinfinity/client/infc-session-proxy.c | 14 +- libinfinity/client/infc-user-request.c | 198 +- libinfinity/client/infc-user-request.h | 28 +- test/inf-test-browser.c | 73 +- test/inf-test-chat.c | 162 +- test/inf-test-gtk-browser.c | 225 +- 28 files changed, 2540 insertions(+), 3011 deletions(-) commit f61334b08604948a49028f50fb9fedcc9fd34d8d Author: Armin Burgmeier Date: Wed Apr 10 22:30:09 2013 +0200 Allow sessions and requests to be global in the InfBrowser interface libinfinity/common/inf-browser.c | 49 ++++++++++++++++++++++---------------- libinfinity/common/inf-browser.h | 5 ++-- 2 files changed, 31 insertions(+), 23 deletions(-) commit 7006e0eb6474ffd90b576ba647dcb99ec44e9aff Author: Armin Burgmeier Date: Wed Apr 10 22:29:41 2013 +0200 Fix a typo in InfBrowserRequest::finished signal declaration libinfinity/common/inf-browser-request.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit 82ea7ffed0fb31c617a58c3918fe56ecd2a9bd1a Author: Armin Burgmeier Date: Mon Apr 8 21:14:32 2013 +0200 Make the type property in InfRequest construct-only libinfinity/common/inf-request.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) commit af894f1e60d2ec35f1bcec74b5957d4457a42f14 Author: Armin Burgmeier Date: Mon Apr 8 21:14:22 2013 +0200 Add INF_DIRECTORY_ERROR_NOT_INITIATED error libinfinity/common/inf-error.c | 5 ++++- libinfinity/common/inf-error.h | 7 +++++-- 2 files changed, 9 insertions(+), 3 deletions(-) commit 9d37b1cd8737a839c5ebed50b099c71de1865f31 Author: Armin Burgmeier Date: Mon Apr 8 21:13:50 2013 +0200 Make the InfBrowserIter argument in InfBrowser signals const libinfinity/common/inf-browser.c | 10 +++++----- libinfinity/common/inf-browser.h | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) commit 1571ddd27941daa30a56e138583de8361f034b07 Author: Armin Burgmeier Date: Mon Apr 8 21:13:16 2013 +0200 Expand a bit on the inf_browser_add_note() documentation Also, add some extra sanity checks libinfinity/common/inf-browser.c | 44 +++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) commit 2bc2544ccac6c4cb4e60c43f34b20621bacd21b3 Author: Armin Burgmeier Date: Mon Apr 8 21:08:32 2013 +0200 Remove a useless prerequisite in InfBrowserRequest libinfinity/common/inf-browser-request.c | 1 - 1 file changed, 1 deletion(-) commit 840c752e76eaf2f776e60e8fde76b650423a8911 Author: Armin Burgmeier Date: Mon Apr 8 21:06:43 2013 +0200 Make inf_browser_iter_copy() take a const InfBrowserIter libinfinity/common/inf-browser-iter.c | 2 +- libinfinity/common/inf-browser-iter.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) commit 42fedd0706d9ae74adddc14ebe734994fbb3d4f7 Author: Armin Burgmeier Date: Sun Apr 7 11:48:29 2013 +0200 Add InfRequest interface .../libinfinity/libinfinity-0.6-docs.sgml | 1 + .../libinfinity/libinfinity-0.6-sections.txt | 13 +++ libinfinity/common/Makefile.am | 2 + libinfinity/common/inf-browser-request.c | 15 +-- libinfinity/common/inf-request.c | 119 ++++++++++++++++++++ libinfinity/common/inf-request.h | 66 +++++++++++ 6 files changed, 204 insertions(+), 12 deletions(-) commit 3cb4273c325ed8199da14ec1133acabba1029fa6 Author: Armin Burgmeier Date: Sat Apr 6 19:36:52 2013 +0200 Add inf_browser_is_subdirectory() And check that a node is (not) a subdirectory in the other browser functions. libinfinity/common/inf-browser.c | 64 +++++++++++++++++++++++++++++++------- libinfinity/common/inf-browser.h | 14 +++++---- 2 files changed, 61 insertions(+), 17 deletions(-) commit 6150df688133f2671cd5b89c9bbfc92af57e370a Author: Armin Burgmeier Date: Mon Feb 6 23:11:13 2012 +0100 Add unsubscribe-session signal to InfBrowser libinfinity/common/inf-browser.c | 54 ++++++++++++++++++++++++++++++++++++++ libinfinity/common/inf-browser.h | 9 +++++++ 2 files changed, 63 insertions(+) commit 2b79c904bbec4219557487b1a908e0b91cc11cd3 Author: Armin Burgmeier Date: Sun Jan 22 23:22:33 2012 +0100 Add the InfBrowser interface ChangeLog | 18 +- .../libinfinity/libinfinity-0.6-docs.sgml | 3 + .../libinfinity/libinfinity-0.6-sections.txt | 65 ++ libinfinity/common/Makefile.am | 6 + libinfinity/common/inf-browser-iter.c | 98 ++ libinfinity/common/inf-browser-iter.h | 48 + libinfinity/common/inf-browser-request.c | 165 ++++ libinfinity/common/inf-browser-request.h | 73 ++ libinfinity/common/inf-browser.c | 957 ++++++++++++++++++++ libinfinity/common/inf-browser.h | 291 ++++++ libinfinity/common/inf-discovery.h | 2 +- libinfinity/inf-marshal.in | 1 + 12 files changed, 1723 insertions(+), 4 deletions(-) commit c53f28a28c740ef187a864d2b00e40079c2a993d Author: Armin Burgmeier Date: Sun Jan 20 23:07:55 2013 +0100 Make infinoted log glib errors Such as failed assertions or preconditions. infinoted/infinoted-log.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ infinoted/infinoted-log.h | 2 ++ 2 files changed, 46 insertions(+) 2012-11-26 Armin Burgmeier * libinfinity/common/inf-xmpp-connection.c (inf_xmpp_connection_send_xml): Don't crash when the connection is deleted during the sent callback. 2012-11-26 Armin Burgmeier * libinftextgtk/inf-text-gtk-view.c: Fix assertion fail at drawing selection of not yet fully synchronized document. 2012-11-11 Armin Burgmeier * infinoted/infinoted-log.c: Log an info message when a connection is added or removed. 2012-11-11 Armin Burgmeier * libinfinity/server/infd-directory.h: * libinfinity/server/infd-directory.c: Added connection-added and connection-removed signals. 2012-11-10 Armin Burgmeier * infinoted/infinoted-log.h: * infinoted/infinoted-log.c: * infinoted/Makefile.am: Add a new object which encapsulates the logging facilities in a class. It can additionally log to a file, and it has an interface to monitor a InfdDirectory for "interesting" events to happen that can then be logged (not implemented yet). * infinoted/infinoted-options.h: * infinoted/infinoted-options.c: Add a --log-path (-l) parameter which, if given, specifies the path to a log file that is written to in addition to logging to syslog and/or stderr. * infinoted/infinoted-util.h: * infinoted/infinoted-util.c: Remove logging functions from infinoted-util. * infinoted/infinoted-config-reload.c: * infinoted/infinoted-dh-params.h: * infinoted/infinoted-dh-params.c: * infinoted/infinoted-directory-sync.h: * infinoted/infinoted-directory-sync.c: * infinoted/infinoted-note-plugin.h: * infinoted/infinoted-note-plugin.c: * infinoted/infinoted-main.c: * infinoted/infinoted-pam.h: * infinoted/infinoted-pam.c: * infinoted/infinoted-run.c: * infinoted/infinoted-signal.c: * infinoted/infinoted-startup.h: * infinoted/infinoted-startup.c: Migrate to new API. 2012-10-21 Armin Burgmeier * libinfinity/common/inf-xmpp-connection.c: Fix a crash that could occur when it is noticed at send time that a connection is down. * test/inf-test-mass-join.c: * test/Makefile.am: Add a test which connects 128 users simultaneously to an infinote server. Disconnecting all these users at once is a way to reproduce the crash the above change fixes. 2012-10-21 Armin Burgmeier * libinfinity/client/infc-browser.c (infc_browser_handle_explore_end): Allow the browser to be disconnected during the request callback. 2012-06-09 Philipp Kern * libinfinity/communication/inf-communication-method.c (inf_communication_method_received): Do not return without a value from a non-void function. 2012-06-02 Philipp Kern * test/Makefile.am: Add non-interactive tests to `make check'. (Except for text-replay, which takes a long time to complete and needs additional CLI parameters.) 2012-06-02 Philipp Kern * configure.ac: Check for libm for libinftextgtk (uses atan2, floor and sin/cos). 2012-05-30 Colomban Wendling * libinfgtk/inf-gtk-browser-model.c: * libinfinity/client/infc-browser.c: * libinfinity/common/inf-xml-connection.c: InfXmlConnectionStatus, InfcBrowserStatus and InfGtkBrowserModelStatus GType registration code missed an array sentinel leading to GType reading invalid memory paste the end of the array. 2012-05-13 Armin Burgmeier * libinfinity/common/inf-simulated-connection.c (inf_simulated_connection_set_property): Allow the value for PROP_IO to be NULL. This is especially important to avoid a warning when the connection is created without an InfIo object at all, since set_property is called by GObject in this case with a NULL InfIo. This is because PROP_IO is a G_PARAM_CONSTRUCT_ONLY property. 2012-05-13 Armin Burgmeier * test/inf-test-text-recover.c: * test/Makefile.am: Add inf-test-text-recover, a tool similar to inf-test-text-replay which aims at recovering text from a record which was, accidentally or not, deleted by a user. 2012-03-18 Philipp Kern * libinfgtk.pc.in: * libinftextgtk.pc.in: Reference the correct lib when built with Gtk3 support. 2012-03-18 Philipp Kern * docs/reference/libinfgtk/Makefile.am: * docs/reference/libinftextgtk/Makefile.am: Reference the correct lib when built with Gtk3 support. 2012-03-18 Philipp Kern * test/Makefile.am: Reference the correct lib when built with Gtk3 support. 2012-03-17 Philipp Kern * Makefile.am: * configure.ac: * libinfgtk/Makefile.am: * libinftextgtk/Makefile.am: Rework Gtk3 support. libinfgtk and libinftextgtk are renamed to libinfgtk3 and libinftextgtk3 when Gtk3 support is requested. This is reflected in the library names, pkg-config files, but not in the header subdirs. This does mean that old binaries linked against a Gtk3 libinf(text)?gtk will break. On the other hand this seems to be the better way than breaking old binaries linked against a Gtk2 libinfgtk when libinfinity is (re)built with Gtk3 support, given that Gtk3 support is optional. Reverse dependencies also need to specify the Gtk3 variant explicitly by using the right pkg-config names. 2012-03-17 Philipp Kern * INSTALL: Boilerplate content updated. 2012-02-07 Armin Burgmeier * libinfgtk/inf-gtk-certificate-manager.c (inf_gtk_certificate_manager_certificate_func): Fix a crash when the certificate has no hostname set. 2012-01-22 Armin Burgmeier * libinfinity/common/inf-discovery.c: Indicate title and stability in docs comment block. 2012-01-09 Dominique Leuenberger * infinoted/infinoted-creds.h: * infinoted/infinoted-util.h: * libinfinity/common/inf-xml-util.h: Fix compilation with glib 2.31. 2011-10-24 Fabian Henze * infinoted/infinoted-autosave.h: * infinoted/infinoted-autosave.c: * infinoted/infinoted-directory-sync.h: * infinoted/infinoted-directory-sync.c: * infinoted/infinoted-options.h: * infinoted/infinoted-options.c: * infinoted/infinoted-run.c: * infinoted/infinoted-config-reload.c: Added the autosave-hook and sync-hook options. 2011-10-13 Philipp Kern * infinoted/infinoted-0.6.man: * infinoted/infinoted-options.c: State that sync interval is in seconds. 2011-08-28 Philipp Kern * infinoted/infinoted-0.6.man: Update whatis entry to be actually useful. 2011-08-09 Armin Burgmeier * libinftext/inf-text-session.c (inf_text_session_join_user): Set caret position property correctly as given, and avoid a warning. 2011-08-09 Armin Burgmeier * libinfinity/common/inf-xmpp-connection.c: Fix a crash when the initial message contains invalid UTF-8. 2011-08-01 Armin Burgmeier * infinoted/infinoted-config-reload.c (infinoted_config_reload): Update directory sync on config reload. 2011-08-01 Armin Burgmeier * infinoted/infinoted-directory-sync.c (infinoted_directory_sync_remove_session): Do not run into an assertion failue if the removed session had a timeout running. 2011-08-01 Armin Burgmeier * libinfinity/common/inf-standalone-io.c (inf_standalone_io_iteration_impl): Wait for the earliest timeout, not for the latest one. 2011-07-17 Armin Burgmeier * infinoted/infinoted-pam.c: Fix pam_appl.h include on MacOS X (#563, nairboon). 2011-06-27 Armin Burgmeier * libinftext/inf-text-chunk.c: Use g_utf8_offset_to_pointer() instead of iconv to determine the byte offset in a segment when the chunk is UTF-8 encoded. This is a significant perforamnce improvement for long segments. 2011-06-23 Philipp Kern * configure.ac: Print if PAM support is enabled or not. 2011-06-19 Benjamin Herr * libinfinity/server/infd-directory.c (infd_directory_node_is_name_available): Disallow node names containing non-printable or only space characters. 2011-06-19 Armin Burgmeier * libinfinity/server/infd-directory.c (infd_directory_node_is_name_available): Enable localization of two error messages. 2011-06-14 Armin Burgmeier * libinftext/inf-text-session.h: * libinftext/inf-text-session.c: Add inf_text_session_join_user() convenience function. 2011-06-02 Armin Burgmeier * libinfinity/server/infd-directory.c: When unlinking a session that keep a weak reference to the session around, in order to re-use it when it is needed again. 2011-06-02 Armin Burgmeier * libinfinity/server/infd-directory.c (infd_directory_add_note): Do not leak a reference on the subscription group. 2011-05-10 Armin Burgmeier * libinfinity/server/infd-directory.c (infd_directory_node_get_and_link_session): Only call infd_directory_node_link_session() if the session is not yet linked, otherwise an assertion fails. This could happen if the infd_directory_iter_get_session() public API function was called when the session existed already. 2011-03-27 Armin Burgmeier * configure.ac: Post-release bump to 0.6.0 * docs/reference/libinfgtk/libinfgtk-0.6-docs.sgml: * docs/reference/libinfgtk/libinfgtk-0.6-overrides.txt: * docs/reference/libinfgtk/libinfgtk-0.6-sections.txt: * docs/reference/libinfinity/libinfinity-0.6-docs.sgml: * docs/reference/libinfinity/libinfinity-0.6-overrides.txt: * docs/reference/libinfinity/libinfinity-0.6-sections.txt: * docs/reference/libinftext/libinftext-0.6-docs.sgml: * docs/reference/libinftext/libinftext-0.6-overrides.txt: * docs/reference/libinftext/libinftext-0.6-sections.txt: * docs/reference/libinftextgtk/libinftextgtk-0.6-docs.sgml: * docs/reference/libinftextgtk/libinftextgtk-0.6-overrides.txt: * docs/reference/libinftextgtk/libinftextgtk-0.6-sections.txt: * infinoted/infinoted-0.6.man: * infinoted/Makefile.am: * libinfgtk/Makefile.am: * libinfinity/Makefile.am: * libinftext/Makefile.am: * libinftextgtk/Makefile.am: Bump API version to 0.6. 2011-03-27 Armin Burgmeier * === Released 0.5.0 === * NEWS: Update for release. * infinoted/Makefile.am: Distribute the manpage since it is not generated. * docs/reference/Makefile.am: * docs/reference/libinfgtk/Makefile.am: * docs/reference/libinfinity/Makefile.am; * docs/reference/libinftext/Makefile.am: * docs/reference/libinftextgtk/Makefile.am: Fix make distcheck with recent gtk-doc. 2011-02-23 Armin Burgmeier * libinfinity/client/infc-note-plugin.h: * libinfinity/server/infd-note-plugin.h: Add typedefs for the function pointers used to be more friendly to binding generators. 2011-02-21 Armin Burgmeier * libinfinity/adopted/inf-adopted-undo-grouping.c (inf_adopted_undo_grouping_class_init): Fix struct offset of the group_requests signal. 2011-01-30 Armin Burgmeier * libinftext/inf-text-session.c (inf_text_session_get_xml_user_props): If the "selection" attribute is not set, default to zero. Otherwise an invalid selection might arise if the selection-length of a rejoined user is kept but caret-position is set to another value. 2011-01-30 Armin Burgmeier * libinftextgtk/inf-text-gtk-view.c (inf_text_gtk_view_expose_event_after_cb): Add a few assertions to make sure our internal state is OK. 2011-01-30 Armin Burgmeier * libinftextgtk/inf-text-gtk-viewport.c (inf_text_gtk_viewport_remove_user): Remove remote cursor position indicator when the corresponding client leaves. 2011-01-30 Armin Burgmeier * libinftextgtk/inf-text-gtk-viewport.c: Adapt remote cursor position indicator when the scrollbar's adjustment changes. This happens for example when GtkTextView lazily computes the height of the text. 2011-01-29 Armin Burgmeier * libinftextgtk/inf-text-gtk-viewport.c: Fix display of remote cursor position in scrollbar with GTK+ 3, and make the marker a bit nicer. 2011-01-29 Armin Burgmeier * libinftextgtk/inf-text-gtk-view.c (inf_text_gtk_view_expose_event_after_cb): With GTK+ 3, fix remote cursors not being drawn if remote selections are not activated to be drawn. 2011-01-23 Armin Burgmeier * all source files: Add 2011 to copyright years. 2011-01-23 Armin Burgmeier * configure.ac: * libinfgtk.pc.in: * libinftextgtk.pc.in: Add a gtk_version variable for pkg-config and request the correct GTK+ version in the pkg-config file. 2011-01-17 Armin Burgmeier * libinfinity/communication/inf-communication-group-private.h: * libinfinity/communication/inf-communication-group.c: Add a private _inf_communication_group_foreach_method() function. * libinfinity/communication/inf-communication-method.h: * libinfinity/communication/inf-communication-method.c: * libinfinity/communication/inf-communication-central-method.c: Change the return type of the _received vfunc to InfCommunicationScope, returning the scope given by the InfCommunicationObject target. * libinfinity/communication/inf-communication-registry.c (inf_communication_registry_received_cb): Relay any received messages with INF_COMMUNICATION_SCOPE_GROUP to connections in other networks of the same group. 2011-01-17 Armin Burgmeier * libinftext/inf-text-undo-grouping.c: Fix two typos in comments. 2011-01-17 Armin Burgmeier * README: Add new gthread-2.0 dependency to the README file. 2011-01-14 Philipp Kern * infinoted/Makefile.am: * infinoted/infinoted-0.5.man: add a manpage for infinoted 2011-01-01 Elliot Kroo * libinfinity/server/infd-filesystem-storage.c (infd_filesystem_storage_remove_rec): If g_unlink fails with EPERM then this can also mean that the file being unlinked is a directory, so also try to recurse in this case. This fixes node removal on Mac OS X. 2010-12-25 Armin Burgmeier * libinfinity/common/inf-standalone-io.c: Don't confuse dispatch list with timeout list on dispatch invocation. * libinfinity/common/inf-sasl-context.h: * libinfinity/common/inf-sasl-context.c: * libinfinity/common/Makefile.am: Add InfSaslContext, which provides a wrapper for Gsasl. It provides an asynchronous callback mechanism, implemented via an extra thread for each authentication session. * libinfinity/common/inf-discovery-avahi.h: * libinfinity/common/inf-discovery-avahi.c: * libinfinity/common/inf-xmpp-connection.h: * libinfinity/common/inf-xmpp-connection.c: * libinfinity/server/infd-xmpp-server.h: * libinfinity/server/infd-xmpp-server.c: * infinoted/infinoted-startup.h: * infinoted/infinoted-startup.c: * infinoted/infinoted-run.h: * infinoted/infinoted-run.c: * infinoted/infinoted-pam.h: * infinoted/infinoted-config-reload.c: Replace Gsasl usage by InfSaslContext and adapt to API changes. 2010-12-25 Armin Burgmeier * libinfinity/common/inf-xmpp-connection.c (inf_xmpp_connection_terminate): If sending an authentication abort, then free the corresponding XML node afterwards. * libinfinity/server/infd-directory.c (infd_directory_dispose): Free the connections hash table. * libinfinity/server/infd-filesystem-storage.c (infd_filesystem_storage_storage_read_subdirectory): Close the DIR* returned by fdopendir(). * infinoted/infinoted-run.c (infinoted_run_start): If the IPv6 server could start but the IPv4 server couldn't (or vice versa), then still free the error from the failing server. 2010-12-25 Armin Burgmeier * libinfgtk/inf-gtk-io.c: Fix a possible race condition. 2010-12-25 Armin Burgmeier * libinfgtk/inf-gtk-browser-view.c (inf_gtk_browser_view_browser_added): Remove two unused variables. 2010-12-25 Armin Burgmeier * libinfinity/common/inf-standalone-io.c (inf_standalone_io_wakeup): Make this actually work by writing to the writing end of the pipe, not to the reading end. 2010-12-14 Felix Kaser * libinftextgtk/inf-text-gtk-hue-chooser.c: Use get_preferred_width and get_preferred_height instead of size_request when building against recent enough GTK+ 3, fixing the build. 2010-11-27 Armin Burgmeier * libinfgtk/inf-gtk-io.c (inf_gtk_io_dispatch_func): Fix a crash when a dispatch handler is supposed to be called (Felix Kaser). 2010-11-27 Armin Burgmeier * libinfinity/common/inf-simulated-connection.h: * libinfinity/common/inf-simulated-connection.c: Add INF_SIMULATED_CONNECTION_IO_CONTROLLED mode. 2010-11-27 Armin Burgmeier * libinfinity/common/inf-simulated-connection.c (inf_simulated_connection_connect): Improve the docs to make it clear that the function needs only to be called once for both connections to be connected to each other. 2010-11-24 Armin Burgmeier * libinfgtk/inf-gtk-browser-view.c (inf_gtk_browser_view_browser_added): Check for browser status to be connected instead of connection status before doing initial root exploration. Otherwise it can happen that the browser is not yet ready for exploration in case it is still waiting for the server's welcome message (Felix Kaser). 2010-11-21 Armin Burgmeier * libinfinity/common/inf-certificate-chain.h: * libinfinity/common/inf-chat-session.c: * libinfinity/common/inf-error.h: * libinfinity/common/inf-io.h: * libinfinity/common/inf-io.c: * libinfinity/common/inf-local-publisher.h: * libinfinity/common/inf-protocol.c: * libinfinity/common/inf-session.h: * libinfinity/common/inf-session.c: * libinfinity/common/inf-xmpp-manager.c: * libinfinity/communication/inf-communication-factory.h: * libinfinity/communication/inf-communication-object.h: * libinfinity/client/infc-browser.h: * libinfinity/client/infc-browser.c: * libinfinity/client/infc-explore-request.h: * libinfinity/client/infc-explore-request.c: * libinfinity/server/infd-directory.c: * libinfinity/server/infd-session-proxy.c: * libinfinity/adopted/inf-adopted-algorithm.c: * libinfinity/adopted/inf-adopted-session.c: * libinfinity/adopted/inf-adopted-state-vector.c: * libinfinity/adopted/inf-adopted-undo-grouping.c: Some documentation fixes. 2010-11-01 Armin Burgmeier * libinfinity/common/inf-xmpp-connection.c (inf_xmpp_connection_sasl_error): Don't assert that sasl session is set since it can happen that it isn't in case the SASL session cannot be initiated. 2010-11-01 Armin Burgmeier * libinfinity.pc.in: * configure.ac: Require and link against gthread-2.0. 2010-10-31 Armin Burgmeier * infinoted/infinoted-record.c (infinoted_record_new): Initialize the record->records list to NULL. 2010-10-31 Armin Burgmeier * libinfinity/common/inf-io.h: * libinfinity/common/inf-io.c: Change the watch interface slightly, add inf_io_add_dispatch() and inf_io_remove_dispatch() and require implementations to be thread-safe. * libinfinity/common/inf-standalone-io.c: * libinfgtk/inf-gtk-io.c: Adapt, and provide thread-safety. * libinfinity/common/inf-init.c: Call g_thread_init as a part of the libinfinity startup procedure. * libinfinity/common/inf-discovery-avahi.c: * libinfinity/common/inf-tcp-connection.c: * libinfinity/adopted/inf-adopted-session.c: * libinfinity/client/infc-browser.c: * libinfinity/server/infd-directory.c: * libinfinity/server/infd-tcp-server.c: * libinftext/inf-text-session.c: * libinftextgtk/inf-text-gtk-view.c: * infinoted/infinoted-signal.h: * infinoted/infinoted-signal.c: * infinoted/infinoted-autosave.c: * infinoted/infinoted-directory-sync.c: * test/inf-test-browser.c: * test/inf-test-chat.c: * test/inf-test-tcp-connection.c: Adapt to the API changes. 2010-10-09 Armin Burgmeier * libinfinity/client/infc-browser.c (infc_browser_disconnected): Discard the browser's chat session on disconnection. 2010-10-09 Armin Burgmeier * test/inf-test-gtk-browser.c: Add a missing include. 2010-10-06 Armin Burgmeier * libinfinity/common/inf-xmpp-connection.c (inf_xmpp_connection_sax_end_element): Fix an assertion so that the ending top-level tag is allowed not to be stream:stream if the connection is going to be terminated. This can happen if the opening and closing XML tag is sent in one go so that both are processed by the parser. The XML handler for the start element will then terminate the connection. Bug #546. 2010-10-03 Armin Burgmeier * libinfinity/communication/inf-communication-central-method.c (inf_communication_central_method_send_all): Make the code aware of the send callback modifying the connection list. 2010-10-03 Armin Burgmeier * libinftext/inf-text-remote-delete-operation.c (inf_text_remote_delete_operation_transform_split): When a remote delete operation is splitted, make sure to keep the recon order in the splitted operations. Also fix recon position index in the second operation. * test/session/test-53.xml: * test/replay/replay-11.record.xml: Add a test and a record which make libinfinity run into a failed assertion when reconstructing the delete operation without this being fixed. 2010-10-02 Armin Burgmeier * test/inf-test-gtk-browser.c (main): Allow to open connections via their IP address when given as commandline arguments. 2010-10-02 Jesse van den Kieboom * libinfgtk/inf-gtk-browser-view.c: * libinftextgtk/inf-text-gtk-hue-chooser.c: * libinftextgtk/inf-text-gtk-view.c: * libinftextgtk/inf-text-gtk-viewport.c: Adapt for latest GTK+3. 2010-09-21 Armin Burgmeier * libinftextgtk/inf-text-gtk-view.h: * libinftextgtk/inf-text-gtk-view.c: Add inf_text_gtk_view_set_show_remote_cursors(), inf_text_gtk_view_set_show_remote_selections() and inf_text_gtk_view_set_show_remote_current_lines(). * libinftextgtk/inf-text-gtk-viewport.h: * libinftextgtk/inf-text-gtk-viewport.c: Add inf_text_gtk_viewport_set_show_user_markers(). 2010-09-19 Armin Burgmeier * libinfgtk/inf-gtk-browser-view.c: * libinfgtk/inf-gtk-certificate-dialog.c: * libinfgtk/inf-gtk-certificate-manager.c: * libinfgtk/inf-gtk-chat.c: * libinftextgtk/inf-text-gtk-hue-chooser.c: Fix the GTK+2 build (#545). 2010-09-19 Armin Burgmeier * infinoted/infinoted-main.c: Include and , so that umask() is available (fixes the build on Ubuntu). 2010-09-19 Armin Burgmeier * libinfinity/server/infd-tcp-server.c (infd_tcp_server_io): Fix a compiler warning. 2010-09-17 Armin Burgmeier * libinfgtk/inf-gtk-browser-view.c: * libinfgtk/inf-gtk-certificate-dialog.c: * libinfgtk/inf-gtk-certificate-manager.c: * libinfgtk/inf-gtk-chat.c: * libinftextgtk/inf-text-gtk-hue-chooser.c: Adapt to recent changes in GTK+ 3. 2010-08-22 Jesse van den Kieboom * libinfinity/common/inf-protocol.h: * libinfinity/common/inf-protocol.c: Add inf_protocol_get_default_port(). * infinoted/infinoted-options.c: * test/inf-test-browser.c: * test/inf-test-chat.c: * test/inf-test-daemon.c: Make use of the new function instead of hardcoding the port value. 2010-08-22 Jesse van den Kieboom * libinftextgtk/inf-text-gtk-hue-chooser.c (inf_text_gtk_hue_chooser_realize): Set correct user_data for correct window, fixing the behavior of the hue chooser. 2010-08-15 Armin Burgmeier * configure.ac: Added a --with-gtk3 switch which makes libinfgtk and libinftexgtk build against GTK+ 3. * libinfgtk/inf-gtk-browser-model-filter.h: * libinfgtk/inf-gtk-browser-model-sort.h: * libinfgtk/inf-gtk-browser-model.h: * libinfgtk/inf-gtk-browser-store.h: * libinfgtk/inf-gtk-browser-store.c: * libinfgtk/inf-gtk-browser-view.h: * libinfgtk/inf-gtk-browser-view.c: * libinfgtk/inf-gtk-certificate-dialog.c: * libinfgtk/inf-gtk-certificate-manager.c: * libinfgtk/inf-gtk-certificate-view.c: * libinfgtk/inf-gtk-chat.c: * libinftextgtk/inf-text-gtk-buffer.h: * libinftextgtk/inf-text-gtk-hue-chooser.h: * libinftextgtk/inf-text-gtk-hue-chooser.c: * libinftextgtk/inf-text-gtk-view.h: * libinftextgtk/inf-text-gtk-view.c: * libinftextgtk/inf-text-gtk-viewport.h: * libinftextgtk/inf-text-gtk-viewport.c: Make libinfgtk and libinftextgtk compile with GTK+ 3. This involves adhering to the single include policy and replacing some sealed struct member accesses with their corresponding accessor functions. 2010-08-15 Armin Burgmeier * libinfinity/common/inf-chat-session.c (inf_chat_session_user_join, inf_chat_session_user_part): Set correct flags for userjoin and userpart messages. 2010-08-15 Armin Burgmeier * libinfinity/common/inf-chat-session.c (inf_chat_session_to_xml_sync): Fix sending chat backlog to clients which was broken since 2010-03-12. 2010-08-15 Armin Burgmeier * test/inf-test-gtk-browser.c: Fixed a crash when closing the chat or session window while joining. Also do not attempt to rejoin with the same user name all the time if the user name is in use already. 2010-08-08 Armin Burgmeier * libinfinity/server/infd-tcp-server.c: Add debugging code to observe badly-behaving accept(). There was a case where accept() returned a valid but non-connected socket which brought down the infinoted server due to getpeername failing. I want to find out more about when exactly this happens and how this can be catched instead of just fixing the symptoms. 2010-06-25 Armin Burgmeier * libinftextgtk/inf-text-gtk-buffer.h: * libinftextgtk/inf-text-gtk-buffer.c: Added inf_text_gtk_buffer_get_user_for_tag(). 2010-06-05 Armin Burgmeier * libinftext/inf-text-move-operation.c (inf_text_move_operation_transform_insert, inf_text_move_operation_transform_delete): Make the delete transformation work correctly when deleting characters from within the selection, make the insert transformation not expand the selection when inserting at the selection bounds. 2010-06-05 Armin Burgmeier * libinftextgtk/inf-text-gtk-view.c: * libinftextgtk/inf-text-gtk-viewport.c: Avoid use of symbols not available in GTK+ 2.12. 2010-06-04 Armin Burgmeier * libinfinity/inf-marshal.in: Remove the VOID:UINT,UINT,OBJECT marshaller. * libinftext/inf-text-buffer.h: * libinftext/inf-text-buffer.c: Rename the insert-text and erase-text signals to text-inserted and text-erased, and make them RUN_FIRST signals. This does not require the signal to be emitted to insert or remove text, but if a modification to the buffer happens externally then the signal can (and should!) still be emitted afterwards. Also, turn the lengeth parameter of the text-erased signal to a InfTextChunk* chunk parameter, so that it is still possible to find out what text was deleted afterwards. * libinftextgtk/inf-text-gtk-buffer.c: Do not stop emission of GtkTextBuffer's insert-text and delete-range signals in our signal handlers. This allows other signal handlers to rely on proper signal emission and makes us handle recursive emissions correctly. * libinftext/inf-text-default-buffer.c: * libinftext/inf-text-session.c: * infinoted/infinoted-directory-sync.c: Adapt for the API change. 2010-05-21 Armin Burgmeier * infinoted/infinoted-util.h: * infinoted/infinoted-util.c: Replaced infinoted_util_set_daemon_pid_file_proc() by infinoted_util_daemon_set_global_pid_file_proc(), infinoted_util_daemon_set_local_pid_file_proc(). Also add infinoted_util_daemon_pid_file_kill(). * infinoted-main.c: * infinoted-options.c: Instead of setting the PID file directory directly, first try the global one and if that fails use the local one. This avoids a race condition which resulted from the previous use of access() to check whether the PID file directory is writable. These changes also fix a bug which prevented infinoted to launch in daemonized mode when the global PID file directory did not exist. 2010-05-08 Armin Burgmeier * infinoted/infinoted-options.c: Include signal.h to fix the build on Debian Lenny (#537). 2010-03-12 Armin Burgmeier * libinfinity/common/inf-chat-buffer.h: * libinfinity/common/inf-chat-buffer.c: Added a flags field to InfGtkChatBufferMessage indicating whether a message is a backlog message or not. * libinfgtk/inf-gtk-chat.c: Show backlog messages also if chat session is attached to widget after synchronization. * libinfinity/common/inf-chat-session.c: * test/inf-test-chat.c: Adapt for API changes. 2010-03-12 Armin Burgmeier * libinfgtk/inf-gtk-chat.c (inf_gtk_chat_init): Fix a typo in a comment. 2010-03-12 Armin Burgmeier * libinfinity/comon/inf-chat-buffer.c (inf_chat_buffer_get_message): Reversed the order in which messages are returned, so that the function does what the docs say. * libinfinity/common/inf-chat-session.c (inf_chat_session_to_xml_sync): Adapt to the API change. 2010-03-05 Benjamin Herr * infinoted/infinoted-main.c: Call umask(077) explicitly after forking since libdaemon < 0.14 sets the mask to 0777. 2010-03-02 Eike Siewertsen * autogen.sh: Check for glibtoolize from OSX in addition to libtoolize * libinfinity/server/infd-filesystem-storage.c: use fdopendir work-around on Apple systems, too 2010-02-27 Armin Burgmeier , Benjamin Herr * libinftextgtk/inf-text-gtk-view.c: Fix rendering multi-selections far down a document, slightly increased minimum value of selection colors. 2010-02-26 Armin Burgmeier * test/inf-test-reduce-replay.c: Make this compile on Windows (but not work yet). 2010-02-26 Armin Burgmeier * libinftextgtk/inf-text-gtk-viewport.c: Fix redraw bugs. 2010-02-25 Armin Burgmeier * libinftextgtk/Makefile.am: * libinftextgtk/inf-text-gtk-viewport.h: * libinftextgtk/inf-text-gtk-viewport.c: Added InfTextGtkViewport, showing remote users' cursor positions in the scrollbar. * test/inf-test-gtk-browser.c: Show the functionality in inf-test-gtk-browser. 2010-02-21 Armin Burgmeier * libinftextgtk/inf-text-gtk-view.c: Highlight current line of remote users. 2010-02-21 Armin Burgmeier * libinfinity/client/infc-session-proxy.c: Improved docs for infc_session_proxy_join_user(). 2010-02-19 Armin Burgmeier * libinftextgtk/inf-text-gtk-view.c: Take TextView's left and right margin into account when drawing remote selections. 2010-02-19 Armin Burgmeier * test/inf-test-text-replay.c: Don't play the first argument N times but every argument once. 2010-02-18 Armin Burgmeier * libinftextgtk/inf-text-gtk-view.c: Show remote selections. 2010-02-17 Armin Burgmeier * libinfinity/inf-marshal.in: * libinftext/inf-text-user.h: * libinftext/inf-text-user.c: Added a by_request parameter to the selection-changed signal. * libinftext/inf-text-move-operation.c: * libinftext/inf-text-session.c: * libinftextgtk/inf-text-gtk-buffer.c: * libinftextgtk/inf-text-gtk-view.c: Adapt for the API change. 2010-02-15 Armin Burgmeier * libinftextgtk/inf-text-gtk-view.c (inf_text_gtk_view_user_invalidate_cursor_rect): Convert to window coordinates before invalidating. 2010-02-15 Armin Burgmeier * libinftextgtk/inf-text-gtk-view.c (inf_text_gtk_view_set_active_user): Readd previously active user correctly to list of users to track. 2010-02-14 Armin Burgmeier * libinfinity/common/inf-xmpp-connection.h: * libinfinity/common/inf-xmpp-connection.c: Added inf_xmpp_connection_get_tls_enabled() and the "tls-enabled" property. 2010-02-14 Armin Burgmeier * libinftextgtk/inf-text-gtk-buffer.h: * libinftextgtk/inf-text-gtk-buffer.c: Added inf_text_gtk_buffer_is_author_toggle(), inf_text_gtk_buffer_forward_to_author_toggle() and inf_text_gtk_buffer_backward_to_tag_toggle(). 2010-02-14 Armin Burgmeier * libinftextgtk/inf-text-gtk-buffer.h: * libinftextgtk/inf-text-gtk-buffer.c: Added the "show-user-colors" property and accessor functions. 2010-02-14 Armin Burgmeier * libinfinity/client/infc-session-proxy.c (infc_session_proxy_unsubscribe_connection): Only send the "session-unsubscribe" message if the connection is still open. We might get to this point with a closed connection if a status::notify signal handler closes the session explicitely before our own signal handler ran (Jesse van den Kieboom). 2010-02-13 Armin Burgmeier * libinftext/inf-text-session.c (inf_text_session_validate_user_props): Fix error domain for the "'caret' attribute is missing" error. 2010-02-13 Armin Burgmeier * libinftextgtk/inf-text-gtk-view.h: * libinftextgtk/inf-text-gtk-view.c: * libinftextgtk/Makefile.am: Added InfTextGtkView, a class which draws remote cursors in a GtkTextView. * test/inf-test-gtk-browser.c: Make this show remote cursors. 2010-02-13 Armin Burgmeier * libinfgtk/inf-gtk-browser-store.c: When emitting "has_child_toggled" after the last node has been removed from a directory make sure that gtk_tree_model_iter_has_child() returns FALSE, and also that the other tree model functions skip the node to be removed. 2010-02-13 Jesse van den Kieboom * libinfgtk/inf-gtk-browser-store.c: * libinfgtk/inf-gtk-browser-store.h: Added inf_gtk_browser_store_set_connection_name() and inf_gtk_browser_store_clear_connection_error(). 2010-02-13 Jesse van den Kieboom * libinfgtk/inf-gtk-browser-store.c: * libinfgtk/inf-gtk-browser-store.h: Added inf_gtk_browser_store_remove_connection(). 2010-02-13 Armin Burgmeier * libinfinity/server/infd-directory.c: * infinoted/infinoted-pam.c: Fixed compiler warnings. 2010-02-12 Armin Burgmeier * all source files: Added 2010 to copyright years. 2010-02-09 Armin Burgmeier * libinfinity/server/infd-directory.h: * libinfinity/server/infd-directory.c: Added infd_directory_foreach_connection(). * libinfinity/common/inf-error.h: * libinfinity/common/inf-error.c: Added INF_AUTHENTICATION_DETAIL_ERROR_TRY_AGAIN. * libinfinity/common/inf-xmpp-connection.h: * libinfinity/common/inf-xmpp-connection.c: Added inf_xmpp_connection_reset_sasl_authentication(), implement gracefully abort of authentication. * infinoted/infinoted-config-reload.c: Set new SASL context and mechanisms for existing connections. 2010-02-11 Armin Burgmeier * configure.ac: Use AC_USE_SYSTEM_EXTENSIONS, bump autoconf requirement to 2.60 to be able to make use of it. Check whether dirent.d_type and PAM_FAIL_DELAY exist. * libinfinity/server/infd-directory.c: Include config.h instead of defining _GNU_SOURCE manually, do lstat if d_type does not exist. * infinoted/infinoted-pam.c: Only set fail delay if HAVE_PAM_FAIL_DELAY is set. 2010-02-11 Armin Burgmeier * libinfgtk/inf-gtk-browser-view.c (inf_gtk_browser_view_status_icon_data_func, inf_gtk_browser_view_status_data_func): Handle INF_GTK_BROWSER_MODEL_DISCONNECTED in switch, to avoid a crash when adding disconnected connections to the browser (Jesse van den Kieboom). 2010-02-10 Benjamin Herr , Armin Burgmeier * configure.ac: Check for SO_REUSEADDR. * libinfinity/server/infd-tcp-server.c: Set SO_REUSEADDR before calling bind() on server sockets. Also do not call infd_tcp_server_close() on error in infd_tcp_server_open() if the socket was bound already. * infinoted/infinoted-run.c: Only log errors on server startup if neither ipv4 nor ipv6 servers could be started. This is because SO_REUSEADDR apparently makes bind() work for both variants on the same port even though a later listen() call will definitely fail. 2010-02-09 Benjamin Herr * infinoted/infinoted-options.c: * infinoted/infinoted-startup.c: Fix stupid compilation errors without LIBINFINITY_HAVE_PAM. 2010-02-09 Benjamin Herr * infinoted/infinoted-options.h: * infinoted/infinoted-options.c: Properly set GError in for invalid authentication-related options in infinoted_options_validate() so that for example config-reloading knows what is up. 2010-02-09 Benjamin Herr * infinoted/infinoted-config-reload.c: Properly require authentication mechanism specified from newly loaded configuration. 2010-02-09 Armin Burgmeier * infinoted/infinoted-startup.c: Changed sasl callback to provide proper authentication error detail for server password authentication. 2010-02-07 Armin Burgmeier * libinfinity/common/inf-error.h: * libinfinity/common/inf-error.c: Added INF_DIRECTORY_ERROR_NO_STORAGE. * libinfinity/server/infd-directory.c: Allow to pass NULL storage to directory in which case all nodes are kept in memory. 2010-02-07 Armin Burgmeier * test/inf-test-text-replay.c (inf_test_text_replay_apply_operation_to_string): Handle the operation being a split operation, and apply both parts of it to the string in that case. * test/replay/replay-10.record.xml: Added a replay which requires this functionality. 2010-02-07 Armin Burgmeier * libinfinity/adopted/inf-adopted-operation.c (inf_adopted_operation_get_concurrency_id): If the second operation is a split operation, then call the function on it, and reverse the result. This prevents every subclass to have to take that case into account. * libinfinity/adopted/inf-adopted-split-operation.c (inf_adopted_split_operation_get_concurrency_id): If both parts of the split operation agree, then return that. If one is none and the other has a decision, then return that decision. Only error out if the two IDs are contradictory. * test/replay/replay-08.record.xml: * test/replay/replay-09.record.xml: Added two records where get_concurrency_id for InfAdoptedSplitOperation is required (08 is a cut-down version of 09). 2009-12-28 Armin Burgmeier * test/inf-test-reduce-replay.c: * test/Makefile.am: Added a tool to reduce a erroneous replay to a minimal testcase. 2009-12-27 Armin Burgmeier * test/inf-test-text-replay.c: Reimplement using InfAdoptedSessionReplay. 2009-12-26 Armin Burgmeier * libinfinity/adopted/inf-adopted-session-replay.h: * libinfinity/adopted/inf-adopted-session-replay.c: * libinfinity/adopted/Makefile.am: Added the InfAdoptedSessionReplay class, which can be used to replay a session recorded with InfAdoptedSessionRecord. * libinfinity/adopted/inf-adopted-session-record.c: Add a reference to InfAdoptedSessionReplay in the docs. 2010-01-31 Benjamin Herr , Armin Burgmeier * libinfinity/common/inf-error.h: * libinfinity/common/inf-error.c: Rename InfPostAuthenticationError to InfAuthenticationDetailError, added INF_AUTHENTICATION_DETAIL_ERROR_AUTHENTICATION_FAILED. * libinfinity/common/inf-xmpp-connection.h: * libinfinity/common/inf-xmpp-connection.c: * libinfinity/server/infd-xmpp-server.h: * libinfinity/server/infd-xmpp-server.c: Removed user-authenticated signals. Instead, allow the gsasl callback to use the new function inf_xmpp_connection_set_sasl_error() to provide further information regarding the failed authentication, which is sent to the clientside and can be queried, for example in error callbacks, on either side with inf_xmpp_connection_get_sasl_error(). The callback now needs to explicitly use inf_xmpp_connection_retry_sasl_authentication() to restart the authentication process. To make that possible, the client will now remember what sasl mechanisms are supported by the server. * infinoted/infinoted-config-reload.c: * infinoted/infinoted-pam.h: * infinoted/infinoted-pam.c: * infinoted/infinoted-run.c: * infinoted/infinoted-startup.c: Adapt to the above API changes. 2010-01-29 Benjamin Herr * infinoted/infinoted-pam.c: Abort checking all groups early when an error happens even if the caller does not care, also localise strings properly and use proper quotation marks. 2010-01-29 Benjamin Herr * libinfinity/common/inf-error.h: * libinfinity/common/inf-error.c: * infinoted/infinoted-pam.c: When an error happens while checking on a user after authentication, log it and also let the user know that something went wrong. 2010-01-28 Benjamin Herr * libinfinity/server/infd-xmpp-server.c: Properly disconnect the post-auth signal handler when the server goes away before the connection either goes away or is done authenticating. 2010-01-27 Benjamin Herr * libinfinity/common/inf-xmpp-connection.c: Handle post-auth error separately from auth error and emit it instead of generic auth error. 2010-01-27 Benjamin Herr * infinoted/Makefile.am: * infinoted/infinoted-startup.c: * infinoted/infinoted-pam.h: * infinoted/infinoted-pam.c: Shuffled pam functions into their own header and translation unit. * infinoted/infinoted-config-reload.c: * infinoted/infinoted-run.c: Connect the pam postauthentication callback to each new InfdXmppServer so that it might disallow clients that have been authenticated. 2010-01-27 Benjamin Herr * libinfinity/inf-marshal.in: * libinfinity/common/inf-xmpp-connection.h: * libinfinity/common/inf-xmpp-connection.c: Added user-authenticated signal that is emitted right before sasl authentication is finished successfully to give a last chance to interrupt it. * libinfinity/server/infd-xmpp-server.h: * libinfinity/server/infd-xmpp-server.c: Added connection-user-authenticated signal that is emitted whenever the above signal is emitted for any connection to this server. * libinfinity/common/inf-error.h: * libinfinity/common/inf-error.c: Added PostAuthentication error domain for authentication failures that happen during the above signals. 2010-01-23 Benjamin Herr * infinoted/infinoted-options.h: * infinoted/infinoted-options.c: * infinoted/infinoted-startup.c: Added support for specifying a limited set of system users or groups that will be accepted after pam authentication. * libinfinity/common/inf-xmpp-connection.c: Added a todo comment that should probably be taken care of for the above changes not to suck. 2010-01-20 Benjamin Herr * infinoted/infinoted-config-reload.c: * infinoted/infinoted-startup.c: * infinoted/infinoted-options.h: * infinoted/infinoted-options.c: --pam is now --pam-service and requires an argument instead of using a gentoo-specific default; added the password pam options to config reloading. 2010-01-20 Benjamin Herr * configure.ac: * libinfinity/inf-config.h.in: * infinoted/infinoted-options.h: * infinoted/infinoted-options.c: * infinoted/infinoted-startup.c: Add option to use pam to check passwords instead of providing a server-wide one. No support for only allowing certain users yet. 2010-01-27 Benjamin Herr * libinfinity/common/inf-xml-util.h: * libinfinity/common/inf-xml-util.c: Added inf_xml_util_new_{error,node}_from_{node,error}() functions for [de]serializing GErrors to xml. * libinfinity/common/inf-session.c: * libinfinity/server/infd-directory.c: * libinfinity/server/infd-session-proxy.c: Partially replaced manual [de]serializing of GErrors to xml with the above functions. 2010-01-22 Armin Burgmeier * infinoted/infinoted-run.c (infinoted_run_free): Avoid a runtime warning when freeing the InfinotedRun without having started it. 2010-01-11 Armin Burgmeier * test/inf-test-browser.c: * test/inf-test-chat.c: Check the result of fgets(). Bug #523 (Philipp Kern). 2010-01-11 Armin Burgmeier * libinfinity/client/infc-browser.h: * libinfinity/client/infc-browser.c: Added infc_browser_iter_is_valid(). Initial patch by Simon Veith. 2010-01-02 Armin Burgmeier * libinftext/inf-text-user.h: * libinftext/inf-text-user.c: Added inf_text_user_new(), to ease language bindings. 2009-12-25 Armin Burgmeier * libinfinity/adopted/inf-adopted-undo-grouping.c (inf_adopted_undo_grouping_execute_request_cb): Also do cleanup if the request does not affect the buffer, but it was issued by the undo grouping's user. In that case that user's vector time increases, which might cause requests being dropped from its request log. * test/replay/replay-07.record.xml: Added a replay in which this caused a problem. 2009-12-24 Armin Burgmeier * libinfinity/adopted/inf-adopted-undo-grouping.c (inf_adopted_undo_grouping_cleanup): Don't throw away requests prematurely, which might result in a failed assertion later when they are needed. This happened when undoing a large number of requests. * test/replay/replay-06.record.xml: Added a replay in which this scenario occurs. 2009-12-22 Armin Burgmeier * libinfinity/common/inf-cert-util.h: * libinfinity/common/inf-certificate-chain.h: * libinfinity/common/inf-certificate-credentials.h: * libinfinity/common/inf-error.c: * libinfinity/common/inf-init.c: * libinfinity/common/inf-ip-address.c: * libinfinity/common/inf-xmpp-connection.h: * libinfinity/common/inf-xmpp-connection.c: * libinfinity/server/infd-xmpp-server.h: * libinfgtk/inf-gtk-certificate-view.h: Include before including , to make sure the definition of ssize_t is available also when compiling with MSVC. * libinfinity/common/inf-tcp-connection.c: * libinfinity/server/infd-tcp-server.c: * libinfinity/server/infd-filesystem-storage.c: #ifdef-out some variables not needed on Windows. * win32/libinfinity/libinfinity.def: * win32/libinftext/libinftext.def: * win32/libinfgtk/libinfgtk.def: * win32/libinftextgtk/libinftextgtk.def: Added module definition files to create proper import libraries with MSVC. * win32/libinfinity/inf-config.h: * win32/libinfinity/inf-marshal.h: * win32/libinfinity/inf-marshal.c: * win32/config.h: Add static versions of files that would otherwise be generated at the configure step, in order to be able to build libinfinity with MSVC. * win32/unistd.h: Added fake unistd.h, declaring ssize_t. * win32/libinfinity/libinfinity.vcproj: * win32/libinftext/libinftext.vcproj: * win32/libinfgtk/libinfgtk.vcproj: * win32/libinftextgtk/libinftextgtk.vcproj: Added MSVC project files for libinfinity. * win32/inf-test-browser/inf-test-browser.vcproj: * win32/inf-test-chat/inf-test-chat.vcproj: * win32/inf-test-chunk/inf-test-chunk.vcproj: * win32/inf-test-daemon/inf-test-daemon.vcproj: * win32/inf-test-gtk-browser/inf-test-gtk-browser.vcproj: * win32/inf-test-state-vector/inf-test-state-vector.vcproj: * win32/inf-test-tcp-connection/inf-test-tcp-connection.vcproj: * win32/inf-test-tcp-server/inf-test-tcp-server.vcproj: * win32/inf-test-text-cleanup/inf-test-text-cleanup.vcproj: * win32/inf-test-text-operations/inf-test-text-operations.vcproj: * win32/inf-test-text-replay/inf-test-text-replay.vcproj: * win32/inf-test-text-session/inf-test-text-session.vcproj: * win32/inf-test-xmpp-connection/inf-test-xmpp-connection.vcproj: * win32/inf-test-xmpp-server/inf-test-xmpp-server.vcproj: Added MSVC project files for its tests. * win32/libinfinity.sln: Added a MSVC solution file containing all the project files mentioned above. 2009-12-22 Armin Burgmeier * test/Makefile.am: Added inf-test-xmpp-server to build. * test/inf-test-xmpp-server.c: Adapt to latest libinfinity API. 2009-12-20 Armin Burgmeier * test/inf-test-text-replay.c: Set connection for users that joined later in the replay, to avoid the request being rejected. 2009-12-19 Armin Burgmeier * configure.ac: Post-release bump to 0.5.0. * docs/reference/libinfinity/libinfinity-0.5-docs.sgml: * docs/reference/libinfinity/libinfinity-0.5-overrides.txt: * docs/reference/libinfinity/libinfinity-0.5-sections.txt: * docs/reference/libinftext/libinftext-0.5-docs.sgml: * docs/reference/libinftext/libinftext-0.5-overrides.txt: * docs/reference/libinftext/libinftext-0.5-sections.txt: * docs/reference/libinfgtk/libinfgtk-0.5-docs.sgml: * docs/reference/libinfgtk/libinfgtk-0.5-overrides.txt: * docs/reference/libinfgtk/libinfgtk-0.5-sections.txt: * docs/reference/libinftextgtk/libinftextgtk-0.5-docs.sgml: * docs/reference/libinftextgtk/libinftextgtk-0.5-overrides.txt: * docs/reference/libinftextgtk/libinftextgtk-0.5-sections.txt: * infinoted/Makefile.am: * libinfgtk/Makefile.am: * libinfinity/Makefile.am: * libinftext/Makefile.am: * libinftextgtk/Makefile.am: Bump API version to 0.5. 2009-12-19 Armin Burgmeier * === Released 0.4.0 === * NEWS: Update for release. 2009-12-19 Armin Burgmeier * libinfinity/common/inf-xmpp-connection.c: Track used SASL mechanism, instead of using gsasl_mechanism_name(), since the latter is only available since gsasl 0.2.28. 2009-12-19 Armin Burgmeier * infinoted/infinoted-util.c (infinoted_util_logv): On Windows, convert the output from UTF-8 to the character set of the console. 2009-12-19 Armin Burgmeier * infinoted/infinoted-directory-sync.c (infinoted_directory_sync_add_session): Fix the build on Windows. 2009-12-19 Armin Burgmeier * libinfinity/common/inf-chat-session.c (inf_chat_session_receive_message): Accept messages not issued from the corresponding's user's connection on synchronization. 2009-12-19 Armin Burgmeier * libinfgtk/inf-gtk-certificate-manager.c: Change the wording of the check button in the certificate dialog, to make clear that it only affects whether to trust the certificate. 2009-12-19 Armin Burgmeier * libinfinity/common/inf-chat-session.c: * libinfinity/adopted/inf-adopted-session.c: Deny operation if the user has not joined from the connection from which the request is received. 2009-12-19 Armin Burgmeier * libinfinity/adopted/inf-adopted-algorithm.c: Added a TODO comment about not considering translation against inactive users. 2009-12-18 Armin Burgmeier * libinfinity/server/infd-filesystem-storage.c (infd_filesystem_storage_open): Specify O_CREAT when opening the file in writing mode. 2009-12-18 Armin Burgmeier * infinoted/infinoted-directory-sync.h: * infinoted/infinoted-directory-sync.c: * infinoted/Makefile.am: Added a new object which synchronizes the document tree to disk. * infinoted/infinoted-options.h: * infinoted/infinoted-options.c: Added the --sync-directory and --sync-interval command line and config file options. * infinoted/infinoted-run.h: * infinoted/infinoted-run.c: Create a InfinotedDirectorySync in case the corresponding options were provided. Bug #428. 2009-12-18 Armin Burgmeier * libinftext/inf-text-buffer.c (inf_text_buffer_create_iter): Fixed a typo in a documentation string. 2009-12-18 Armin Burgmeier * libinftextgtk/inf-text-gtk-buffer.h: * libinftextgtk/inf-text-gtk-buffer.c: Added inf_text_gtk_buffer_show_user_colors(). 2009-12-18 Armin Burgmeier * libinfinity/server/infd-filesystem-storage.c (infd_filesystem_storage_storage_read_subdirectory): If readdir_r does not report the type of the enumerated file, then find it out via lstat(). 2009-12-18 Armin Burgmeier * infinoted/infinoted-signal.c: Replace C++ style comments by C style comments. * infinoted/infinoted-option.c: Fix #ifdef check, to avoid a warning. 2009-12-16 Armin Burgmeier * libinfinity/client/infc-browser.c: * libinfinity/server/infd-xmpp-server.c: #undef ERROR on Windows. Some crazy Windows header defines it, but we want to use it as an identifier. * infinoted/infinoted-options.c: * infinoted/infinoted-signal.c: * infinoted/infinoted-util.c: Fix the build on Windows. 2009-12-16 Benjamin Herr * libinfinity/server/infd-filesystem-storage.c: Try to ignore symlinks when reading directories or opening files. 2009-12-15 Benjamin Herr * ChangeLog: * infinoted/infinoted-config-reload.c: * infinoted/infinoted-options.h: * infinoted/infinoted-options.c: * infinoted/infinoted-run.h: * infinoted/infinoted-run.c: * infinoted/infinoted-startup.h: * infinoted/infinoted-startup.c: Enable requiring authentication via SASL PLAIN, giving a server-wide password via startup options. * libinfinity/common/inf-xmpp-connection.c: Perform multiple authentication attempts. 2009-12-14 Armin Burgmeier * libinfinity/common/inf-xmpp-connection.c (inf_xmpp_connection_notify_status_cb): Reset priv->position when the TCP connection was closed. (inf_xmpp_connection_clear): Reset priv->pull_data and priv->pull_len. 2009-12-14 Armin Burgmeier * infinoted/Makefile.am: Create PID file directory via an empty _DATA variable, for make distcheck to pass. 2009-12-14 Armin Burgmeier * libinfinity/client/infc-browser.c: Reset exploration flag for root node. * libinfinity/common/inf-xmpp-manager.h: * libinfinity/common/inf-xmpp-manager.c: Keep closed connections, handle changing addresses or ports. * libinfinity/common/inf-xml-connection.h: * libinfinity/common/inf-xml-connection.c: Added inf_xml_connection_open(), and a corresponding vfunc. * libinfinity/common/inf-xmpp-connection.c: Implement inf_xml_connection_open(). * libinfinity/common/inf-discovery-avahi.c: Reopen existing connections, if any, instead of opening new connections. * libinfgtk/inf-gtk-browser-view.c: Reconnect when double-clicking an item with a disconnected browser. * libinfgtk/inf-gtk-browser-store.c: Keep undiscovered items if they have browser or error set. 2009-12-14 Armin Burgmeier * libinfgtk/inf-gtk-certificate-manager.c: Don't complain about a certificate having changed if the new certificate was issued by a CA. 2009-12-12 Benjamin Herr * configure.ac: Added AM_SILENT_RULES, defaulting to off. * docs/reference/libinfinity/Makefile.am: * infinoted/infinoted-autosave.c: * infinoted/infinoted-note-plugin.c: * infinoted/infinoted-options.c: * infinoted/infinoted-record.c: * infinoted/infinoted-startup.c: * infinoted/note-plugins/text/infd-note-plugin-text.c: * libinfgtk/inf-gtk-browser-model-filter.c: * libinfgtk/inf-gtk-browser-model-sort.c: * libinfgtk/inf-gtk-browser-store.c: * libinfgtk/inf-gtk-browser-view.c: * libinfgtk/inf-gtk-certificate-dialog.c: * libinfgtk/inf-gtk-certificate-manager.c: * libinfgtk/inf-gtk-chat.c: * libinfinity/Makefile.am: * libinfinity/adopted/inf-adopted-algorithm.c: * libinfinity/adopted/inf-adopted-request-log.c: * libinfinity/adopted/inf-adopted-session-record.c: * libinfinity/adopted/inf-adopted-session.c: * libinfinity/adopted/inf-adopted-split-operation.c: * libinfinity/adopted/inf-adopted-state-vector.c: * libinfinity/adopted/inf-adopted-undo-grouping.c: * libinfinity/client/infc-browser.c: * libinfinity/client/infc-request-manager.c: * libinfinity/client/infc-session-proxy.c: * libinfinity/common/Makefile.am: * libinfinity/common/inf-chat-buffer.c: * libinfinity/common/inf-chat-session.c: * libinfinity/common/inf-session.c: * libinfinity/common/inf-tcp-connection-private.h: * libinfinity/common/inf-tcp-connection.c: * libinfinity/common/inf-user-table.c: * libinfinity/common/inf-user.h: * libinfinity/common/inf-user.c: * libinfinity/common/inf-xml-util.c: * libinfinity/common/inf-xmpp-connection.c: * libinfinity/common/inf-xmpp-manager.c: * libinfinity/inf-communication-central-method.c: * libinfinity/communication/inf-communication-group.c: * libinfinity/communication/inf-communication-joined-group.c: * libinfinity/communication/inf-communication-manager.c: * libinfinity/communication/inf-communication-registry.c: * libinfinity/inf-i18n.c: * libinfinity/inf-signals.h: * libinfinity/inf-signals.c: * libinfinity/server/infd-directory.c: * libinfinity/server/infd-filesystem-storage.c: * libinfinity/server/infd-server-pool.c: * libinfinity/server/infd-session-proxy.c: * libinfinity/server/infd-tcp-server.c: * libinfinity/server/infd-xmpp-server.c: * libinftext/inf-text-chunk.c: * libinftext/inf-text-default-buffer.c: * libinftext/inf-text-default-delete-operation.c: * libinftext/inf-text-default-insert-operation.c: * libinftext/inf-text-move-operation.c: * libinftext/inf-text-remote-delete-operation.c: * libinftext/inf-text-session.c: * libinftext/inf-text-undo-grouping.c: * libinftextgtk/inf-text-gtk-buffer.c: * libinftextgtk/inf-text-gtk-hue-chooser.c: * test/inf-test-browser.c: * test/inf-test-chat.c: * test/inf-test-gtk-browser.c: * test/inf-test-tcp-connection.c: * test/inf-test-xmpp-connection.c: * test/util/inf-test-util.c: Fixed warnings. To that effect, introduced wrappers for glib functions with funny types and did a lot of casting-const-away or casting between object pointers and function pointers with more indirection, so that gcc would not notice it, and a few other minor changes. Also some whitespace. Everything appears to build with -Werror now for at least the following CFLAGS: -pedantic -ansi -Wall -Wextra -Wwrite-strings -Wpointer-arith -Wcast-qual -Wno-missing-field-initializers -Wdeclaration-after-statement -Wbad-function-cast -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wnested-externs -Waggregate-return -Wno-unused-parameter. 2009-12-12 Armin Burgmeier * libinfinity/communication/inf-communication-method.h: * libinfinity/communication/inf-communication-method.c: * libinfinity/communication/inf-communication-group.h: * libinfinity/communication/inf-communication-group.c: Removed the except parameter for sending a message to the whole group. * libinfinity/communication/inf-communication-central-method.c: Adapt. * libinfinity/common/inf-session.h: * libinfinity/common/inf-session.c: Removed the except parameter for inf_session_send_to_subscriptions(). * libinfinity/common/inf-chat-session.c: * libinfinity/adopted/inf-adopted-session.c: * libinfinity/server/infd-session-proxy.c: * libinftext/inf-text-session.c: * test/inf-test-text-replay.c: Adapt. 2009-12-11 Armin Burgmeier * libinfinity/inf-marshal.in: Added VOID:OBJECT,UINT marshaller. * libinfinity/server/infd-session-proxy.h: * libinfinity/server/infd-session-proxy.c: * libinfinity/server/infd-directory.c: Send seqs in the form "seq-id/seq-num". This allows to send the same message to the whole group, not requiring an extra message for the host which issued the request. Added the seq_id parameter to InfdSessionProxy's add-subscription signal. * libinfinity/client/infc-request-manager.h: * libinfinity/client/infc-request-manager.c: * libinfinity/client/infc-session-proxy.h: * libinfinity/client/infc-session-proxy.c: * libinfinity/client/infc-browser.c: Correctly deal with this kind of seqs; pass sequence-id from welcome message to request manager and session proxy and added the sequence-id property for InfcRequestManager. 2009-12-10 Armin Burgmeier * libinfinity/common/inf-error.h: * libinfinity/common/inf-error.c: Added INF_DIRECTORY_ERROR_NO_WELCOME_MESSAGE and INF_DIRECTORY_ERROR_VERSION_MISMATCH error codes. * libinfinity/common/inf-protocol.h: * libinfinity/common/inf-protocol.c: * libinfinity/common/Makefile.am: Added this new file containing common protocol properties used by both client and server. Currently contains a function returning the Infinote protocol version implemented by libinfinity, and a function to split the version string. * libinfinity/server/infd-directory.c: Send a welcome message to the client, telling it the protocol version the server uses and a sequence identifier. * libinfinity/client/infc-browser.c: Only activate itself after the welcome message was received, produce an error if it did not arrive after 5 seconds. Remember the sequence identifier which will be used in a followup patch. 2009-12-10 Benjamin Herr * libinfinity/common/inf-error.c: Include gsasl.h so that gsasl_strerror() is not assumed to return int and consequently works on non-32bit platforms, fixing a crash. 2009-12-10 Benjamin Herr * infinoted/infinoted-config-reload.c: * infinoted/infinoted-options.h: * infinoted/infinoted-options.c: * infinoted/infinoted-run.h: * infinoted/infinoted-run.c: * infinoted/infinoted-startup.h: * infinoted/infinoted-startup.c: Added --password/-P option to require a password from clients via GNU SASL 'PLAIN' authentication. 2009-12-10 Benjamin Herr * libinfinity/common/inf-error.h: * libinfinity/common/inf-error.c: Add public inf_gsasl_error_quark(), inf_gsasl_set_error() for error codes returned from GNU GSASL functions. * libinfinity/common/inf-xmpp-connection.c: Use inf_gsasl_error_set_error() instead of manually setting errors for gsasl error codes. 2009-12-10 Benjamin Herr * libinfinity/common/inf-tcp-connection.h: * libinfinity/common/inf-tcp-connection.c: Add functions to create new connections: inf_tcp_connection_new(), inf_tcp_connection_new_and_open(). * libinfinity/common/inf-discovery-avahi.c: * test/inf-test-browser.c: * test/inf-test-chat.c: * test/inf-test-tcp-connection.c: * test/inf-test-xmpp-connection.c: * libinfinity/common/inf-tcp-connection.c: Use inf_tcp_connection_new(), inf_tcp_connection_new_and_open() instead of manually creating new InfTcpConnection objects. 2009-12-08 Armin Burgmeier * libinftext/inf-text-session.c (inf_text_session_remove_local_user): Fix a crash a user's selection changes after it becomes non-local. 2009-12-08 Armin Burgmeier * libinftextgtk/inf-text-gtk-buffer.c (inf_text_gtk_buffer_set_modified): Notify the "modified" property. 2009-12-07 Armin Burgmeier * libinfinity/client/infc-browser.c: Move root node destruction to finalize. 2009-12-07 Armin Burgmeier * libinfinity/client/infc-browser.h: * libinfinity/client/infc-browser.c: Added the "status" property, infc_browser_get_status() and the "error" signal. Keep connection around if it is closed, to allow easy reconnections. * libinfgtk/inf-gtk-browser-model.h: Added INF_GTK_BROWSER_MODEL_DISCONNECTED status. * libinfgtk/inf-gtk-browser-store.c: Drop connection bookkeeping, keep browser alive when it reaches INFC_BROWSER_DISCONNECTED status. * test/inf-test-browser.c: * test/inf-test-gtk-browser.c: Simplify the code by making use of the new API. * libinfinity/communication/inf-communication-manager.c: Added a TODO comment questioning whether we should continue to allow joining groups with connections with status INF_XML_CONNECTION_OPENING. 2009-12-07 Armin Burgmeier * test/inf-test-text-replay.c: Added an Undo Grouping for each user in the replay, to test that undo grouping can at least handle all cases. * libinfinity/adopted/inf-adopted-undo-grouping.c: Fixed some bugs which showed up when replaying test/replays/. 2009-12-07 Armin Burgmeier * test/inf-test-text-replay.c: Allow UTF-8 input files. 2009-12-05 Armin Burgmeier * libinfinity/inf-marshal.in: Added a BOOL:OBJECT,OBJECT marshaller. * libinfinity/adopted/inf-adopted-undo-grouping.h: * libinfinity/adopted/inf-adopted-undo-grouping.c: * libinfinity/adopted/Makefile.am: Added the #InfAdoptedUndoGrouping class. It allows to group requests to be undone at the same time. * libinftext/inf-text-undo-grouping.h: * libinftext/inf-text-undo-grouping.c: * libinftext/Makefile.am: Added a specialization of that class for text operations. 2009-12-05 Armin Burgmeier * libinftext/inf-text-session.h: Removed INF_TEXT_TYPE_SESSION_STATUS define as it's not used. * libinftext/inf-text-chunk.c: Removed commented-out code to serialize a chunk to/from XML. * libinfinity/adopted/inf-adopted-algorithm.c (inf_adopted_algorithm_class_init): Fixed a typo in the signal documentation. 2009-12-02 Armin Burgmeier * libinftextgtk/inf-text-gtk-buffer.c (inf_text_gtk_buffer_active_user_notify_status_cb): Added a TODO comment about unsetting active-user when it gets unavailable. 2009-12-02 Armin Burgmeier * libinfinity/adopted/inf-adopted-request-log.h: * libinfinity/adopted/inf-adopted-request-log.c: Added the "add-request" signal. 2009-12-02 Armin Burgmeier * libinfinity/adopted/inf-adopted-algorithm.h: * libinfinity/adopted/inf-adopted-algorithm.c: Made inf_adopted_algorithm_translate_request() public. 2009-12-02 Armin Burgmeier * libinfinity/adopted/inf-adopted-session.h: * libinfinity/adopted/inf-adopted-session.c: Allow repetitive requests by sending a num="n" attribute in the message. Add a guint parameter to inf_adopted_session_undo() and inf_adopted_session_redo() to undo or redo multiple requests at once. * test/inf-test-gtk-browser.c: Adapt to the API change. 2009-12-01 Benjamin Herr * infinoted/infinoted-config-reload.c: Properly wrap reference to startup->options->daemonize in #ifdef LIBINFINITY_HAVE_LIBDAEMON. 2009-11-30 Armin Burgmeier * libinfinity/server/infd-directory.c: Immediately write an empty session to disk on sync-in, and refuse sync-in if that fails. 2009-11-30 Armin Burgmeier * libinfinity/common/inf-session.h: * libinfinity/common/inf-session.c: Added INF_SESSION_PRESYNC status, and the inf_session_synchronize_from() function. Require setting status at construction. * libinfinity/common/inf-chat-session.h: * libinfinity/common/inf-chat-session.c (inf_chat_session_new): Added status parameter. * libinfinity/server/infd-note-plugin.h: * libinfinity/client/infc-note-plugin.h: Added a status parameter to the session_new function. * libinftext/inf-text-session.h: * libinftext/inf-text-session.c: Added a status parameter to inf_text_session_new() and inf_text_session_new_with_user_table(). * libinfinity/adopted/inf-adopted-session.c: * libinfinity/server/infd-directory.c: * libinfinity/client/infc-browser.c: * libinftext/inf-text-session.c: * test/inf-test-gtk-browser.c: * test/inf-test-text-replay.c: * test/inf-test-text-session.c: Adapt to the API change. 2009-11-30 Armin Burgmeier * infinoted/infinoted-autosave.c (infinoted_autosave_remove_session): Disconnect from the notify::modified signal handler, preventing a crash when the autosaver is disabled at runtime. 2009-11-29 Armin Burgmeier * infinoted/infinoted-config-reload.h: * infinoted/infinoted-config-reload.c: * infinoted/Makefile.am: Added a new file which handles reloading infinoted's configuration at runtime. * infinoted/infinoted-signal.c: Call it on SIGHUP (#509). * infinoted/infinoted-main.c (infinoted_main_run): After InfinotedRun terminates, check run->startup->options->daemonize, not startup->options->daemonize, since config reload might have invalidated the latter. 2009-11-29 Armin Burgmeier * infinoted/infinoted-autosave.c (infinoted_autosave_walk_directory): Make this actually work, by initializing child before using it. This is used only when adding an autosaver at runtime. 2009-11-29 Armin Burgmeier * libinfinity/server/infd-server-pool.h: * libinfinity/server/infd-server-pool.c: Added infd_server_pool_remove_server() and infd_server_pool_foreach_server(). Changed semantics so that when a server is closed it is no longer removed automatically from the pool. * infinoted/infinoted-run.h: * infinoted/infinoted-run.c: Adapt to that, and remove a server from the pool if infd_tcp_server_open() failed (which it normally does not since we have bound it already, but just to be sure). 2009-11-29 Armin Burgmeier * libinfinity/common/inf-discovery-avahi.c: * libinfinity/server/infd-xmpp-server.c: Allow changing credentials, SASL context and SASL mechanisms at runtime. * libinfinity/server/infd-directory.c: Allow setting a new storage backend at runtime. 2009-11-29 Armin Burgmeier * infinoted/infinoted-creds.c (READ_FUNC_IMPL): Fixed a memory leak: Don't leak the data variable. 2009-11-29 Armin Burgmeier * libinfinity/common/inf-certificate-credentials.h: * libinfinity/common/inf-certificate-credentials.c: * libinfinity/common/Makefile.am: Added a wrapper for gnutls_certificate_credentials_t which does reference counting. * libinfinity/common/inf-xmpp-connection.h: * libinfinity/common/inf-xmpp-connection.c: * libinfinity/common/inf-discovery-avahi.h: * libinfinity/common/inf-discovery-avahi.c: * libinfinity/server/infd-xmpp-server.h: * libinfinity/server/infd-xmpp-server.c: Use InfCertificateCredentials instead of gnutls_certificate_credentials_t. * infinoted/infinoted-creds.h: * infinoted/infinoted-creds.c: * infinoted/infinoted-dh-params.h: * infinoted/infinoted-dh-params.c: * infinoted/infinoted-startup.h: * infinoted/infinoted-startup.c: Adapt to the changed API. 2009-11-29 Armin Burgmeier * infinoted/infinoted-util.h: Added a TODO comment about moving the logging functions to an extra file. * infinoted/infinoted-dh-params.h: * infinoted/infinoted-dh-params.c: * infinoted/Makefile.am: Renamed infinoted_run_ensure_dh_params() to infinoted_dh_params_ensure() and moved this to an extra file. * infinoted/infinoted-run.h: * infinoted/infinoted-run.c: Adapt. 2009-11-28 Armin Burgmeier * infinoted/infinoted-util.h: * infinoted/infinoted-util.c: Added infinoted_util_set_errno_error() and infinoted_util_set_daemon_pid_file_proc(). * infinoted/infinoted-options.c: Added the -D option to kill a daemonized process. * infinoted/infinoted-main.c: Use infinoted_util_set_daemon_pid_file_proc(). 2009-11-28 Armin Burgmeier * infinoted/infinoted-main.c: Tell parent process whether PID file creation failed or not. 2009-11-28 Armin Burgmeier * infinoted/infinoted-main.c: Change the location of the PID file to localstatedir/run, append libinfinity API version to PID file name. * infinoted/Makefile.am: Create directory for PID file on install. 2009-11-28 Armin Burgmeier * infinoted/infinoted-util.c (infinoted_util_logv): Put an extra newline after the log message. * infinoted/infinoted-note-plugin.c: * infinoted/infinoted-run.c: * infinoted/infinoted-signal.c: * infinoted/infinoted-startup.c: * infinoted/infinoted-main.c: Remove newline from calls to infinoted_util_log_*() to prevent it from appearing in the syslog. 2009-11-28 Benjamin Herr * infinoted-util.h: * infinoted-util.c: Added infinoted_util_log_{error,warning,info} that delegate to either fprintf(stderr, ...), or daemon_log with the proper priority when building with libdaemon. * infinoted-main.c: * infinoted-note-plugin.c: * infinoted-signal.c: * infinoted-startup.c: Use infinoted_util_log_{error,warning,info} instead of fprintf(stderr, ...). 2009-11-28 Armin Burgmeier * infinoted/infinoted-signal.c (infinoted_signal_terminate): Fixed indentation. 2009-11-28 Armin Burgmeier * infinoted/infinoted-run.h: * infinoted/infinoted-run.c: Added infinoted_run_ensure_dh_params(), take ownership of startup. * infinoted/infinoted-startup.c (infinoted_startup_load): Fixed documentation comment stating that this takes care about generating DH params. It does not anymore, the code has moved to InfinotedRun. * infinoted/infinoted-main.c: Adapt to startup ownership change in InfinotedRun. 2009-11-28 Benjamin Herr * infinoted/infinoted-main.c: When daemonizing, write the pid file to $HOME/.infinoted/infinote.pid if the default location is not writable. 2009-11-28 Armin Burgmeier * infinoted/infinoted-options.c: Allow passing NULL argc and argv in which case options are only read from config file. 2009-11-28 Armin Burgmeier * infinoted/infinoted-signal.h: * infinoted/infinoted-signal.c: Implemented serial signal handling via libdaemon, handle SIGQUIT and SIGHUP signals. Bug #507 (Yarek "Fx3" Tyshchenko). 2009-11-28 Armin Burgmeier * libinfinity/common/inf-discovery-avahi.c (inf_discovery_avahi_create_client): Pass the error variable to the avahi_client_new() call, not NULL. 2009-11-25 Armin Burgmeier * configure.ac: Check for libdaemon presence. * libinfinity/inf-config.h.in: Add a LIBINFINITY_HAVE_LIBDAEMON entry. * infinoted/infinoted-options.h: * infinoted/infinoted-options.c: Added a daemonize option. * infinoted/infinoted-main.c: Fork and create a PID file if the daemonize option is given, and libdaemon support is present. Bug #507 (Yarek "Fx3" Tyshchenko). * infinoted/Makefile.am: Link against libdaemon. * docs/reference/libinfinity/compiling.sgml: * README: Mention libdaemon as an optional dependency for the package. 2009-11-25 Armin Burgmeier * infinoted/infinoted-note-plugin.c: Fixed the build, broken by my last commit. 2009-11-24 Armin Burgmeier * infinoted/infinoted-note-plugin.c: Fixed some strings. 2009-11-23 Armin Burgmeier * infinoted/infinoted-record.h: * infinoted/infinoted-record.c: * infinoted/Makefile.am: Moved the session recording code to this new source file. * infinoted/infinoted-run.h: * infinoted/infinoted-run.c: Use the new file, removed the equivalent code from this file. 2009-11-23 Armin Burgmeier * infinoted/infinoted-util.h: * infinoted/infinoted-util.c: * infinoted/Makefile.am: Added this new source file, containing infinoted_util_create_dirname(), moved from infinoted-startup. * infinoted/infinoted-creds.h: * infinoted/infinoted-creds.c (infinoted_creds_create_credentials): Don't set DH params. * infinoted/infinoted-startup.h: * infinoted/infinoted-startup.c: Don't load DH params in startup. * infinoted/infinoted-run.h: * infinoted/infinoted-run.c: Load DH params in run instead, and set them for the credentials after loading. Also bind the server sockets in _new() before starting the server. Create DH params just before starting it. This prepares for the upcoming daemonizing; the server should do all non-blocking work that might fail before fork()ing (so that an error message can be reported), and potentially blocking work (DH params generation) after fork()ing (so that it does not the block boot process). * infinoted-main.c: Adapt to infinoted_run_start() not taking an error argument anymore. 2009-11-23 Armin Burgmeier * libinfinity/server/infd-tcp-server.h: * libinfinity/server/infd-tcp-server.c: Added infd_tcp_server_bind(), and a INFD_TCP_SERVER_BOUND state. * libinfinity/server/infd-xmpp-server.c: Treat INFD_TCP_SERVER_BOUND the same as INFD_TCP_SERVER_CLOSED. 2009-11-23 Armin Burgmeier * test/session/test-52.xml: * test/session/Makefile.am: Added one more test which requires recon in remote delete operations. 2009-11-22 Benjamin Herr * libinfinity/common/inf-chat-buffer.c (inf_chat_buffer_reserve_message): Properly set offset into allocated messages when prepending a new message. 2009-11-22 Armin Burgmeier * libinfinity/common/inf-chat-buffer.c (inf_chat_buffer_reserve_message): Return the new message in case we wrap around, not another one. 2009-11-21 Armin Burgmeier * libinfinity/common/inf-user.h: * libinfinity/common/inf-user.c: Added the set-status signal which allows to access the previous user status. * libinfinity/common/inf-chat-session.c: Don't emit a new message userjoin message for each active->inactive and inactive->active user status change. 2009-11-21 Armin Burgmeier * libinfinity/adopted/inf-adopted-session.c: * libinftext/inf-text-session.c: Made some clarifying comments about implicit user activation and flushing pending requests. 2009-11-18 Armin Burgmeier * libinfgtk/inf-gtk-chat.c (inf_gtk_chat_commit_message): Fixed parantheses so that an emote message is only triggered when there is /me at the beginning, not when the fourth character is whitespace. 2009-11-17 Armin Burgmeier * libinfgtk/inf-gtk-chat.c (inf_gtk_chat_commit_message): Send messages beginning with /me as emote messages. (inf_gtk_chat_init): Fix a compiler warning. 2009-11-15 Armin Burgmeier * libinfinity/server/infd-filesystem-storage.h: * libinfinity/server/infd-filesystem-storage.c: Fixed directory deletion on Windows. Bug #501. 2009-11-13 Armin Burgmeier * libinfinity/server/infd-directory.c (infd_directory_node_name_equal): Don't always return TRUE. (infd_directory_handle_subscribe_ack): Use existing session and session proxy to notify client about cancellation in case the parent node was removed, instead of creating a new proxy. 2009-11-13 Armin Burgmeier * libinfinity/common/inf-error.h: * libinfinity/common/inf-error.c: Added INF_DIRECTORY_ERROR_INVALID_NAME error code. * libinfinity/server/infd-directory.c (infd_directory_node_name_equal): Use Unicode-aware case-insensitive comparison. (infd_directory_node_is_name_available): Don't allow nodes with '/' in the name. * libinfinity/server/infd-filesystem-storage.c: Don't allow empty path components. 2009-11-11 Armin Burgmeier * libinfinity/common/inf-xml-util.c: Added documentation comments. 2009-11-11 Armin Burgmeier * libinfinity/client/infc-browser.c: Check for non-NULL iter in infc_browser_return_if_iter_fail() and infc_browser_return_val_if_iter_fail(). 2009-11-11 Armin Burgmeier * libinfgtk/inf-gtk-chat.c: Avoid the use of gtk_entry_get_text_length() because this is only available since GTK+ 2.14. 2009-11-11 Armin Burgmeier * libinftextgtk/inf-text-gtk-buffer.h: * libinftextgtk/inf-text-gtk-buffer.c: Added the "saturation" and "value" properties, and the inf_text_gtk_buffer_set_saturation_value(), inf_text_gtk_buffer_get_saturation(), inf_text_gtk_buffer_get_value(). 2009-11-10 Armin Burgmeier * libinfinity/common/inf-chat-buffer.c (inf_chat_buffer_finalize): Take into account that we may have preallocated space at the beginning of the buffer, so don't try to free the text of all entries from the beginning, avoiding a crash. 2009-11-10 Armin Burgmeier * libinfgtk/inf-gtk-chat.c (inf_gtk_chat_init): Set indentation of wrapped lines to 12 pixels. 2009-11-10 Armin Burgmeier * libinfgtk/inf-gtk-chat.c (inf_gtk_chat_init): Wrap text in the chat widget. 2009-11-10 Armin Burgmeier * libinfinity/server/infd-directory.c (infd_directory_handle_subscribe_ack): Fix a crash in the ADD_NODE case introduced by my last change. 2009-11-10 Armin Burgmeier * libinfinity/server/infd-directory.c: Fix crash when session could not initially be saved in response to an add-node request with initial-subscribe set. This fixes a crash on creating documents with names '.', '..'. Still not handled properly for sync-in. 2009-11-09 Armin Burgmeier * libinfinity/common/inf-chat-buffer.c: Added missing paranthesis to constructs like (priv->first_message + n) % priv->size, fixing a crash when the buffer starts to wrap around. 2009-11-08 Armin Burgmeier * libinfgtk/inf-gtk-chat.c: Make sure to scroll to bottom initially, and keep bottom row in viewport visible on size change, instead of top row. 2009-11-08 Benjamin Herr * libinfinity/common/inf-chat-session.c (inf_chat_session_message_from_xml): Fixed bytes/chars mixup. 2009-11-08 Armin Burgmeier * infinoted/infinoted-run.c: Enable chat. 2009-11-07 Armin Burgmeier * libinfgtk/inf-gtk-chat.h: * libinfgtk/inf-gtk-chat.c: Added inf_gtk_chat_get_active_user() as a complement to inf_gtk_chat_set_active_user(). 2009-11-07 Armin Burgmeier * libinfinity/common/inf-tcp-connection.c (inf_tcp_connection_open): Fix the condition for closing an existing socket. Spotted by Gabríel A. Pétursson. 2009-11-07 Armin Burgmeier * libinfgtk/inf-gtk-browser-store.c (inf_gtk_browser_store_tree_model_get_column_type): Handle the case when index is INF_GTK_BROWSER_MODEL_COL_NAME. 2009-11-07 Armin Burgmeier * docs/reference/libinfinity/compiling.sgml: Added a chapter about compiling libinfinity. * docs/reference/libinfinity/libinfinity-0.4-docs.sgml: Added it to the documentation. * docs/reference/libinfinity/Makefile.am: Added it to the build. 2009-11-07 Armin Burgmeier * configure.ac: Removed the --enable-traffic-output option. * libinfinity/common/inf-xmpp-connection.c: Add a global boolean variable called INF_XMPP_CONNECTION_PRINT_TRAFFIC instead of a #define with the same name. * libinfinity/common/inf-init.c: Set that variable in inf_init() based on the presence of the environment variable LIBINFINITY_DEBUG_PRINT_TRAFFIC. Bug #502. 2009-11-07 Armin Burgmeier * libinfinity/common/inf-xmpp-connection.c (inf_xmpp_connection_initiate): Removed commented-out try to allow non-printable characters via XML entities. 2009-11-07 Armin Burgmeier * libinfinity/common/inf-tcp-connection (inf_tcp_connection_error): Fix a typo in a comment. 2009-11-07 Armin Burgmeier * libinfinity/common/inf-xmpp-connection.c: Don't crash if the underlying TCP connection goes down in an XML parser callback. This also involved simplifying the code a bit by introducing an additional state variable that tracks whether we are currently in an XML parser callback or not. 2009-11-07 Armin Burgmeier * libinfinity/server/infd-session-proxy.c (infd_session_proxy_set_property): When connecting to the "close" signal of a new session, connect before the default signal handler, not after, so that our signal handler can still figure out the synchronization status of the subscribed connections, to avoid sending "session-close" if the sync is/was in progress. Bug #499. 2009-11-06 Benjamin Herr * libinfinity/common/inf-xml-util.c: In inf_xml_util_add_child_text, only escape the characters which are actually forbidden by XML, not newlines and friends. 2009-11-06 Benjamin Herr * libinfinity/common/inf-xml-util.h: * libinfinity/common/inf-xml-util.c: * docs/reference/libinfinity/libinfinity-0.4-sections.txt: Added inf_xml_util_add_child_text and inf_xml_util_get_child_text which get the text content of an xml element while encoding or decoding unprintable characters as child elements. * infinoted/note-plugins/text/infd-note-plugin-text.c: * libinfinity/common/inf-chat-session.c: * libinftext/inf-text-chunk.c: * libinftext/inf-text-session.c: * test/util/inf-test-util.c: Use inf_xml_util_add_child_text and inf_xml_util_get_child_text instead of using the libxml2 calls directly. Bug #499. 2009-10-26 Armin Burgmeier * libinfgtk/inf-gtk-certificate-manager.c (inf_gtk_certificate_manager_certificate_func): Don't crash if a certificate of a known host does not have a hostname set. Ignore the certificate instead, because we can't identify it with a host properly. Bug #484. 2009-10-22 Armin Burgmeier * libinfinity/common/inf-standalone-io.c (inf_standalone_io_io_watch): Update event pointers after realloc. This fixes sporadic disconnections when there are more than two clients on a Windows infinoted. 2009-10-12 Armin Burgmeier * libinfgtk/inf-gtk-chat.h: * libinfgtk/inf-gtk-chat.c: Added the InfGtkChat class, a widget to show the conversation of an InfChatSession and to write messages if a local user has joined the session. * libinfgtk/Makefile.am: Added the new files to the build. * test/inf-test-gtk-browser.c: When connecting to a host, subscribe to its chat and open a window showing a InfGtkChat to make use of it. 2009-10-10 Armin Burgmeier * libinfinity/common/inf-user.c: * libinfinity/server/infd-session-proxy.c: * libinfgtk/inf-gtk-io.c: Minor documentation fixes. 2009-10-09 Armin Burgmeier * test/inf-test-chat.c: Added simple command-line based chat client as a test for InfChatSession. * test/inf-test-daemon.c: Enable the chat on the server. * test/Makefile.am: Added the file to the build. 2009-10-09 Armin Burgmeier * libinfinity/common/inf-chat-buffer.c (inf_chat_buffer_reserve_message): Fixed logic for first inserted message and fixed return value when the first message is reordered in memory. * libinfinity/common/inf-chat-session.c (inf_chat_session_message_from_xml): Don't require the "type" attribute being set but default to INF_CHAT_BUFFER_MESSAGE_NORMAL if it isn't. This is compatible to the way the inverse function, inf_chat_session_message_to_xml(), generates XML messages. * libinfinity/client/infc-browser.c (infc_browser_communication_object_sent): Handle correctly the case when the outgoing message has no ID set (chat subscription). 2009-10-08 Armin Burgmeier * libinfinity/common/inf-chat-buffer.c (inf_chat_buffer_get_size): Added a formal description of the return type in the documentation comment. 2009-10-08 Armin Burgmeier * libinfinity/common/inf-chat-session.c: Make InfChatSession's description appear in the documentation. 2009-10-08 Armin Burgmeier * libinfinity/client/infc-browser.h: * libinfinity/client/infc-browser.c: Added infc_browser_subscribe_chat(), infc_browser_get_subscribe_chat_request() and infc_browser_get_chat_session(). This handles the client-side part of subscribing to a server's global chat. * libinfgtk/inf-gtk-browser-store.c: * libinfgtk/inf-gtk-browser-view.c: Ignore chat subscriptions in begin-subscribe and subscribe-session signal handlers. 2009-10-07 Armin Burgmeier * libinfinity/common/inf-error.h: * libinfinity/common/inf-error.c: Added the INFD_DIRECTORY_ERROR_CHAT_DISABLED error code which is generated when a client tries to subscribe to a chat that is disabled on the server. * libinfinity/server/infd-directory.h: * libinfinity/server/infd-directory.c: Added infd_directory_enable_chat(), infd_directory_get_chat_session() and handle requests from clients. 2009-10-07 Armin Burgmeier * libinfinity/common/inf-chat-buffer.h: * libinfinity/common/inf-chat-buffer.c: Added the InfChatBuffer class. This is an InfBuffer-implementing class that holds chat messages in a ring-like structure (new messages replace old ones when a certain message size has been exceeded). * libinfinity/common/inf-chat-session.h: * libinfinity/common/inf-chat-session.c: Added the InfChatSession class which is a session allowing joined users to exchange messages. * libinfinity/common/Makefile.am: Added the new files to the build. 2009-10-08 Armin Burgmeier * libinfinity/communication/inf-communication-manager.c: Fixed a typo in a comment. 2009-10-08 Armin Burgmeier * libinfinity/client/infc-browser.c: Declared the iter member in the InfcBrowserIterGetSyncInRequestsForeachData, InfcBrowserIterGetNodeRequestForeachData and InfcBrowserIterGetExploreRequestForeachData structs as const to avoid compiler warnings. 2009-10-08 Armin Burgmeier * autogen.sh: Updated autogen.sh from gnome-common. Bug #476. 2009-10-07 Armin Burgmeier * libinfinity/server/infd-session-proxy.c: Fixed the documentation comment of the infd_session_proxy_get_session() function. 2009-10-07 Armin Burgmeier * libinfinity/server/infd-directory.c (infd_directory_handle_remove_node): Fixed the error domain of the error generated when attempting to remove the root node. 2009-10-07 Armin Burgmeier * libinfinity/communication/inf-communication-manager.c: * libinfinity/common/inf-init.c: * libinfinity/common/inf-standalone-io.c: * libinfinity/common/inf-xmpp-manager.c: * libinfinity/adopted/inf-adopted-state-vector.c: * libinfinity/client/infc-browser.c: * libinfinity/client/infc-explore-request.c: * libinfinity/server/infd-directory.c: * libinfinity/server/infd-filesystem-storage.c: * libinfinity/server/infd-tcp-server.c: Fixed a few documentation comments. 2009-06-03 Armin Burgmeier * libinftext/inf-text-session.c (inf_text_session_request_to_xml): For delete operations, don't assert that at least one segment exists. This avoids a crash when synchronizing a zero-length delete operation. 2009-05-13 Armin Burgmeier * libinftextgtk.pc.in: Fixed "Name:" field. This is libinftextgtk, not libinftext. 2009-05-11 Armin Burgmeier * libinfinity/client/infc-browser.h: * libinfinity/client/infc-browser.c: Made several InfcBrowserIter arguments const. 2009-05-02 Armin Burgmeier * libinfgtk/inf-gtk-browser-store.c: Fixed a typo in a comment. 2009-05-02 Armin Burgmeier * test/inf-test-browser.c: Connect after the default handler on the connection's notify::status, to give the communication method a chance to register the connection with the registry before we try to send stuff through it. 2009-05-02 Armin Burgmeier * libinfinity/common/inf-error.h: * libinfinity/common/inf-error.c: Added INF_DIRECTORY_ERROR_ROOT_NODE_REMOVE_ATTEMPT error. * libinfinity/server/infd-directory.c (infd_directory_handle_remove_node): Produce the newly introduced error if a client attempts to remove the root node. This fixes bug #442 (Gregory Haynes). (infd_directory_remove_node): Added a g_return_val_if_fail() if a the root node is attempted to be removed. * libinfinity/client/infc-browser.c (infc_browser_remove_node): Added a g_return_val_if_fail() if the root node is attempted to be removed. 2009-04-26 Armin Burgmeier * README: Added some notes about development of libinfinity. 2009-04-26 Armin Burgmeier * configure.ac: Post-release bump to 0.4.0. * docs/reference/libinfinity/libinfinity-0.4-docs.sgml: * docs/reference/libinfinity/libinfinity-0.4-overrides.txt: * docs/reference/libinfinity/libinfinity-0.4-sections.txt: * docs/reference/libinftext/libinftext-0.4-docs.sgml: * docs/reference/libinftext/libinftext-0.4-overrides.txt: * docs/reference/libinftext/libinftext-0.4-sections.txt: * docs/reference/libinfgtk/libinfgtk-0.4-docs.sgml: * docs/reference/libinfgtk/libinfgtk-0.4-overrides.txt: * docs/reference/libinfgtk/libinfgtk-0.4-sections.txt: * docs/reference/libinftextgtk/libinftextgtk-0.4-docs.sgml: * docs/reference/libinftextgtk/libinftextgtk-0.4-overrides.txt: * docs/reference/libinftextgtk/libinftextgtk-0.4-sections.txt: * infinoted/Makefile.am: * libinfgtk/Makefile.am: * libinfinity/Makefile.am: * libinftext/Makefile.am: * libinftextgtk/Makefile.am: Bump API version to 0.4. * docs/reference/libinfgtk/Makefile.am: * docs/reference/libinftext/Makefile.am: * docs/reference/libinftextgtk/Makefile.am: Clear .types file correctly on distclean. 2009-04-24 Armin Burgmeier * === Released 0.3.0 === * NEWS: Update for release. 2009-04-24 Armin Burgmeier * libinfinity/inf-i18n.c: Change gettext directory from lib/locale to share/locale on Windows. 2009-04-24 Armin Burgmeier * libinfinity/client/infc-browser.c: * libinfinity/server/infd-directory.c: Updated a few comments. 2009-04-24 Armin Burgmeier * docs/reference/api_version.xml.in.in: Moved from api_version.xml.in. * docs/reference/version.xml.in.in: Moved from version.xml.in. * docs/reference/Makefile.am: Generate (api_)version.xml from (api_)version.xml.in by removing the trailing newline. This is to prevent that newline from appearing in the docbook XML when substituting the external entities. * configure.ac: Generate docs/reference/(api_)version.xml.in. 2009-04-22 Armin Burgmeier * docs/reference/libinftext/libinftext-0.3-docs.sgml: * docs/reference/libinftext/libinftext-0.3-overrides.txt: * docs/reference/libinftext/libinftext-0.3-sections.txt: * docs/reference/libinfgtk/libinfgtk-0.3-docs.sgml: * docs/reference/libinfgtk/libinfgtk-0.3-overrides.txt: * docs/reference/libinfgtk/libinfgtk-0.3-sections.txt: * docs/reference/libinftextgtk/libinftextgtk-0.3-docs.sgml: * docs/reference/libinftextgtk/libinftextgtk-0.3-overrides.txt: * docs/reference/libinftextgtk/libinftextgtk-0.3-sections.txt: Moved from the unversioned files. * docs/reference/libinftext/Makefile.am: * docs/reference/libinfgtk/Makefile.am: * docs/reference/libinftextgtk/Makefile.am: Adapted DOC_MODULE accordingly. 2009-04-21 Armin Burgmeier * docs/reference/api_version.xml.in: Added another external entity for the API version. There is still one newline too much at the end in the generated file, but I have currently no idea how to get rid of it. * configure.ac: Generate docs/reference/api_version.xml. * libinfinity/Makefile.am: Added inf-marshal.in to EXTRA_DIST instead of dist_pkgdata_DATA, so that it is not installed. * libinfinity/common/inf-discovery.h: Fixed a typo in a parameter name. * docs/reference/libinfinity/libinfinity-0.3-docs.sgml: * docs/reference/libinfinity/libinfinity-0.3-overrides.txt: * docs/reference/libinfinity/libinfinity-0.3-sections.txt: Moved from the non-versioned files for parallel installation of the documentation. This requires renaming these files with every API version bump. The other libraries (libinftext, libinfgtk, libinftextgtk) will follow soon. * docs/reference/libinfinity/Makefile.am: Changed DOC_MODULE to libinfinity-0.3 for parallel installation. * docs/reference/libinftext/libinftext-docs.sgml: * docs/reference/libinfgtk/libinfgtk-docs.sgml: * docs/reference/libinftextgtk/libinftextgtk-docs.sgml: Include the new external entity, and name the API version in the book title. 2009-04-21 Armin Burgmeier * libinfinity/adopted/inf-adopted-operation.h: Removed commented-out documentation as this causes a warning when building the documentation. 2009-04-21 Armin Burgmeier * libinfinity/adopted/inf-adopted-session-record.c (inf_adopted_session_record_stop_recording): Fixed two compiler warnings about incompatible pointer types by properly casting them. 2009-04-21 Armin Burgmeier * libinfgtk/Makefile.am: * libinftext/Makefile.am: Removed -release from LDFLAGS to not duplicate the API version number in the .so filename. 2009-04-21 Philipp Kern * test/util/Makefile.am: correct hardcoded *-1.0.la import. 2009-04-20 Armin Burgmeier * libinfgtk.pc.in: * libinfinity.pc.in: * libinftext.pc.in: * libinftextgtk.pc.in: Moved from *-1.0.pc.in, respectively. The API version of the generated .pc file is not determined by the configure script. * infinoted/Makefile.am: * infinoted/note-plugins/text/Makefile.am: * libinfinity/Makefile.am: * libinfinity/common/Makefile.am: * libinfinity/communication/Makefile.am: * libinfinity/adopted/Makefile.am: * libinfinity/client/Makefile.am: * libinfinity/server/Makefile.am: * libinfgtk/Makefile.am: * libinftext/Makefile.am: * libinftextgtk/Makefile.am: * test/Makefile.am: * docs/reference/libinfinity/Makefile.am: * docs/reference/libinftext/Makefile.am: * docs/reference/libinfgtk/Makefile.am: * docs/reference/libinftextgtk/Makefile.am: * configure.ac: * Makefile.am: Introduce libtool versioning, make libinfinity parallel-installable with future versions. The pkg-config files are now prefixed with the corresponding libinfinity API version, such as libinfinity-0.3.pc. 2009-04-20 Armin Burgmeier * libinfinity/communication/inf-communication-hosted-group.c: Fixed the length of a documentation comment. 2009-02-28 Armin Burgmeier * libinfinity/common/inf-error.h: * libinfinity/common/inf-error.c: Added INF_DIRECTORY_ERROR_NO_SUCH_SUBSCRIPTION_REQUEST, and some documentation fixes. * libinfinity/common/inf-session.c: Added a TODO item. * libinfinity/client/infc-browser.c: Send or after subscriptions, actually perform the subscription when the message has been sent. This is used to tell the server whether a subscription was successful or not. The subscription can fail if the client does not support the communication method used, or if it does not know the note type. * libinfinity/server/infd-directory.h: Made the InfdNotePlugin parameter const in infd_directory_add_note(). * libinfinity/server/infd-directory.c: Don't immediately subscribe the client in or requests, but wait for instead. Don't add the node in the latter case if the client replies with , so that operations are atomic. 2009-02-28 Armin Burgmeier * libinfinity/communication/inf-communication-group.c: Documentation fix for inf_communication_group_get_method_for_network(): Mention that conn does not need to be a member of the group. 2009-02-26 Armin Burgmeier * libinfinity/common/inf-discovery-avahi.c: Added include to allow compilation on FreeBSD. Bug #430. Patch by Romain Tartière. 2009-02-15 Armin Burgmeier * libinfgtk/inf-gtk-certificate-dialog.c: * libinfgtk/inf-gtk-certificate-manager.c: Added TODO comments about how to improve certificate handling: For trusted hosts, we shouldn't show the hijack warning, and we should remember trusted hosts in the known hosts file. 2009-02-15 Armin Burgmeier * libinfinity/common/inf-xml-util.h: * libinfinity/common/inf-xml-util.c: Added xml property setter and getter functions for long and unsigned long values. 2009-02-14 Armin Burgmeier * libinfinity/common/inf-tcp-connection.c (inf_tcp_connection_io_incoming): Make sure we don't try to read again when the connection has been closed in a signal handler. 2009-02-14 Armin Burgmeier * libinfgtk/inf-gtk-certificate-manager.c (inf_gtk_certificate_manager_certificate_func): Added GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT flag. 2009-02-14 Armin Burgmeier * libinfinity/common/inf-cert-util.h: * libinfinity/common/inf-cert-util.c: Added a "current" GPtrArray parameter to inf_cert_util_load_file(), to which newly read certificates will be added, if non-NULL. * libinfgtk/inf-gtk-certificate-manager.c: Adapt to the API change. * infinoted/infinoted-options.h: * infinoted/infinoted-options.c: Added a certificate-chain command-line and configuration option, so that other certificates belonging to the certificate chain can be read from a separate file. * infinoted/infinoted-startup.c: Load more certificates from the certificate-chain-file, if given. 2009-01-15 Armin Burgmeier * all source files: Added 2009 to copyright years. 2009-01-04 Armin Burgmeier * configure.ac: Post-release bump to 0.3.0. 2009-01-04 Armin Burgmeier * === Released 0.2.0 === * NEWS: Update for release. 2009-01-04 Armin Burgmeier * libinfinity/common/inf-tcp-connection.c (inf_tcp_connection_get_property): Compare priv->socket against INVALID_SOCKET instead of NULL in assertion for PROP_LOCAL_ADDRESS and PROP_LOCAL_PORT. 2009-01-04 Armin Burgmeier * infinoted/infinoted-run.c (infinoted_run_load_directory): Fixed a warning about an unused variable. 2009-01-04 Armin Burgmeier * infinoted/infinoted-startup.h: * infinoted/infinoted-startup.c: * infinoted/infinoted-run.c: Moved directory creation from InfinotedStartup to InfinotedRun. * infinoted/infinoted-signal.c: Terminate directly on signal handler, without relying on the mainloop being exited properly. Also set a ConsoleCtrlHandler on Windows, to save the documents when the server's console window is closed. 2009-01-04 Armin Burgmeier * infinoted/Makefile.am: Replace PLUGIN_PATH define by PLUGIN_LIBPATH and PLUGIN_BASEPATH. * infinoted/infinoted-startup.c (infinoted_startup_load_directory): Lookup the module path relative to the application's executable. 2009-01-04 Armin Burgmeier * libinftextgtk/inf-text-gtk-buffer.h: * libinftextgtk/inf-text-gtk-buffer.c: Added inf_text_gtk_buffer_get_author(). 2009-01-04 Armin Burgmeier * libinfinity/communication/inf-communication-registry.c (inf_communication_registry_is_registered): Don't leak the publisher ID, and use g_return_val_if_reached instead of g_return_if_reached to avoid a warning. (inf_communication_registry_unregister): Fixed another compiler warning. 2008-12-30 Armin Burgmeier * libinfinity/server/infd-xmpp-server.h: * libinfinity/server/infd-xmpp-server.c: Made "security-policy" a construct property, don't allow passing NULL credentials for a non-only-unsecured security policy. * libinfinity/client/inf-xmpp-connections.c: Enable built-in credentials only for client connections, require valid credentials including certificate for server connections in case security policy is not only-unsecured. * infinoted/infinoted-run.c: * test/inf-test-daemon.c: Adapt to API change. 2008-12-30 Armin Burgmeier * libinfinity/common/inf-standalone-io.c: Some code cleanup, gather some common platform-specific stuff at the top. 2008-12-30 Armin Burgmeier * infinoted/infinoted-run.h: * infinoted/infinoted-run.c: Delay server opening to infinoted_run_start(), create both IPv6 and IPv4 server when possible. * infinoted/infinoted-main.c: Handle errors from infinoted_run_start(). 2008-12-30 Armin Burgmeier * libinfinity/communication/inf-communication-registry.h: * libinfinity/communication/inf-communication-registry.c: Added inf_communication_registry_is_registered(). * libinfinity/communication/inf-communication-central-method.c: Make sure we don't try to unregister a connection we never registered. 2008-12-30 Armin Burgmeier * libinfinity/common/inf-xmpp-connection.c (inf_xmpp_connection_received_cb): Make sure we read the whole gnutls buffer, so that we don't stall when gnutls buffers some data. 2008-12-29 Armin Burgmeier * libinfinity/common/inf-tcp-connection.c: Allow retrieving local remote and port on closed connections by keeping the native socket alive until disposal. * libinfinity/communication/inf-communication-method.h: * libinfinity/communication/inf-communication-method.c: Removed the unregistered method. * libinfinity/communication/inf-communication-registry.c: Support and require closed connections to be unregistered. * libinfinity/communication/inf-communication-central-method.c: Unregister the connection even if it has been closed already. 2008-12-29 Armin Burgmeier * libinfinity/common/inf-standalone-io.c: Added Win32 implementation using Winsock2's WSAWaitForMultipleEvents(). 2008-12-29 Armin Burgmeier * libinfinity/communication/inf-communication-central-method.c: Remember whether a connection has been open, so we do remove it from its group if it has not already been registered. 2008-12-29 Armin Burgmeier * libinfinity/communication/inf-communication-central-method.c: Do not unregister unregistered connection when in _CONNECTION_OPENING status in inf_communication_central_method_remove_member() 2008-12-29 Armin Burgmeier * libinfinity/server/infd-directory.c: Negated wrongly negated assertion in infd_directory_node_register_reply_subscription(). 2008-12-29 Armin Burgmeier * libinfinity/common/inf-xmpp-connection.c: Make sure inf_xml_connection_sent() is not called twice for the same message, and that it is not omitted for others. 2008-12-28 Armin Burgmeier * libinfinity/common/inf-session.c (inf_session_send_sync_error): Send synchronization error to synchronization client instead of whole group except client. 2008-12-28 Armin Burgmeier * libinfinity/communication/inf-communication-registry.c (inf_communication_registry_register): Fixed reactivation of previously unregistered connection which still has final messages scheduled. 2008-12-28 Armin Burgmeier * libinfinity/adopted/inf-adopted-session-record.c (inf_adopted_session_record_stop_recording): Avoid another warning. 2008-12-28 Armin Burgmeier * libinfinity/adopted/inf-adopted-session-record.c (inf_adopted_session_record_stop_recording): Avoid runtime warnings when the recorded session is still in INF_SESSION_SYNCHRONIZING status. 2008-12-28 Armin Burgmeier * libinfinity/server/infd-session-proxy.c (infd_session_proxy_set_property): Connect after the default handler for the close signal, so that the session has a chance to cancel any synchronizations before we remove group membership of all subscribed connections. * libinfinity/communication/inf-communication-registry.c: Make flushing final messages on group unref for unregistered connections work. 2008-12-28 Armin Burgmeier * libinfinity/communication/inf-communication-manager.h: * libinfinity/communication/inf-communication-manager.c: * libinfinity/communication/inf-communication-group-private.h: * libinfinity/communication/inf-communication-group.h: * libinfinity/communication/inf-communication-group.c: * libinfinity/communication/inf-communication-method.h: * libinfinity/communication/inf-communication-method.c: * libinfinity/communication/inf-communication-factory.h: * libinfinity/communication/inf-communication-factory.c: * libinfinity/communication/inf-communication-object.h: * libinfinity/communication/inf-communication-object.c: * libinfinity/communication/inf-communication-joined-group.h: * libinfinity/communication/inf-communication-joined-group.c: * libinfinity/communication/inf-communication-hosted-group.h: * libinfinity/communication/inf-communication-hosted-group.c: * libinfinity/communication/inf-communication-registry.h: * libinfinity/communication/inf-communication-registry.c: * libinfinity/communication/inf-communication-central-method.h: * libinfinity/communication/inf-communication-central-method.c: * libinfinity/communication/inf-communication-central-factory.h: * libinfinity/communication/inf-communication-central-factory.c: * libinfinity/communication/Makefile.am: Added new "communication" API replacing the connection manager system. This allows multiple connections to the same host, and gets rid of the requirement for UUIDs. * libinfinity/common/inf-net-object.h: * libinfinity/common/inf-net-object.c: * libinfinity/common/inf-method-manager.h: * libinfinity/common/inf-method-manager.c: * libinfinity/common/inf-connection-manager.h: * libinfinity/common/inf-connection-manager.c: * libinfinity/common/inf-central-method.h: * libinfinity/common/inf-central-method.c: * libinfinity/methods/local-central/inf-method-local-central.c: * libinfinity/methods/local-central/Makefile.am: * libinfinity/methods/Makefile.am: Removed. These files are obsoleted by the communication API. * libinfinity/common/Makefile.am: Removed the above files from the build. * libinfinity/Makefile.am: Decend into communication subdirectory, link against libinfinity_communication. * configure.ac: Removed dependency on libuuid, don't link against rpcrt4 on Windows. * libinfinity/common/inf-simulated-connection.c: Small documentation fix. * libinfinity/common/inf-xmpp-connection.c: Renamed network from "local" to "tcp/ip". * libinfinity/common/inf-session.h: * libinfinity/common/inf-session.c: * libinfinity/adopted/inf-adopted-session.c: * libinfinity/client/infc-note-plugin.h: * libinfinity/client/infc-browser.h: * libinfinity/client/infc-browser.c: * libinfinity/client/infc-session-proxy.h: * libinfinity/client/infc-session-proxy.c: * libinfinity/server/infd-note-plugin.h: * libinfinity/server/infd-filesystem-storage.h: * libinfinity/server/infd-session-proxy.h: * libinfinity/server/infd-session-proxy.c: * libinfinity/server/infd-directory.h: * libinfinity/server/infd-directory.c: * libinftext/inf-text-session.h: * libinftext/inf-text-session.c: * libinfgtk/inf-gtk-browser-store.h: * libinfgtk/inf-gtk-browser-store.c: * infinoted/note-plugins/text/infd-note-plugin-text.c: * infinoted/infinoted-startup.c: * test/inf-test-browser.c: * test/inf-test-daemon.c: * test/inf-test-gtk-browser.c: * test/inf-test-text-cleanup.c: * test/inf-test-text-replay.c: * test/inf-test-text-session.c: Adapt to API change. 2008-12-28 Armin Burgmeier * libinfinity/configure.ac: Added an --enable-traffic-output configure option, defining INF_XMPP_CONNECTION_PRINT_TRAFFIC. * libinfinity/common/inf-xmpp-connection.c: Include config.h, so that we see when INF_XMPP_CONNECTION_PRINT_TRAFFIC is defined. 2008-12-28 Armin Burgmeier * libinfinity-1.0.pc.in: * libinfgtk-1.0.pc.in: * libinftextgtk-1.0.pc.in: Fixed dependencies in pkg-config files. 2008-12-27 Armin Burgmeier * libinfinity/server/infd-server-pool.c (infd_server_pool_entry_free): Free the InfdServerPoolPublisher struct for each publisher. * libinfinity/server/infd-directory.c (infd_directory_node_explore): Don't leak the path variable. * libinfinity/common/inf-xmpp-connection.c (inf_xmpp_connection_process_authentication): Free the result of xmlNodeGetContent() as we are supposed to. * libinfinity/adopted/inf-adopted-algorithm.c (inf_adopted_algorithm_dispose): Don't leak the buffer_modified_time. 2008-12-27 Armin Burgmeier * infinoted/infinoted-options.c (infinoted_options_load): Don't leak default security_policy if overwritten by command line. * infinoted/infinoted-startup.c (infinoted_startup_free): Don't leak options and the startup struct. 2008-12-27 Armin Burgmeier * libinfinity/common/inf-xmpp-connection.c: Improved error message when the remote site seems not to be an XMPP server. 2008-12-23 Armin Burgmeier * libinfinity/common/inf-certificate-chain.h: * libinfinity/common/inf-certificate-chain.c: Made inf_certificate_chain_ref return the passed chain, so the function fulfills the requirements for a GBoxedCopyFunc. This lead to a crash with optimization enabled. 2008-12-23 Armin Burgmeier * libinfgtk/inf-gtk-certificate-dialog.c (inf_gtk_certificate_dialog_init): Free the icon_info so that we don't leak it. 2008-12-23 Armin Burgmeier * libinfgtk/inf-gtk-browser-view.c (inf_gtk_browser_view_progress_data_func): Free browser_iter to avoid a memory leak. 2008-12-22 Armin Burgmeier * libinfinity/common/inf-io.c (inf_io_event_get_type): Null-terminate the list of flags values. 2008-12-21 Armin Burgmeier * libinfgtk/inf-gtk-browser-view.c (inf_gtk_browser_view_row_changed_cb): Removed two unused variables. * libinftextgtk/inf-text-gtk-buffer.c (inf_text_gtk_buffer_buffer_init): Connect the get_modified and set_modified buffer implementations to the InfBufferIface. * libinftextgtk/inf-text-gtk-hue-chooser.c: (inf_text_gtk_hue_chooser_class_init): Install the dispose and finalize handlers. * infinoted/infinoted-creds.c (infinoted_creds_create_self_signed_certificate_impl): Removed an unused variable. * infinoted/infinoted-main.c (infinoted_main): Removed an unused variable. 2008-12-21 Armin Burgmeier * libinfinity/common/inf-cert-util.c: Include inf-error.h to avoid a warning. * libinfinity/adopted/inf-adopted-request-log.c (inf_adopted_request_log_is_empty): Use g_return_val_if_reached instead of g_return_if_reached, to avoid a warning. (inf_adopted_request_log_add_request): Cast the log to GObject before calling g_object_notify_freeze, to avoid a warning. 2008-12-21 Armin Burgmeier * libinfinity/common/inf-xmpp-connection.c (inf_xmpp_connection_send_chars): Fix a warning caused by += being used on a void pointer. (inf_xmpp_connection_process_features): Cast a xmlChar* to const char* before passing to strcmp(), to avoid a warning. 2008-12-21 Armin Burgmeier * libinfinity/common/inf-xmpp-connection.c: Added ctype.h inclusion. 2008-12-13 Armin Burgmeier * test/inf-test-text-replay.c: Allow multiple record files to be passed. 2008-12-07 Armin Burgmeier * infinoted/infinoted-run.c: Record sessions into ~/.infinoted-records. 2008-12-02 Armin Burgmeier * libinfinity/common/inf-buffer.h: * libinfinity/common/inf-buffer.c: Added a "modified" property, and get_modified/set_modified accessors. * libinftext/inf-text-default-buffer.c: Implement the property of the InfBuffer interface. * libinftextgtk/inf-text-gtk-buffer.c: Implement the "modified" property, keep it synchronized with the GtkTextBuffer's "modified" property. * libinfinity/server/infd-directory.h: * libinfinity/server/infd-directory.c: Added infd_directory_iter_peek_session(), infd_directory_iter_get_name() and infd_directory_iter_get_path(). * libinfinity/adopted/inf-adopted-algorithm.c: Track modification status of the buffer. If the buffer is considered not modified in a certain state, then set it modified if the buffer changes, but set it non-modified again when all users undid their changes since the last time when the buffer was considered non-modified. * infinoted/infinoted-autosave.h: * infinoted/infinoted-autosave.c: * infinoted/Makefile.am: Added an autosaver for infinoted. * infinoted/infinoted-options.h: * infinoted/infinoted-options.c: Added an autosave-interval option. * infinoted/infinoted-run.h: * infinoted/infinoted-run.c: Instantiate the autosaver when the autosave-interval is nonzero. * infinoted/infinoted-main.c: Added vim modelines. 2008-11-27 Armin Burgmeier * libinfinity/server/infd-directory.h: * libinfinity/server/infd-directory.c: Added infd_directory_iter_save_session(), and the "add-session" and "remove-session" signals. 2008-11-14 Armin Burgmeier * libinftextgtk/inf-text-gtk-hue-chooser.c: Don't use cairo_format_stride_for_width, so we don't need cairo 1.6 (Bug #393). 2008-11-08 Armin Burgmeier * libinfinity/adopted/inf-adopted-request-log.h: * libinfinity/adopted/inf-adopted-request-log.c: Added inf_adopted_request_log_set_begin() and inf_adopted_request_log_is_empty(). * libinfinity/adopted/inf-adopted-algorithm.c (inf_adopted_algorithm_is_component_reachable): Added an assertion that the request is either contained in the user's request log, or is to be added. * libinfinity/adopted/inf-adopted-session.c: Upon successful synchronization, set begin index of empty request logs to the corresponding user's time of the current state vector (#389, Matthias Prinz). * test/replay/replay-05.record.xml: Added a test for this. 2008-11-08 Armin Burgmeier * libinfinity/common/inf-user-table.c: Fixed a typo that prevented inf_user_table_foreach_user to appear in the documentation. 2008-11-08 Benjamin Herr * libinfinity/inf-xmpp-connection.c: Properly advance data pointer on partial writes (fixed bug #387). 2008-11-05 Armin Burgmeier * libinftext/inf-text-move-operation.h: * libinftext/inf-text-move-operation.c: Added a left_gravity parameter to inf_text_move_operation_transform_insert(). Always set it to TRUE in inf_text_move_operation_transform(), assuming a remote operation. * libinftext/inf-text-session.c: Interpret all requests as non-caret versions by default. Use right gravity when adjusting the author's cursor on an insert operation. * libinftextgtk/inf-text-gtk-buffer.c: Block selection-changed signal handler of active user in inf_text_gtk_buffer_insert_text_cb() and inf_text_gtk_buffer_delete_range_cb() since GtkTextBuffer already takes care of adjusting the buffer marks in response to index changes on insert or delete operations. These changes fix pasting text over selected text (#390, Georg Kapeller). 2008-11-02 Armin Burgmeier * libinfinity/common/inf-discovery-avahi.c: Added a documentation note that this class is only available when LIBINFINITY_HAVE_AVAHI is defined. 2008-11-02 Armin Burgmeier * configure.ac: Add LIBINFINITY_HAVI_AVAHI as an AM_CONDITIONAL. * docs/reference/libinfinity/Makefile.am: Add inf-discovery-avahi.h to the header files to ignore, and pass --rebuild-types to gtkdoc-scan. This way, inf_discovery_avahi_get_type is not listed in the .types file when avahi support is not enabled (#386, Gregory Haynes). * docs/reference/libinftext/Makefile.am: * docs/reference/libinfgtk/Makefile.am: * docs/reference/libinftextgtk/Makefile.am: Also added --rebuild-types to gtkdoc-scan. * docs/reference/libinfinity/libinfinity.types: * docs/reference/libinftext/libinftext.types: * docs/reference/libinfgtk/libinfgtk.types: * docs/reference/libinftextgtk/libinftextgtk.types: Removed, since these are now autogenerated. 2008-11-02 Armin Burgmeier * infinoted/note-plugins/text/Makefile.am: * libinfinity/methods/local-central/Makefile.am: Changed module installation path to be versioned. * infinoted/Makefile.am: * libinfinity/common/Makefile.am: Adapt module lookup path accordingly. 2008-10-30 Armin Burgmeier * libinfgtk/inf-gtk-browser-store.c (inf_gtk_browser_store_tree_model_iter_children): Make sure parent is not dereferenced for an assertion check if it is NULL, preventing a crash when this function was called with NULL parent and assertions enabled (#388). 2008-10-25 Philipp Kern * configure.ac: check for MSG_NOSIGNAL * libinfinity/common/inf-tcp-connection.c: conditionally define INF_TCP_CONNECTION_SENDRECV_FLAGS 2008-10-19 Armin Burgmeier * libinfinity/common/inf-connection-manager.c: Added #InfMethodManager to @see_also in section documentation. * libinfinity/common/inf-discovery-avahi.c: Added #InfLocalPublisher to @see_also in section documentation. * libinfinity/common/inf-discovery.h: Make virtual functions of the InfDiscoveryIface struct appear in the documentation. * libinfinity/server/infd-directory.c (infd_directory_set_method_manager): Added a clarifying comment. * libinfinity/common/inf-io.h: * libinfinity/common/inf-io.c: * libinfinity/common/inf-ip-address.h: * libinfinity/common/inf-ip-address.c: * libinfinity/common/inf-local-publisher.h: * libinfinity/common/inf-local-publisher.c: * libinfinity/common/inf-method-manager.h: * libinfinity/common/inf-method-manager.c: * libinfinity/common/inf-net-object.h: * libinfinity/common/inf-net-object.c: * libinfinity/common/inf-session.h: * libinfinity/common/inf-session.c: Added class and section documentation. 2008-10-19 Armin Burgmeier * libinfinity/common/inf-connection-manager.c: * libinfinity/common/inf-connection-manager.h: Removed some obsolete commented-out code. * libinfinity/common/inf-certificate-chain.h: Document the InfCertificateChain symbol. * libinfinity/common/inf-discovery-avahi.h: * libinfinity/common/inf-discovery-avahi.c: * libinfinity/common/inf-discovery.h: * libinfinity/common/inf-discovery.c: * libinfinity/common/inf-error.h: * libinfinity/common/inf-error.c: Added class and section documentation. 2008-10-18 Armin Burgmeier * libinfinity/inf-i18n.c: Set localedir relative to libinfinity DLL on Windows, so i18n is properly relocatable. 2008-10-18 Armin Burgmeier * configure.ac: Post-release bump to 0.2.0. 2008-10-18 Armin Burgmeier * === Released 0.1.0 === 2008-10-18 Armin Burgmeier * infinoted/infinoted-creds.c: Don't set the SAN to $hostname.local since the common name is no longer checked when a SAN is present. * infinoted/infinoted-startup.c (infinoted_startup_load_certificate): Error out if a self-signed certificate could not be created. 2008-10-17 Armin Burgmeier * libinfinity/common/inf-connection-manager.c (inf_connection_manager_send_ctrl): Fixed an assignment in an assertion that should be a comparison. (inf_connection_manager_group_real_send): Removed an unused variable. * libinfinity/common/inf-discovery-avahi.c (inf_discovery_avahi_client_callback): Removed an unused variable. 2008-10-17 Armin Burgmeier * configure.ac: Don't require avahi-glib for avahi support, as we don't use it. 2008-10-17 Armin Burgmeier * docs/reference/libinftext/Makefile.am: * docs/reference/libinfgtk/Makefile.am: * docs/reference/libinftextgtk/Makefile.am: Added underlying libraries as --extra-dir to FIXXREF_ARGS. * docs/reference/libinfinity/libinfinity-docs.sgml: * docs/reference/libinftext/libinftext-docs.sgml: * docs/reference/libinfgtk/libinfgtk-docs.sgml: * docs/reference/libinftextgtk/libinftextgtk-docs.sgml: Adjust online location. 2008-10-17 Armin Burgmeier * libinfinity/client/infc-browser.c: Add sync-in before emitting the NODE_ADDED signal, so that the signal handler can access the sync-in via infc_browser_iter_get_sync_in(). This allows InfGtkBrowserView to show progress for sync-ins. * libinfgtk/inf-gtk-browser-view: Removed a TODO comment about showing progress for sync-ins. 2008-10-17 Armin Burgmeier * infinoted/infinoted-options.c: Don't crash when reading options from config files. 2008-10-17 Armin Burgmeier * libinfinity/common/inf-connection-manager.c (inf_connection_manager_group_real_send): Removed debug logs. 2008-10-16 Armin Burgmeier * libinfinity/common/inf-tcp-connection.c: Consider INF_IO_ERROR with no error code as an ordinary disconnection. This is currently the way to be notified about disconnection on Windows, because InfGtkIo maps G_IO_HUP to INF_IO_ERROR. * libinfgtk/inf-gtk-io.c: Also watch for G_IO_HUP in addition to G_IO_ERR when INF_IO_ERROR is requested. 2008-10-16 Armin Burgmeier * libinfinity/common/inf-connection-manager.c (inf_connection_manager_group_real_send): Make sure all queued messages are sent, even if the callback for the last item adds new messages to the queue. 2008-10-16 Armin Burgmeier * libinfinity/common/inf-session.c (inf_session_close): Make sure the session's status is not already closed via a g_return_if_fail(), to prevent a failing assertion in the default handler. 2008-10-16 Armin Burgmeier * libinfinity/common/inf-connection-manager.c (inf_connection_manager_handle_message): Make sure a group's object is only finalized after we have unrefed the group, to prevent warnings when a received handler releases the NetObject. 2008-10-16 Armin Burgmeier * libinfinity/common/inf-tcp-connection.c (inf_tcp_connection_send): Always queue data we could not sent immediately. There was a bug that data wasn't queued if more than the half of it has been sent already. 2008-10-16 Armin Burgmeier * libinfinity/common/inf-xmpp-connection.c (inf_xmpp_connection_received_cb): Don't call gnutls_record_recv with a NULL session when a TLS error occured. 2008-10-16 Armin Burgmeier * infinoted/infinoted-note-plugin.c (infinoted_note_plugin_load_directory): Added missing return value in success case. 2008-10-16 Armin Burgmeier * libinftextgtk/inf-text-gtk-buffer.c: Fixed a stupid type error in the setter for the wake-on-cursor-movement property. 2008-10-16 Armin Burgmeier * libinfinity/Makefile.am: * libinfinity/common/Makefile.am: * libinfinity/adopted/Makefile.am: * libinfinity/client/Makefile.am: * libinfinity/server/Makefile.am: * libinfinity/methods/local-central/Makefile.am: * libinftext/Makefile.am: * libinfgtk/Makefile.am: * libinftextgtk/Makefile.am: * infinoted/Makefile.am: * infinoted/note-plugins/text/Makefile.am: * test/Makefile.am: Moved -I$(top_srcdir) from AM_CPPFLAGS to $lib_CPPFLAGS, because the former is not used when the latter is present. This is required for `make distcheck'. * docs/reference/Makefile.am: Added version.xml.in to EXTRA_DIST. * docs/reference/libinfinity/Makefile.am: * docs/reference/libinftext/Makefile.am: * docs/reference/libinfgtk/Makefile.am: * docs/reference/libinftextgtk/Makefile.am: Added ../version.xml to content_files, to fix `make distcheck'. * docs/reference/libinfinity/libinfinity-docs.sgml: Reordered documentation sections. 2008-10-16 Armin Burgmeier * libinfinity/common/inf-tcp-connection.c: Make sure that calling inf_tcp_connection_send() in a SENT callback does send things in a different order, or even breaks consistency of the queue. * libinfinity/common/inf-connection-manager.c (inf_connection_manager_group_real_send): Fixed a memory corruption problem. 2008-10-16 Armin Burgmeier * infinoted/infinoted-note-plugin.h: * infinoted/infinoted-note-plugin.c: Print a warning when no note plugins could be loaded. * infinoted/infinoted-startup.c: Don't start the server if there are no note plugins available. 2008-10-16 Armin Burgmeier * NEWS: Update for initial release. 2008-10-16 Armin Burgmeier * libinfinity/common/inf-xmpp-connection.c: Removed network traffic output. 2008-10-16 Armin Burgmeier * all source files: Fixed copyright period in GPL header, and changed the package description. 2008-10-15 Armin Burgmeier * configure.ac: Changed some occurences of infinote to libinfinity where the implementation rather than the protocol is meant. This changes the INFINOTE_HAVE_AVAHI define to LIBINFINITY_HAVE_AVAHI. * libinfinity/inf-config.h.in: * libinfinity/common/inf-discovery-avahi.h: * libinfinity/common/inf-discovery-avahi.c: * infinoted/infinoted-run.c: * test/inf-test-daemon.c: * test/inf-test-gtk-browser.c: * doc/reference/version.xml.in: Adapt to the changes. 2008-10-15 Armin Burgmeier * libinfinity/inf-dll.h: * libinfinity/inf-dll.c: * libinfinity/Makefile.am: Added new files that implement DllMain() on Windows, to save the DLL Handle. This can be used with g_win32_get_package_installation_directory_of_module(). * libinfinity/common/Makefile.am: Split the METHODS_PATH define in METHODS_LIBDIR and METHODS_BASEDIR, where METHODS_BASEDIR is the application-specific part of the path. * libinfinity/common/inf-method-manager.c: On Windows, locate the methods relative to the libinfinity DLL instead of using a hardcoded path. * libinfinity/methods/local-central/Makefile.am: Added a comment about renaming renaming the directory into which the methods are stored. However, this doesn't work yet because of some evil libtool weirdness. 2008-10-15 Armin Burgmeier * libinfinity/inf-i18n.h: Fixed a misleading comment in the first line, originating from a copy+paste from inf-config.h. 2008-10-15 Armin Burgmeier * libinfinity/client/infc-browser.c: Make sure signals are emitted before data any is sent out for various operations. 2008-10-15 Armin Burgmeier * libinfinity/common/inf-tcp-connection.c: Only queue new data if it can't be sent directly. This allows a call to inf_tcp_connection_send() to emit the "sent" signal directly. * libinfinity/common/inf-xmpp-connection.c: * libinfinity/common/inf-connection-manager.c: Fixes to honor this. 2008-10-14 Armin Burgmeier * libinfinity/common/inf-tcp-connection.c: Changed INF_TCP_CONNECTION_EINPROGRESS to be WSAEWOULDBLOCK on Windows because this is what connect() yields for non-blocking sockets. 2008-10-14 Armin Burgmeier * libinfinity/common/inf-connection-manager.c: * libinfinity/common/inf-error.c: * libinfinity/common/inf-init.c: * libinfinity/common/inf-io.h: * libinfinity/common/inf-ip-address.c: * libinfinity/common/inf-standalone-io.c: * libinfinity/common/inf-tcp-connection.c: * libinfinity/server/infd-tcp-server.c: Fixed the build on Windows. InfStandaloneIo only has a stub implementation for now. GtkIo does not work correctly with glib 2.18, though I believe that's a regression in glib because it works with glib 2.16. Let's see whether I can track that down. * configure.ac: Don't require libuuid on Windows since we use native Windows API there. 2008-10-14 Armin Burgmeier * libinfinity/common/inf-init.h: Include only for G_BEGIN_DECLS and G_END_DECLS, removed inculdes that we don't need in inf-init.h. 2008-10-14 Armin Burgmeier * libinfinity/Makefile.am: * libinftext/Makefile.am: * libinfgtk/Makefile.am: * libinftextgtk/Makefile.am: * infinoted/Makefile.am: * libinftextgtk/Makefile.am: Fixed linking order so that libraries that depend on others appear first in the command line. 2008-10-14 Armin Burgmeier * libinfinity/methods/local-central/Makefile.am: * infinoted/note-plugins/text/Makefile.am: Added -avoid-version, -module and -no-undefined LDFLAGS. Also fixed the linking order. 2008-10-14 Armin Burgmeier * infinoted/infinoted-options.c: * infinoted/infinoted-startup.c: Fixed a few warnings. 2008-10-14 Armin Burgmeier * po/LINGUAS: Added a file that lists all languages, as required by `make dist'. * configure.ac: Use that file to set ALL_LINGUAS. 2008-10-14 Armin Burgmeier * libinfinity/common/inf-init.h: * libinfinity/common/inf-init.c * libinfinity/common/Makefile.am: New file that contains a function to initialize the library. * infinoted/infinoted-main.c: Don't call g_type_init() anymore in main(). * infinoted/infinoted-startup.c: Instead, call inf_init() which does g_type_init in startup. * libinfinity/inf-i18n.h: * libinfinity/inf-i18n.c: Rely on gettext being initialized all the time. This means inf_init() needs to have been called before. 2008-10-14 Armin Burgmeier * libinftextgtk/inf-text-gtk-buffer.h: * libinftextgtk/inf-text-gtk-buffer.c: Added inf_text_gtk_buffer_get_wake_on_cursor_movement() and inf_text_gtk_buffer_set_wake_on_cursor_movement(). This setting specifies whether to make inactive users active when the cursor position of the underlying TextBuffer changes, or to resync when the user is explicitely set to be active. 2008-10-13 Armin Burgmeier * libinftextgtk/inf-text-gtk-buffer.c: Make sure only one author tag can be applied to a range of text. Applying multiple tags could still occur when copying and pasting text from the same buffer. 2008-10-13 Armin Burgmeier * libinfinity/common/inf-connection-manager.c (inf_connection_manager_handle_message): Keep a reference on the group that is currently processed, and unref at the end. This prevents a crash when net_object_received() does a final unref on the group. 2008-10-12 Armin Burgmeier * libinfinity/common/inf-connection-manager.c (inf_connection_manager_group_unref): Allow final unref of groups not in the tree (because of duplicate IDs). This is a temporary workaround until the handling of such groups has been fixed. 2008-10-12 Armin Burgmeier * libinfgtk/inf-gtk-browser-store.c: Removed an unnecessary gtk_tree_model_row_changed() call. * libinfgtk/inf-gtk-browser-view.c: Fixed automatic expansion of root node when multiple views show the same model. 2008-10-11 Armin Burgmeier * libinfinity/adopted/inf-adopted-session.c (inf_adopted_session_process_xml_sync): Don't leak the processed request. * inf_adopted_split_operation_revert (inf_adopted_split_operation_revert): Don't leak the two reverted child operations. * libinfinity/common/inf-connection-manager.c (inf_connection_manager_group_free): Don't leak the InfConnectionManagerMethodInstance instance. (inf_connection_manager_handle_message): Don't leak scope_attr. * libinfinity/common/inf-session.c (inf_session_get_xml_user_props_impl): Don't leak status. * libinftext/inf-text-session.c (inf_text_session_process_xml_sync): Don't leak the GIconv conversion descriptor. (inf_text_session_process_xml_sync): Don't leak text. 2008-10-09 Armin Burgmeier * libinfinity/common/inf-discovery-avahi.c: Don't assert when the avahi client could not be created. Even though we pass AVAHI_CLIENT_NO_FAIL, sometimes the client still can't be created it seems. 2008-10-09 Armin Burgmeier * libinfinity/adopted/inf-adopted-state-vector.c (inf_adopted_state_vector_vdiff): Changed an assertion that effectively checks an input parameter to a g_return_val_if_fail. * libinftext/inf-text-chunk.c: Disable chunk integrity check by default. * libinftext/inf-text-default-delete-operation.c: Disable text match check by default. 2008-10-09 Armin Burgmeier * libinfinity/adopted/inf-adopted-algorithm.c: Don't let unavailable users prevent cleanup. 2008-10-09 Armin Burgmeier * libinftext/inf-text-session.c: Send undo-caret and redo-caret. We still don't make a difference internally, but let's be gentle to implementations which do. * libinftextgtk/inf-text-gtk-buffer.c: Update "insert" and "selection-bound" markers when the active user's selection changes. 2008-10-09 Armin Burgmeier * infinoted/infinoted-run.h: * infinoted/infinoted-run.c: Moved server running code from infinoted-main.c to a new file. * infinoted/infinoted-signal.h: * infinoted/infinoted-signal.c: New files to handle SIGINT and SIGTERM properly by saving the directory and then shutting down. * infinoted/infinoted-main.c: Register the signals, call into infinoted-run. * infinoted/Makefile.am: Add the new files to the build. * libinfinity/common/inf-standalone-io.c (inf_standalone_io_iteration_impl): Return if poll returned EINTR, to allow shutting down the server in a signal handler. * libinfinity/server/infd-server-pool.c (infd_server_pool_entry_unpublish_with): Fixed unwanted fallthrough in a switch statement. * libinfinity/common/inf-discovery-avahi.c (inf_discovery_avahi_unpublish): Fixed an assertion. * libinfinity/adopted/inf-adopted-split-operation.c: Fixed a typo in a comment. 2008-10-08 Armin Burgmeier * libinfinity/common/inf-user.h: * libinfinity/adopted/inf-adopted-user.h: * libinfinity/adopted/inf-adopted-request.h: * libinfinity/adopted/inf-adopted-request-log.h: * libinfinity/adopted/inf-adopted-algorithm.h: * libinfinity/common/inf-user.c: * libinfinity/adopted/inf-adopted-user.c: * libinfinity/adopted/inf-adopted-request.c: * libinfinity/adopted/inf-adopted-request-log.c: * libinfinity/adopted/inf-adopted-algorithm.c: Added a priv pointer to the instance struct, initialize it in instance_init and use this instead of calling g_type_instance_get_private all the time. This gets us a performance gain of about 9%. 2008-10-08 Armin Burgmeier * infinoted/infinoted-creds.c: Set the subject alternatime name to hostname.local for newly created self-signed certificates, because this is what avahi discovers in a local network. 2008-10-08 Armin Burgmeier * libinfgtk/inf-gtk-certificate-dialog.c: Fixed messages when the certificate has changed. The normal message and the one shown when the old certificate has expired were swapped. 2008-10-08 Armin Burgmeier * libinfgtk/inf-gtk-certificate-manager.c: Don't crash when no certificate warnings are shown, but just go on without showing a dialog. 2008-10-08 Armin Burgmeier * libinfinity/common/inf-discovery-avahi.c: Emit undiscovered signals on correct discovery infos. 2008-10-08 Armin Burgmeier * libinfinity/common/inf-xmpp-connection.h: * libinfinity/common/inf-xmpp-connection.c: Added a sasl-mechanisms property that specifies what mechanisms to accept or offer, respectively, for authentication. * libinfinity/server/infd-xmpp-server.h: * libinfinity/server/infd-xmpp-server.c: * libinfinity/common/inf-discovery-avahi.h: * libinfinity/common/inf-discovery-avahi.c: Added the same property, and forward to created connections. * infinoted/infinoted-main.c: * test/inf-test-browser.c: * test/inf-test-daemon.c: * test/inf-test-gtk-browser.c: * test/inf-test-xmpp-connection.c: Adapt to API changes. * libinfinity/client/infc-browser.c: Don't unref the default method manager. 2008-10-07 Armin Burgmeier * libinfinity/adopted/inf-adopted-state-vector.h: * libinfinity/adopted/inf-adopted-state-vector.c: Added inf_adopted_state_vector_vdiff(). * libinfinity/adopted/inf-adopted-algorithm.c: Use that function to calculate required vdiffs, instead of a slower, own implementation. 2008-10-07 Armin Burgmeier * libinfinity/adopted/inf-adopted-state-vector.h: * libinfinity/adopted/inf-adopted-state-vector.c: Added inf_adopted_state_vector_causally_before_inc(). * libinfinity/adopted/inf-adopted-algorithm.c: Use this new function, to save some copies. * test/inf-test-state-vector.c: Verify that inf_adopted_state_vector_causally_before_inc(, , 1) yields FALSE. 2008-10-07 Armin Burgmeier * libinfinity/adopted/inf-adopted-state-vector.c: Fixed an assertion in inf_adopted_state_vector_add(). * libinfinity/adopted/inf-adopted-algorithm.c: Cleaned up the code in inf_adopted_translate_request(), don't make a copy of the 'to' parameter anymore. 2008-10-07 Armin Burgmeier * libinfinity/adopted/inf-adopted-algorithm.c (inf_adopted_algorithm_translate_request): Don't leak v when a cached request is returned. (inf_adopted_algorithm_execute_request): Don't leak log_request when the request must be made reversible. * libinfinity/adopted/inf-adopted-request.c (inf_adopted_request_transform), (inf_adopted_request_mirror): Don't leak the newly created operations. * libinftext/inf-text-session.c (inf_text_session_xml_to_request): Don't leak the parsed operation. * test/inf-test-chunk.c: Don't leak the two chunks. * test/inf-test-text-operations.c: Don't leak the users array. * test/util/inf-test-util.c: Don't leak the XML content of nodes for buffers. 2008-10-07 Armin Burgmeier * libinfinity/adopted/inf-adopted-algorithm.c: Removed the ugly can_cache paramatere for inf_adopted_algorithm_translate_request() and inf_adopted_algorithm_transform_request(). Instead, translate_request checks itself whether a request is cachable or not. 2008-10-07 Armin Burgmeier * libinfinity/adopted/inf-adopted-request.h: * libinfinity/adopted/inf-adopted-request.c: Made InfAdoptedRequest immutable, which means that the request cannot be altered anymore once created. The functions inf_adopted_request_transform(), inf_adopted_request_mirror() and inf_adopted_request_fold() now return new requests instead of modifying the given one. * libinfinity/adopted/inf-adopted-algorithm.c: Adapt to that change. Given that requests are now immutable, we can save a few copies. This speeds up inf-test-text-session about 11%. 2008-10-07 Armin Burgmeier * test/util/inf-test-util.c (inf_test_dir_util_foreach): Iterate alphabetically through the file names. * test/inf-test-text-session.c: Actually make setting a random seed work, added time measurement. 2008-10-06 Armin Burgmeier * libinfinity/adopted/inf-adopted-session-record.c: Fixed a few warnings. * configure.ac: Added check-news to AM_INIT_AUTOMAKE. * NEWS: Removed the dummy entry, so I don't forget to create a real one for the release. 2008-10-06 Armin Burgmeier * libinfinity/adopted/inf-adopted-operation.h: * libinfinity/adopted/inf-adopted-operation.c: Added two new virtual functions, need_concurrency_id() and get_concurrency_id(). These are used to correctly handle situations when two requests insert text at the same position concurrently. * libinfinity/adopted/inf-adopted-request.h: * libinfinity/adopted/inf-adopted-request.c: Added inf_adopted_request_need_concurrency_id() and inf_adopted_request_get_concurrency_id() which are simple wrapper functions for the underlying operation functions. * libinfinity/adopted/inf-adopted-algorithm.c: If a concurrency ID is needed during transformation, then acquire one from the same requests in a previous state. * libinfinity/adopted/inf-adopted-no-operation.c: * libinfinity/adopted/inf-adopted-split-operation.c: Implement the two new virtual functions. * libinftext/inf-text-pword.h: * libinftext/inf-text-pword.c: Removed, since pwords are no longer used. These did not handle the situation described above well enough, since the algorithm did not pass one of the tests in test/session since the request cache has been introduced (see my change from 2008-02-22). The test in question is now test #28. Also, the adOPTed algorithm relies on the fact that it must not matter on which path a request has been transformed to reach a certain state. The pword concept did not fulfill this requirement. * libinftext/Makefile.am: Removed the files from the build. * libinftext/inf-text-insert-operation.h: * libinftext/inf-text-insert-operation.c: Added inf_text_insert_operation_need_concurrency_id() and inf_text_insert_operation_get_concurrency_id(), and replaced the get_pword() virtual function by get_position(). * libinftext/inf-text-delete-operation.h: * libinftext/inf-text-delete-operation.c: Added inf_text_delete_operation_need_concurrency_id() and inf_text_delete_operation_get_concurrency_id(). * libinftext/inf-text-default-insert-operation.c: * libinftext/inf-text-default-delete-operation.c: * libinftext/inf-text-remote-delete-operation.c: * libinftext/inf-text-move-operation.c: Implement the two new virtual functions from InfAdoptedOperation, and adapt to the get_pword() -> get_position() change in InfTextDefaultInsertOperation. * test/inf-test-text-operations.c: Correctly supply concurrency IDs for the C2 tests to pass. * test/inf-test-text-session.c: Always show the random seed used, also if given. * test/session/*.xml: Regenerated tests. * test/session/Makefile.am: Added the new files to the distribution. 2008-10-06 Armin Burgmeier * libinfinity/inf-i18n.h: * libinfinity/inf-i18n.c: Added vim modelines. * libinfinity/adopted/inf-adopted-concurrency-warning.h: * libinfinity/adopted/inf-adopted-concurrency-warning.c: Helper files that contain a function to print a warning used in the upcoming modification of the algorithm when a concurrency ID is requested for types that don't support it yet. * libinfinity/adopted/Makefile.am: Add the files to the build. 2008-10-03 Armin Burgmeier * libinfinity/adopted/inf-adopted-algorithm.c (inf_adopted_algorithm_translate_request): Simplified the code a bit. 2008-10-01 Armin Burgmeier * libinfinity/inf-i18n.h: * libinfinity/inf-i18n.c: Added _inf_gettext_init() in case somebody needs the infinote gettext translation domain being set without having called _inf_gettext() before. * infinoted/infinoted-creds.h: * infinoted/infinoted-creds.c: Fixed a typo. * infinoted/infinoted-options.h: * infinoted/infinoted-startup.h: * infinoted/infinoted-options.c: * infinoted/infinoted-startup.c: New files, containing some functionality from infinoted-main.c, due to code refactorings. * infinoted/infinoted-main.c: Adapt. * infinoted/Makefile.am: Build the new files. * README: * configure.ac: Require at least glib 2.16. 2008-09-29 Armin Burgmeier * libinfinity/common/inf-cert-util.c (inf_cert_util_save_file): Fixed storage of more than one certificate. 2008-09-25 Armin Burgmeier * libinftext/inf-text-chunk.c: Fixed another problem when a chunk was inserted into another chunk between two segments when the last part could be merged. * test/replay/replay-03.record.xml: * test/replay/replay-04.record.xml: Added two new records, to test the the InfTextChunk. 2008-09-23 Armin Burgmeier * libinftext/inf-text-chunk.c: Fixed a problem when a chunk was inserted into another chunk between two segments, and the last part could not be merged. * test/inf-test-text-replay.c: Cleaned up the code a bit. 2008-09-22 Armin Burgmeier * libinftext/inf-text-chunk.c (inf_text_chunk_erase): Fixed a problem that the erase operation did not produce a correct result when both the first and the last segment of the erasure bounds were in different segments of the same author. * test/inf-test-text-replay.c: Added code to set a breakpoint just before the algorithm applies a request, to be able to debug the InfTextChunk internals. 2008-09-22 Armin Burgmeier * test/inf-test-text-replay.c: Added functionality to check for InfTextChunk errors by performing all the buffer operations on an (ascii-only) GString and comparing the result with the buffer. * libinfinity/adopted/inf-adopted-algorithm.c: Documented a missing parameter in InfAdoptedAlgorithm::execute-request. * test/replay/replay-01.record.xml: * test/replay/replay-02.record.xml: Added two records that currently fail to replay correctly. 2008-09-22 Armin Burgmeier * libinftext/inf-text-session.h: * libinftext/inf-text-session.c: Reorganized the code a bit, added inf_text_session_flush_requests_for_user(). 2008-09-21 Armin Burgmeier * libinftextgtk/inf-text-gtk-buffer.h: * libinftextgtk/inf-text-gtk-buffer.c: Added inf_text_gtk_buffer_ensure_author_tags_priority(). 2008-09-21 Armin Burgmeier * libinfgtk/inf-gtk-certificate-manager.c: Fixed a crash when setting a new trust file. 2008-09-21 Armin Burgmeier * libinfgtk/inf-gtk-browser-store.c: * libinfgtk/inf-gtk-browser-view.c: Allow activating an item with error status and discovery set in which case another connection attempt is made. 2008-09-21 Armin Burgmeier * libinfinity/common/inf-discovery-avahi.c: Fixed usage of alternative service name on collision. 2008-09-21 Armin Burgmeier * libinfinity/server/infd-directory.c: Save new and synced-in sessions initially to storage, to prevent later data loss and to avoid a failure when a user deletes a newly added document (It has not yet been saved to storage, so the deletion of it caused an error). 2008-09-19 Armin Burgmeier * libinfgtk/inf-gtk-browser-store.c: Fixed a crash when the network interface used goes suddenly down. * libinfgtk/inf-gtk-browser-view.c: Fixed a reference counting problem. 2008-09-19 Armin Burgmeier * libinfgtk/inf-gtk-certificate-view.c: Fixed a crash when instantiating InfGtkCertificateView. 2008-09-18 Armin Burgmeier * update-potfiles: Added a small script to generate the po/POTFILES.in. It is simple, but enough for our needs. 2008-09-18 Armin Burgmeier * libinfinity/common/inf-connection-manager.c: * libinfinity/common/inf-discovery-avahi.c: * libinfinity/common/inf-method-manager.c: * libinfinity/common/inf-tcp-connection.c: * libinfinity/common/inf-xmpp-connection.c: * libinfinity/client/infc-browser.c: * libinfinity/server/infd-directory.c: * libinfinity/server/infd-filesystem-storage.c: * libinfinity/adopted/inf-adopted-session-record.c: * libinfgtk/inf-gtk-certificate-manager.c: Marked a few more strings for translation. 2008-09-18 Armin Burgmeier * infinoted/infinoted-main.c: Added --require-tls and --no-tls command line options. 2008-09-18 Armin Burgmeier * libinfinity/server/infd-directory.c infd_directory_node_explore(): Prevent a crash when exploring an unknown note type from the storage. 2008-09-18 Armin Burgmeier * libinfinity/common/inf-xmpp-connection.h: * libinfinity/common/inf-xmpp-connection.c: Added a security-policy property that specifies how to decide whether to use TLS or not. This allows not to use TLS for specific purposes. * libinfinity/server/infd-xmpp-server.h: * libinfinity/server/infd-xmpp-server.c: * libinfinity/common/inf-discovery-avahi.h: * libinfinity/common/inf-discovery-avahi.c: Added the same property that is delegated to created XMPP connections. * test/inf-test-browser.c: * test/inf-test-xmpp-connection.c: Adapted to API change. 2008-09-17 Armin Burgmeier * configure.ac: * Makefile.am: Added gettext support. * libinfinity/inf-i18n.h: * libinfinity/inf-i18n.c: New files containing the common _() macro and a wrapper function to initialize gettext before the first string is translated. * libinfinity/Makefile.am: Add the new files to the build. * libinfinity/common/inf-cert-util.c: * libinfinity/common/inf-connection-manager.c: * libinfinity/common/inf-discovery-avahi.c: * libinfinity/common/inf-error.c: * libinfinity/common/inf-session.c: * libinfinity/common/inf-tcp-connection.c: * libinfinity/common/inf-user.c: * libinfinity/common/inf-xml-util.c: * libinfinity/common/inf-xmpp-connection.c: * libinfinity/client/infc-browser.c: * libinfinity/client/infc-request-manager.c: * libinfinity/client/infc-session-proxy.c: * libinfinity/server/infd-directory.c: * libinfinity/server/infd-filesystem-storage.c: * libinfinity/server/infd-session-proxy.c: * libinfinity/server/infd-xml-server.c: * libinfinity/adopted/inf-adopted-session-record.c: * libinfinity/adopted/inf-adopted-session.c: * libinfinity/adopted/inf-adopted-state-vector.c: * libinftext/inf-text-session.c: * libinfgtk/inf-gtk-browser-store.c: * libinfgtk/inf-gtk-browser-view.c: * libinfgtk/inf-gtk-certificate-dialog.c: * libinfgtk/inf-gtk-certificate-manager.c: * libinfgtk/inf-gtk-certificate-view.c: * libinftextgtk/inf-text-gtk-buffer.c: * infinoted/infinoted-main.c: * infinoted/infinoted-note-plugin.c: Mark all translatable strings. Strings in g_warning() have been omitted, but it might make sense to mark them, too, or at least some of them. 2008-09-17 Armin Burgmeier * libinfinity/common/inf-xmpp-connection.h: * libinfinity/common/inf-xmpp-connection.c: Correctly import certificate chains, produce an error if the server does not provide a certificate. * libinfinity/common/inf-certificate-chain.c: Changed direction so that the first certificate is the server's and the last certificate is the root's, since this how we get the list from GnuTLS. * libinfgtk/inf-gtk-certificate-dialog.c: Fixed showing certificate chains consisting of more than one certificate. * infinoted/infinoted-main.c: Fixed using a whole certificate chain for the server. * infinoted/infinoted-creds.h: * infinoted/infinoted-creds.c: Removed infinoted_creds_read_certificate and infinoted_creds_write_certificate since we use the inf_cert_util functions instead. * configure.ac: * README: Raise required GTK+ version to 2.12, since we use gtk_tree_view_set_show_expanders() which is only available since 2.12. 2008-09-17 Armin Burgmeier * libinfinity/server/infd-directory.c: Fixed warnings about incompatible pointer type in calls to inf_connection_manager_open_group(). 2008-09-17 Armin Burgmeier * libinfinity/common/inf-error.h: * libinfinity/common/inf-error.c: Added inf_gnutls_error_quark() and inf_gnutls_set_error() to convert a gnutls error code into a GError. * libinfinity/common/inf-cert-util.c: * libinfinity/common/inf-xmpp-connection.c: Make use of the new functions, to simplify the code. 2008-09-17 Armin Burgmeier * libinfinity/common/inf-cert-util.h: * libinfinity/common/inf-cert-util.c: Added inf_cert_util_load_file and inf_cert_util_save_file to load or save a certificate list. * libinfgtk/inf-gtk-certificate-manager.c: Use these functions instead of the private inf_gtk_certificate_manager_load_certificate_file and inf_gtk_certificate_manager_save_certificate_file. * libinfgtk/inf-gtk-certificate-dialog.c: Fixed usage of the return value of gtk_icon_theme_lookup_icon. 2008-09-16 Armin Burgmeier * infinoted/infinoted/creds.h: * infinoted/infinoted/creds.c: Include only in the source file not in the header, it is not needed for the declarations. Also set the common name of a generated self-signed certificate to g_get_host_name(). * infinoted/infinoted/main.c: Include since it is no longer included by including infinoted/creds.h. 2008-09-16 Armin Burgmeier * libinfgtk/inf-gtk-certificate-view.h: * libinfgtk/inf-gtk-certificate-view.c: Added a widget that shows a certificate. * libinfgtk/inf-gtk-certificate-dialog.h: * libinfgtk/inf-gtk-certificate-dialog.c: Added a dialog that warns the user when certain things are wrong with a certificate, such as when the issuer is not trusted, the hostname does not match or the certificate expired. * libinfgtk/inf-gtk-certificate-manager.h: * libinfgtk/inf-gtk-certificate-manager.c: Added a class that verifies the certificates of all client connections of a InfXmppManager, and shows InfGtkCertificateDialogs if necessary. * libinfgtk/Makefile.am: Added the new files to the build. 2008-09-16 Armin Burgmeier * libinfinity/common/inf-cert-util.h: * libinfinity/common/inf-cert-util.c: New file containing a few convenience functions to deal with X.509 certificates. * libinfinity/common/inf-certificate-chain.h: * libinfinity/common/inf-certificate-chain.c: Very thin wrapper around an array of gnutls_x509_crt_t to ref-count it and integrate it into the gobject type system. * libinfinity/common/Makefile.am: Added the new files to the build. * libinfinity/common/inf-xmpp-manager.h: * libinfinity/common/inf-xmpp-manager.c: Added a "add-connection" signal that is emitted when a new connection has been added to the manager. * libinfinity/common/inf-xmpp-connection.h: * libinfinity/common/inf-xmpp-connection.c: Query server certificate(s) if we are client, and call a callback to decide whether to accpet the certificate or not. 2008-09-13 Armin Burgmeier * libinfinity/common/inf-xmpp-connection.h: * libinfinity/common/inf-xmpp-connection.c: Make InfXmppConnection take local and remote server address instead of local jid only, and send correct header as required by the RFC. Added support for verification of server's certificate, via a callback. * libinfinity/server/infd-xmpp-server.h: * libinfinity/server/infd-xmpp-server.c: * libinfinity/common/inf-discovery-avahi.c: Set remote server name appropriately. * infinoted/infinoted-main.c: * test/inf-test-browser.c: * test/inf-test-daemon.c: * test/inf-test-xmpp-connection.c: Adapt to API change. 2008-09-11 Armin Burgmeier * libinftextgtk/inf-text-gtk-buffer.c: Don't move own cursor or selection bound if a remote insert operation occurs at the same position. 2008-09-10 Armin Burgmeier * libinftextgtk/inf-text-gtk-buffer.c: Fixed a bug causing wrong text colors when undoing a delete operation having erased text from multiple users. 2008-09-10 Armin Burgmeier * libinfinity/server/infd-session-proxy.c: Notify clients when a connection with subscribed users has unsubscribed. 2008-09-10 Armin Burgmeier * libinftext/inf-text-session.h: * libinftext/inf-text-session.c: Added inf_text_session_set_user_color(), and handle on remote site. 2008-09-10 Armin Burgmeier * libinfinity/client/infc-session-proxy.c: Set connection of joining users to the publisher connection if none was specified. 2008-09-09 Armin Burgmeier * libinfinity/inf-marshal.in: Added VOID:DOUBLE and VOID:ENUM marshallers. * libinftextgtk/inf-text-gtk-hue-chooser.h: * libinftextgtk/inf-text-gtk-hue-chooser.c: Added a new class to choose a hue value. This is basically the same as GtkHSV without the inner triangle. * libinftextgtk/Makefile.am: Added the new files to the build. * libinftextgtk/inf-text-gtk-buffer.c: Added a TODO comment about using gtk_hsv_to_rgb from GTK+ 2.14. 2008-09-07 Armin Burgmeier * libinfinity/client/infc-session-proxy.h: * libinfinity/client/infc-session-proxy.c: Removed infc_session_proxy_set_user_status(), don't handle user-status-change request anymore. * libinfinity/server/infd-session-proxy.c: Don't handle user-status-change anymore, update subscription lists on user status notify. * libinfinity/common/inf-session.h: * libinfinity/common/inf-session.c: Added inf_session_set_user_status(), handle user-status-change requests. 2008-08-27 Armin Burgmeier * libinfinity/adopted/inf-adopted-session-record.c: Flush record file after every request written, so that we don't miss any when we crash. 2008-08-27 Armin Burgmeier * libinftext/inf-text-session.c inf_text_session_request_to_xml(): Don't require a delete operation to be a InfTextDefaultDeleteOperation when for_sync is FALSE, because we only need the length of the operation anyway then. This fixes records of remote delete operations. 2008-08-27 Armin Burgmeier * libinfinity/adopted/inf-adopted-request-log.c: Correctly subtract begin index from end index before dereferencing. 2008-08-27 Armin Burgmeier * libinftext/inf-text-session.c: Correctly read synchronized delete requests, instead of only creating an empty one. 2008-08-26 Armin Burgmeier * libinfinity/server/infd-note-plugin.h: * libinfinity/client/infc-note-plugin.h: Added a user_data parameter to the structs and the callback functions, to ease wrapping InfcNotePlugin and InfdNotePlugin by language bindings. * infinoted/note-plugins/text/infd-note-plugin-text.c: * libinfinity/client/infc-browser.c: * libinfinity/server/infd-directory.c: * test/inf-test-gtk-browser.c: Adapt to API changes. 2008-08-25 Armin Burgmeier * libinfinity/common/inf-user.h: * libinfinity/common/inf-user.c: Replaced INF_USER_AVAILABLE status by INF_USER_ACTIVE and INF_USER_INACTIVE, added inf_user_status_to_string() and inf_user_status_from_string(). * libinfinity/common/inf-error.h: * libinfinity/common/inf-error.c: Merged InfUserJoinError and InfUserStatusChangeError to InfUserError. * libinfinity/adopted/inf-adopted-session.c: Automatically set inactive users active when they issue non-noop requests. * libinfinity/client/infc-session-proxy.h: * libinfinity/client/infc-session-proxy.c: Replaced infc_session_proxy_leave_user() by infc_session_proxy_set_user_status(). * libinfinity/common/inf-session.c: * libinfinity/server/infd-session-proxy.c: * test/inf-test-gtk-browser.c: * test/inf-test-text-cleanup.c: * test/inf-test-text-session.c: Adapt to API changes. 2008-08-24 Armin Burgmeier * libinfinity/server/infd-storage.h: * libinfinity/server/infd-storage.c: Make the remove_node function take an identifier, so that it knows what node to remove. * libinfinity/server/infd-filesystem-storage.c: Implemented accordingly. * libinfinity/server/infd-directory.c: Adapt to API change. 2008-08-24 Armin Burgmeier * libinfgtk/inf-gtk-browser-view.h: * libinfgtk/inf-gtk-browser-view.c: Added inf_gtk_browser_view_set_selected(). 2008-08-23 Armin Burgmeier * libinfgtk/inf-gtk-browser-view.h: * libinfgtk/inf-gtk-browser-view.c: Added the "populate-popup" signal. If signal handlers add menu items to the popup menu, then a popup menu is displayed. 2008-08-22 Armin Burgmeier * libinfinity/common/inf-simulated-connection.h: * libinfinity/common/inf-simulated-connection.c: * libinfinity/common/Makefile.am: Added InfSimulatedConnection, an InfXmlConnection implementation that sends XML data from one simulated connection to another. * libinfinity/adopted/inf-adopted-session-record.c: Add sync-begin and sync-end to initial, so that the content can directly be fed to an InfSession in INF_SESSION_SYNCHRONIZING state on replay. * libinfinity/common/inf-connection-manager.h: * libinfinity/common/inf-connection-manager.c (inf_connection_manager_open_group): Added correct const qualifiers to methods parameter. * libinftext/inf-text-session.c: Don't disconnect from algorithm's signals in INF_SESSION_SYNCHRONIZING state, because we don't have an algorithm yet at that point. This prevents glib warnings. * test/inf-test-text-replay.c: * test/Makefile.am: Added test that replays a record from InfAdoptedSessionRecord internally (without visualization). This can be used to reproduce libinfinity bugs. 2008-08-22 Armin Burgmeier * libinfinity/inf-marshal.in: Added VOID:OBJECT,OBJECT,BOOLEAN marshaller. * libinfinity/adopted/inf-adopted-algorithm.h: * libinfinity/adopted/inf-adopted-algorithm.c: Added user parameter for the "execute-request" signal. * libinfinity/adopted/inf-adopted-session.c: Adapt. * libinfinity/adopted/inf-adopted-session-record.c: Store vector time diffs between requests of the same user, so that the XML can be given directly to InfAdoptedSession for replay. 2008-08-22 Armin Burgmeier * libinfinity/inf-central-method.h: * libinfinity/inf-central-method.c: Moved the implementation of a method implementing central communication into the public libinfinity API, so that it can be used by different networks. * libinfinity/method/local-central/inf-method-local-central.c: Use the InfCentralMethod API. * libinfinity/Makefile.am: Added InfCentralMethod to the build. 2008-08-14 Armin Burgmeier * libinftextgtk/inf-text-gtk-buffer.c (inf_text_gtk_buffer_buffer_iter_get_bytes): Fixed a bug when the iterator only contains a newline. In that case, the function fielded totally wrong values due to an underflow. 2008-08-14 Armin Burgmeier * libinfinity/adopted/inf-adopted-session-record.h: * libinfinity/adopted/inf-adopted-session-record.c: * libinfinity/adopted/Makefile.am: Introduced InfAdoptedSessionRecord, a class to record sessions to replay later. 2008-08-14 Armin Burgmeier * libinfinity/adopted/inf-adopted-session.c: Double the interval within which noop requests are sent, and only send a noop if a remote request has been executed since the last request was sent. 2008-08-08 Armin Burgmeier * libinftextgtk/inf-text-gtk-buffer.c: Call base class dispose instead of finalize, on dispose. 2008-08-08 Armin Burgmeier * libinfgtk/inf-gtk-browser-model.h * libinfgtk/inf-gtk-browser-store.c * libinfgtk/inf-gtk-browser-view.c: Fix searching in browser view by setting the search column correctly, and allowing non-toplevel columns to have a name. 2008-07-23 Benjamin Herr * libinftext/inf-text-session.c: Apply attributes to operation xml element instead of its parent. 2008-07-23 Benjamin Herr * libinftext/inf-text-session.c: Properly initialised operation variable before accessing it. * ChangeLog: Fixed date of preceeding change log entry. 2008-07-18 Armin Burgmeier * libinfinity/adopted/inf-adopted-session.h: * libinfinity/adopted/inf-adopted-session.c: Changed the xml_to_operation and operation_to_xml vfuncs to xml_to_request and request_to_xml, to allow generation of custom requests, and to decouple the update of local user's last send vector from the serialization of a request. Added inf_adopted_session_read_request_info() and inf_adopted_session_write_request_info() to ease implementation by derived classes. * libinftext/inf-text-session.c: Adapted to API change. 2008-07-17 Armin Burgmeier * libinfinity/common/inf-connection-manager.h: * libinfinity/common/inf-connection-manager.c: Added documentation, removed has_connection and lookup_connection functions from InfConnectionManagerMethodDesc, we just rely on the registered connections for this. * libinfinity/methods/local-central/inf-method-local-central.c: Adapt to the API change. * libinfinity/adopted/inf-adopted-session.h: * libinfinity/adopted/inf-adopted-session.c: * libinfinity/adopted/inf-adopted-split-operation.h: * libinfinity/adopted/inf-adopted-state-vector.h: * libinfinity/adopted/inf-adopted-user.h: * libinfinity/common/inf-buffer.h: Added some more documentation. 2008-07-16 Armin Burgmeier * libinfinity/adopted/inf-adopted-algorithm.h: * libinfinity/adopted/inf-adopted-algorithm.c: Added "execute-request" signal that is emitted every time a request is executed. 2008-07-15 Armin Burgmeier * libinfinity/adopted/inf-adopted-request-log.h: * libinfinity/adopted/inf-adopted-request-log.c: Added more documentation. * libinfinity/adopted/inf-adopted-state-vector.c: Fixed formatting slightly. * TODO: Added ideas to improve performance. 2008-07-15 Benjamin Herr * libinfinity/adopted/inf-state-vector.h: Changed state vector typedef from GSequence to an opaque type. * libinfinity/adopted/inf-state-vector.c: Changed state vector to use an array of ids and timestamps instead of a GSequence. * tests/inf-test-state-vector.c: Added a bunch of poorly-thought-out tests. 2008-07-12 Armin Burgmeier * libinfinity/adopted/inf-adopted-algorithm.h: * libinfinity/adopted/inf-adopted-algorithm.c: * libinfinity/adopted/inf-adopted-no-operation.h: * libinfinity/adopted/inf-adopted-no-operation.c: * libinfinity/adopted/inf-adopted-operation.h: * libinfinity/adopted/inf-adopted-operation.c: * libinfinity/adopted/inf-adopted-request.h: * libinfinity/adopted/inf-adopted-request.c: * libinfinity/common/inf-user-table.h: * libinfinity/common/inf-user-table.c: * libinfinity/common/inf-connection-manager.c: * libinfinity/common/inf-io.c: * libinfinity/common/inf-session.c: Added/Fixed documentation. 2008-07-12 Armin Burgmeier * test/inf-test-text-cleanup.c (perform_test): Terminate the call to g_object_new that creates the InfTextSession with NULL, preventing memory corruption. 2008-07-12 Armin Burgmeier * libinfinity/client/infc-browser.c (infc_session_proxy_set_connection): Correctly thaw the notification queue of the session at the end of the function. 2008-07-11 Armin Burgmeier * libinftextgtk/inf-text-gtk-buffer.c: Update user tag "background-color" property on user color change. 2008-07-06 Armin Burgmeier * libinfinity/adopted/inf-adopted-algorithm.c (inf_adopted_algorithm_can_undo_redo): Changed semantics of this function for non-local users so that it returns whether the user in question can issue an Undo or Redo command in its own current state (as known to the local site). * test/inf-test-text-cleanup.c: Allow can-undo and can-redo verifications when the user's vector does not match the current one from the algorithm. * test/cleanup/cleanup-05.xml: * test/cleanup/cleanup-06.xml: * test/cleanup/cleanup-07.xml: Yet another three tests. 2008-07-06 Armin Burgmeier * libinfinity/adopted/inf-adopted-algorithm.c (inf_adopted_algorithm_cleanup): Don't use least common successor but least common predecessor as reference when cleaning up requests. This was always meant to be the predecessor, but used the successor until now because of me being stupid. Also fixed the cleanup process so that when all sites processed all operations the max total log size really is not exceeded. * libinfinity/adopted/inf-adopted-request-log.c (inf_adopted_request_log_remove_requests): Don't touch next-undo or next-redo when no requests are removed. * test/cleanup/cleanup-01.xml: Empty the initial buffer for simplicity. * test/cleanup/cleanup-02.xml: * test/cleanup/cleanup-03.xml: * test/cleanup/cleanup-04.xml: Three more cleanup tests. 2008-07-06 Armin Burgmeier * libinfinity/adopted/inf-adopted-algorithm.c: Use G_MAXUINT instead of 0 for max-total-log-size to mean unlimited, so a max-total-log-size of 0 is allowed. * test/inf-test-text-cleanup.c: * test/inf-test-text-session.c: Only process XML files in the subdirectories, not Makefiles and other stuff. 2008-07-05 Armin Burgmeier * libinfinity/adopted/inf-adopted-algorithm.c (inf_adopted_algorithm_can_undo, inf_adopted_algorithm_can_redo): Added support for returning undo/redo status for non-local users. However, this currently returns whether those users can issue undo/redo in the algorithm's current state. This especially means that a request received from such a non-local user may be valid even if this function returns false, if the request was generated at another state. This will probably be changed in the future to return whether the given user can issue an Undo/Redo request in its own state (as known to the local site). * libinfinity/adopted/inf-adopted-session.c: Added the "max-total-log-size" property that is delegated to the construction of the algorithm. * test/inf-test-text-cleanup.c: Added a test that reads XML files specifying test scenarios from test/cleanup to test whether the algorithm's cleanup routines (correctly shrink request logs, correctly issue can-undo/can-redo) work. * test/cleanup/cleanup-01.xml: First simple cleanup test. * test/session/Makefile.am: * test/cleanup/Makefile.am: * configure.ac: Add the test files to the distribution. * test/Makefile.am: Add the new file to the build. 2008-07-05 Armin Burgmeier * test/session/: Renamed from test/std/. * docs/reference/libinfgtk/Makefile.am: * docs/reference/libinfinity/Makefile.am: * docs/reference/libinftext/Makefile.am: * docs/reference/libinftextgtk/Makefile.am: * libinfgtk/Makefile.am: * libinfinity/Makefile.am: * libinfinity/adopted/Makefile.am: * libinfinity/client/Makefile.am: * libinfinity/common/Makefile.am: * libinfinity/server/Makefile.am: * libinftext/Makefile.am: * libinftextgtk/Makefile.am: Use AM_CPPFLAGS instead of INCLUDES which is deprecated. * test/util/inf-test-util.h: * test/util/inf-test-util.c: Moved some common functions used in multiple tests here for code reuse. * test/Makefile.am: * configure.ac: Add to build. * test/inf-test-text-session.c: Use the new test functions. 2008-07-03 Armin Burgmeier * libinftextgtk/inf-text-gtk-buffer.c (inf_text_gtk_buffer_insert_text_cb, inf_text_gtk_buffer_delete_range_cb): Revalidate iterators at the end, so that others can call gtk_text_buffer_insert and gtk_text_buffer_delete with normal semantics. 2008-06-29 Armin Burgmeier * libinfinity/server/infd-session-proxy.c: Don't assign user IDs that are already in use by users that were already in the initial session. 2008-06-28 Armin Burgmeier * libinfinity/common/inf-xmpp-connection.c: Fixed a crash when was received. * libinfinity/client/infc-session-proxy.h: * libinfinity/client/infc-session-proxy.c: Added infc_session_proxy_get_connection and infc_session_proxy_get_subscription_group, correctly unset underlying session's subscription group when the connection is released. 2008-06-27 Armin Burgmeier * libinfinity/adopted/inf-adopted-session.c (inf_adopted_session_constructor): Add initial local users to the list of local users. * libinfinity/client/infc-browser.c (infc_browser_handle_add_node): Fix the check for a child being present. * libinfinity/common/inf-user-table.c (inf_user_table_add_user_handler): Ref users put into the user table. * libinfinity/common/inf-session.c (inf_session_net_object_sent): Don't assert that the sent message was a synchronization message if we found a synchronization to the connection since we could already have sent stuff that is meant to be processed after the synchronization. (inf_session_add_user): Unref user after having put it into the user table. * libinfinity/server/infd-directory.c: Removed the check that available users in a synced-session need to be from the synchronizing connections since that check has been moved to InfdSessionProxy. * libinfinity/server/infd-session-proxy.c: Added the mentioned check here, and additionally add the user to the list of subscribed users for that connection so that, when the connection unbsubscribes again, the user will be set to unavailable. Also removed the subscribe-sync-conn property, instead allow calling infd_session_proxy_subscribe_to() when the session is in INF_SESSION_SYNCHRONIZING state. * test/inf-test-text-session.c: Unref user after having put in into the user table. * infinoted/note-plugins/text/infd-note-plugin-text.c (infd_note_plugin_text_read_user): Unref user after having put it into the user table. 2008-06-27 Armin Burgmeier * libinfinity/common/inf-session.c (inf_session_sync_strerror): Fix a typo. (inf_session_process_xml_sync_impl): Set connection property to the synchronizing connection if not given. (inf_session_handle_received_sync_message): Cope with the fact that some callback in process_xml_sync could have cancelled the synchronization. * libinfinity/server/infd-directory.c: Make sure that available users in a synced-in session are from the synchronizing connection, and only allow them if the synchronizing connection is subscribed. Otherwise, close the session which effectively cancels the sync-in. * libinfinity/server/infd-session-proxy.c: Fixed two typos in comments. 2008-06-25 Armin Burgmeier * libinfinity/common/infc-session-proxy.c (infc_session_proxy_dispose): Properly release connection on dispose, chain to base class after having unrefed the session, so that weak references are notified after object has been fully disposed. This fixes a warning when a successful sync-in is removed. * libinfinity/common/inf-session.c (inf_session_close_handler): Changed a comment to make clear how synchronizations are removed. 2008-06-24 Armin Burgmeier * libinfinity/common/inf-connection-manager.c (inf_connection_manager_register_connection): Fixed a severe reference counting issue: Registering a connection multiple times did not increase the reference count. * libinftext/inf-text-session.c (inf_text_session_selection_changed_data_free): Fixed the function signature to match GClosureNotify. (inf_text_session_segment_to_xml): Don't assert if the input text is too large, this will be handled in a second run. 2008-06-22 Armin Burgmeier * libinftextgtk/inf-text-gtk-buffer.c (inf_text_gtk_buffer_buffer_iter_get_bytes): Fix two logic errors so that the function behaves as expected. 2008-06-22 Armin Burgmeier * libinfinity/client/infc-browser.c (infc_browser_handle_sync_in): Free type after it has been used, not before, and add the sync in after having created the node, because the sync-in needs to know the node. * libinfinity/client/infc-session-proxy.c (infc_session_proxy_net_object_received): Fix an assertion so that synchronization messages are passed to the underlying InfSession even when they do not come from the subscription connection. * libinfinity/server/infd-directory.c (infd_directory_node_add_sync_in): Send parent node of sync-in, add connection to sync group if it is not the subscription group. * libinfgtk/inf-gtk-browser-view.c: Added two TODO comments about watching a signal to get notified when a sync-in begins. 2008-06-22 Armin Burgmeier * libinfinity/common/inf-session.c (inf_session_close_handler): Check that the connection is still open before calling inf_session_send_sync_error(). This fails otherwise if the session was closed explictely in response to the status change notify of the underlaying connection. (inf_session_synchronization_failed_handler): Don't assert on INF_SESSION_CLOSED since the session could be closed between the beginning of the signal emission and the run of the default handler. * libinfinity/client/infc-browser.c (infc_browser_net_object_received): If an error was set, and the node had a seq set, then fail the corresponding request since the server reply could not be processed. * libinfinity/server/infd-directory.c (infd_directory_add_sync_in): Unref the synchronization group after having passed it to _create_session_proxy(). * libinftextgtk/inf-text-gtk-buffer.c (inf_text_gtk_buffer_set_active_user): Allow the new active user to be NULL to unset the active user, as used in _dispose(). 2008-06-21 Armin Burgmeier * libinfinity/client/infc-browser.h: * libinfinity/client/infc-browser.c: Added infc_browser_iter_get_path(). 2008-06-15 Armin Burgmeier * libinfinity/common/inf-connection-manager.h: * libinfinity/common/inf-connection-manager.c: Added parent parameter for inf_connection_manager_add_connection() and inf_connection_manager_register_connection(). * libinfinity/server/infd-session-proxy.h: * libinfinity/server/infd-session-proxy.c: Added parent_group parameter for infd_session_proxy_subscribe_to(), making sure the first message in the subscription group is sent after the client knows about the subscription (group). * libinfinity/server/infd-directory.c: * libinfinity/methods/local-central/inf-method-local-central.c: Adapt to API changes. 2008-06-14 Armin Burgmeier * test/inf-test-text-operations.c: Remove an unused variable. * infinoted/infinoted-main.c: Listen on IPv6, fall back to IPv4 if that fails. * libinfinity/common/inf-connection-manager.h: * libinfinity/common/inf-connection-manager.c: Do no longer rely on the local/remote address for publisher identification, but use a host-local UUID for this. * libinfinity/common/inf-method-manager.c: Print error message when a method could not be loaded. * libinfinity/methods/local-central/inf-method-local-central.c: * README: * configure.ac: Depend on libuuid. 2008-05-18 Armin Burgmeier * libinfinity/client/infc-browser.c: Added two assertions in infc_browser_handle_sync_in() and infc_browser_add_note_with_content() that make sure that the provided session is not yet subscribed in case that the client wants to subscribe to the newly created node. * libinfgtk/inf-gtk-browser-view.c: Show progress of sync-ins. 2008-05-17 Armin Burgmeier * libinfinity/client/infc-browser.h: * libinfinity/client/infc-browser.c: Replaced the "begin-sync-in" signal and the infc_browser_iter_get_sync_in_requests() method by a infc_browser_iter_get_sync_in() method that provides the same information. 2008-05-17 Armin Burgmeier * libinfinity/common/inf-error.h: * libinfinity/common/inf-error.c: Added INF_DIRECTORY_ERROR_UNEXPECTED_SYNC_IN error code. * libinfinity/client/infc-browser.h: * libinfinity/client/infc-browser.c: Added support for Sync-Ins, resulting in these new methods: infc_browser_add_note_with_content(), infc_browser_iter_get_sync_in_requests(), and the "begin-sync-in" signal. * libinfinity/server/infd-directory.c: Added node name and node type in the reply. 2008-05-13 Armin Burgmeier * libinfinity/server/infd-directory.c: Added child tags into replies that have a child set, telling group name and method of subscription group. 2008-05-12 Armin Burgmeier * libinfinity/adopted/inf-adopted-session.c: Correctly remove noop timer when the session is destroyed. 2008-05-12 Armin Burgmeier * libinfinity/server/infd-session-proxy.h: * libinfinity/server/infd-session-proxy.c: Added a synchronize parameter to infd_session_proxy_subscribe_to, that specifies whether to synchronize the session before subscription. * libinfinity/server/infd-directory.h: * libinfinity/server/infd-directory.c: Added support for so-called Sync-Ins. Sync-Ins are nodes created upon a client request that have initial content synchronized from the client. 2008-05-09 Armin Burgmeier * libinfgtk/inf-gtk-browser-view.c: Don't rely on the underlying model containing all browser nodes since a InfGtkBrowserModelFilter might filter some. 2008-05-09 Armin Burgmeier * libinfgtk/inf-gtk-browser-model-sort.c: * libinfgtk/inf-gtk-browser-model-filter.c: Fix call to gtk_tree_model_{filter,sort}_convert_child_iter_to_iter() in browser_iter_to_tree_iter. * libinfgtk/inf-gtk-browser-view.c: Don't rely on the model to have GTK_TREE_MODEL_ITERS_PERSIST set. 2008-05-09 Armin Burgmeier * libinfinity/common/inf-standalone-io.c: Fixed endless loop when two or more timeouts have been registered. 2008-05-09 Armin Burgmeier * libinfgtk/inf-gtk-browser-model-sort.c: * libinfgtk/inf-gtk-browser-model-filter.c: Explicitely sync with initial model in constructor since we don't get notified for it. 2008-05-09 Armin Burgmeier * libinfgtk/inf-gtk-browser-view.h: * libinfgtk/inf-gtk-browser-view.c: Added the "selection_changed" signal. 2008-05-09 Armin Burgmeier * libinfgtk/inf-gtk-browser-model-filter.c: (inf_gtk_browser_model_filter_new): Fixed property name in g_object_new which is "child-model" instead of "model" for GtkTreeModelFilter. 2008-05-09 Armin Burgmeier * libinfinity/client/infc-browser.h: * libinfinity/client/infc-browser.c: Made the plugin parameter to infc_browser_add_note() const. 2008-05-09 Armin Burgmeier * libinfgtk/inf-gtk-browser-view.h: * libinfgtk/inf-gtk-browser-view.c: Added inf_gtk_browser_view_get_selected(). 2008-05-08 Armin Burgmeier * libinfgtk/inf-gtk-browser-store.h: Removed declaration of inf_gtk_browser_store_resolve(). * libinfgtk/inf-gtk-browser-model.c: Adjusted reference from inf_gtk_browser_store_resove() to inf_gtk_browser_model_resolve(). 2008-05-08 Armin Burgmeier * docs/reference/libinfinity/libinfinity-docs.sgml: Reordered, added a separate section for each sub-library (common, adopted, client, server). * docs/reference/libinftext/Makefile.am: * docs/reference/libinftext/tmpl/*.sgml: * docs/reference/libinftext/libinftext-docs.sgml: * docs/reference/libinftext/libinftext-overrides.txt: * docs/reference/libinftext/libinftext-sections.txt: * docs/reference/libinftext/libinftext.types: * docs/reference/Makefile.am: * configure.ac: Added gtk-doc documentation for libinftext. * docs/reference/libinfgtk/Makefile.am: * docs/reference/libinfgtk/tmpl/*.sgml: * docs/reference/libinfgtk/libinfgtk-docs.sgml: * docs/reference/libinfgtk/libinfgtk-overrides.txt: * docs/reference/libinfgtk/libinfgtk-sections.txt: * docs/reference/libinfgtk/libinfgtk.types: * docs/reference/Makefile.am: * configure.ac: Added gtk-doc documentation for libinfgtk. * docs/reference/libinftextgtk/Makefile.am: * docs/reference/libinftextgtk/tmpl/*.sgml: * docs/reference/libinftextgtk/libinftextgtk-docs.sgml: * docs/reference/libinftextgtk/libinftextgtk-overrides.txt: * docs/reference/libinftextgtk/libinftextgtk-sections.txt: * docs/reference/libinftextgtk/libinftextgtk.types: * docs/reference/Makefile.am: * configure.ac: Added gtk-doc documentation for libinftextgtk. * libinftext/inf-text-buffer.c: * libinftext/inf-text-chunk.c: * libinfgtk/inf-gtk-browser-model.c: * libinfgtk/inf-gtk-browser-model.h: * libinfgtk/inf-gtk-browser-view.c: * libinfgtk/inf-gtk-io.c: Fixed minor documentation errors. 2008-05-08 Armin Burgmeier * libinfgtk/inf-gtk-browser-model-sort.c: Don't call inf_gtk_browser_model_set_browser() on child model in default signal handler of set_browser. This would lead to endless recursion. * libinfgtk/inf-gtk-browser-model-filter.h: * libinfgtk/inf-gtk-browser-model-filter.c: * libinfgtk/Makefile.am: Added InfGtkBrowserModelFilter, deriving from GtkTreeModelFilter and implementing InfGtkBrowserModel. 2008-05-08 Armin Burgmeier * libinfgtk/inf-gtk-browser-store.h: Removed two declarations that are already in inf-gtk-browser-model.h. * libinfgtk/inf-gtk-browser-model-sort.h: * libinfgtk/inf-gtk-browser-model-sort.c: * libinfgtk/Makefile: Added a new class deriving from GtkTreeModelSort that implements InfGtkBrowserModel. 2008-04-20 Armin Burgmeier * libinfgtk/inf-gtk-browser-model.h: * libinfgtk/inf-gtk-browser-model.c: * Makefile.am: Changed this class to an interface with a resolve() and browser_iter_to_tree_iter() virtual function, to allow custom models to be given to InfGtkBrowserView. * libinfgtk/inf-gtk-browser-store.h: * libinfgtk/inf-gtk-browser-store.c: Moved the original InfGtkBrowserModel class to InfGtkBrowserStore, implementing the new interface. * libinfgtk/inf-gtk-browser-view.c: Added a missing include, remove some unused variables. * test/inf-test-gtk-browser.c: Adapt to the new API. 2008-04-20 Armin Burgmeier * infinoted/note-plugins/text/infd-note-plugin-text.c: * libinfinity/common/inf-connection-manager.c: Improved error messages. * libinfinity/server/infd-session-proxy.c: Added a TODO comment about not propagating non-fatal errors to the connection manager. 2008-04-13 Armin Burgmeier * libinfinity/client/infc-browser.c: Remove the session proxy associated to an entry when the corresponding session is closed. 2008-04-13 Armin Burgmeier * libinfinity/common/inf-connection-manager.c: Reset the _private field of queued xmlNodePtr, so that libxml++ (when linked in) does not assume that's the C++ wrapper for the node (it tries to delete it). 2008-04-12 Armin Burgmeier * libinftextgtk/inf-text-gtk-buffer.c: Allow moving the text buffer's cursor and selection without active user. 2008-04-12 Armin Burgmeier * libinfinity/client/infc-browser.c: Emit the subscribe-session signal before finishing a pending request, so that signal handlers of InfcNodeRequest::finished can access the newly created session via infc_browser_iter_get_session(). * libinfinity/common/inf-xmpp-connection.c: Added some more comments about RFC compliance. 2008-03-06 Armin Burgmeier * libinfinity/Makefile.am: Build methods after having built libinfinity, so they can link against it. * libinfinity/methods/local-central/Makefile.am: Link against libinfinity-1.0 instead of libinfinity_common so that the marshal functions are not undefined. 2008-03-06 Armin Burgmeier * libinfgtk/inf-gtk-browser-model.h: * libinfgtk/inf-gtk-browser-model.c: Added a "name" column for toplevel items, to support sensible item names for direct connections. * libinfgtk/inf-gtk-browser-view.c: Show that name. * libinfinity/common/inf-connection-manager.c: Check that such a group is not already present in inf_connection_manager_create_group() and inf_connection_manager_join_group(). * libinfinity/common/inf-discovery-avahi.c: Also weakref discovered XMPP connection when we did not need to create it. We don't strongref it here neither, and must get notified when to invalidate the cache. 2008-03-06 Armin Burgmeier * libinfinity/inf-config.h.in: Configuration file that only contains prefixed defines, so it is safe to be installed. * libinfinity/Makefile.am: Noted that inf-config.h should be installed, in contrast to inf-marshal.h. * configure.ac: Let autoheader generate config.h, not libinfinity/inf-config.h. * libinfinity/common/inf-tcp-connection.c: Fixed a typo (#error -> @error). 2008-03-04 Armin Burgmeier * libinfinity/Makefile.am: * libinfinity/common/Makefile.am: * libinfinity/adopted/Makefile.am: * libinfinity/client/Makefile.am: * libinfinity/server/Makefile.am: Fixed include files installation path. 2008-03-04 Armin Burgmeier * libinfgtk/inf-gtk-browser-view.h: * libinfgtk/inf-gtk-browser-view.c: Don't subscribe on row activation, but emit an activate signal so that client code can subscribe. * test/inf-test-gtk-browser.c: Adapt. 2008-08-24 Armin Burgmeier * libinfinity/common/inf-xml-util.h: * libinfinity/common/inf-xml-util.c: Added inf_xml_util_get_attribute_double(), inf_xml_util_get_attribute_double_required() and inf_xml_util_set_attribute_double(). * libinftext/inf-text-user.h: * libinftext/inf-text-user.c: Added the "hue" property. * libinftext/inf-text-session.c: Adapted get_xml_user_props and set_xml_user_props. * infinoted/note-plugins/text/infd-note-plugin-text.c: Save hue property in filesystem storage. * libinftextgtk/inf-text-gtk-buffer.h: * libinftextgtk/inf-text-gtk-buffer.c: Set tag background color according tu hue property of author, added the "user-table" property, take in inf_text_gtk_buffer_new(). * test/inf-test-gtk-browser.c: Adapt to API change. 2008-02-24 Armin Burgmeier * libinftext/inf-text-session.c: Delay caret updates if too frequent. * libinfinity/common/inf-io.h: * libinfinity/common/inf-io.c: Added a GDestroyNotify parameter to inf_io_watch() and inf_io_add_timeout(). * libinfinity/common/inf-standalone-io.c * libinfgtk/inf-gtk-io.c: Adapt implementation. * libinfinity/common/inf-tcp-connection.c: * libinfinity/common/inf-discovery-avahi.c: * libinfinity/adopted/inf-adopted-session.c: * libinfinity/server/infd-tcp-server.c: * test/inf-test-browser.c: Adapt usage. * libinfinity/server/infd-directory.c: Make use of the notify to get rid of an unpleasant hack. 2008-02-23 Armin Burgmeier * libinfinity/common/inf-session.c: inf_session_get_synchronization_progress(): Don't divide by zero if the initial sync-begin was not yet received. * libinfinity/adopted/inf-adopted-session.c: Send noop request after 15 seconds of inactivity. 2008-02-23 Armin Burgmeier * libinfinity/client/infc-browser.h: * libinfinity/client/infc-browser.c: Added infc_browser_iter_save_session(). * libinfinity/common/inf-session.h: * libinfinity/common/inf-session.c: Added the synchronization-begin signal. * libinfinity/server/infd-session-proxy.c: Don't consider the session idle when there are ongoing synchronizations. 2008-02-22 Armin Burgmeier * libinfinity/server/infd-directory.c: Handle request, automatically store idle sessions into storage, unload from RAM. * libinfinity/server/infd-session-proxy.h: * libinfinity/server/infd-session-proxy.c: Added the "idle" property, the "add-subscription" and "remove-subscription" signals and infd_session_proxy_has_subscriptions(), infd_session_proxy_is_subscribed() and infd_session_proxy_is_idle(). * libinfinity/common/inf-error.h: * libinfinity/common/inf-error.c: Added INF_DIRECTORY_ERROR_UNSUBSCRIBED. * infinoted/note-plugins/text/infd-note-plugin-text.c: Fix a bug (an error was reported when everything was OK) when loading user-modified text. 2008-02-22 Armin Burgmeier * libinfinity/adopted/inf-adopted-request-log.h: * libinfinity/adopted/inf-adopted-request-log.c: Changed inf_adopted_request_log_upper_related() to take the request index instead of the request itself. * libinfinity/common/inf-method-manager.h: * libinfinity/common/inf-user-table.h: * libinfinity/adopted/inf-adopted-session.h: Removed superflous #defines, resulting from cut'n'pasted code. * libinfinity/adopted/inf-adopted-algorithm.c: Implemented caching for translated requests. This speeds up translation of undo requests that need to be transformed against several requests of others. This breaks test #25. However, the problem seems not to be with the cache but with the transformation function. I need to investigate this separately. Also simplified cleanup of request logs. * libinfinity/common/inf-buffer.c: * libinfinity/common/inf-session.c: * libinfinity/adopted/inf-adopted-user.c: * libinfinity/server/infd-directory.c: * docs/reference/libinfinity/libinfinity-sections.txt: Documentation fixes. * test/inf-test-text-session.c: Don't interpret given random seed as test directory. * test/std/test-47.xml: Added new test transforming ten undo requests against ten requests from another user. This is unacceptably slow without the request cache mentioned above. 2008-02-17 Armin Burgmeier * libinfinity/adopted/inf-adopted-split-operation.c: * libinfinity/common/inf-ip-address.c: More documentation. 2008-02-17 Benjamin Herr * libinfinity/common/inf-discovery.c: * libinfinity/common/inf-session.c: Added some more completely made-up documentation! 2008-02-17 Armin Burgmeier * libinfinity/common/inf-io.h: * libinfinity/common/inf-io.c: * libinfinity/server/infd-directory.c: * libinfinity/common/inf-net-object.c: * libinfinity/common/inf-connection-manager.c: * libinfinity/client/infc-request.c: Documented these classes. * docs/reference/libinfinity/libinfinity.types: Committed types file as it seems to be required to generate correct documentation. * docs/reference/libinfinity/libinfinity-sections.txt: Order a bit. 2008-02-17 Benjamin Herr * libinfinity/common/inf-user-table.c: * libinfinity/common/inf-tcp-connection.c: * libinfinity/common/inf-xml-connection.c: Added preliminary documentation to a few signals. 2008-02-17 Benjamin Herr * libinfinity/adopted/inf-adopted-no-operation.c: * libinfinity/adopted/inf-adopted-split-operation.c: * libinfinity/server/infd-storage.c: * libinfinity/server/infd-storage.h: * libinfinity/common/inf-net-object.c: * libinfinity/common/inf-standalone-io.c: * libinfinity/common/inf-user-table.c: * libinfinity/common/inf-method-manager.c: * libinfinity/common/inf-ip-address.c: * libinfinity/common/inf-xmpp-manager.c: * libinfinity/common/inf-connection-manager.c: * libinfinity/common/inf-session.c: * libinfinity/client/infc-request-manager.c: * libinfinity/client/infc-request-manager.h: Solved minor documentation generation errors/warnings 2008-02-17 Armin Burgmeier * docs/reference/libinfinity/tmpl/*.sgml: Committed SGML files required by gtk-doc. 2008-02-17 Benjamin Herr * **/*.c: changes "/** foo:\n *" into "/**\n * foo:" 2008-02-17 Armin Burgmeier * autogen.sh: Added autogen.sh which also calls gtkdocize in addition to creating all the necessary build files. * configure.ac: Added gtk-doc support. * Makefile.am: Added docs to subdirs. * libinfinity/adopted/inf-adopted-state-vector.h: * libinfinity/adopted/inf-adopted-state-vector.c: * libinfinity/client/infc-browser-iter.c: * libinfinity/client/infc-browser.h: * libinfinity/client/infc-browser.c: Documentation fixes. * m4: Added m4 directory as required by some new configure macro. * docs/Makefile.am: * docs/reference/Makefile.am: * docs/reference/libinfinity/Makefile.am: * docs/reference/version.xml.in: * docs/reference/libinfinity/libinfinity-sections.txt: * docs/reference/libinfinity/libinfinity-docs.sgml: * docs/reference/libinfinity/libinfinity-overrides.txt: Added initial gtk-doc files to create documentation. Perhaps some more are required which I will commit when someone misses them. I just don't want to check in generated files. * test/inf-test-text-session.c: Reduced permutations to 100 so that it finishes earlier. 2008-02-15 Armin Burgmeier * libinfinity/adopted/inf-adopted-request-log.c: Fixed possible memory corruption when entries need to be reallocated. * TODO: Update. 2008-02-15 Armin Burgmeier * libinfinity/adopted/inf-adopted-algorithm.c: Replaced user_id -> requset log hash table by a user array, hopefully making some loops faster. 2008-02-15 Armin Burgmeier * libinfinity/adopted/inf-adopted-algorithm.h: * libinfinity/adopted/inf-adopted-algorithm.c: Read participating users directly from user table, remove inf_adopted_algorithm_add_user(). * libinfinity/adopted/inf-adopted-session.c: Adapt to API change. 2008-02-15 Armin Burgmeier * libinfinity/adopted/inf-adopted-algorithm.c: Split the transformation part of inf_adopted_algorithm_translate_request() into a separate function inf_adopted_algorithm_transform_request(). 2008-02-14 Armin Burgmeier * libinfinity/adopted/inf-adopted-algorithm.c: Fixed a bug introduced with the last commit that broke collaboration. 2008-02-14 Armin Burgmeier * libinfinity/common/inf-user-table.h: * libinfinity/common/inf-user-table.c: Added add-local-user and remove-local-user signals, and inf_user_table_foreach_local_user(). * libinfinity/server/infd-note-plugin.h: * libinfinity/server/infd-directory.c: Changed note plugin API so that read_session() creates the session instead of filling an existing session object. * infinoted/note-plugins/text/infd-note-plugin-text.c: Adapt. * libinfinity/client/infc-session-proxy.c: Removed some commented-out code. * libinfinity/adopted/inf-adopted-request.h: * libinfinity/adopted/inf-adopted-request.c: Added inf_adopte_request_affects_buffer(). * libinfinity/adopted/inf-adopted-algorithm.c: Don't increase vector time of an incoming request's user if the request does not affect the buffer. * libinfinity/adopted/inf-adopted-session.c: Don't increase the last send vector if the sent request does not affect the buffer. * libinftext/inf-text-session.c: Broadcast cursor positions and selections. * libinftextgtk/inf-text-gtk-buffer.c: Update active user's cursor position when the "insert" or "selection-bound" mark is moved in the buffer. 2008-02-11 Armin Burgmeier * libinfinity/adopted/inf-adopted-algorithm.h: * libinfinity/adopted/inf-adopted-algorithm.c: Added inf_adopted_algorithm_can_undo() and inf_adopted_algorithm_can_redo() and the apply-request signal. * libinfinity/adopted/inf-adopted-session.h: * libinfinity/adopted/inf-adopted-session.c: Added inf_adopted_session_undo() and inf_adopted_session_redo(). * libinftext/inf-text-session.c: Don't broadcast while the algorithm itself is applying a request. * test/inf-test-gtk-browser.c: Added GUI for undo/redo. 2008-02-11 Armin Burgmeier * libinfinity/adopted/inf-adopted-session.c: Send undo and redo operations as child of the element instead of as an attribute of it. This is how the receiving code expects it. 2008-02-10 Armin Burgmeier * libinfinity/common/inf-connection-manager.h: * libinfinity/common/inf-connection-manager.c: Rewrite connection manager to allow different publishers for groups with the same name, as in the spec. Also support dynamic loading of additional communication methods. * libinfinity/common/Makefile.am * libinfinity/common/inf-method-manager.h: * libinfinity/common/inf-method-manager.c: New InfMethodManager class to manage available communication methods. * libinfinity/Makefile.am * libinfinity/methods/Makefile.am: * libinfinity/methods/local-central/Makefile.am: * libinfinity/methods/local-central/inf-method-local-central.c: Simple "central" method for local networks that uses the publisher as server through which all messages are relayed. * libinfinity/common/inf-error.h: * libinfinity/common/inf-net-object.h: * libinfinity/common/inf-session.h: * libinfinity/common/inf-user.h: * libinfinity/common/inf-error.c: * libinfinity/common/inf-net-object.c: * libinfinity/common/inf-session.c: * libinfinity/common/inf-user.c: * libinfinity/common/inf-xml-connection.c: * libinfinity/common/inf-xmpp-connection.c: * libinfinity/adopted/inf-adopted-session.c: * libinfinity/adopted/inf-adopted-split-operation.c: * libinfinity/server/infd-directory.h: * libinfinity/server/infd-directory.c: * libinfinity/server/infd-server-pool.c: * libinfinity/server/infd-session-proxy.c: * libinfinity/client/infc-browser.h: * libinfinity/client/infc-browser.c: * libinfinity/client/infc-session-proxy.c: * test/inf-test-browser.c: * test/inf-test-daemon.c: * test/inf-test-text-session.c: * test/inf-test-gtk-browser.c: * libinfgtk/inf-gtk-browser-model.h: * libinfgtk/inf-gtk-browser-model.c: * libinftext/inf-text-session.c: * infinoted/infinoted-main.c: Adapt to API changes. * configure.ac: Generate Makefiles in newly added directories. * INSTALL: Autotools seemed to update this. 2007-12-22 Armin Burgmeier * libinftext/inf-text-chunk.c: Fixed a crash on amd64. * infinoted/note-plugins/text/infd-note-plugin-text.c: * libinfinity/adopted/inf-adopted-session.c: * libinfinity/adopted/inf-adopted-split-operation.c: * libinfinity/common/inf-xmpp-manager.c: * libinfinity/common/inf-connection-manager.c: * libinfinity/common/inf-xmpp-connection.c: * libinftext/inf-text-default-insert-operation.c: * test/inf-test-chunk.c: Fixed several warnings. 2007-12-22 Armin Burgmeier * libinfinity/common/inf-connection-manager.c: Changed scope for point to point connections from "p2p" to "ptp", as in the spec. * libinftextgtk/inf-text-gtk-buffer.c: Make sure only one user color tag is applied at once. 2007-12-22 Armin Burgmeier * libinfinity/common/inf-error.c: * libinfinity/common/inf-error.h: * libinfinity/common/inf-session.c: * libinfinity/server/infd-session-proxy.c: * libinfinity/client/infc-session-proxy.c: Replaced user-leave by user-status-change request, which is more general. * libinfinity/server/infd-directory.c: Indentation fixes, fixed a memory leak in infd_directory_handle_explore_node(). * libinftext/inf-text-session.c: Fixed an infinite loop when writing delete operations to XML. * infinoted/infinoted-creds.c: Include for glib 2.15 compatibility. 2007-12-22 Armin Burgmeier * libinfinity/adopted/inf-adopted-session.c: Correctly pass for_sync to inf_adopted_session_xml_to_request() in inf_adopted_session_process_xml_sync(). This fixes editing documents with non-empty history. * libinfinity/adopted/inf-adopted-request-log.c: Adjust log begin when adding first entry to request log and that entry has non-zero vector time for the log's user. * libinfinity/adopted/inf-adopted-algorithm.c: Initialize new user's component of current vector time with the corresponding component of its vector time instead of the end of its request log because the request log might be empty. * infinoted/infinoted-main.c: Don't leak dirname in infinoted_main_create_dirname() in case of success. 2007-12-21 Armin Burgmeier * libinftext/inf-text-chunk.c: * libinftext/inf-text-session.c: Swapped bytes/length arguments to inf_text_chunk_insert_text to fix handling of non-ASCII chars. * test/inf-test-chunk.c: Add an umlaut to the chunk to check UTF-8. * libinfinity/common/inf-session.c: Fixed signature of inf_session_connection_notify_status_cb(). * TODO: Added a note about adding a connection-closed signal to connection manager. 2007-12-21 Armin Burgmeier * libinfinity/common/inf-connection-manager.c: Forward scope="group" messages. * test/inf-test-gtk-browser.c: Retry user join with another name if the name is already in use, use algorithm's current vector time as initial time. 2007-12-04 Armin Burgmeier * configure.ac: * README: Require gnutls >= 1.7.2 and gsasl >= 0.2.21. 2007-12-04 Armin Burgmeier * configure.ac: Define INFINOTE_HAVE_AVAHI instead of HAVE_AVAHI to not conflict with other packages. We probably still need to get rid of autoheader to remove the default defines from inf-config.h. * libinfinity/common/inf-discovery-avahi.h: * libinfinity/common/inf-discovery-avahi.c: * infinoted/infinoted-main.c: * test/inf-test-daemon.c: * test/inf-test-gtk-browser.c: Adjusted and fixed non-avahi build. 2007-12-02 Armin Burgmeier * libinftextgtk-1.0.pc.in: Added missing file. 2007-12-02 Armin Burgmeier * libinfinity/adopted/inf-adopted-request-log.c: * libinfinity/adopted/inf-adopted-session.c: Allow arbitrary ID for first request. * libinfinity/common/inf-connection-manager.c: Re-lookup NetObject for every request in group message. * libinftextgtk/inf-text-gtk-buffer.c: Fixed inf_text_gtk_buffer_buffer_get_slice if region to slice ends before segment ends. 2007-10-21 Armin Burgmeier * libinfinity/common/inf-user.c: Return flags instead of status in inf_user_get_flags. * libinfinity/common/inf-connection-manager.c: Flag all messages as point-to-point in inf_connection_manager_send_multiple_to(), instead of just the first one. Also copy _private the private field in inf_connection_manager_send_to_group() because xmlCopyNode does not already do this. * libinfinity/common/inf-session.c: Correctly initialize GValue with zeroes before calling g_value_init(), implemented status user property. Emit close signal in synchronization failed default handler. * libinfinity/adopted/inf-adopted-request-log.h: * libinfinity/adopted/inf-adopted-request-log.c: Don't take log_begin parameter in inf_adopted_request_log_new(), return NULL instead of crashing in inf_adopted_request_log_next_undo() and inf_adopted_request_log_next_redo() when there is no next undo or redo request, respectively. * libinfinity/adopted/inf-adopted-user.c: Adapt to API change in InfAdoptedRequestLog. * libinfinity/adopted/inf-adopted-session.c: Increase last send vector instead of request's vector in inf_adopted_session_request_to_xml() (as originally intended). Initialize user field when creating InfAdoptedSessionLocalUser. Removed log-begin user property as in the spec. * libinfinity/server/infd-session-proxy.c: Use INF_SESSION_GET_CLASS instead of INF_SESSION_CLASS in infd_session_proxy_handle_user_join, initialize GValues correctly. * libinfinity/client/infc-session-proxy.c: Correctly set flags on user (re)join, don't release session when when it is closed so it is still accessible. * libinftext/inf-text-user.c: Don't make the caret-position and selection-length properties construct only. * libinftext/inf-text-session.c: Deal with author_id=0 in inf_text_session_process_xml_sync(). * libinftextgtk/inf-text-gtk-buffer.c: Fixed assertions in inf_text_gtk_buffer_set_active_user(), fixed potential endless loops in inf_text_gtk_buffer_iter_prev_author_toggle(), inf_text_gtk_buffer_iter_next_author_toggle() and inf_text_gtk_buffer_buffer_get_slice(), connect to text buffer's signals when the buffer property is set, stop emission in inf_text_gtk_buffer_delete_range_cb() and inf_text_gtk_buffer_insert_text_cb() on the correct object. * test/inf-test-gtk-browser.c: Set vector property for join request. 2007-10-17 Armin Burgmeier * infinoted/infinoted-main.c: Added --port-number command line option and load/save diffie-hellman parameters to current directory. This is just temporary to ease testing for me, so I don't have to wait too long when I need to restart the server again. * infinoted/note-plugins/text/infd-note-plugin-text.c: Allow author of segments to be 0, adapt to infd_filesystem_storage_open() API change. * libinfinity/inf-marshal.in: Added VOID:BOXED,BOXED,OBJECT marshaller. * libinfinity/common/inf-connection-manager.c: Allow inf_net_object_received() to remove itself from the connection manager group through which the message was passed, don't print a warning if a message for a nonexistant group is received. * libinfinity/common/inf-session.c: Only unref connection manager group in inf_session_release_connection() when it is set. * libinfinity/server/infd-filesystem-storage.h: * libinfinity/server/infd-filesystem-storage.c: Added note type parameter to infd_filesystem_storage_open(), and address correctly the file on disk. * libinfinity/server/infd-session-proxy.c: Keep session when it is closed, release in disponse(). * libinfinity/server/infd-directory.c: Correctly unref InfConnectionManagerGroup (can't be freed with g_free()) in infd_directory_node_add_note(). * libinfinity/server/infd-server-pool.c: Release reference on InfdTcpServer in infd_server_pool_entry_publish_with(). * libinfinity/client/infc-note-plugin.h: Added an IO parameter to session_new(). * libinfinity/client/infc-browser.h: * libinfinity/client/infc-browser.c: Added infc_browser_iter_get_note_type(), infc_browser_iter_get_plugin() and renamed -infc_browser_subscribe_session() to infc_browser_iter_subscribe_session(). Also take an IO parameter in infc_browser_new(). * libinfinity/client/infc-node-request.c: Register private struct in class_init. * libinftext/inf-text-session.c: Allow user to be NULL in text buffer signal handlers, swap code and domain in invocation of g_set_error in inf_text_session_process_xml_sync() which were the other way around. * libinfgtk/inf-gtk-browser-model.h: * libinfgtk/inf-gtk-browser-model.c: Take an IO parameter in inf_gtk_browser_model_new() for the browsers to create, added the set-browser signal in whose default handler the browser is associated with the InfGtkBrowserModelItem and signal handlers are registered. * libinfgtk/inf-gtk-browser-view.h: * libinfgtk/inf-gtk-browser-view.c: Use the new "set-browser" signal of the model to connect to browser's signals, subscribe to sessions when a non-subdirectory node is activated and a plugin present. * libinftextgtk/inf-text-gtk-buffer.h: * libinftextgtk/inf-text-gtk-buffer.c: Added inf_text_gtk_buffer_get_text_buffer(), fixed interface registration (implement INF_TEXT_TYPE_BUFFER, not INF_TEXT_GTK_TYPE_BUFFER which is not even an interface). * test/inf-test-gtk-browser.c: Added support for subscribing to text sessions. * test/inf-test-browser.c: Pass IO to InfcBrowser. * test/Makefile.am: Link inf-test-gtk-browser against InfText and InfTextGtk. 2007-10-16 Armin Burgmeier * libinfinity/common/inf-session.h: * libinfinity/common/inf-session.c: Added the inf_session_get_synchronization_progress() and inf_session_get_status() functions. * libinfinity/server/infd-directory.c: Fixed a wrong assertion in infd_directory_node_link(). * libinfinity/client/infc-node-request.c: Added the node-id property. * libinfinity/client/infc-browser.h: * libinfinity/client/infc-browser.c: Set node-id property on node requests, added the begin_subscribe and subscribe_session signals, added infc_node_iter_get_subscribe_request() and infc_browser_iter_from_node_request() functions. * libinfgtk/inf-gtk-browser-model.h: * libinfgtk/inf-gtk-browser-model.c: Made error column valid for inner nodes, store errors from explore and subscription requests (We should expand this for all node requests later). * libinfgtk/inf-gtk-browser-view.h: * libinfgtk/inf-gtk-browser-view.c: Show synchronization progress and errors from inner nodes. 2007-10-12 Armin Burgmeier * libinftext/inf-text-session.c: Fixed cursor positioning of executing user after deleting text. * libinftextgtk/inf-text-gtk-buffer.h: * libinftextgtk/inf-text-gtk-buffer.c: * libinftextgtk/Makefile.am: Implemented the InfTextBuffer interface using a GtkTextBuffer. * Makefile.am: * configure.ac: Build libinftextgtk. * README: Update. 2007-10-11 Armin Burgmeier * libinfinity/server/infd-directory.h: * libinfinity/server/infd-directory.c: Added the "io" property and construction paramater. * libinfinity/server/infd-note-plugin.h: Take an InfIo in session_new(). * test/inf-test-daemon.c: Adapt. * infinoted/infinoted-note-plugin.c: Ignore all but the platform's module suffix in infinoted_note_plugin_load_directory(). * infinoted/infinoted-main.c: Load all plugins in ${libdir}/infinoted/note-plugins/. * infinoted/note-plugins/text/infd-note-plugin-text.c: * infinoted/note-plugins/text/Makefile.am: * infinoted/note-plugins/Makefile.am: * infinoted/Makefile.am: * configure.ac: Added a text plugin that saves sessions into an XML tree, in a InfdFilesystemStorage. 2007-10-10 Armin Burgmeier * libinfinity/server/infd-directory.h: * libinfinity/server/infd-directory.c: Added infd_directory_lookup_plugin(). * infinoted/infinoted-note-plugin.h: * infinoted/infinoted-note-plugin.c: * infinoted/Makefile.am: Added functions to load note plugins from a certain directory. * configure.ac: Make infinoted depend on gmodule-2.0. 2007-10-09 Armin Burgmeier * infinoted/infinoted-creds.h: * infinoted/infinoted-creds.c: * infinoted/infinoted-main.c: Made the server actually working. 2007-10-08 Armin Burgmeier * libinfinity/common/inf-tcp-connection.c: Don't ifdef out _inf_tcp_connection_accepted because libinfinity/server is always built. * libinfinity/server/infd-note-plugin.h: Renamed identifier to note_type add added a storage_type member. * libinfinity/server/infd-directory.c: Adapt, and check storage type in infd_directory_add_plugin. * libinfinity/server/infd-filesystem-storage.h: * libinfinity/server/infd-filesystem-storage.c: Added infd_filesystem_storage_open() function. * infinoted/infinoted-creds.h: * infinoted/infinoted-creds.c: * infinoted/infinoted-main.c: * infinoted/Makefile.am: Added code which yields the infinote standalone server one day. Currently it only does certificate handling. * Makefile.am: * configure.ac: Build infinoted. 2007-10-07 Armin Burgmeier * libinfinity/inf-marshal.in: Added VOID:BOXED,OBJECT marshaller. * libinfinity/common/inf-io.c: Return the value returned by the implementation to the caller in inf_io_add_timeout(), instead of nothing. * libinfinity/common/inf-standalone-io.c: Fixed two bugs in timeout handling. * libinfinity/common/inf-tcp-connection.c: Added the device-index and device-name properties. These are only used in IPv6 to set the scope ID for link-local messaging. * libinfinity/common/inf-discovery.h: * libinfinity/common/inf-discovery.c: Make the get_service_name() returned a new string so the implementation does not have to cache the service name. * libinfinity/common/inf-xml-connection.h: * libinfinity/common/inf-xml-connection.c: Added an error signal and local-id and remote-id properties. * libinfinity/common/inf-xmpp-connection.h: * libinfinity/common/inf-xmpp-connection.c: Removed error signal because it is now provided by InfXmlConnection, override the local-id and remote-id properties by using the ip/port pair of the underlaying TCP connection. Allow gnutls to return with GNUTLS_E_AGAIN in gnutls_record_recv since it seems to sometimes call the pull function multiple times. Don't wait for terminating , but just close the connection on failed TLS handshake. * libinfinity/common/inf-discovery-avahi.c: Adapt to interface change in InfDiscovery, include device name and protocol in service name output. * libinfinity/common/inf-local-publisher.c: Replaced g_return_if_fail by g_return_val_if_fail in function returning non-void. * libinfinity/common/inf-xmpp-manager.c: Unref objects retrieved via g_object_get(), connect to every connection's notify::status signal to remove the connection when it is closed. * libinfinity/common/inf-connection-manager.c: Remove the group from the list of groups in inf_connection_manager_group_free(). * libinfinity/client/infc-browser.h: * libinfinity/client/infc-browser.c: Added an iterator pointing to the subdirectory being explored to the begin-explore signal. Don't clear directory tree when the connection is lost but rather when a new connection is set so we can still browse the explored paths when disconnected. * libinfinity/client/infc-explore-request.c: Replaced g_value_set_finished by g_value_set_boolean as it ought to be. I must have been asleep when having coded this. * libinfinity/server/infd-server-pool.c: Use username for service name when the real name is not known. * libinfgtk/inf-gtk-browser-model.h: * libinfgtk/inf-gtk-browser-model.c: Added the INVALID status, keep the item after disconnection so a potential error can still be displayed. Fixed several bugs. * libinfgtk/inf-gtk-browser-view.c: Propagate size_request and size_allocate. Implemented exploration and fixed several bugs. * libinfgtk/inf-gtk-io.h: * libinfgtk/inf-gtk-io.c: * libinfgtk/Makefile.am: Added a InfIo implementation using the default Glib mainloop. * test/inf-test-daemon.c: Publish the infinote service on avahi. * test/inf-test-gtk-browser.c: * test/Makefile.am: Added a test showing a InfGtkBrowserView to browse avahi-discovered infinote servers. 2007-10-04 Armin Burgmeier * libinfinity/inf-marshal.in: Added VOID:OBJECT,OBJECT marshaller. * libinfinity/common/inf-discovery.c: Fixed return statements in functions returning non-void. * libinfinity/client/infc-browser.h: * libinfinity/client/infc-browser.c: Added the infc_browser_iter_is_subdirectory() function. * libinfinity/client/infc-explore-request.h: * libinfinity/client/infc-explore-request.c: Added the infc_explore_request_get_initiated() and infc_explore_request_get_finished() functions. * libinfgtk/inf-gtk-browser-model.h: * libinfgtk/inf-gtk-browser-model.c: Take InfConnectionManager in constructor, added inf_gtk_browser_model_browser_iter_to_tree_iter() and the INF_GTK_BROWSER_MODEL_COL_DISCOVERY column. Fixed reordering when a resolve yielded an already existing connection. * libinfgtk/inf-gtk-browser-view.h: * libinfgtk/inf-gtk-browser-view.c: * libinfgtk/Makefile.am: Implemnted InfGtkBrowserView, a widget displaying a InfGtkBrowserModel. Some implementation bits (mostly exploration on expansion) are still missing. 2007-10-03 Armin Burgmeier * libinfinity/common/infc-browser.c: Removed a TODO comment that was already done by the last commit. * libinfgtk/inf-gtk-browser-model.h: * libinfgtk/inf-gtk-browser-model.c: * libinfgtk/Makefile.am: A container for multiple InfcBrowser and InfDiscovery objects that implements GtkTreeModel to be shown by a GtkTreeView. * Makefile.am: Changed order of SUBDIRS so that always the library directories are walked first, and then pixmaps/ and test/. * configure.ac: Cleaned up final status output. I still don't know why it sometimes appears above the "config.status: Creating Foo/Makfile" output. 2007-10-03 Armin Burgmeier * libinfinity/client/infc-browser.h: * libinfinity/client/infc-browser.c: Added infc_browser_iter_get_explore_request(), infc_browser_iter_from_explore_request() and the begin-explore signal. * pixmaps/16x16/infinote.png: * pixmaps/16x16/Makefile.am: * pixmaps/22x22/infinote.png: * pixmaps/22x22/Makefile.am: Added bitmap icons for small sizes. * pixmaps/scalable/infinote.svg: * pixmaps/scalable/Makefile.am: Moved from pixmaps/infinote.svg * pixmaps/Makefile.am: * configure.ac: Process pixmaps/16x16, pixmaps/22x22 and pixmaps/scalable. 2007-10-02 Armin Burgmeier * libinfinity/common/inf-discovery-info.h: * libinfinity/common/inf-discovery-info.c: Removed, the functioality is incorporated into InfDiscovery. * libinfinity/common/inf-local-publisher.h: * libinfinity/common/inf-local-publisher.c: * libinfinity/common/Makefile.am: A new interface that is implemented by objects that can publish services on the local network. * libinfinity/common/inf-discovery.h: * libinfinity/common/inf-discovery.c: Removed the publish vfunc in favour of InfLocalPublisher. Added info_get_service_name and info_get_service_type vfuncs. * libinfinity/common/inf-discovery-avahi.h: * libinfinity/common/inf-discovery-avahi.c: Class that implements InfDiscovery and InfLocalPublisher by using Avahi. * libinfinity/server/infd-server-pool.h: * libinfinity/server/infd-server-pool.c: Added functionality to associate local publishers with servers and automatically publish service when the corresponding server is up. * libinfinity/Makefile.am: Build with and link against avahi. 2007-09-27 Armin Burgmeier * libinfinity/common/inf-xmpp-connection.c: Set xmpp connection as gsasl session hook so that callback implementations can access the InfXmppConnection object. 2007-09-27 Armin Burgmeier * libinfinity/common/inf-xmpp-connection.h: Fix indentation. * libinfinity/common/inf-xmpp-connection.c: Added a TODO about retrieving the server's (or other entity's) JID. * libinfinity/common/inf-tcp-connection.h: * libinfinity/common/inf-tcp-connection.c: Added inf_tcp_connection_get_remote_address() and inf_tcp_connection_get_remote_port(). * libinfinity/common/inf-discovery.h: * libinfinity/common/inf-discovery.c: Added the get_discovered vfunc and inf_discovery_get_discovered(). * libinfinity/common/inf-xmpp-manager.h: * libinfinity/common/inf-xmpp-manager.c: * libinfinity/common/Makefile.am: Added the InfXmppManager class that manages XMPP connections and provides lookup by IP address and port so that existing connections can be reused. * libinfinity/server/infd-storage.h: Added a TODO comment about possible notification when stored items change. * libinfgtk/Makefile.am: * libinfgtk-1.0.pc.in: * Makefile.am: * configure.ac: Added libinfgtk component, but there are not yet any source files. 2007-09-25 Armin Burgmeier * pixmaps/infinote.svg: Moved from artwork/infinote.svg to pixmaps/infinote.svg. * pixmaps/Makefile.am: Install the icon into $(datadir)/hicolor/scalable/apps. I am not sure whether this in the correct location, though. * libinfinity-1.0.pc.in: * libinftext-1.0.pc.in: * Makefile.am: Added pkgconfig files, added pixmaps subdir. * configure.ac: Added new files to output. * TODO: Added gettext support to TODO list. 2007-09-25 Armin Burgmeier * libinfinity/common/inf-net-object.c: Allow connection to be NULL in inf_net_object_received for now, so the session test can simulate incoming XML. * libinfinity/common/inf-user-table.c: Fixed two typos. * libinfinity/common/inf-buffer.c: Removed read-only property. We might re-introduce an editable property later. * libinfinity/common/inf-session.c: Cope with NULL group and sync connection in inf_session_set_property(). * libinfinity/adopted/inf-adopted-request-log.c: Return NULL in inf_adopted_request_log_find_associated() when there is no Undo request associated to a redo request, instead of running in a failed assertion. This is a completely legal case for caching next_undo and next_redo operations. * libinfinity/adopted/inf-adopted-user.c: Cope with NULL request log in inf_adopted_user_set_property(), don't copy result in inf_adopted_user_get_vector(). * libinfinity/adopted/inf-adopted-state-vector.c: Fixed a crash in inf_adopted_state_vector_causally_before() when the highest key in the first vector was not contained in the second. Also fixed a typo leading to a crash in inf_adotped_state_vector_from_string_diff(). * libinfinity/adopted/inf-adopted-session.c: Include current request in last send vector after having sent the request. Otherwise, we are sending an unnecessary, additional "$id:1" component for each following request. Recognize undo requests by child instead of type="undo" attribute, as in the protocol specification. Keep users in the user table in-sync with those in InfAdoptedAlgorithm. Don't leak the request in inf_adopted_session_process_xml_run(). * libinfinity/adopted/inf-adopted-algorithm.c: Update user vector after having received a request, not only when having processed it. When transforming two operations in the request log, first transform both to the least common successor and then transform both from that point to the final destination. This way, pwords of insert operations are updated correctly. This could lead to a desync. Change the state of undo and redo requests to the same state of the original operation (except the issuing user's component) because they only depend on the original operation. * libinfinity/adopted/inf-adopted-split-operation.h: * libinfinity/adopted/inf-adopted-split-operation.c: Added the inf_adopted_split_operation_transform_other() function that transfors an operation against the split operation. Also don't leak the resulting operations in inf_adopted_split_operation_transform(). * libinfinity/adopted/inf-adopted-operation.c: Use inf_adopted_split_operation_transform_other() in inf_adopted_operation_transform() when against is a InfAdoptedSplitOperation. Fix a copy'n'paste error in the interface's GTypeInfo struct. * libinftext/inf-text-move-operation.h: * libinftext/inf-text-move-operation.c: Renamed inf_text_move_operation_get_pword() to inf_text_move_operation_get_position() and inf_text_move_operation_get_chunk() to inf_text_move_operation_get_length(). This was also a copy'n'paste error by copying the file from libinftext/inf-text-insert-operation.c. * libinftext/inf-text-chunk.h: * libinftext/inf-text-chunk.c: Added a GString to each chunk that holds the chunk's content without author information for integrity checking (can be disabled by not defining CHUNK_DEBUG). Added the inf_text_chunk_equal() function. Fixed two errors when inserting a chunk into another chunk that broke the chunk's integrity. * libinftext/inf-text-buffer.h: * libinftext/inf-text-buffer.c: Reorded bytes and length parameters in inf_text_buffer_insert_text() to match the order of corresponding functions in libinftext. Allow the user parameter to be NULL in which case the text is inserted as author 0. * libinftext/inf-text-user.h: * libinftext/inf-text-user.c: Derive from InfAdoptedUser not from InfUser. * libinftext/inf-text-default-delete-operation.c: End g_object_new() invocation in inf_text_default_delete_operation_transform_split() with NULL so that g_object_new() does not start reading random memory. * libinftext/inf-text-default-insert-operation.c: Cast result to InfTextInsertOperation instead of InfAdoptedOperation in inf_text_default_insert_operation_transform_position(). * libinftext/inf-text-remote-delete-operation.c: Append final recon chunk to list in inf_text_remote_delete_operation_recon_feed(). Don't leak the InfTextChunk obtained by inf_text_buffer_get_slice() in inf_text_remote_delete_operation_make_reversible(). Don't leak the unsplit list in the same function. Feed recon to the resulting operation in inf_text_remote_delete_operation_transform_overlap(), not to the original operation. * libinftext/inf-text-default-buffer.c: Implement the InfBuffer interface. * libinftext/inf-text-pword.c: Swapped the result of inf_text_pword_compare() when the two pwords have different length to obtain the intended behaviour. * libinftext/inf-text-session.c: Pass correct text to g_convert() and xmlFree() in inf_text_session_xml_to_operation(). Don't forget final NULL in g_object_new() call in inf_text_session_new() and inf_text_session_new_with_user_table(). * test/inf-test-chunk.c: Test some basic InfTextChunk operations. * test/inf-test-text-operations.c: Test C1 and C2 properties of the InfText operations. * test/inf-test-text-session.c: Test the implementation of the concurrency control algorithm implemented by InfAdoptedAlgorithm by reading test scenarios from XML files in std/. * test/Makefile.am: Added the new files * test/std/test-01.xml: * test/std/test-02.xml: * test/std/test-03.xml: * test/std/test-04.xml: * test/std/test-05.xml: * test/std/test-06.xml: * test/std/test-07.xml: * test/std/test-08.xml: * test/std/test-09.xml: * test/std/test-10.xml: * test/std/test-11.xml: * test/std/test-12.xml: * test/std/test-13.xml: * test/std/test-14.xml: * test/std/test-15.xml: * test/std/test-16.xml: * test/std/test-17.xml: * test/std/test-18.xml: * test/std/test-19.xml: * test/std/test-20.xml: * test/std/test-21.xml: * test/std/test-22.xml: * test/std/test-23.xml: * test/std/test-24.xml: * test/std/test-25.xml: * test/std/test-26.xml: * test/std/test-27.xml: * test/std/test-28.xml: * test/std/test-29.xml: * test/std/test-30.xml: * test/std/test-31.xml: * test/std/test-32.xml: * test/std/test-33.xml: * test/std/test-34.xml: * test/std/test-35.xml: * test/std/test-36.xml: * test/std/test-37.xml: * test/std/test-38.xml: * test/std/test-39.xml: * test/std/test-40.xml: * test/std/test-41.xml: * test/std/test-42.xml: * test/std/test-43.xml: * test/std/test-44.xml: * test/std/test-45.xml: * test/std/test-46.xml: Added 46 test files for inf-test-text-session.c. 2007-09-17 Armin Burgmeier * libinftext/inf-text-operations.h: File to just forward declare InfTextInsertOperation and InfTextDeleteOperation because their headers both need the two to be declared. * libinftext/inf-text-session.h: * libinftext/inf-text-session.c: Implemented InfTextSession. * libinftext/Makefile.am: Added the new files to the build. 2007-09-17 Armin Burgmeier * libinfinity/common/inf-xml-util.h: * libinfinity/common/inf-xml-util.c: Implemented inf_xml_util_set_attribute_int() and inf_xml_util_set_attribute_int_required(). * libinfinity/adopted/inf-adopted-operation.h: * libinfinity/adopted/inf-adopted-operation.c: Added concurrency_id paramater to the transform vfunc. * libinfinity/adopted/inf-adopted-request.c: * libinfinity/adopted/inf-adopted-no-operation.c: * libinfinity/adopted/inf-adopted-split-operation.c: Adapt to the above API change. * libinfinity/adopted/inf-adopted-session.h: * libinfinity/adopted/inf-adopted-session.c: Added InfUser parameter to the xml_to_operation vfunc. * libinftext/inf-text-delete-operation.h: * libinftext/inf-text-insert-operation.h: * libinftext/inf-text-delete-operation.c: * libinftext/inf-text-insert-operation.c: Made interfaces out of these, implement transformation. * libinftext/inf-text-move-operation.h: * libinftext/inf-text-move-operation.c: Added inf_text_move_operation_transform_insert() and inf_text_move_operation_transform_delete(). * libinftext/inf-text-buffer.h: * libinftext/inf-text-buffer.c: * libinftext/inf-text-default-buffer.c: Added the get_length vfunc. * libinftext/inf-text-default-insert-operation.h: * libinftext/inf-text-default-insert-operation.c: * libinftext/inf-text-default-delete-operation.c: * libinftext/inf-text-default-delete-operation.h: * libinftext/Makefile.am: Readded normal reversible insert and delete operations that were in inf-text-{insert,delete}-operation.[ch] before, and implement the new interface. * libinftext/inf-text-remote-delete-operation.h: * libinftext/inf-text-remote-delete-operation.c: Implement the InfTextDeleteOperation interface. 2007-09-15 Armin Burgmeier * libinfinity/inf-marshal.in: Added VOID:UINT,INT marshaller. * libinftext/inf-text-user.h: * libinftext/inf-text-move-operation.h: * libinftext/inf-text-remote-delete-operation.h: * libinftext/inf-text-user.c: * libinftext/inf-text-move-operation.c: * libinftext/inf-text-remote-delete-operation.c: * libinftext/Makefile.am: Implement InfTextUser (storing cursor and selected text), InfTextMoveOperation (an operation that changes a user's selection and cursor position) and InfTextRemoteDeleteOperation (a delete operation that only saves position and length of the deleted text, but not the actual text that was deleted). 2007-09-14 Armin Burgmeier * libinfinity/adopted/inf-adopted-operation.h: * libinfinity/adopted/inf-adopted-operation.c: * libinfinity/adopted/inf-adopted-no-operation.c: * libinfinity/adopted/inf-adopted-split-operation.c: Removed the is_reversible vfunc and added it as an operation flag. * libinfinity/server/infd-session-proxy.c: Fixed message handling (the message is called user-join, not join-user). * libinftext/inf-text-pword.h: * libinftext/inf-text-insert-operation.h: * libinftext/inf-text-delete-operation.h: * libinftext/inf-text-pword.c: * libinftext/inf-text-insert-operation.c: * libinftext/inf-text-delete-operation.c: * libinftext/Makefile.am: Added the two bosic text operations. * TODO: Removed finished tasks, added new ones about making InfTextChunk reference-counted. 2007-09-10 Armin Burgmeier * libinftext/inf-text-buffer.c: Fixed a marshaller. * libinftext/inf-text-default-buffer.h: * libinftext/inf-text-default-buffer.c: * libinftext/Makefile.am: Added a InfTextBuffer implementation using an underlaying InfTextChunk. 2007-09-10 Armin Burgmeier * libinfinity/common/inf-user-table.h: * libinfinity/common/inf-user-table.c: * libinfinity/common/Makefile.am: Added user table class managing users and providing lookup by ID and name. * libinfinity/common/inf-session.h: * libinfinity/common/inf-session.c: Make use of InfUserTable instead of using an own hash table. Removed some API that is not provided by InfUserTable. * libinfinity/client/infc-session-proxy.c: * libinfinity/server/infd-session-proxy.c: * libinfinity/adopted/inf-adopted-session.c: Adjusted for API change introduced by the new user table. * libinfinity/inf-ink-buffer.h: * libinfinity/inf-ink-stroke.h: * libinfinity/inf-ink-buffer.c: * libinfinity/inf-ink-stroke.c: Removed from repository, InfInk will not be implemented in the short-term. * libinftext/inf-text-chunk.h: * libinftext/inf-text-chunk.c: Added InfTextChunkIter API to iterate over segments. * libinfinity/inf-marshal.in: Replaced POINTER,UINT,UINT,OBJET byC UINT,BOXED,OBJECT marshaller. * libinftext/inf-text-buffer.h: * libinftext/inf-text-buffer.c: * libinftext/Makefile.am: Added InfTextBuffer interface. 2007-09-10 Philipp Kern * configure.ac: some fixes 2007-09-09 Armin Burgmeier * libinfinity/adopted/inf-adopted-request-log.c: Added a TODO comment about possible memory corruption. * libinfinity/inf-text-buffer.h: * libinfinity/inf-text-buffer.c: Removed. InfTextBuffer will get resurrected in the inftext separate module. * libinftext/inf-text-chunk.h: * libinftext/inf-text-chunk.c: * libinftext/Makefile.am: Created inftext module with a first boxed type to store and operate on strings with author information. * Makefile.am: * configure.ac: Added libinftext to build. 2007-09-06 Armin Burgmeier * libinfinity/adopted/inf-adopted-state-vector.h: * libinfinity/adopted/inf-adopted-operation.h: * libinfinity/adopted/inf-adopted-request-log.h: * libinfinity/adopted/inf-adopted-request.h: * libinfinity/adopted/inf-adopted-algorithm.h: * libinfinity/adopted/inf-adopted-state-vector.c: * libinfinity/adopted/inf-adopted-operation.c: * libinfinity/adopted/inf-adopted-request-log.c: * libinfinity/adopted/inf-adopted-request.c: * libinfinity/adopted/inf-adopted-algorithm.c: Made these only have a user ID instead of a user object, so they can exist without actual user objects and InfAdoptedUser can have InfAdoptedRequestLog as property. * libinfinity/adopted/inf-adopted-user.h: * libinfinity/adopted/inf-adopted-user.c: Added the request-log property. * test/inf-test-state-vector.c: Adjusted for the change mentioned above. * libinfinity/adopted/inf-adopted-session.c: * libinfinity/adopted/inf-adopted-session.h: * libinfinity/adopted/Makefile.am: Added the InfAdoptedSession class, implementing the other half of the dark magic (although not-so-dark). Timeouts are not yet implemented. * libinfinity/common/inf-standalone-io.c: Fixed a compiler warning. * libinfinity/common/inf-xml-util.h: Fixed indentation. * libinfinity/common/inf-xml-util.c: Changed an error message so that it includes the (errornous) request's name. * libinfinity/common/inf-error.c: Added a TODO comment. * libinfinity/common/inf-session.h: * libinfinity/common/inf-session.c: Added an error parameter to the process_xml_run vfunc. * libinfinity/client/infc-session-proxy.c: Set subscription group in infc_session_proxy_set_connection(). * TODO: Removed finished items, added the addition of a reversible flag for InfAdoptedOperation instead of an extra vfunc. 2007-09-02 Armin Burgmeier * libinfinity/server/infd-session.h: * libinfinity/server/infd-session.c: * libinfinity/client/infc-session.h: * libinfinity/client/infc-session.c: Removed. * libinfinity/common/inf-session.h: * libinfinity/common/inf-session.c: Added subscription group property. * libinfinity/server/infd-session-proxy.h: * libinfinity/server/infd-session-proxy.c: * libinfinity/client/infc-session-proxy.h: * libinfinity/client/infc-session-proxy.c: Added InfcSessionProxy and InfdSessionProxy classes. These basically have the same functionality as the old InfcSession and InfdSession but own them rather than inherit from them. This is needed because GObject does not allow multiple inheritance: Other types can now inherit from InfSession while InfcSessionProxy (or InfdSessionProxy, respectively) can still do their job. * libinfinity/server/infd-note-plugin.h: * libinfinity/server/infd-directory.h: * libinfinity/server/infd-directory.c: * libinfinity/server/Makefile.am: * libinfinity/client/infc-note-plugin.h: * libinfinity/client/infc-browser.h: * libinfinity/client/infc-browser.c: * libinfinity/client/Makefile.am: Adjusted accordingly. * TODO: Removed finished items 2007-09-01 Armin Burgmeier * libinfinity/common/inf-connection-manager.h: * libinfinity/common/inf-connection-manager.c: Made InfConnectionManagerGroup a boxed type, allow changing a group's InfNetObject via inf_connection_manager_group_set_object(). * TODO: Added plans about making InfcSession and InfdSession not inherit from InfSession. 2007-08-31 Armin Burgmeier * libinfinity/common/inf-connection-manager.h: * libinfinity/common/inf-connection-manager.c: Redesigned connection manager. Now there are groups of which connections can be a member. * libinfinity/common/inf-session.h: * libinfinity/common/inf-session.c: * libinfinity/server/infd-session.h: * libinfinity/server/infd-session.c: * libinfinity/client/infc-session.h: * libinfinity/client/infc-session.c: * libinfinity/client/infc-browser.c: * libinfinity/server/infd-directory.c: Adjusted use. * TODO: Added another item about dropping the message table in InfcSession/InfdSession. 2007-08-27 Armin Burgmeier * libinfinity/common/inf-io.h: * libinfinity/common/inf-io.c: * libinfinity/common/inf-standalone-io.c: Implemented addition and removal of timeouts for InfIo. * TODO: Noted down some basic TODO items that would be nice to have for a first release. 2007-08-26 Armin Burgmeier * libinfinity/inf-marshal.in: Added VOID:OBJECT,BOOLEAN marshaller. * libinfinity/inf-text-chunk.c: Added a comment, and a TODO item. * libinfinity/adopted/inf-adopted-operation.h: Added another TODO item. * libinfinity/adopted/inf-adopted-request-log.h: * libinfinity/adopted/inf-adopted-request-log.c: Added the inf_adopted_request_log_next_undo(), inf_adopted_request_log_next_redo() and inf_adopted_request_log_upper_related() functions. * libinfinity/adopted/inf-adopted-algorithm.h: * libinfinity/adopted/inf-adopted-algorithm.c: * libinfinity/adopted/Makefile.am: Implemented the first part of the really dark magic. 2007-08-22 Armin Burgmeier * libinfinity/adopted/inf-adopted-request-log.c: Allow the given request to be one past the end of the log in which case it is treated as it was the newest in the log. 2007-08-22 Armin Burgmeier * libinfinity/inf-text-chunk.h: * libinfinity/inf-text-chunk.c: Beginning of a InfTextChunk implementation, storing text written by specific users. This will probably later be moved into a separate InfText library. This code is partly written by Benjamin Herr . 2007-08-22 Benjamin Herr * all source files: Appended vim modelines. 2007-08-20 Armin Burgmeier * libinfinity/adopted/inf-adopted-state-vector.h: * libinfinity/adopted/inf-adopted-state-vector.c: Added compare and causal relation functions. * libinfinity/adopted/inf-adopted-request.h: * libinfinity/adopted/inf-adopted-request.c: Made a GObject out of this and implement transfrom, mirror and fold operations. * libinfinity/adopted/inf-adopted-request-log.c: Added next-undo and next-redo properties and additional linking between the entries (original, next associated and previous associated request). 2007-08-18 Armin Burgmeier * libinfinity/adopted/inf-adopted-operation.h: Removed superfluous comma at end of enumeration. * libinfinity/adopted/inf-adopted-request.h: * libinfinity/adopted/inf-adopted-request-log.h: * libinfinity/adopted/inf-adopted-request.c: * libinfinity/adopted/inf-adopted-request-log.c: Implemnted InfAdoptedRequest and InfAdoptedRequestLog, though the latter is still missing can-undo/can-redo tracking. * libinfinity/adopted/Makefile.am: Build the new files. 2007-08-18 Armin Burgmeier * libinfinity/common/inf-buffer.c: Set initialized to TRUE in inf_buffer_base_init so the interface is only initialized once. * libinfinity/common/inf-user.c: Correctly register user flags type as flags instead of as enum. * libinfinity/adopted/inf-adopted-state-vector.h: * libinfinity/adopted/inf-adopted-user.h: * libinfinity/adopted/inf-adopted-operation.h: * libinfinity/adopted/inf-adopted-split-operation.h: * libinfinity/adopted/inf-adopted-no-operation.h: * libinfinity/adopted/inf-adopted-state-vector.c: * libinfinity/adopted/inf-adopted-user.c: * libinfinity/adopted/inf-adopted-operation.c: * libinfinity/adopted/inf-adopted-split-operation.c: * libinfinity/adopted/inf-adopted-no-operation.c: * libinfinity/adopted/Makefile.am: Implemented some initial types for the yet-to-come adopted implementation. * libinfinity/Makefile.am: * configure.ac: Include libinfinity/adopted to build, generate libinfinity/adopted/Makefile. * test/inf-test-state-vector.c: * test/Makefile.am: Added simple state vector test. 2007-08-15 Armin Burgmeier * libinfinity/common/inf-user.h: * libinfinity/common/inf-user.c: Added a flags property with user flags with INF_USER_LOCAL being the only user property so far. * libinfinity/client/infc-session.c: * libinfinity/server/infd-session.c: Set the INF_USER_LOCAL flag as appropriate. * README: Require glib-2.14 to be able to use GSequence. 2007-07-22 Armin Burgmeier * libinfinity/client/infc-browser.h: * libinfinity/client/infc-browser.c: Added infc_browser_iter_get_name(). * libinfinity/common/inf-xmpp-connection.c: ref/unref the XMPP connection object around callback for sent messages because those callbacks might unref the XMPP connection. * libinfinity/common/inf-net-object.c: Don't require virtual functions to be implemented. * libinfinity/common/inf-xml-connection.c: Fixed signal emission of sent and received signal, wrong parameter was passed. * libinfinity/common/inf-connection-manager.c: Only send further messages if there are any, after previous messages have been sent out. * libinfinity/server/infd-filesystem-storage.c: Fixed path to file on disk which was wrong in infd_filesystem_storage_read_subdirectory(). * libinfinity/server/infd-directory.c: Only call infd_directory_node_remove_connection() for explored subdirectory nodes because only those can have connections that have explored that node. * libinfinity/client/infc-request-manager.c: Don't unref the request when removing from the hash table because the hash table already does it via its value_destroy func. Initialize the parameters array with zero in infc_request_manager_add_request_valist() because the GValues therein need to be zero-initialized. * test/inf-test-browser.c: * test/Makefile.am: Added (interactive) test for InfcBrowser connecting to a running infinote server. 2007-07-20 Armin Burgmeier * libinfinity/common/inf-error.h: * libinfinity/common/inf-error.c: Added INF_DIRECTORY_ERROR_ALREADY_SUBSCRIBED. * libinfinity/common/inf-xml-util.c: Fixed error formatting for inf_xml_util_string_to_uint(). * libinfinity/server/infd-directory.c: Changed "subscribe-session" reply request name to from "session-subscribe" to "subscribe-session" and set ID attribute in that request. Don't leak the identifier string in infd_directory_handle_subscribe_session(). * libinfinity/client/infc-explore-request.c: Implement default signal handlers for the "initiated" and "progress" signals that notify the corresponding properties. * libinfinity/client/infc-request-manager.h: * libinfinity/client/infc-request-manager.c: Changed infc_request_manager_add_request(InfcRequestManager*, InfcRequest*) to infc_request_manager_add_request(InfcRequestManager*, GType, const gchar*, const gchar*, ...) and added infc_request_manager_add_request_valist(). * libinfinity/client/infc-node-request.h: * libinfinity/client/infc-node-request.c: Added another request type that handles requests related to nodes in the directory tree. * libinfinity/client/infc-browser-iter.h: * libinfinity/client/infc-browser-iter.c: * libinfinity/client/infc-browser.h: * libinfinity/client/infc-browser.c: Implemented InfcBrowser class that allows browsing a remote directory tree. * libinfinity/client/Makefile.am: Build the new files. 2007-07-19 Armin Burgmeier * libinfinity/common/inf-error.h: * libinfinity/common/inf-error.c: Replaced several "this or that attribute is missing" error by a general "No such attribute" error. * libinfinity/client/infc-request-manager.h: * libinfinity/client/infc-request-manager.c: Added infc_request_manager_get_request_by_xml_required(). * libinfinity/common/inf-xml-util.h: * libinfinity/common/inf-xml-util.c: * libinfinity/common/Makefile.am: Added some common helper functions read attributes from a XML node. * libinfinity/client/infc-session.c: * libinfinity/server/infd-session.c: * libinfinity/server/infd-directory.c: Make use of them. 2007-07-17 Armin Burgmeier * libinfinity/inf-marshal.in: Added VOID:UINT and VOID:UINT,UINT marshallers. * libinfinity/common/inf-error.h: * libinfinity/common/inf-error.c: Added INF_REQUEST_ERROR_INVALID_SEQ, INF_DIRECTORY_ERROR_TOO_MUCH_CHILDREN and INF_REQUEST_ERROR_TOO_FEW_CHILDREN. * libinfinity/server/infd-directory.h: * libinfinity/server/infd-directory.c: Removed g_return_if_fail from non-public functions, initialize next and prev fields of root node to NULL, unref session if corresponding node is freed, send number of child nodes in explore-begin. * libinfinity/client/infc-request-manager.h: * libinfinity/client/infc-request-manager.c: Added InfcRequestManager class that stores pending requests and provides lookup by seq. * libinfinity/client/infc-request.h: * libinfinity/client/infc-request.c: Removed the succeeded signal because it was too specific. It should rather be implemented by subclasses. * libinfinity/client/infc-user-request.h: * libinfinity/client/infc-user-request.c: * libinfinity/client/infc-explore-request.h: * libinfinity/client/infc-explore-request.c: Implemented specific requests for those which affect a user and for exploring a subdirectory. * libinfinity/client/infc-session.h: * libinfinity/client/infc-session.c: Use request manager instead of managing the requests on our own, use InfcUserRequest in infc_session_join_user and infc_session_leave_user. * libinfinity/client/Makefile.am: Added new source files to build. * README: Updated dependencies of infinote. 2007-07-15 Armin Burgmeier * artwork/infinote.svg: Added infinote icon by Benjamin Herr. 2007-06-21 Armin Burgmeier * libinfinity/common/inf-error.h: * libinfinity/common/inf-error.c: Moved directory error codes to common so they can be checked on client side. * libinfinity/server/infd-directory.h: * libinfinity/server/infd-directory.c: Added correct request handling. 2007-06-21 Armin Burgmeier * libinfinity/common/inf-session.h: * libinfinity/common/inf-session.c: Make sure that the synchronization terminates correctly when both sender and receiver sessions are closed any time during synchronization. 2007-05-27 Armin Burgmeier * libinfinity/common/inf-error.h: * libinfinity/common/inf-error.c: Added some more error codes. Those are only used on the client side and so should probably moved into somewhere in libinfinity/client. * libinfinity/client/infc-request.h: * libinfinity/client/infc-request.c: Added seq and name properties. * libinfinity/client/infc-session.h: * libinfinity/client/infc-session.c: * libinfinity/client/Makefile.am: Implemented client-side session. 2007-05-19 Armin Burgmeier * libinfinity/common/inf-error.h: * libinfinity/common/inf-error.c: Added INF_USER_LEAVE_NO_SUCH_USER error code, InfRequestError codes and public API to access error quarks. * libinfinity/server/infd-session.h: * libinfinity/server/infd-session.c: Made xmlNodePtr non-const in InfdSessionMessageFunc because it only makes the pointer const (and not the XML node pointed to). * libinfinity/client/infc-request.h: * libinfinity/client/infc-request.c: Added a general request-specific pointer parameter to the succeeded signal. * docs/terminology: Added a few words about request and seq. 2007-04-18 Armin Burgmeier * configure.ac: * libinfinity/Makefile.am: Added client directory, create libinfinity/client/Makefile. * libinfinity/inf-marshal.in: Added VOID:VOID marshaller. * libinfinity/common/infd-request.h: * libinfinity/common/infd-request.c: * libinfinity/common/Makefile.am: Added InfcRequest class. * libinfinity/common/inf-session.h: * libinfinity/common/inf-session.c: * libinfinity/server/infd-session.c: Replace user_to_xml vfunc by set_xml_user_props, added inf_session_user_to_xml which implements the functionality via the new vfunc. 2007-04-12 Armin Burgmeier * libinfinity/test/inf-test-daemon.c: * libinfinity/test/Makefile.am: Added test file that launches a simple infinote daemon with a filesystem storage in $HOME/.infinote. 2007-04-12 Armin Burgmeier * libinfinity/server/infd-filesystem-storage.h: * libinfinity/server/infd-filesystem-storage.c: * libinfinity/server/Makefile.am: Added a simple storage implementation that maps the directory tree to the disk. 2007-04-11 Armin Burgmeier * libinfinity/server/infd-server-pool.h: * libinfinity/server/infd-server-pool.c: * libinfinity/server/Makefile.am: Renamed from infd-server.[ch], manages an arbitrary amount of InfdXmlServers. 2007-04-10 Armin Burgmeier * libinfintiy/common/inf-connection-manager.h: * libinfintiy/common/inf-connection-manager.c: Removed inf_connection_manager_add_connection, and add connection automatically on first invocation of inf_connection_manager_add_object. * libinfinity/common/inf-session.c: * libinfinity/server/infd-directory.c: Adjusted use. 2007-04-10 Armin Burgmeier * libinfinity/common/inf-xmpp-connection.c: Fixed bugs, server side mostly works. * libinfinity/server/infd-xml-server.h: Fixed typo in InfdXmlServerStatus typedef. * libinfinity/server/infd-xmpp-server.h: * libinfinity/server/infd-xmpp-server.c: Build and Runtime fixes, use key.pem and cert.pem as key files for now. This should probably be replaced with a newly-created certificate later. * test/inf-test-xmpp-server.c: Added simple XMPP server test. * test/inf-test-xmpp-connection.c: Connect to local server instead of jabber.0x539.de. * test/key.pem: * test/cert.pem: Temporary example key files, copied from the GnuTLS distribution. 2007-04-08 Armin Burgmeier * libinfinity/common/inf-xmpp-connection.c: Notify credentials and sasl-context properties when they are created. * libinfinity/server/infd-xmpp-server.h: * libinfintiy/server/infd-xmpp-server.c: * libinfinity/server/Makefile.am: Added XMPP server class, yet untested. 2007-03-29 Armin Burgmeier * libinfinity/server/infd-tcp-server.h: * libinfinity/server/infd-tcp-server.c: Added InfdTcpServer object. * libinfinity/server/infd-xml-server.h: * libinfinity/server/infd-xml-server.c: Added InfdXmlServer interface. * libinfinity/common/inf-tcp-connection.c: Added _inf_tcp_connection_accepted function, do not leak a socket if the connection attempt fails in inf_tcp_connection_open, do not chain up to finalize in dispose, do not leak the IO object, don't rely on errno keeping its value at the end of the recv/send loop. * test/inf-test-tcp-server.c: * test/Makefile.am: Added test for the TCP server. 2007-03-28 Armin Burgmeier * libinfinity/common/inf-xmpp-connection.c: Fixed some bugs, client part mostly works. * libinfinity/common/inf-tcp-connection.c: Exit receiving/sending loop if the connection has been closed in a received/sent signal handler. * libinfinity/common/inf-xml-connection.c: Initialize interface only once. * test/inf-test-xmpp-connection.c: * test/Makefile.am: Added XMPP client test. 2007-03-28 Armin Burgmeier * libinfinity/common/: Moved all libinfinity sources and headers except inf-config.h and inf-marshal.h into a subdirectory. * libinfinity/server/: Moved all libinfinited files into another subdirectory. * libinfinited/: Removed. * libinfinity/common/Makefile.am: * libinfinity/server/Makefile.am: * libinfinity/Makefile.am: * configure.ac: Adjusted build for new directory structure. 2070-03-27 Armin Burgmeier * libinfinity/inf-xmpp-connection.h: * libinfinity/inf-xmpp-connection.c: Added XMPP client and server implementation, yet untested. * libinfinity/inf-xml-stream.h: * libinfinity/inf-xml-stream.c: Removed, this is no longer used and replaced by XMPP. * configure.in: * libinfinity/Makefile.am: Depend on gnutls and libgsasl. 2007-03-19 Armin Burgmeier * libinfinity/inf-marshal.in: Added VOID:POINTER,UINT marshaller. * libinfinity/inf-standalone-io.h: * libinfinity/inf-standalone-io.c: Added simple InfIo implementation. * libinfinity/inf-tcp-connection.h: * libinfinity/inf-tcp-connection.c: Implemented a TCP connection object. * libinfinity/Makefile.am: Added InfIoStandalone and InfTcpConnection to build. * test/inf-test-stream.xml: * test/inf-test-xml-stream.c: Removed those since InfXmlStream will probably be removed too, or at least change semantics. * test/inf-test-tcp-connection.c: * test/Makefile.am: Added simple TCP connection test. 2007-03-18 Armin Burgmeier * libinfinity/inf-ip-address.h: * libinfinity/inf-ip-address.c: * Makefile.am: Boxed type managing an IP address. 2007-03-18 Armin Burgmeier * libinfinity/inf-discovery-info.h: * libinfinity/inf-discovery.h: * libinfinity/inf-discovery-info.c: * libinfinity/inf-discovery.c: * Makefile.am: Added InfDiscovery and InfDiscoveryInfo interfaces. 2007-03-17 Armin Burgmeier * libinfinity/inf-io.h: * libinfinity/inf-io.c: * Makefile.am: Added InfIo interface. 2007-03-15 Armin Burgmeier * libinfinity/inf-xml-connection.h: * libinfinity/inf-xml-connection.c: Added an InfXmlConnection interface that replaces GNetworkConnection. * libinfinity/inf-buffer.c: * libinfinity/inf-buffer.h: Made a property out of the read-only functions and signal. * libinfinity/inf-marshal.in: Replaced VOID:BOOLEAN by VOID:POINTER for InfXmlConnection. * libinfinity/inf-net-object.h: * libinfinity/inf-connection-manager.h: * libinfinity/inf-session.h: * libinfinited/infd-note-plugin.h: * libinfinited/infd-session.h: * libinfinited/infd-directory.h: * libinfinity/inf-net-object.c: * libinfinity/inf-connection-manager.c: * libinfinity/inf-session.c: * libinfinited/infd-session.c: * libinfinited/infd-directory.c: Adjusted to use InfXmlConnection instead of GNetworkConnection. * configure.ac: * libinfinity/Makefile.am: * libinfinited/Makefile.am: Dropped dependency on libgnetwork. Also excluded infd-server.[hc] from build because they would still require GNetworkServer. Another interface in libinfinited is required here. 2007-03-15 Armin Burgmeier * libinfinited/infd-storage.h: * libinfinited/infd-storage.c: Turned the path field of InfdStorageNode to name. * libinfinited/infd-directory.h: * libinfinited/infd-directory.c: Implemented remaining functionality that was missing, some more enhanced operations like copying or moving nodes are still not supported, though. 2007-03-12 Armin Burgmeier * libinfinited/infd-storage.h: * libinfinited/infd-storage.c: Renamed InfdDirectoryStorage to InfdStorage. * libinfinited/infd-note-plugin.h: Added interface for a note plugin. * libinfinited/infd-session.h: * libinfinited/infd-session.c: * libinfinined/Makefile.am: Implemented user joins. 2007-03-12 Armin Burgmeier * libinfinity/inf-user.h: * libinfinity/inf-user.c: Removed connection field again. I don't think it is useful. * libinfinity/inf-session.h: * libinfinity/inf-session.c: Added inf_session_get_synchronization_status() and an exclude parameter to the validate_user_props vfunc. * libinfinity/inf-error.h: * libinfinity/inf-error.c: * libinfinity/Makefile.am: These specify some error codes that are commonly used by client and server. 2007-03-08 Armin Burgmeier * libinfinity/inf-session.c: Connect to notify::status to find out when a connection is closed. 2007-03-08 Armin Burgmeier * libinfinity/inf-session.h: * libinfinity/inf-session.c: Provide getters for connection manager and buffer. Also do a ref on the connection we get in inf_session_synchronize_to() because it will be unrefed when the synchronization is complete or failed. 2007-03-08 Armin Burgmeier * libinfinity/inf-session.c: Before removing the session from the connection manager in inf_session_release_connection(), make sure that the connection manager still has the connection. If the connection was closed, the connection manager might have dropped the connection earlier. * libinfinity/inf-connection-manager.c: Refcount netobject registrations, but make sure objects are added with the same identifier. 2007-03-08 Armin Burgmeier * libinfinity/inf-user.h: * libinfinity/inf-user.c: Added a connection field to InfUser specifiying a (not necessarily direct) connection between the local host and that user. 2007-03-07 Armin Burgmeier * docs/plugin: Added notes about the plugin interface. It is not yet implemented, these are my just ideas how it should work, so I do not forget and could be expanded to a complete specification later. 2007-03-06 Armin Burgmeier * libinfinity/inf-marshal.in: Added VOID:OBJECT,DOUBLE and VOID:OBJECT,POINTER marshallers for synchronization signals. * libinfinity/inf-net-object.h: * libinfinity/inf-net-object.c: * libinfinity/inf-connection-manager.h: * libinfinity/inf-connection-manager.c: Implemented separation between inner and outer queue, added enqueued vfunc in InfNetObject. * libinfinity/inf-session.h: * libinfinity/inf-session.c: Implemented session synchronization. * libinfinity/inf-buffer.c: Minor build fixes. * libinfinity/docs/terminology: Added inner queue and outer queue of connection manager. * libinfinity/docs/session: Applied slight changes that came up during implementation. 2007-03-01 Armin Burgmeier * libinfinity/docs: * libinfinity/docs/terminology: * libinfinity/docs/session: Added some notes, mostly for me to not forget how things are supposed to work, but perhaps also interesting to others. 2007-03-01 Armin Burgmeier * libinfinity/inf-marshal.in: Added VOID:BOOLEAN marshaller. * libinfinity/inf-buffer.h: * libinfinity/inf-buffer.c: * libinfinity/Makefile.am: Added common buffer interface. * libinfinity/inf-text-buffer.c: * libinfinity/inf-ink-buffer.c: Changed prerequiste from GObject to InfBuffer. 2007-02-27 Armin Burgmeier * libinfinity/infd-directory.h: * libinfinity/infd-directory.c: Added some directory API, but most implementations are still missing. 2007-02-27 Armin Burgmeier * libinfinity/inf-marshal.in: Added marshallers required for InfTextBuffer. * libinfinity/inf-text-buffer.h: * libinfinity/inf-text-buffer.c: * libinfinity/Makefile.am: Added InfTextBuffer interface. * libinfinited/inf-directory-storage.h: * libinfinited/inf-directory-storage.c: Added methods to read text notes, write ink and text notes, create a subdirectory and remove nodes. 2007-02-26 Armin Burgmeier * libinfinity/inf-connection-manager.h: * libinfinity/inf-connection-manager.c: Added inf_connection_manager_has_connection(). Also do strong refs instead of weak refs on added net object. This way, net objects are kept alive if there are still connections open. Especially, this should allow keeping sessions alive even if the document in the directory tree is removed. * libinfinited/infd-server.h: * libinfinited/infd-server.c: * libinfinited/Makefile.am: New server class managing acception of incoming connections and (yet to come) service publishing. * libinfinited/infd-directory.h: * libinfinited/infd-directory.c: Implemented directory tree structure, but accessing background storage and handling client requests still missing. 2007-02-26 Armin Burgmeier * libinfinity/inf-marshal.in: Added VOID:OBJECT marshaller. * libinfinity/inf-user.h: * libinfinity/inf-user.c: * libinfinity/inf-session.h: * libinfinity/inf-session.c: * Makefile.am: Added InfUser and InfSession classes. * libinfinity/inf-ink-buffer.c: Changed signal flags for the remove-stroke signal from G_SIGNAL_RUN_CLEANUP to G_SIGNAL_RUN_LAST and surrounded the signal emission by a g_object_ref / g_object_unref pair. This way, the stroke should stay alive after having been removed from the buffer and signal handlers running after the default handler don't get corrupted memory. 2007-02-23 Armin Burgmeier * libinfinity/inf-ink-stroke.h: * libinfinity/inf-ink-stroke.c: Renamed from InfStroke to InfInkStroke. * libinfinity/inf-ink-buffer.h: * libinfinity/inf-ink-buffer.c: Made an interface out of InfBuffer, renamed to InfInkBuffer. * libinfinity/Makefile.am: Adjusted build rules for renamed files. * libinfinited/infd-directory-storage.h: * libinfinited/infd-directory-storage.c: Include inf-ink-buffer.h instead of inf-buffer.h, added text node type for upcoming collaborative text editing support, removed empty flag from node (client should query a node to check whether it is empty, this way it can also treat it as empty if it only contains nodes it is not interested in, for example a subdirectory containing only ink nodes will be shown empty in a text editor). 2007-02-21 Armin Burgmeier * libinfinited/infd-directory.h: * libinfinited/infd-directory.c: Added GNetworkTcpServer object, close on error. 2007-02-21 Armin Burgmeier * libinfinity/inf-connection-manager.c: Take a reference of the connection in inf_connection_manager_add_connection(). * libinfinited/infd-directory.c: * libinfinited/infd-directory-storage.c: * libinfinited/infd-directory.h: * libinfinited/infd-directory-storage.h: * libinfinited/infd-marshal.in: * libinfinited/Makefile.am: Added interface for directory storage in libinfinited and initial directory class. * Makefile.am: * configure.ac: Build libinfinited. 2007-02-21 Armin Burgmeier * libinfinity: Renamed infinity directory to libinfinity. * configure.ac: * Makefile.am: * test/Makefile.am: * test/inf-test-xml-stream.c: * libinfinity/*.[ch]: Changed references and includes from infinity to libinfinity. Also implemented inf_stroke_new_at(). 2007-02-21 Armin Burgmeier * infinity/inf-net-object.c: Add G_TYPE_OBJECT prerequisite. 2007-02-20 Armin Burgmeier * infinity/inf-connection-manager.c: * infinity/inf-xml-stream.c: Chain up in destructor. * infinity/inf-buffer.h: * infinity/inf-buffer.c: Added InfBuffer class managing multiple InfStrokes. * infinity/inf-marshal.in: Added input file for glib-genmarshal. * infinity/Makefile.am: Create inf-marshal.h and inf-marshal.c from inf-marshal.in. Also added inf-buffer.c to build. 2007-02-20 Armin Burgmeier * infinity/inf-stroke.h: * infinity/inf-stroke.c: Added position to InfStroke to which the coordinates of the contained InfStrokePoints are relative. 2007-02-20 Armin Burgmeier * infinity/inf-xml-stream.c: * infinity/inf-connection-manager.c: Documentation fixes. * infinity/inf-net-object.c: Removed return in inf_net_object_sent() and inf_net_object_received() because these functions are void. * infinity/inf-stroke.h: * infinity/inf-stroke.c: Added object representing a single stroke. * infinity/Makefile.am: Added inf-stroke.c to build. 2007-02-19 Armin Burgmeier * infinity/inf-connection-manager.h: * infinity/inf-connection-manager.c: Implemented message processing and inf_connection_manager_send_to_object(). 2007-02-19 Armin Burgmeier * infinity/inf-xml-stream.c: * infinity/inf-xml-stream.h: * infinity/Makefile.am: Added InfXmlStream class. * test/inf-test-xml-stream.c: * test/inf-test-stream.xml: * test/Makefile.am: Simple test routine to test functionality of InfXmlStream. * configure.ac: Create test/Makefile. * Makefile.am: Added test to SUBDIRS. 2007-02-18 Armin Burgmeier * infinity/inf-connection-manager.c: * infinity/inf-connection-manager.h: Added InfConnectionManager class, not yet fully implemented, but compilable. * infinity/Makefile.am: Added inf-connection-manager.[ch]. 2007-02-18 Armin Burgmeier * infinity/inf-net-object.h: * infinity/inf-net-object.c: Renamed inf-netobject.[ch] to inf-net-object.[ch]. 2007-02-18 Armin Burgmeier * infinity/inf-netobject.h: Replaced INF_NET_OBJECT_TYPE by INF_TYPE_NET_OBJECT to follow gobject naming conventions. 2007-02-18 Armin Burgmeier * configure.ac: Added check for glib, gobject, libgnetwork and libxml2. * infinity/Makefile.am: Add CFLAGS and libs of dependencies to libinfinity_1_0_la_CPPFLAGS respectively libinfinity_1_0_la_LIBADD. * infinity/inf-netobject.h: Added libgnetwork/gnetwork-connection.h and libxml/tree.h includes to make it actually compile. * infinity/inf-config.h.in: Removed generated file from repository. 2007-02-16 Armin Burgmeier * configure.ac: * Makefile.am: * AUTHORS: * NEWS: * README: * COPYING: * INSTALL: * infinity/Makefile.am: * infinity/inf-config.h.in: * infinity/inf-netobject.h: * infinity/inf-netobject.c: Initial revision. libinfinity-0.7.1/PaxHeaders.26529/NEWS0000644000000000000000000000013213055210717014303 xustar0030 mtime=1488261583.660150705 30 atime=1488261583.660150705 30 ctime=1488261588.772139564 libinfinity-0.7.1/NEWS0000644000175000017500000001722313055210717015042 0ustar00arminarmin00000000000000libinfinity 0.7.1: * Fix a possible crash when uploading a document to the infinoted server. (gobby #142) * Fix two instances of possible format string injection. (#17) libinfinity 0.7.0: * infinoted: Allow to listen on a specific interface instead of all interfaces (Lukas Kupczyk). * infinoted: Add a dbus plugin which allows some interaction with reading and modifying the directory tree. * Removed support for GTK+ 2.x. libinfinity-0.7 can only be built against GTK+ 3.x. * Generate gobject-introspection repositories, allowing libinfinity to be used from higher-level programming languages such as Python. * Enable TCP keepalives on all connections to prevent inactive connections from being dropped by a firewall, and to allow quicker detection of an actual disconnect. libinfinity 0.6.7: * Fix a possible crash when an entry is removed from the document browser. * Fix a possible crash in infinoted when access control lists are enabled. * Fix an assertion failure when operating with text documents and using glib 2.46 or newer. libinfinity 0.6.6: * Fix certificates being only verified for expiration and other criteria such as weak algorithms if the CA is not trusted. (gobby #61) * Fix some assertion failures and inconsistencies in InfTextFixlineBuffer. * Fix a client-side crash when the server shuts down ordinarily while still connected. libinfinity 0.6.5: * Fix memory corruption in InfTextFixlineBuffer. * infinoted: Fix error message in server log when a client certificate is not trusted. * Fix various crashes related to sending data to already closed connections. * Build fix when res_query is provided by libc, not libresolv, such as on FreeBSD (gobby #23, Samantha Michelle Smith). libinfinity 0.6.4: * Build fixes for Mac OS X (#7, Dominyk Tiller). libinfinity 0.6.3: * infinoted: Fix a possible timing attack on the server password (Jann Horn). * infinoted: Use mode 0777 instead of 0700 when creating directories in the directory-sync plugin. * Write certificates not seen before into the known hosts file. libinfinity 0.6.2: * Fix accounts being deleted when a plugin overrides the default account storage. * The infinoted manual page has been corrected for the syntax of the --plugins option. * A crash has been fixed when a connection is closed for which the the certificate dialog was shown. libinfinity 0.6.1: * Explicitly link against libresolv on unix-based systems, to avoid a possible build failure. libinfinity 0.6.0: * infinoted: Introduced a plugin infrastructure, and ported some of the previous functionality to plugins. * infinoted: Add a plugin for client authentication with certificates. * Add a system for user management and access control lists (ACLs). * Change certificate checker to a trust-on-first-use (SSH-like) mechanism when the signer cannot be verified. * Code refactorings, and many new interfaces and APIs. libinfinity 0.5.5: * Fix a crash in infinoted when nmap scans the infinote port (Rainer Rehak). libinfinity 0.5.4: * Fix crashes that can happen when the connection goes down at unexpected moments. * Fix a crash when when drawing remote cursors or selections and the initial document has not yet been fully transmitted. * Fix a possible crash when undoing or redoing many operations in a row (Sven Brauch). libinfinity 0.5.3: * Fix a crash when a connection goes down at the moment libinfinity is trying to send data. * Fix possible undefined behavior at type registration (Colomban Wendling). libinfinity 0.5.2: * Fix a crash when a server certificate does not have a hostname set * Fix a crash when the remote side sends invalid UTF-8 * Fix compilation with glib >= 2.31 libinfinity 0.5.1: * infinoted: Update directory sync settings on config reload * infinoted: Fix a crash when directory sync was enabled (#556) * Fix the build on Mac OS X (#563) * Disallow node names containing non-printable or only space characters * Fixed a reference leak in infd_directory_add_note() * Fixed a crash in infd_directory_iter_get_session() libinfinity 0.5.0: * infinoted: Added the --pam-server, --allow-user and --allow-group command line options. * Show cursor and selection of remote users in the own textview and the scrollbar. * Add optional support for GTK+ 3. * Provide asynchronous SASL authentication. libinfinity 0.4.2: * infinoted: Fixed a bug when infinoted did not launch in daemonized mode when the global PID file directory did not exist. * Fixed a crash which could occur in high latency concurrent situations. * Fixed a possible crash when multiple connections time out at the same time. * Fixed a crash when receiving an unexpected XML opening and ending tag on the top-level. libinfinity 0.4.1: * infinoted: Avoid a runtime warning when infinoted can not be started. * Fixed a crash in undo grouping when undoing a large number of requests. * Fixed a crash when showing closed connections in a InfGtkBrowserView (Jesse van den Kieboom). * Fixed expander arrows on non-expandable columns in InfGtkBrowserView. * Fixed a crash when closing an XML connection still in use by a session (Jesse van den Kieboom). * Introduced new API: - inf_xmpp_connection_get_tls_enabled() - inf_gtk_browser_store_remove_connection() - inf_gtk_browser_store_set_connection_name() - inf_gtk_browser_store_clear_connection_error() - inf_text_gtk_buffer_is_tag_toggle() - inf_text_gtk_buffer_forward_to_tag_toggle() - inf_text_gtk_buffer_backward_to_tag_toggle() libinfinity 0.4.0: * infinoted: Added the --password, --sync-directory, --sync-interval, --daemonize and --kill-daemon command line options. * infinoted: Reload configuration file at runtime on SIGHUP * Added an IRC-like chat, driven by InfChatSession. * Added functionality to group undo requests to be undone in a single step. libinfinity 0.3.1: * Avoid a crash when synchronizing a zero-length delete operation * Fix sporadic disconnections on Windows libinfinity 0.3.0: * infinoted: Added the --certificate-chain command line option. * Support rejecting a subscription on the client side, for example when the client does not support the communication method. * Made libinfinity parallel-installable with future versions. libinfinity 0.2.1: * Fixed compilation on FreeBSD (#430, Romain Tartière) * Fixed a crash that could occur on connection loss. * Accept v1 X.509 certificates. libinfinity 0.2.0: * infinoted records sessions to ~/.infinoted-records * Added proper modification tracking, and an autosave feature for infinoted. * Implemented InfStandaloneIo on Windows, making infinoted run on Windows * Refactored connection manager, introducing InfCommunication API for high-level network handling. This breaks protocol compatibility with libinfinity 0.1.x. libinfinity 0.1.2: * Fixed required dependencies in pkg-config files * Improved error message when the remote host does not send XMPP * Fixed a crash when compiling with -O2 or above * Fixed a few memory leaks * Fixed build with cairo 1.4 (#393) libinfinity 0.1.1: * Made libinfinity properly relocatable on Windows * Fixed the documentation build when avahi is disabled (#386, Gregory Haynes) * Fixed a segfault when showing the file list (#388, Georg) * Fixed pasting a lot amount of text (#387, Benjamin Herr) * Fixed connection to server with much history (#389, Matthias Prinz) libinfinity 0.1.0: * Initial release of libinfinity * Provides an API for real-time collaboration on plain text documents * This in an UNSTABLE release! Both API and ABI are about to change in future versions. The 0.1.x line is guaranteed to be stable, though. libinfinity-0.7.1/PaxHeaders.26529/libinftext.pc.in0000644000000000000000000000013112400102201016661 xustar0030 mtime=1409320065.127132027 30 atime=1409320065.127132027 29 ctime=1488261588.76013959 libinfinity-0.7.1/libinftext.pc.in0000644000175000017500000000051012400102201017410 0ustar00arminarmin00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: libinftext Description: Infinote text processing library Requires: libinfinity-@LIBINFINITY_API_VERSION@ Version: @VERSION@ Libs: -L${libdir} -linftext-@LIBINFINITY_API_VERSION@ Cflags: -I${includedir}/libinftext-@LIBINFINITY_API_VERSION@ libinfinity-0.7.1/PaxHeaders.26529/libinfgtk.pc.in0000644000000000000000000000013213034342512016502 xustar0030 mtime=1483851082.017718362 30 atime=1483851082.017718362 30 ctime=1488261588.756139598 libinfinity-0.7.1/libinfgtk.pc.in0000644000175000017500000000053413034342512017236 0ustar00arminarmin00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: libinfgtk Description: Common infinote GTK+ UI functionality Requires: libinfinity-@LIBINFINITY_API_VERSION@ @gtk_requirement@ Version: @VERSION@ Libs: -L${libdir} -linfgtk-@LIBINFINITY_API_VERSION@ Cflags: -I${includedir}/libinfgtk-@LIBINFINITY_API_VERSION@ libinfinity-0.7.1/PaxHeaders.26529/docs0000644000000000000000000000013213055210725014456 xustar0030 mtime=1488261589.956136975 30 atime=1488261589.932137027 30 ctime=1488261589.956136975 libinfinity-0.7.1/docs/0000755000175000017500000000000013055210725015265 5ustar00arminarmin00000000000000libinfinity-0.7.1/docs/PaxHeaders.26529/Makefile.in0000644000000000000000000000013213051241007016571 xustar0030 mtime=1487225351.593148064 30 atime=1487225351.593148064 30 ctime=1488261589.952136983 libinfinity-0.7.1/docs/Makefile.in0000644000175000017500000004756413051241007017343 0ustar00arminarmin00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 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__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) 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@ subdir = docs ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/gtk-doc.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/libinfinity/inf-config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = $(SUBDIRS) am__DIST_COMMON = $(srcdir)/Makefile.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ 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@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIRNAME = @DATADIRNAME@ 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@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ GTKDOC_CHECK = @GTKDOC_CHECK@ GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ GTKDOC_MKPDF = @GTKDOC_MKPDF@ GTKDOC_REBASE = @GTKDOC_REBASE@ HTML_DIR = @HTML_DIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INSTOBJEXT = @INSTOBJEXT@ INTLLIBS = @INTLLIBS@ INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBINFINITY_API_VERSION = @LIBINFINITY_API_VERSION@ LIBINFINITY_LIBTOOL_VERSION = @LIBINFINITY_LIBTOOL_VERSION@ LIBINFINITY_VERSION = @LIBINFINITY_VERSION@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGFMT_OPTS = @MSGFMT_OPTS@ 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@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ 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@ avahi_CFLAGS = @avahi_CFLAGS@ avahi_LIBS = @avahi_LIBS@ 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@ gio_CFLAGS = @gio_CFLAGS@ gio_LIBS = @gio_LIBS@ gtk_requirement = @gtk_requirement@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infgtk_CFLAGS = @infgtk_CFLAGS@ infgtk_LIBS = @infgtk_LIBS@ infinity_CFLAGS = @infinity_CFLAGS@ infinity_LIBS = @infinity_LIBS@ infinoted_CFLAGS = @infinoted_CFLAGS@ infinoted_LIBS = @infinoted_LIBS@ infodir = @infodir@ inftext_CFLAGS = @inftext_CFLAGS@ inftext_LIBS = @inftext_LIBS@ inftextgtk_CFLAGS = @inftextgtk_CFLAGS@ inftextgtk_LIBS = @inftextgtk_LIBS@ install_sh = @install_sh@ libdaemon_CFLAGS = @libdaemon_CFLAGS@ libdaemon_LIBS = @libdaemon_LIBS@ 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@ runstatedir = @runstatedir@ 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@ SUBDIRS = reference all: all-recursive .SUFFIXES: $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(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) --foreign docs/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign docs/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: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ 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-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ 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" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files 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 @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive 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: 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." clean: clean-recursive clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-recursive -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: .MAKE: $(am__recursive_targets) install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-am clean clean-generic clean-libtool cscopelist-am ctags \ ctags-am distclean 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-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ installdirs-am maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ ps ps-am tags tags-am uninstall uninstall-am .PRECIOUS: Makefile # 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: libinfinity-0.7.1/docs/PaxHeaders.26529/reference0000644000000000000000000000013213055210763016416 xustar0030 mtime=1488261619.104072279 30 atime=1488261589.956136975 30 ctime=1488261619.104072279 libinfinity-0.7.1/docs/reference/0000755000175000017500000000000013055210763017225 5ustar00arminarmin00000000000000libinfinity-0.7.1/docs/reference/PaxHeaders.26529/api_version.xml0000644000000000000000000000013013045432620021526 xustar0029 mtime=1486239120.41814751 29 atime=1486239120.41814751 30 ctime=1488261590.876134961 libinfinity-0.7.1/docs/reference/api_version.xml0000644000175000017500000000000313045432620022253 0ustar00arminarmin000000000000000.7libinfinity-0.7.1/docs/reference/PaxHeaders.26529/Makefile.in0000644000000000000000000000013213051241007020527 xustar0030 mtime=1487225351.625148166 30 atime=1487225351.625148166 30 ctime=1488261589.980136922 libinfinity-0.7.1/docs/reference/Makefile.in0000644000175000017500000005242713051241007021273 0ustar00arminarmin00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 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__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) 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@ @WITH_INFGTK_TRUE@am__append_1 = libinfgtk @WITH_INFTEXTGTK_TRUE@am__append_2 = libinftextgtk @WITH_INFINOTED_TRUE@am__append_3 = libinfinoted-plugin-manager subdir = docs/reference ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/gtk-doc.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/libinfinity/inf-config.h CONFIG_CLEAN_FILES = version.xml.in api_version.xml.in CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(nodist_noinst_DATA) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ distdir am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DIST_SUBDIRS = . libinfinity libinftext libinfgtk libinftextgtk \ libinfinoted-plugin-manager am__DIST_COMMON = $(srcdir)/Makefile.in \ $(srcdir)/api_version.xml.in.in $(srcdir)/version.xml.in.in DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ 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@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIRNAME = @DATADIRNAME@ 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@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ GTKDOC_CHECK = @GTKDOC_CHECK@ GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ GTKDOC_MKPDF = @GTKDOC_MKPDF@ GTKDOC_REBASE = @GTKDOC_REBASE@ HTML_DIR = @HTML_DIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INSTOBJEXT = @INSTOBJEXT@ INTLLIBS = @INTLLIBS@ INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBINFINITY_API_VERSION = @LIBINFINITY_API_VERSION@ LIBINFINITY_LIBTOOL_VERSION = @LIBINFINITY_LIBTOOL_VERSION@ LIBINFINITY_VERSION = @LIBINFINITY_VERSION@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGFMT_OPTS = @MSGFMT_OPTS@ 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@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ 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@ avahi_CFLAGS = @avahi_CFLAGS@ avahi_LIBS = @avahi_LIBS@ 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@ gio_CFLAGS = @gio_CFLAGS@ gio_LIBS = @gio_LIBS@ gtk_requirement = @gtk_requirement@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infgtk_CFLAGS = @infgtk_CFLAGS@ infgtk_LIBS = @infgtk_LIBS@ infinity_CFLAGS = @infinity_CFLAGS@ infinity_LIBS = @infinity_LIBS@ infinoted_CFLAGS = @infinoted_CFLAGS@ infinoted_LIBS = @infinoted_LIBS@ infodir = @infodir@ inftext_CFLAGS = @inftext_CFLAGS@ inftext_LIBS = @inftext_LIBS@ inftextgtk_CFLAGS = @inftextgtk_CFLAGS@ inftextgtk_LIBS = @inftextgtk_LIBS@ install_sh = @install_sh@ libdaemon_CFLAGS = @libdaemon_CFLAGS@ libdaemon_LIBS = @libdaemon_LIBS@ 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@ runstatedir = @runstatedir@ 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@ SUBDIRS = . libinfinity libinftext $(am__append_1) $(am__append_2) \ $(am__append_3) # Note that nodist doesn't work here actually because gtk-doc pulls them # in anyway (see content_files in a subdirectory's Makefile.am) nodist_noinst_DATA = version.xml api_version.xml CLEANFILES = version.xml api_version.xml DISTCLEANFILES = version.xml.in api_version.xml.in all: all-recursive .SUFFIXES: $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(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) --foreign docs/reference/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign docs/reference/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: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): version.xml.in: $(top_builddir)/config.status $(srcdir)/version.xml.in.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ api_version.xml.in: $(top_builddir)/config.status $(srcdir)/api_version.xml.in.in cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ 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-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ 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" cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files 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 @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done check-am: all-am check: check-recursive all-am: Makefile $(DATA) installdirs: installdirs-recursive installdirs-am: install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive 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) -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-recursive clean-am: clean-generic clean-libtool mostlyclean-am distclean: distclean-recursive -rm -f Makefile distclean-am: clean-am distclean-generic distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: .MAKE: $(am__recursive_targets) install-am install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \ check-am clean clean-generic clean-libtool cscopelist-am ctags \ ctags-am distclean 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-ps install-ps-am \ install-strip installcheck installcheck-am installdirs \ installdirs-am maintainer-clean maintainer-clean-generic \ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \ ps ps-am tags tags-am uninstall uninstall-am .PRECIOUS: Makefile # Remove the trailing newline of the version files, to have the entities # in the docbook XML substituted without it. version.xml: version.xml.in rm -f version.xml echo -n `cat version.xml.in` > version.xml api_version.xml: api_version.xml.in rm -f api_version.xml echo -n `cat api_version.xml.in` > api_version.xml # 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: libinfinity-0.7.1/docs/reference/PaxHeaders.26529/Makefile.am0000644000000000000000000000013212631745142020532 xustar0030 mtime=1449642594.101165475 30 atime=1449642594.101165475 30 ctime=1488261589.980136922 libinfinity-0.7.1/docs/reference/Makefile.am0000644000175000017500000000143312631745142021265 0ustar00arminarmin00000000000000SUBDIRS = . libinfinity libinftext if WITH_INFGTK SUBDIRS += libinfgtk endif if WITH_INFTEXTGTK SUBDIRS += libinftextgtk endif if WITH_INFINOTED SUBDIRS += libinfinoted-plugin-manager endif # Note that nodist doesn't work here actually because gtk-doc pulls them # in anyway (see content_files in a subdirectory's Makefile.am) nodist_noinst_DATA = version.xml api_version.xml # Remove the trailing newline of the version files, to have the entities # in the docbook XML substituted without it. version.xml: version.xml.in rm -f version.xml echo -n `cat version.xml.in` > version.xml api_version.xml: api_version.xml.in rm -f api_version.xml echo -n `cat api_version.xml.in` > api_version.xml CLEANFILES = version.xml api_version.xml DISTCLEANFILES = version.xml.in api_version.xml.in libinfinity-0.7.1/docs/reference/PaxHeaders.26529/libinfinoted-plugin-manager0000644000000000000000000000013213055210765023772 xustar0030 mtime=1488261621.148067674 30 atime=1488261619.104072279 30 ctime=1488261621.148067674 libinfinity-0.7.1/docs/reference/libinfinoted-plugin-manager/0000755000175000017500000000000013055210765024601 5ustar00arminarmin00000000000000libinfinity-0.7.1/docs/reference/libinfinoted-plugin-manager/PaxHeaders.26529/html0000644000000000000000000000013213055210765024736 xustar0030 mtime=1488261621.180067602 30 atime=1488261621.140067692 30 ctime=1488261621.180067602 libinfinity-0.7.1/docs/reference/libinfinoted-plugin-manager/html/0000755000175000017500000000000013055210765025545 5ustar00arminarmin00000000000000libinfinity-0.7.1/docs/reference/libinfinoted-plugin-manager/html/PaxHeaders.26529/libinfinoted-plug0000644000000000000000000000033513055210765030356 xustar00131 path=libinfinity-0.7.1/docs/reference/libinfinoted-plugin-manager/html/libinfinoted-plugin-manager-0.7-InfinotedParameter.html 30 mtime=1488261621.180067602 30 atime=1488261621.180067602 30 ctime=1488261621.180067602 libinfinity-0.7.1/docs/reference/libinfinoted-plugin-manager/html/libinfinoted-plugin-manager-0.7-In0000644000175000017500000022607513055210765033724 0ustar00arminarmin00000000000000 InfinotedParameter: libinfinoted-plugin-manager-0.7 Reference Manual

InfinotedParameter

InfinotedParameter — Declare parameters of infinoted plugins.

Stability Level

Unstable, unless otherwise indicated

Object Hierarchy

    GBoxed
    ╰── InfinotedParameterTypedValue

Includes

#include <infinoted/infinoted-parameter.h>

Description

The InfinotedParameterInfo structure allows to declare a parameter that can then be used as an input value to a plugin. While the types for input data are limited, the mechanism allows to provide a powerful validation and transformation function which can turn the input value to the final internal representation in the plugin data structure.

Parameters are declared by providing a InfinotedParameterInfo structure, and an array of such structures is then given to InfinotedPlugin which declares a plugin.

Functions

InfinotedParameterConvertFunc ()

gboolean
(*InfinotedParameterConvertFunc) (gpointer out,
                                  gpointer in,
                                  GError **error);

Definition of a parameter conversion function. A parameter conversion function transforms the value of a read which is one of the InfinotedParameterValue enumeration to its final internal representation. It can change the C type of the parameter, and it can also validate the input and produce an error if the input value is invalid.

While plugin developers can write their own conversion functions, many are already provided by libinfinoted-plugin-manager that cover the most basic usecases. These functions are infinoted_parameter_convert_string(), infinoted_parameter_convert_string_list(), infinoted_parameter_convert_filename(), infinoted_parameter_convert_boolean(), infinoted_parameter_convert_port(), infinoted_parameter_convert_nonnegative(), infinoted_parameter_convert_positive(), infinoted_parameter_convert_security_policy() and infinoted_parameter_convert_ip_address().

Parameters

out

Location where the converted value should be written to.

 

in

Location where the original input value should be taken from.

 

error

Location for error information, if any, or NULL.

 

Returns

TRUE on success or FALSE if an error occurred.


infinoted_parameter_typed_value_new ()

InfinotedParameterTypedValue *
infinoted_parameter_typed_value_new (void);

Creates a new instance of a InfinotedParameterTypedValue . The new instance will be uninitialized. Its type and value members need to be set before the object can be used or given to infinoted_parameter_typed_value_free().

Returns

A new InfinotedParameterTypedValue. Free with infinoted_parameter_typed_value_free() when no longer needed.


infinoted_parameter_typed_value_copy ()

InfinotedParameterTypedValue *
infinoted_parameter_typed_value_copy (const InfinotedParameterTypedValue *val);

Makes a dynamically allocated copy of val .

Parameters

val

The value to copy.

 

Returns

A new InfinotedParameterTypedValue. Free with infinoted_parameter_typed_value_free() when no longer needed.


infinoted_parameter_typed_value_free ()

void
infinoted_parameter_typed_value_free (gpointer data);

Frees an instance of InfinotedParameterTypedValue. Formally the argument is kept as a generic pointer so that this function can be used as a GDestroyNotify callback.

Note that the InfinotedParameterTypedValue needs to be correctly initialized, i.e. its type must be set, before it can be freed.

Parameters

data

The InfinotedParameterTypedValue to free.

 

infinoted_parameter_error_quark ()

GQuark
infinoted_parameter_error_quark (void);

Returns the GQuark for errors from the InfinotedParameter module.

Returns

The error domain for the InfinotedParameter module.


infinoted_parameter_load_from_key_file ()

gboolean
infinoted_parameter_load_from_key_file
                               (const InfinotedParameterInfo *infos,
                                GKeyFile *key_file,
                                const gchar *group,
                                gpointer base,
                                GError **error);

Attempts to read each parameter in infos from key_file and store them in a user-specified structure base . The offset field of InfinotedParameterInfo specifies where inside base the read parameter value will be written, and the convert field specifies a function which converts the parameter type (integer, string or string list) into the type of the field in the target structure.

If the key file does not have an entry for one of the entries in infos , then the current value in the base structure is untouched. This allows setting default values prior to calling this function.

If the function fails, for example because the conversion into the target type failed (which, in turn, might be due to invalid user input), FALSE is returned and error is set.

Parameters

infos

A 0-terminated array of InfinotedParameterInfo objects.

[array zero-terminated=1]

key_file

The GKeyFile to load parameter values from.

 

group

The keyfile group to load the values from.

 

base

The instance into which to write the read parameters.

 

error

Location to store error information, if any, or NULL.

 

Returns

TRUE on success, otherwise FALSE.


infinoted_parameter_convert_boolean ()

gboolean
infinoted_parameter_convert_boolean (gpointer out,
                                     gpointer in,
                                     GError **error);

This function simply writes the boolean value from in to out without any further validation.

This is a InfinotedParameterConvertFunc function that can be used for boolean values.

Parameters

out

The pointer to the output gboolean.

[type gboolean*][out]

in

The pointer to the input gboolean.

[type gboolean*][in]

error

Location to store error information, if any, or NULL.

 

Returns

This function always returns TRUE.


infinoted_parameter_convert_filename ()

gboolean
infinoted_parameter_convert_filename (gpointer out,
                                      gpointer in,
                                      GError **error);

This function converts the input string from UTF-8 to the Glib file name encoding.

This is a InfinotedParameterConvertFunc function that can be used for strings that should be in Glib file name encoding format instead of UTF-8.

Parameters

out

The pointer to the output string location.

[type gchar**][out]

in

A pointer to the input string location.

[type gchar**][in]

error

Location to store error information, if any, or NULL.

 

Returns

TRUE on success, or FALSE otherwise.


infinoted_parameter_convert_nonnegative ()

gboolean
infinoted_parameter_convert_nonnegative
                               (gpointer out,
                                gpointer in,
                                GError **error);

This function validates the input number to be non-negative, and converts it into an unsigned integer.

This is a InfinotedParameterConvertFunc function that can be used for any non-negative numbers.

Parameters

out

The pointer to the output guint.

[type guint*][out]

in

The pointer to the input gint.

[type gint*][in]

error

Location to store error information, if any, or NULL.

 

Returns

TRUE on success, or FALSE otherwise.


infinoted_parameter_convert_port ()

gboolean
infinoted_parameter_convert_port (gpointer out,
                                  gpointer in,
                                  GError **error);

This function validates the input number to be in the valid range for TCP or UDP ports between 1 and 65535, and converts it to an unsigned integer.

This is a InfinotedParameterConvertFunc function that can be used for TCP or UDP port numbers.

Parameters

out

The pointer to the output guint.

[type guint*][out]

in

The pointer to the input gint.

[type gint*][in]

error

Location to store error information, if any, or NULL.

 

Returns

TRUE on success, or FALSE otherwise.


infinoted_parameter_convert_positive ()

gboolean
infinoted_parameter_convert_positive (gpointer out,
                                      gpointer in,
                                      GError **error);

This function validates the input number to be positve, i.e. greater than zero, and converts it into an unsigned integer.

This is a InfinotedParameterConvertFunc function that can be used for any non-negative numbers.

Parameters

out

The pointer to the output guint.

[type guint*][out]

in

The pointer to the input gint.

[type gint*][in]

error

Location to store error information, if any, or NULL.

 

Returns

TRUE on success, or FALSE otherwise.


infinoted_parameter_convert_security_policy ()

gboolean
infinoted_parameter_convert_security_policy
                               (gpointer out,
                                gpointer in,
                                GError **error);

Converts the string that in points to to an InfXmppConnectionSecurityPolicy value, by requiring that it is either "no-tls", "allow-tls" or "require-tls". If the string is none of these three the function fails and error is set.

This is a InfinotedParameterConvertFunc function that can be used for fields of type InfXmppConnectionSecurityPolicy.

Parameters

out

The pointer to the output InfXmppConnectionSecurityPolicy.

[type InfXmppConnectionSecurityPolicy*][out]

in

The pointer to the input string location.

[type gchar**][in]

error

Location to store error information, if any, or NULL.

 

Returns

TRUE on success, or FALSE otherwise.


infinoted_parameter_convert_string ()

gboolean
infinoted_parameter_convert_string (gpointer out,
                                    gpointer in,
                                    GError **error);

This is basically a no-op, moving the string from the in location to the out location. In case in points to the empty string, it is freed and the output string is set to be NULL.

This is a InfinotedParameterConvertFunc function that can be used for strings that should not be processed further or validated.

Parameters

out

The pointer to the output string location.

[type gchar**][out]

in

A pointer to the input string location.

[type gchar**][in]

error

Location to store error information, if any, or NULL.

 

Returns

This function always returns TRUE.


infinoted_parameter_convert_string_list ()

gboolean
infinoted_parameter_convert_string_list
                               (gpointer out,
                                gpointer in,
                                GError **error);

This is basically a no-op, moving the string list from the in location to the out location. In case in points to an empty string list, or to a string list with only one entry which is the empty string, then the string list is freed and the output string list is set to be NULL.

This is a InfinotedParameterConvertFunc function that can be used for string lists that should not be processed further or validated.

Parameters

out

The pointer to the output string list.

[type gchar***][out]

in

The pointer to the input string list.

[type gchar***][array zero-terminated=1][in]

error

Location to store error information, if any, or NULL.

 

Returns

This function always returns TRUE.


infinoted_parameter_convert_flags ()

gboolean
infinoted_parameter_convert_flags (gpointer out,
                                   gpointer in,
                                   const GFlagsValue *values,
                                   GError **error);

Converts the string list that in points to to a bitmask. This function can not directly be used as a convert function as expected by InfinotedParameterInfo since it has an additional argument. However, an actual convert function can make use of this function.

Each string entry is interpreted as a value of a bitmask. The values list specifies which string constant corresponds to which flag value.

Parameters

out

The pointer to the output flags (a gint).

[type gint*][out]

in

The pointer to the input string list.

[type gchar***][in][array zero-terminated=1]

values

Allowed flag values.

 

error

Location to store error information, if any, or NULL.

 

Returns

TRUE on success, or FALSE otherwise.


infinoted_parameter_convert_ip_address ()

gboolean
infinoted_parameter_convert_ip_address
                               (gpointer out,
                                gpointer in,
                                GError **error);

Types and Values

enum InfinotedParameterType

Allowed types for a parameter that can be given to a infinoted plugin.

Members

INFINOTED_PARAMETER_BOOLEAN

A boolean parameter.

 

INFINOTED_PARAMETER_INT

A signed integer parameter.

 

INFINOTED_PARAMETER_STRING

A string parameter.

 

INFINOTED_PARAMETER_STRING_LIST

An array of strings.

 

enum InfinotedParameterFlags

Additional flags for parameters that can be given to infinoted plugins.

Members

INFINOTED_PARAMETER_REQUIRED

The parameter is required and cannot be omitted.

 

union InfinotedParameterValue

Holds the value of a infinoted parameter. The type of the parameter must be known. See also InfinotedParameterTypedValue.

Members

gboolean yesno;

The parameter value for type INFINOTED_PARAMETER_BOOLEAN.

 

gint number;

The parameter value for type INFINOTED_PARAMETER_INT.

 

gchar *str;

The parameter value for type INFINOTED_PARAMETER_STRING.

 

gchar **strv;

The parameter value for type INFINOTED_PARAMETER_STRING_LIST.

 

struct InfinotedParameterTypedValue

struct InfinotedParameterTypedValue {
  InfinotedParameterType type;
  InfinotedParameterValue value;
};

Holds the type and value of a parameter that can be passed to an infinoted plugin.

Members

InfinotedParameterType type;

The type of the parameter.

 

InfinotedParameterValue value;

The value of the parameter.

 

struct InfinotedParameterInfo

struct InfinotedParameterInfo {
  const char* name;
  InfinotedParameterType type;
  InfinotedParameterFlags flags;
  size_t offset;
  InfinotedParameterConvertFunc convert;
  char short_name;
  const char* description;
  const char* arg_description;
};

This structure contains generic information about a parameter that can be passed to an infinoted plugin.

Members

const char *name;

The name of the parameter.

 

InfinotedParameterType type;

The input type of the parameter.

 

InfinotedParameterFlags flags;

Additional flags for the parameter.

 

size_t offset;

Offset of the output value in the structure of the plugin. Should be determined with G_STRUCT_OFFSET.

 

InfinotedParameterConvertFunc convert;

The conversion function for the parameter, see InfinotedParameterConvertFunc.

 

char short_name;

A short name (one character) for the parameter, used for command line option parsing.

 

const char *description;

A description for the parameter that can be shown in --help output

 

const char *arg_description;

A description for the argument of the parameter in --help output, if any.

 

enum InfinotedParameterError

Specifies the possible error conditions for errors in the INFINOTED_PARAMETER_ERROR domain. These typically occur when parsing and processing input parameters for plugins.

Members

INFINOTED_PARAMETER_ERROR_REQUIRED

A parameter is required but was not provided to the plugin.

 

INFINOTED_PARAMETER_ERROR_INVALID_NUMBER

The number given as a parameter is not valid, for example a negative time interval.

 

INFINOTED_PARAMETER_ERROR_INVALID_FLAG

The flag with the given name does not exist.

 

INFINOTED_PARAMETER_ERROR_INVALID_SECURITY_POLICY

A security policy given as a parameter is not valid. The only allowed values are "no-tls", "allow-tls", and "require-tls".

 

INFINOTED_PARAMETER_ERROR_INVALID_IP_ADDRESS

   
libinfinity-0.7.1/docs/reference/libinfinoted-plugin-manager/html/PaxHeaders.26529/left-insensitive.0000644000000000000000000000013213055210765030304 xustar0030 mtime=1488261621.144067683 30 atime=1488261621.144067683 30 ctime=1488261621.144067683 libinfinity-0.7.1/docs/reference/libinfinoted-plugin-manager/html/left-insensitive.png0000644000175000017500000000061313055210765031543 0ustar00arminarmin00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEà 4ÓkMIDAT8ËÍ’­NQ…¿éö†…@¡p üdsÛÀÖ`*š4Á@ò„W@ A!ÈÔ†@6Ü^ƒ 5hxèIH R`sQpäÌ™339þBÊó|Ês¤ªKEQTÛíöK°@·ÛÎià¦^¯Ï~îWʆ½÷‹ÀÕûðå`0˜åTJ6·Tõ˜‘cYn6›AÞû Æ€½~¿ß±Ö>}Ç­Žœs;ªº ¨ˆlYkwËÞürˆ¼†ºó£ Þû5U= °/"›ÖÚç  ¬µ‡"ÒuU=ɲlü×ArÎÕDä˜zÃáp5I’ûà4^E+ÀP3Æœçàq_«êp Ì¥iñ¯ðUY¥‚p=#IEND®B`‚libinfinity-0.7.1/docs/reference/libinfinoted-plugin-manager/html/PaxHeaders.26529/libinfinoted-plug0000644000000000000000000000031613055210765030355 xustar00116 path=libinfinity-0.7.1/docs/reference/libinfinoted-plugin-manager/html/libinfinoted-plugin-manager-0.7.devhelp2 30 mtime=1488261621.144067683 30 atime=1488261621.144067683 30 ctime=1488261621.144067683 libinfinity-0.7.1/docs/reference/libinfinoted-plugin-manager/html/libinfinoted-plugin-manager-0.7.de0000644000175000017500000003475713055210765033753 0ustar00arminarmin00000000000000 libinfinity-0.7.1/docs/reference/libinfinoted-plugin-manager/html/PaxHeaders.26529/annotation-glossa0000644000000000000000000000013213055210765030376 xustar0030 mtime=1488261621.180067602 30 atime=1488261621.180067602 30 ctime=1488261621.180067602 libinfinity-0.7.1/docs/reference/libinfinoted-plugin-manager/html/annotation-glossary.html0000644000175000017500000001155113055210765032451 0ustar00arminarmin00000000000000 Annotation Glossary: libinfinoted-plugin-manager-0.7 Reference Manual

Annotation Glossary

A

allow-none

NULL is OK, both for passing and for returning.

array

Parameter points to an array of items.

C

constructor

This symbol is a constructor, not a static method.

I

in

Parameter for input. Default is transfer none.

O

out

Parameter for returning results. Default is transfer full.

T

transfer full

Free data after the code is done.

transfer none

Don't free data after the code is done.

type

Override the parsed C type with given type.

U

Unstable

Unstable interfaces are experimental or transitional. They are typically used to give outside developers early access to new or rapidly changing technology, or to provide an interim solution to a problem where a more general solution is anticipated. No claims are made about either source or binary compatibility from one minor release to the next. The Unstable interface level is a warning that these interfaces are subject to change without warning and should not be used in unbundled products. Given such caveats, customer impact need not be a factor when considering incompatible changes to an Unstable interface in a major or minor release. Nonetheless, when such changes are introduced, the changes should still be mentioned in the release notes for the affected release.

libinfinity-0.7.1/docs/reference/libinfinoted-plugin-manager/html/PaxHeaders.26529/up-insensitive.pn0000644000000000000000000000013213055210765030334 xustar0030 mtime=1488261621.144067683 30 atime=1488261621.144067683 30 ctime=1488261621.144067683 libinfinity-0.7.1/docs/reference/libinfinoted-plugin-manager/html/up-insensitive.png0000644000175000017500000000056613055210765031244 0ustar00arminarmin00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEà 4ÓkMIDAT8Ëí’?/QÅÏ™?[êu$¾€V³î›ÑâHTD³ø”ÛˆBM+¡!™ÂÌ<ˆDã+èô[mdÞ\…·bø{º{sÎ/97˜ªSÖÚ£º®»<ìTõ8ŒcÌÉ¿UU­‘¼‡•WÕÍ,Ë®ÿ”e¹EÑ €žªîÉSïmÛ®æy~û+À9·è½¿0`hŒ9u†ªº`Çñr¿ßùpÎÍ{ïÌ8‘m’ ªJkí€-o$—Dä¢  išË¾'¹; ‡ Jr‡äCð\¨*¿HΑ|JÓtCDÆßo#"ã$IÖ<«êBQ½é£êêÉ]•TKúIEND®B`‚libinfinity-0.7.1/docs/reference/libinfinoted-plugin-manager/html/PaxHeaders.26529/index.html0000644000000000000000000000013213055210765027010 xustar0030 mtime=1488261621.180067602 30 atime=1488261621.180067602 30 ctime=1488261621.180067602 libinfinity-0.7.1/docs/reference/libinfinoted-plugin-manager/html/index.html0000644000175000017500000000461013055210765027543 0ustar00arminarmin00000000000000 libinfinoted-plugin-manager-0.7 Reference Manual: libinfinoted-plugin-manager-0.7 Reference Manual

for libinfinoted-plugin-manager 0.7.0. The latest version of this documentation can be found on-line at http://infinote.0x539.de/libinfinity/API/libinfinoted-plugin-manager/.


libinfinoted-plugin-manager API reference
InfinotedPluginManager — Loads and propagates events to infinoted plugins.
InfinotedParameter — Declare parameters of infinoted plugins.
InfinotedLog — A class to handle logging of messages.
InfinotedUtil — Miscellaneous helper functions.
Annotation Glossary
libinfinity-0.7.1/docs/reference/libinfinoted-plugin-manager/html/PaxHeaders.26529/InfinotedPluginMa0000644000000000000000000000013213055210765030312 xustar0030 mtime=1488261621.180067602 30 atime=1488261621.180067602 30 ctime=1488261621.180067602 libinfinity-0.7.1/docs/reference/libinfinoted-plugin-manager/html/InfinotedPluginManager.html0000644000175000017500000013420513055210765033031 0ustar00arminarmin00000000000000 InfinotedPluginManager: libinfinoted-plugin-manager-0.7 Reference Manual

InfinotedPluginManager

InfinotedPluginManager — Loads and propagates events to infinoted plugins.

Stability Level

Unstable, unless otherwise indicated

Properties

InfCertificateCredentials * credentials Read / Write / Construct Only
InfdDirectory * directory Read / Write / Construct Only
InfinotedLog * log Read / Write / Construct Only
gchar * path Read

Object Hierarchy

    GObject
    ╰── InfinotedPluginManager

Includes

#include <infinoted/infinoted-plugin-manager.h>

Description

InfinotedPluginManager handles the loading of plugins for the infinoted server. It initializes and deinitializes plugins, and it makes callbacks when connections or sessions are added or removed. Furthermore, it provides an interface for plugins to obtain and interact with the server itself, most notable its InfdDirectory instance.

Functions

infinoted_plugin_manager_new ()

InfinotedPluginManager *
infinoted_plugin_manager_new (InfdDirectory *directory,
                              InfinotedLog *log,
                              InfCertificateCredentials *creds);

Creates a new InfinotedPluginManager with the given directory, log and credentials. These three objects will be available for plugins to enhance the infinoted functionality. Plugins can be loaded with infinoted_plugin_manager_load().

[constructor]

Parameters

directory

The InfdDirectory on which plugins should operate.

 

log

The InfinotedLog to write log messages to.

 

creds

The InfCertificateCredentials used to secure data transfer with the clients, or NULL.

[allow-none]

Returns

A new InfinotedPluginManager.

[transfer full]


infinoted_plugin_manager_load ()

gboolean
infinoted_plugin_manager_load (InfinotedPluginManager *manager,
                               const gchar *plugin_path,
                               const gchar * const*plugins,
                               GKeyFile *options,
                               GError **error);

Loads all plugins specified in plugins from the location at plugin_path . If loading one of the module fails the function sets error and returns FALSE, and the object ends up with no plugins loaded. If plugins is NULL, no plugins are loaded.

If this function is called while there are already plugins loaded, all existing plugins are unloaded first.

Parameters

manager

A InfinotedPluginManager.

 

plugin_path

The path from which to load plugins.

 

plugins

A list of plugins to load, or NULL.

[array zero-terminated=1][allow-none]

options

A GKeyFile with configuration options for the plugins.

 

error

Location to store error information, if any, or NULL.

 

Returns

TRUE on success or FALSE on error.


infinoted_plugin_manager_get_directory ()

InfdDirectory *
infinoted_plugin_manager_get_directory
                               (InfinotedPluginManager *manager);

Returns the InfdDirectory used by the plugin manager.

Parameters

manager

A InfinotedPluginManager.

 

Returns

A InfdDirectory owned by the plugin manager.

[transfer none]


infinoted_plugin_manager_get_io ()

InfIo *
infinoted_plugin_manager_get_io (InfinotedPluginManager *manager);

Returns the InfIo of the InfdDirectory used by the plugin manager.

Parameters

manager

A InfinotedPluginManager.

 

Returns

A InfIo owned by the plugin manager.

[transfer none]


infinoted_plugin_manager_get_log ()

InfinotedLog *
infinoted_plugin_manager_get_log (InfinotedPluginManager *manager);

Returns the InfinotedLog that the plugin manager and the plugins do write log messages to.

Parameters

manager

A InfinotedPluginManager.

 

Returns

A InfinotedLog owned by the plugin manager.

[transfer none]


infinoted_plugin_manager_get_credentials ()

InfCertificateCredentials *
infinoted_plugin_manager_get_credentials
                               (InfinotedPluginManager *manager);

Returns the InfCertificateCredentials used for securing the data transfer with all clients.

Parameters

manager

A InfinotedPluginManager.

 

Returns

A InfCertificateCredentials object owned by the plugin manager.

[transfer none]


infinoted_plugin_manager_get_connection_info ()

gpointer
infinoted_plugin_manager_get_connection_info
                               (InfinotedPluginManager *mgr,
                                gpointer plugin_info,
                                InfXmlConnection *connection);

Queries the connection-specfic plugin data for the plugin instance plugin_info . Returns NULL if no such object exists, i.e. when the plugin's connection_info_size is set to 0.

Parameters

mgr

A InfinotedPluginManager.

 

plugin_info

The plugin_info pointer of a plugin instance.

 

connection

The InfXmlConnection for which to retrieve plugin data.

 

Returns

A pointer to the connection-specific plugin data, or NULL.

[transfer none][allow-none]


infinoted_plugin_manager_get_session_info ()

gpointer
infinoted_plugin_manager_get_session_info
                               (InfinotedPluginManager *mgr,
                                gpointer plugin_info,
                                InfSessionProxy *proxy);

Queries the session-specfic plugin data for the plugin instance plugin_info . Returns NULL if no such object exists, i.e. when the plugin's session_info_size is set to 0.

Parameters

mgr

A InfinotedPluginManager.

 

plugin_info

The plugin_info pointer of a plugin instance.

 

proxy

The InfSessionProxy for which to retrieve plugin data.

 

Returns

A pointer to the session-specific plugin data, or NULL.

[transfer none][allow-none]


infinoted_plugin_manager_error_quark ()

GQuark
infinoted_plugin_manager_error_quark (void);

Returns the GQuark for errors from the InfinotedPluginManager module.

Returns

The error domain for the InfinotedPluginManager module.

Types and Values

struct InfinotedPluginManager

struct InfinotedPluginManager;

InfinotedPluginManager is an opaque data type. You should only access it via the public API functions.


struct InfinotedPluginManagerClass

struct InfinotedPluginManagerClass {
};

This structure does not contain any public fields.


struct InfinotedPlugin

struct InfinotedPlugin {
  const gchar* name;
  const gchar* description;
  const InfinotedParameterInfo* options;

  gsize info_size;
  gsize connection_info_size;
  gsize session_info_size;
  const gchar* session_type;

  void(*on_info_initialize)(gpointer plugin_info);

  gboolean(*on_initialize)(InfinotedPluginManager* manager,
                           gpointer plugin_info,
                           GError** error);

  void(*on_deinitialize)(gpointer plugin_info);

  void(*on_connection_added)(InfXmlConnection* connection,
                             gpointer plugin_info,
                             gpointer connection_info);

  void(*on_connection_removed)(InfXmlConnection* connection,
                               gpointer plugin_info,
                               gpointer connection_info);

  void(*on_session_added)(const InfBrowserIter* iter,
                          InfSessionProxy* proxy,
                          gpointer plugin_info,
                          gpointer session_info);

  void(*on_session_removed)(const InfBrowserIter* iter,
                            InfSessionProxy* proxy,
                            gpointer plugin_info,
                            gpointer session_info);
};

Declares a InfinotedPlugin. If an instance of this structure is called INFINOTED_PLUGIN and exported from a shared object, it can be loaded as a plugin by infinoted.

Members

const gchar *name;

The name of the plugin. The filename of the shared object should be libinfinoted-plugin-<name>.

 

const gchar *description;

A human-readable description of what the plugin does.

 

const InfinotedParameterInfo *options;

A 0-terminated list of plugin parameters. The parameters are provided to the plugin via the infinoted configuration file or the command line. The last element of the list must have the name field set to NULL.

 

gsize info_size;

The size of the plugin instance structure. When the plugin is instantiated, this amount of memory will be allocated for the plugin instance. This field must be different from 0.

 

gsize connection_info_size;

The size of the plugin's connection info structure. For each plugin instance, this amount of memory will be allocated for each connection of the server. The plugin can use it to store connection-specific data. This field can be 0.

 

gsize session_info_size;

The size of the plugin's session info structure. For each plugin instance, this amount of memory will be allocated for each session that is currently active on the server. The plugin can use it to store session-specific data. This field can be 0.

 

const gchar *session_type;

If non-NULL, specifies the session type handled by the plugin. Only for sessions of this type or a derived type a session info structure is allocated. The on_session_added and on_session_removed callbacks are always made, independent of this field.

 

on_info_initialize ()

Function called after the plugin has been instantiated. It should initialize all fields of the plugin instance to a sane default value.

 

on_initialize ()

Function called to initialize the plugin. The function can return FALSE and set the error parameter to prevent the plugin from being used. The server will not be started in this case. Even if this function returns FALSE, on_deinitialize will be called on the plugin to clean up partly constructed plugin data by this function.

 

on_deinitialize ()

Function called when the plugin is unloaded. Should clean up all resources the plugin has allocated.

 

on_connection_added ()

Function called when there is a new connection to the server. It is also called for all existing connections at the time the plugin is loaded.

 

on_connection_removed ()

Function called when a client connection has been dropped. It is also called for all existing connections right before the plugin is unloaded.

 

on_session_added ()

Function called when a new session has become active on the server. It is also called for all existing sessions at the time the plugin is loaded.

 

on_session_removed ()

Function called when a session has become inactive and the server is freeing resources allocated to it. It is also called for all existing sessions right before the plugin is unloaded.

 

enum InfinotedPluginManagerError

Error codes for the INFINOTED_PLUGIN_MANAGER_ERROR error domain. These errors can occur when loading a plugin with infinoted_plugin_manager_load().

Members

INFINOTED_PLUGIN_MANAGER_ERROR_OPEN_FAILED

Failed to open the code module of a plugin.

 

INFINOTED_PLUGIN_MANAGER_ERROR_NO_ENTRY_POINT

The code module of a plugin does not provide the INFINOTED_PLUGIN symbol.

 

Property Details

The “credentials†property

  “credentials†             InfCertificateCredentials *

The server's TLS credentials.

Flags: Read / Write / Construct Only


The “directory†property

  “directory†               InfdDirectory *

The infinote directory served by the server.

Flags: Read / Write / Construct Only


The “log†property

  “log†                     InfinotedLog *

The log object into which to write log messages.

Flags: Read / Write / Construct Only


The “path†property

  “path†                    gchar *

The path from which plugins are loaded.

Flags: Read

Default value: NULL

libinfinity-0.7.1/docs/reference/libinfinoted-plugin-manager/html/PaxHeaders.26529/ch01.html0000644000000000000000000000013213055210765026434 xustar0030 mtime=1488261621.180067602 30 atime=1488261621.180067602 30 ctime=1488261621.180067602 libinfinity-0.7.1/docs/reference/libinfinoted-plugin-manager/html/ch01.html0000644000175000017500000000501413055210765027166 0ustar00arminarmin00000000000000 libinfinoted-plugin-manager API reference: libinfinoted-plugin-manager-0.7 Reference Manual

libinfinoted-plugin-manager API reference

InfinotedPluginManager — Loads and propagates events to infinoted plugins.
InfinotedParameter — Declare parameters of infinoted plugins.
InfinotedLog — A class to handle logging of messages.
InfinotedUtil — Miscellaneous helper functions.
libinfinity-0.7.1/docs/reference/libinfinoted-plugin-manager/html/PaxHeaders.26529/libinfinoted-plug0000644000000000000000000000033013055210765030351 xustar00126 path=libinfinity-0.7.1/docs/reference/libinfinoted-plugin-manager/html/libinfinoted-plugin-manager-0.7-InfinotedUtil.html 30 mtime=1488261621.180067602 30 atime=1488261621.180067602 30 ctime=1488261621.180067602 libinfinity-0.7.1/docs/reference/libinfinoted-plugin-manager/html/libinfinoted-plugin-manager-0.7-In0000644000175000017500000003137013055210765033714 0ustar00arminarmin00000000000000 InfinotedUtil: libinfinoted-plugin-manager-0.7 Reference Manual

InfinotedUtil

InfinotedUtil — Miscellaneous helper functions.

Stability Level

Unstable, unless otherwise indicated

Includes

#include <infinoted/infinoted-util.h>

Description

This section contains a few helper functions that are used in the infinoted implementation and are exposed to the plugin interface for convenience of plugin developers.

Functions

infinoted_util_create_dirname ()

gboolean
infinoted_util_create_dirname (const gchar *path,
                               GError **error);

Creates directories leading to the given path. Does not create a directory for the last component of the path, assuming that it is a filename that you are going to write into that directory later.

Parameters

path

The filename to create a path to.

[type filename]

error

Location to store error information, if any.

 

Returns

TRUE on success, or FALSE on error in which case error is set.


infinoted_util_set_errno_error ()

void
infinoted_util_set_errno_error (GError **error,
                                int save_errno,
                                const char *prefix);

Sets error to save_errno with domain ERRNO_ERROR. If prefix is non-NULL, prefix is prefixed to error 's message, obtained by strerror().

Parameters

error

A pointer to a GError pointer, or NULL.

 

save_errno

An errno variable.

 

prefix

A prefix string, or NULL.

[allow-none]

infinoted_util_daemon_set_global_pid_file_proc ()

void
infinoted_util_daemon_set_global_pid_file_proc
                               (void);

When attempting to read or write the PID file use the global file.


infinoted_util_daemon_set_local_pid_file_proc ()

void
infinoted_util_daemon_set_local_pid_file_proc
                               (void);

When attempting to read or write the PID file use the local file which is in the owner's home directory.


infinoted_util_daemon_pid_file_kill ()

int
infinoted_util_daemon_pid_file_kill (int sig);

This is a thin wrapper for daemon_pid_file_kill() which uses daemon_pid_file_kill_wait() if available with a timeout of 5 seconds.

Parameters

sig

The signal to send to the daemon process.

 

Returns

0 if the signal was sent or nonzero otherwise.

Types and Values

libinfinity-0.7.1/docs/reference/libinfinoted-plugin-manager/html/PaxHeaders.26529/up.png0000644000000000000000000000013213055210765026145 xustar0030 mtime=1488261621.144067683 30 atime=1488261621.144067683 30 ctime=1488261621.144067683 libinfinity-0.7.1/docs/reference/libinfinoted-plugin-manager/html/up.png0000644000175000017500000000040413055210765026675 0ustar00arminarmin00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEà 4ÓkM‘IDAT8Ëí’1 ƒ@DŸ•¶{ƒxa™ƒØÄ;$]r =JR´È1,Ë øSd„-©}0°ÌŸÙÏÂÂÎàüo¹L:m-˜¤QÞOäÀ[› Éäåkå T¸zþMÞ Lè¬Ì,š:ךuÀ!tÁK;æ ðP¦õÌôÀp Ot@£l¼ÿò/̵*á§l}IEND®B`‚libinfinity-0.7.1/docs/reference/libinfinoted-plugin-manager/html/PaxHeaders.26529/home.png0000644000000000000000000000013213055210765026451 xustar0030 mtime=1488261621.140067692 30 atime=1488261621.140067692 30 ctime=1488261621.140067692 libinfinity-0.7.1/docs/reference/libinfinoted-plugin-manager/html/home.png0000644000175000017500000000040013055210765027175 0ustar00arminarmin00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEà 4ÓkMIDAT8ËÝÒ½ AÅñßž¦f`n v`6`/¶`Y€š˜Ü¡`f&k$,Ëá}˜ˆ ÌüßÀ0ü§bŒ+Ô¸aQW~bæ ËOà e˜{‡y N°Á£üö[LáØÌ}.pÇiÀ­÷¨BzüžÆmm Šoæ·.I]7Ì^[úÃô;%:å†ÁVIEND®B`‚libinfinity-0.7.1/docs/reference/libinfinoted-plugin-manager/html/PaxHeaders.26529/right-insensitive0000644000000000000000000000013213055210765030411 xustar0030 mtime=1488261621.144067683 30 atime=1488261621.144067683 30 ctime=1488261621.144067683 libinfinity-0.7.1/docs/reference/libinfinoted-plugin-manager/html/right-insensitive.png0000644000175000017500000000056513055210765031734 0ustar00arminarmin00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEà 4ÓkMIDAT8ËÍ’±JÃ`…¿ ‚“‹³«/ S’_$ÄÁÁAqrÐÙW(>€“à‚®©“m¥"]\œ„è(‘49.NÚdÒ3¸ß9Ü{á¯eM#MSI‡Î¹·E¯iHz|3{̲l½3 ,K˜k’ž†ÃáV'@EŸEQlwÀŠçyišî·Äqüçù‘™]KÀíh4:mµÄ¦²,;“t˜¤sç\aƒÆR5/¬7'¹W×õp”’Žs×­I’,Kº1³=àËÌÂ0´j0Wg³ÙØ>€Ý ¦­¯PUÕýïð»¤0 §]?qCÒ«™ùιgþ½~œÉkÄAâ…_IEND®B`‚libinfinity-0.7.1/docs/reference/libinfinoted-plugin-manager/html/PaxHeaders.26529/right.png0000644000000000000000000000013213055210765026636 xustar0030 mtime=1488261621.144067683 30 atime=1488261621.144067683 30 ctime=1488261621.144067683 libinfinity-0.7.1/docs/reference/libinfinoted-plugin-manager/html/right.png0000644000175000017500000000040513055210765027367 0ustar00arminarmin00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEà 4ÓkM’IDAT8ËÕÒ¯aÇñ?›M´½IdErš,¾Ù-¸ÑhîAâIl’Í ¯r’äy§ž}¿ç·s¿X6èæ ö!9¢Ÿ#èD‚ Œr$-¬BrÃ$GÒÀ"$”¹;™á‰æŸÍú—WZêä&–!¸cš·±øŠq \`ðÃÔ軀Oä¾ò=QouføòIEND®B`‚libinfinity-0.7.1/docs/reference/libinfinoted-plugin-manager/html/PaxHeaders.26529/style.css0000644000000000000000000000013213055210765026665 xustar0030 mtime=1488261621.144067683 30 atime=1488261621.144067683 30 ctime=1488261621.144067683 libinfinity-0.7.1/docs/reference/libinfinoted-plugin-manager/html/style.css0000644000175000017500000002115413055210765027422 0ustar00arminarmin00000000000000body { font-family: cantarell, sans-serif; } .synopsis, .classsynopsis { /* tango:aluminium 1/2 */ background: #eeeeec; background: rgba(238, 238, 236, 0.5); border: solid 1px rgb(238, 238, 236); padding: 0.5em; } .programlisting { /* tango:sky blue 0/1 */ /* fallback for no rgba support */ background: #e6f3ff; border: solid 1px #729fcf; background: rgba(114, 159, 207, 0.1); border: solid 1px rgba(114, 159, 207, 0.2); padding: 0.5em; } .variablelist { padding: 4px; margin-left: 3em; } .variablelist td:first-child { vertical-align: top; } div.gallery-float { float: left; padding: 10px; } div.gallery-float img { border-style: none; } div.gallery-spacer { clear: both; } a, a:visited { text-decoration: none; /* tango:sky blue 2 */ color: #3465a4; } a:hover { text-decoration: underline; /* tango:sky blue 1 */ color: #729fcf; } div.informaltable table { border-collapse: separate; border-spacing: 1em 0.3em; border: none; } div.informaltable table td, div.informaltable table th { vertical-align: top; } .function_type, .variable_type, .property_type, .signal_type, .parameter_name, .struct_member_name, .union_member_name, .define_keyword, .datatype_keyword, .typedef_keyword { text-align: right; } /* dim non-primary columns */ .c_punctuation, .function_type, .variable_type, .property_type, .signal_type, .define_keyword, .datatype_keyword, .typedef_keyword, .property_flags, .signal_flags, .parameter_annotations, .enum_member_annotations, .struct_member_annotations, .union_member_annotations { color: #888a85; } .function_type a, .function_type a:visited, .function_type a:hover, .property_type a, .property_type a:visited, .property_type a:hover, .signal_type a, .signal_type a:visited, .signal_type a:hover, .signal_flags a, .signal_flags a:visited, .signal_flags a:hover { color: #729fcf; } td p { margin: 0.25em; } div.table table { border-collapse: collapse; border-spacing: 0px; /* tango:aluminium 3 */ border: solid 1px #babdb6; } div.table table td, div.table table th { /* tango:aluminium 3 */ border: solid 1px #babdb6; padding: 3px; vertical-align: top; } div.table table th { /* tango:aluminium 2 */ background-color: #d3d7cf; } h4 { color: #555753; margin-top: 1em; margin-bottom: 1em; } hr { /* tango:aluminium 1 */ color: #d3d7cf; background: #d3d7cf; border: none 0px; height: 1px; clear: both; margin: 2.0em 0em 2.0em 0em; } dl.toc dt { padding-bottom: 0.25em; } dl.toc > dt { padding-top: 0.25em; padding-bottom: 0.25em; font-weight: bold; } dl.toc > dl { padding-bottom: 0.5em; } .parameter { font-style: normal; } .footer { padding-top: 3.5em; /* tango:aluminium 3 */ color: #babdb6; text-align: center; font-size: 80%; } .informalfigure, .figure { margin: 1em; } .informalexample, .example { margin-top: 1em; margin-bottom: 1em; } .warning { /* tango:orange 0/1 */ background: #ffeed9; background: rgba(252, 175, 62, 0.1); border-color: #ffb04f; border-color: rgba(252, 175, 62, 0.2); } .note { /* tango:chameleon 0/0.5 */ background: #d8ffb2; background: rgba(138, 226, 52, 0.1); border-color: #abf562; border-color: rgba(138, 226, 52, 0.2); } div.blockquote { border-color: #eeeeec; } .note, .warning, div.blockquote { padding: 0.5em; border-width: 1px; border-style: solid; margin: 2em; } .note p, .warning p { margin: 0; } div.warning h3.title, div.note h3.title { display: none; } p + div.section { margin-top: 1em; } div.refnamediv, div.refsynopsisdiv, div.refsect1, div.refsect2, div.toc, div.section { margin-bottom: 1em; } /* blob links */ h2 .extralinks, h3 .extralinks { float: right; /* tango:aluminium 3 */ color: #babdb6; font-size: 80%; font-weight: normal; } .lineart { color: #d3d7cf; font-weight: normal; } .annotation { /* tango:aluminium 5 */ color: #555753; font-weight: normal; } .structfield { font-style: normal; font-weight: normal; } acronym,abbr { border-bottom: 1px dotted gray; } /* code listings */ .listing_code .programlisting .normal, .listing_code .programlisting .normal a, .listing_code .programlisting .number, .listing_code .programlisting .cbracket, .listing_code .programlisting .symbol { color: #555753; } .listing_code .programlisting .comment, .listing_code .programlisting .linenum { color: #babdb6; } /* tango: aluminium 3 */ .listing_code .programlisting .function, .listing_code .programlisting .function a, .listing_code .programlisting .preproc { color: #204a87; } /* tango: sky blue 3 */ .listing_code .programlisting .string { color: #ad7fa8; } /* tango: plum */ .listing_code .programlisting .keyword, .listing_code .programlisting .usertype, .listing_code .programlisting .type, .listing_code .programlisting .type a { color: #4e9a06; } /* tango: chameleon 3 */ .listing_frame { /* tango:sky blue 1 */ border: solid 1px #729fcf; border: solid 1px rgba(114, 159, 207, 0.2); padding: 0px; } .listing_lines, .listing_code { margin-top: 0px; margin-bottom: 0px; padding: 0.5em; } .listing_lines { /* tango:sky blue 0.5 */ background: #a6c5e3; background: rgba(114, 159, 207, 0.2); /* tango:aluminium 6 */ color: #2e3436; } .listing_code { /* tango:sky blue 0 */ background: #e6f3ff; background: rgba(114, 159, 207, 0.1); } .listing_code .programlisting { /* override from previous */ border: none 0px; padding: 0px; background: none; } .listing_lines pre, .listing_code pre { margin: 0px; } @media screen { /* these have a as a first child, but since there are no parent selectors * we can't use that. */ a.footnote { position: relative; top: 0em ! important; } /* this is needed so that the local anchors are displayed below the naviagtion */ div.footnote a[name], div.refnamediv a[name], div.refsect1 a[name], div.refsect2 a[name], div.index a[name], div.glossary a[name], div.sect1 a[name] { display: inline-block; position: relative; top:-5em; } /* this seems to be a bug in the xsl style sheets when generating indexes */ div.index div.index { top: 0em; } /* make space for the fixed navigation bar and add space at the bottom so that * link targets appear somewhat close to top */ body { padding-top: 2.5em; padding-bottom: 500px; max-width: 60em; } p { max-width: 60em; } /* style and size the navigation bar */ table.navigation#top { position: fixed; background: #e2e2e2; border-bottom: solid 1px #babdb6; border-spacing: 5px; margin-top: 0; margin-bottom: 0; top: 0; left: 0; z-index: 10; } table.navigation#top td { padding-left: 6px; padding-right: 6px; } .navigation a, .navigation a:visited { /* tango:sky blue 3 */ color: #204a87; } .navigation a:hover { /* tango:sky blue 2 */ color: #3465a4; } td.shortcuts { /* tango:sky blue 2 */ color: #3465a4; font-size: 80%; white-space: nowrap; } td.shortcuts .dim { color: #babdb6; } .navigation .title { font-size: 80%; max-width: none; margin: 0px; font-weight: normal; } } @media screen and (min-width: 60em) { /* screen larger than 60em */ body { margin: auto; } } @media screen and (max-width: 60em) { /* screen less than 60em */ #nav_hierarchy { display: none; } #nav_interfaces { display: none; } #nav_prerequisites { display: none; } #nav_derived_interfaces { display: none; } #nav_implementations { display: none; } #nav_child_properties { display: none; } #nav_style_properties { display: none; } #nav_index { display: none; } #nav_glossary { display: none; } .gallery_image { display: none; } .property_flags { display: none; } .signal_flags { display: none; } .parameter_annotations { display: none; } .enum_member_annotations { display: none; } .struct_member_annotations { display: none; } .union_member_annotations { display: none; } /* now that a column is hidden, optimize space */ col.parameters_name { width: auto; } col.parameters_description { width: auto; } col.struct_members_name { width: auto; } col.struct_members_description { width: auto; } col.enum_members_name { width: auto; } col.enum_members_description { width: auto; } col.union_members_name { width: auto; } col.union_members_description { width: auto; } .listing_lines { display: none; } } @media print { table.navigation { visibility: collapse; display: none; } div.titlepage table.navigation { visibility: visible; display: table; background: #e2e2e2; border: solid 1px #babdb6; margin-top: 0; margin-bottom: 0; top: 0; left: 0; height: 3em; } } libinfinity-0.7.1/docs/reference/libinfinoted-plugin-manager/html/PaxHeaders.26529/left.png0000644000000000000000000000013213055210765026453 xustar0030 mtime=1488261621.144067683 30 atime=1488261621.144067683 30 ctime=1488261621.144067683 libinfinity-0.7.1/docs/reference/libinfinoted-plugin-manager/html/left.png0000644000175000017500000000040613055210765027205 0ustar00arminarmin00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEà 4ÓkM“IDAT8ËÕÒ¯Áa‡ñ?ÁDAPY‘\‚$‹º[p¢+ÐÜIÐIªMlfü('Úì}MpâÙyží{Îá_ª…ž¨¤ÂÞ¥Â}œ^£‘q xZ <Æ=àYjî) <0ù4\~Ó+Púöl#Ü"ÂÕÉ—,QÏ‘ôp ÉÍIÇlswÒÆ>÷•[/]_i0‘3ÃIEND®B`‚libinfinity-0.7.1/docs/reference/libinfinoted-plugin-manager/html/PaxHeaders.26529/InfinotedLog.html0000644000000000000000000000013213055210765030262 xustar0030 mtime=1488261621.180067602 30 atime=1488261621.180067602 30 ctime=1488261621.180067602 libinfinity-0.7.1/docs/reference/libinfinoted-plugin-manager/html/InfinotedLog.html0000644000175000017500000006434513055210765031030 0ustar00arminarmin00000000000000 InfinotedLog: libinfinoted-plugin-manager-0.7 Reference Manual

InfinotedLog

InfinotedLog — A class to handle logging of messages.

Stability Level

Unstable, unless otherwise indicated

Properties

gchar * file-path Read

Signals

Types and Values

Object Hierarchy

    GObject
    ╰── InfinotedLog

Includes

#include <infinoted/infinoted-log.h>

Description

InfinotedLog manages a message log. Messages can be written to the log either as informational, warning and error messages. If the log was successfully opened, also a glib logging handler is installed which redirects glib logging to this class. Log output is always shown on stderr and, optionally, can be duplicated to a file as well.

Functions

infinoted_log_new ()

InfinotedLog *
infinoted_log_new (void);

Creates a new InfinotedLog.

[constructor]

Returns

A new InfinotedLog. Free with g_object_unref() when no longer needed.

[transfer full]


infinoted_log_open ()

gboolean
infinoted_log_open (InfinotedLog *log,
                    const gchar *path,
                    GError **error);

Attempts to open the log file at the given path. If the log file could not be opened the function returns FALSE and error is set. If the log file exists already then new log messages will be appended.

If path is NULL no log file is opened and logging only occurs to stderr.

Parameters

log

A InfinotedLog.

 

path

The path to the log file to write, or NULL.

[type filename][allow-none]

error

Location to store error information, if any, or NULL.

 

Returns

TRUE on success, or FALSE otherwise.


infinoted_log_close ()

void
infinoted_log_close (InfinotedLog *log);

Closes a InfinotedLog object opened with infinoted_log_open(). After the log was closed it can be opened again with a different file. The log is closed automatically on destruction.

Parameters

log

A InfinotedLog.

 

infinoted_log_log ()

void
infinoted_log_log (InfinotedLog *log,
                   guint prio,
                   const char *fmt,
                   ...);

Logs a message with the given priority. The priority is one of LOG_ERR, LOG_WARNING or LOG_INFO. If the server is daemonized, log to syslog, otherwise log to stderr. If a logfile is given in the options when log was created, the logfile is written to as well.

Parameters

log

A InfinotedLog.

 

prio

Priority of the logged message.

 

fmt

A printf-style format string.

 

...

Format arguments.

 

infinoted_log_info ()

void
infinoted_log_info (InfinotedLog *log,
                    const char *fmt,
                    ...);

Logs an info message. If the server is daemonized, log to syslog, otherwise log to stderr. If a logfile is given in the options when log was created, the logfile is written to as well.

Parameters

log

A InfinotedLog.

 

fmt

A printf-style format string.

 

...

Format arguments.

 

infinoted_log_warning ()

void
infinoted_log_warning (InfinotedLog *log,
                       const char *fmt,
                       ...);

Logs a warning message. If the server is daemonized, log to syslog, otherwise log to stderr. If a logfile is given in the options when log was created, the logfile is written to as well.

Parameters

log

A InfinotedLog.

 

fmt

A printf-style format string.

 

...

Format arguments.

 

infinoted_log_error ()

void
infinoted_log_error (InfinotedLog *log,
                     const char *fmt,
                     ...);

Logs an error message. If the server is daemonized, log to syslog, otherwise log to stderr. If a logfile is given in the options when log was created, the logfile is written to as well.

Parameters

log

A InfinotedLog.

 

fmt

A printf-style format string.

 

...

Format arguments.

 

Types and Values

struct InfinotedLog

struct InfinotedLog;

InfinotedLog is an opaque data type. You should only access it via the public API functions.


struct InfinotedLogClass

struct InfinotedLogClass {
  void (*log_message)(InfinotedLog* log,
                      guint prio,
                      guint depth,
                      const gchar* text);
};

This structure contains default signal handlers for InfinotedLog.

Members

log_message ()

Default signal handler for the “log-message†signal.

 

Property Details

The “file-path†property

  “file-path†               gchar *

Path to the log file.

Flags: Read

Default value: NULL

Signal Details

The “log-message†signal

void
user_function (InfinotedLog *log,
               guint         prio,
               guint         depth,
               gchar        *text,
               gpointer      user_data)

This signal is emitted when a new line of log message is written to the log.

Parameters

log

The InfinotedLog that is logging a message.

 

prio

The priority of the logged message.

 

depth

The recursion depth of the logged message.

 

text

The logged message text.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run First

libinfinity-0.7.1/docs/reference/libinfinoted-plugin-manager/PaxHeaders.26529/Makefile.in0000644000000000000000000000013213051241007026101 xustar0030 mtime=1487225351.721148471 30 atime=1487225351.721148471 30 ctime=1488261619.892070505 libinfinity-0.7.1/docs/reference/libinfinoted-plugin-manager/Makefile.in0000644000175000017500000007012413051241007026637 0ustar00arminarmin00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 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@ # -*- mode: makefile -*- #################################### # Everything below here is generic # #################################### VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) 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@ subdir = docs/reference/libinfinoted-plugin-manager ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/gtk-doc.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/libinfinity/inf-config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/gtk-doc.make DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ 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@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIRNAME = @DATADIRNAME@ 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@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ GTKDOC_CHECK = @GTKDOC_CHECK@ GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ GTKDOC_MKPDF = @GTKDOC_MKPDF@ GTKDOC_REBASE = @GTKDOC_REBASE@ HTML_DIR = @HTML_DIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INSTOBJEXT = @INSTOBJEXT@ INTLLIBS = @INTLLIBS@ INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBINFINITY_API_VERSION = @LIBINFINITY_API_VERSION@ LIBINFINITY_LIBTOOL_VERSION = @LIBINFINITY_LIBTOOL_VERSION@ LIBINFINITY_VERSION = @LIBINFINITY_VERSION@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGFMT_OPTS = @MSGFMT_OPTS@ 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@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ 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@ avahi_CFLAGS = @avahi_CFLAGS@ avahi_LIBS = @avahi_LIBS@ 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@ gio_CFLAGS = @gio_CFLAGS@ gio_LIBS = @gio_LIBS@ gtk_requirement = @gtk_requirement@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infgtk_CFLAGS = @infgtk_CFLAGS@ infgtk_LIBS = @infgtk_LIBS@ infinity_CFLAGS = @infinity_CFLAGS@ infinity_LIBS = @infinity_LIBS@ infinoted_CFLAGS = @infinoted_CFLAGS@ infinoted_LIBS = @infinoted_LIBS@ infodir = @infodir@ inftext_CFLAGS = @inftext_CFLAGS@ inftext_LIBS = @inftext_LIBS@ inftextgtk_CFLAGS = @inftextgtk_CFLAGS@ inftextgtk_LIBS = @inftextgtk_LIBS@ install_sh = @install_sh@ libdaemon_CFLAGS = @libdaemon_CFLAGS@ libdaemon_LIBS = @libdaemon_LIBS@ 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@ runstatedir = @runstatedir@ 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@ # We require automake 1.6 at least. AUTOMAKE_OPTIONS = 1.6 # This is a blank Makefile.am for using gtk-doc. # Copy this to your project's API docs directory and modify the variables to # suit your project. See the GTK+ Makefiles in gtk+/docs/reference for examples # of using the various options. # The name of the module, e.g. 'glib'. DOC_MODULE = libinfinoted-plugin-manager-$(LIBINFINITY_API_VERSION) # The top-level SGML file. You can change this if you want to. DOC_MAIN_SGML_FILE = $(DOC_MODULE)-docs.sgml # The directory containing the source code. Relative to $(srcdir). # gtk-doc will search all .c & .h files beneath here for inline comments # documenting the functions and macros. # e.g. DOC_SOURCE_DIR=../../../gtk DOC_SOURCE_DIR = $(top_srcdir)/infinoted # Extra options to pass to gtkdoc-scangobj. Not normally needed. SCANGOBJ_OPTIONS = # Extra options to supply to gtkdoc-scan. # e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED" SCAN_OPTIONS = --rebuild-types # Extra options to supply to gtkdoc-mkdb. # e.g. MKDB_OPTIONS=--sgml-mode --output-format=xml MKDB_OPTIONS = --sgml-mode --output-format=xml # Extra options to supply to gtkdoc-mktmpl # e.g. MKTMPL_OPTIONS=--only-section-tmpl MKTMPL_OPTIONS = # Extra options to supply to gtkdoc-fixref. Not normally needed. # e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html FIXXREF_OPTIONS = \ --extra-dir=../libinfinity/html # Used for dependencies. The docs will be rebuilt if any of these change. # e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h # e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c HFILE_GLOB = \ $(top_srcdir)/infinoted/infinoted-log.h \ $(top_srcdir)/infinoted/infinoted-parameter.h \ $(top_srcdir)/infinoted/infinoted-plugin-manager.h \ $(top_srcdir)/infinoted/infinoted-util.h CFILE_GLOB = \ $(top_srcdir)/infinoted/infinoted-log.c \ $(top_srcdir)/infinoted/infinoted-parameter.c \ $(top_srcdir)/infinoted/infinoted-plugin-manager.c \ $(top_srcdir)/infinoted/infinoted-util.c # Header files to ignore when scanning. # e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h IGNORE_HFILES = \ infinoted-config-reload.h \ infinoted-dh-params.h \ infinoted-options.h \ infinoted-pam.h \ infinoted-run.h \ infinoted-signal.h \ infinoted-startup.h \ infinoted-plugin-util-navigate-browser.h # Images to copy into HTML directory. # e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png HTML_IMAGES = # Extra SGML files that are included by $(DOC_MAIN_SGML_FILE). # e.g. content_files=running.sgml building.sgml changes-2.0.sgml content_files = \ ../version.xml # SGML files where gtk-doc abbrevations (#GtkWidget) are expanded # These files must be listed here *and* in content_files # e.g. expand_content_files=running.sgml expand_content_files = # CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library. # Only needed if you are using gtkdoc-scangobj to dynamically query widget # signals and properties. # e.g. INCLUDES=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS) # e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib) AM_CPPFLAGS = $(infinoted_CFLAGS) GTKDOC_LIBS = \ $(top_builddir)/infinoted/libinfinoted-plugin-manager-$(LIBINFINITY_API_VERSION).la \ $(top_builddir)/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la\ $(infinoted_LIBS) \ $(libdaemon_LIBS) @GTK_DOC_USE_LIBTOOL_FALSE@GTKDOC_CC = $(CC) $(INCLUDES) $(GTKDOC_DEPS_CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) @GTK_DOC_USE_LIBTOOL_TRUE@GTKDOC_CC = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(INCLUDES) $(GTKDOC_DEPS_CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) @GTK_DOC_USE_LIBTOOL_FALSE@GTKDOC_LD = $(CC) $(GTKDOC_DEPS_LIBS) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) @GTK_DOC_USE_LIBTOOL_TRUE@GTKDOC_LD = $(LIBTOOL) --tag=CC --mode=link $(CC) $(GTKDOC_DEPS_LIBS) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) @GTK_DOC_USE_LIBTOOL_FALSE@GTKDOC_RUN = @GTK_DOC_USE_LIBTOOL_TRUE@GTKDOC_RUN = $(LIBTOOL) --mode=execute # We set GPATH here; this gives us semantics for GNU make # which are more like other make's VPATH, when it comes to # whether a source that is a target of one rule is then # searched for in VPATH/GPATH. # GPATH = $(srcdir) TARGET_DIR = $(HTML_DIR)/$(DOC_MODULE) SETUP_FILES = \ $(content_files) \ $(expand_content_files) \ $(DOC_MAIN_SGML_FILE) \ $(DOC_MODULE)-sections.txt \ $(DOC_MODULE)-overrides.txt # This includes the standard gtk-doc make rules, copied by gtkdocize. # Other files to distribute # e.g. EXTRA_DIST += version.xml.in EXTRA_DIST = $(HTML_IMAGES) $(SETUP_FILES) DOC_STAMPS = setup-build.stamp scan-build.stamp sgml-build.stamp \ html-build.stamp pdf-build.stamp \ sgml.stamp html.stamp pdf.stamp SCANOBJ_FILES = \ $(DOC_MODULE).args \ $(DOC_MODULE).hierarchy \ $(DOC_MODULE).interfaces \ $(DOC_MODULE).prerequisites \ $(DOC_MODULE).signals REPORT_FILES = \ $(DOC_MODULE)-undocumented.txt \ $(DOC_MODULE)-undeclared.txt \ $(DOC_MODULE)-unused.txt CLEANFILES = $(SCANOBJ_FILES) $(REPORT_FILES) $(DOC_STAMPS) gtkdoc-check.test @GTK_DOC_BUILD_HTML_FALSE@HTML_BUILD_STAMP = @GTK_DOC_BUILD_HTML_TRUE@HTML_BUILD_STAMP = html-build.stamp @GTK_DOC_BUILD_PDF_FALSE@PDF_BUILD_STAMP = @GTK_DOC_BUILD_PDF_TRUE@PDF_BUILD_STAMP = pdf-build.stamp #### setup #### GTK_DOC_V_SETUP = $(GTK_DOC_V_SETUP_$(V)) GTK_DOC_V_SETUP_ = $(GTK_DOC_V_SETUP_$(AM_DEFAULT_VERBOSITY)) GTK_DOC_V_SETUP_0 = @echo " DOC Preparing build"; #### scan #### GTK_DOC_V_SCAN = $(GTK_DOC_V_SCAN_$(V)) GTK_DOC_V_SCAN_ = $(GTK_DOC_V_SCAN_$(AM_DEFAULT_VERBOSITY)) GTK_DOC_V_SCAN_0 = @echo " DOC Scanning header files"; GTK_DOC_V_INTROSPECT = $(GTK_DOC_V_INTROSPECT_$(V)) GTK_DOC_V_INTROSPECT_ = $(GTK_DOC_V_INTROSPECT_$(AM_DEFAULT_VERBOSITY)) GTK_DOC_V_INTROSPECT_0 = @echo " DOC Introspecting gobjects"; #### xml #### GTK_DOC_V_XML = $(GTK_DOC_V_XML_$(V)) GTK_DOC_V_XML_ = $(GTK_DOC_V_XML_$(AM_DEFAULT_VERBOSITY)) GTK_DOC_V_XML_0 = @echo " DOC Building XML"; #### html #### GTK_DOC_V_HTML = $(GTK_DOC_V_HTML_$(V)) GTK_DOC_V_HTML_ = $(GTK_DOC_V_HTML_$(AM_DEFAULT_VERBOSITY)) GTK_DOC_V_HTML_0 = @echo " DOC Building HTML"; GTK_DOC_V_XREF = $(GTK_DOC_V_XREF_$(V)) GTK_DOC_V_XREF_ = $(GTK_DOC_V_XREF_$(AM_DEFAULT_VERBOSITY)) GTK_DOC_V_XREF_0 = @echo " DOC Fixing cross-references"; #### pdf #### GTK_DOC_V_PDF = $(GTK_DOC_V_PDF_$(V)) GTK_DOC_V_PDF_ = $(GTK_DOC_V_PDF_$(AM_DEFAULT_VERBOSITY)) GTK_DOC_V_PDF_0 = @echo " DOC Building PDF"; # Files not to distribute # for --rebuild-types in $(SCAN_OPTIONS), e.g. $(DOC_MODULE).types # for --rebuild-sections in $(SCAN_OPTIONS) e.g. $(DOC_MODULE)-sections.txt DISTCLEANFILES = libinfinoted-plugin-manager-$(LIBINFINITY_API_VERSION).types version.xml all: all-am .SUFFIXES: $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/gtk-doc.make $(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) --foreign docs/reference/libinfinoted-plugin-manager/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign docs/reference/libinfinoted-plugin-manager/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_srcdir)/gtk-doc.make $(am__empty): $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs tags TAGS: ctags CTAGS: cscope cscopelist: 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 $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-hook check-am: all-am check: check-am @ENABLE_GTK_DOC_FALSE@all-local: all-am: Makefile all-local installdirs: install: 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) -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic distclean-local dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-data-local install-dvi: install-dvi-am install-dvi-am: install-exec-am: 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 -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic \ maintainer-clean-local mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-local .MAKE: install-am install-strip .PHONY: all all-am all-local check check-am clean clean-generic \ clean-libtool clean-local cscopelist-am ctags-am dist-hook \ distclean distclean-generic distclean-libtool distclean-local \ distdir dvi dvi-am html html-am info info-am install \ install-am install-data install-data-am install-data-local \ 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-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ maintainer-clean-local mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \ uninstall-am uninstall-local .PRECIOUS: Makefile gtkdoc-check.test: Makefile $(AM_V_GEN)echo "#!/bin/sh -e" > $@; \ echo "$(GTKDOC_CHECK_PATH) || exit 1" >> $@; \ chmod +x $@ all-gtk-doc: $(HTML_BUILD_STAMP) $(PDF_BUILD_STAMP) .PHONY: all-gtk-doc @ENABLE_GTK_DOC_TRUE@all-local: all-gtk-doc docs: $(HTML_BUILD_STAMP) $(PDF_BUILD_STAMP) $(REPORT_FILES): sgml-build.stamp setup-build.stamp: -$(GTK_DOC_V_SETUP)if test "$(abs_srcdir)" != "$(abs_builddir)" ; then \ files=`echo $(SETUP_FILES) $(DOC_MODULE).types`; \ if test "x$$files" != "x" ; then \ for file in $$files ; do \ destdir=`dirname $(abs_builddir)/$$file`; \ test -d "$$destdir" || mkdir -p "$$destdir"; \ test -f $(abs_srcdir)/$$file && \ cp -pf $(abs_srcdir)/$$file $(abs_builddir)/$$file || true; \ done; \ fi; \ fi $(AM_V_at)touch setup-build.stamp scan-build.stamp: setup-build.stamp $(HFILE_GLOB) $(CFILE_GLOB) $(GTK_DOC_V_SCAN)_source_dir='' ; \ for i in $(DOC_SOURCE_DIR) ; do \ _source_dir="$${_source_dir} --source-dir=$$i" ; \ done ; \ gtkdoc-scan --module=$(DOC_MODULE) --ignore-headers="$(IGNORE_HFILES)" $${_source_dir} $(SCAN_OPTIONS) $(EXTRA_HFILES) $(GTK_DOC_V_INTROSPECT)if grep -l '^..*$$' $(DOC_MODULE).types > /dev/null 2>&1 ; then \ scanobj_options=""; \ gtkdoc-scangobj 2>&1 --help | grep >/dev/null "\-\-verbose"; \ if test "$$?" = "0"; then \ if test "x$(V)" = "x1"; then \ scanobj_options="--verbose"; \ fi; \ fi; \ CC="$(GTKDOC_CC)" LD="$(GTKDOC_LD)" RUN="$(GTKDOC_RUN)" CFLAGS="$(GTKDOC_CFLAGS) $(CFLAGS)" LDFLAGS="$(GTKDOC_LIBS) $(LDFLAGS)" \ gtkdoc-scangobj $(SCANGOBJ_OPTIONS) $$scanobj_options --module=$(DOC_MODULE); \ else \ for i in $(SCANOBJ_FILES) ; do \ test -f $$i || touch $$i ; \ done \ fi $(AM_V_at)touch scan-build.stamp $(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(DOC_MODULE)-sections.txt $(DOC_MODULE)-overrides.txt: scan-build.stamp @true sgml-build.stamp: setup-build.stamp $(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(HFILE_GLOB) $(CFILE_GLOB) $(DOC_MODULE)-sections.txt $(DOC_MODULE)-overrides.txt $(expand_content_files) xml/gtkdocentities.ent $(GTK_DOC_V_XML)_source_dir='' ; \ for i in $(DOC_SOURCE_DIR) ; do \ _source_dir="$${_source_dir} --source-dir=$$i" ; \ done ; \ gtkdoc-mkdb --module=$(DOC_MODULE) --output-format=xml --expand-content-files="$(expand_content_files)" --main-sgml-file=$(DOC_MAIN_SGML_FILE) $${_source_dir} $(MKDB_OPTIONS) $(AM_V_at)touch sgml-build.stamp sgml.stamp: sgml-build.stamp @true xml/gtkdocentities.ent: Makefile $(GTK_DOC_V_XML)$(MKDIR_P) $(@D) && ( \ echo ""; \ echo ""; \ echo ""; \ echo ""; \ echo ""; \ echo ""; \ echo ""; \ ) > $@ html-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) $(expand_content_files) $(GTK_DOC_V_HTML)rm -rf html && mkdir html && \ mkhtml_options=""; \ gtkdoc-mkhtml 2>&1 --help | grep >/dev/null "\-\-verbose"; \ if test "$$?" = "0"; then \ if test "x$(V)" = "x1"; then \ mkhtml_options="$$mkhtml_options --verbose"; \ fi; \ fi; \ gtkdoc-mkhtml 2>&1 --help | grep >/dev/null "\-\-path"; \ if test "$$?" = "0"; then \ mkhtml_options="$$mkhtml_options --path=\"$(abs_srcdir)\""; \ fi; \ cd html && gtkdoc-mkhtml $$mkhtml_options $(MKHTML_OPTIONS) $(DOC_MODULE) ../$(DOC_MAIN_SGML_FILE) -@test "x$(HTML_IMAGES)" = "x" || \ for file in $(HTML_IMAGES) ; do \ if test -f $(abs_srcdir)/$$file ; then \ cp $(abs_srcdir)/$$file $(abs_builddir)/html; \ fi; \ if test -f $(abs_builddir)/$$file ; then \ cp $(abs_builddir)/$$file $(abs_builddir)/html; \ fi; \ done; $(GTK_DOC_V_XREF)gtkdoc-fixxref --module=$(DOC_MODULE) --module-dir=html --html-dir=$(HTML_DIR) $(FIXXREF_OPTIONS) $(AM_V_at)touch html-build.stamp pdf-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) $(expand_content_files) $(GTK_DOC_V_PDF)rm -f $(DOC_MODULE).pdf && \ mkpdf_options=""; \ gtkdoc-mkpdf 2>&1 --help | grep >/dev/null "\-\-verbose"; \ if test "$$?" = "0"; then \ if test "x$(V)" = "x1"; then \ mkpdf_options="$$mkpdf_options --verbose"; \ fi; \ fi; \ if test "x$(HTML_IMAGES)" != "x"; then \ for img in $(HTML_IMAGES); do \ part=`dirname $$img`; \ echo $$mkpdf_options | grep >/dev/null "\-\-imgdir=$$part "; \ if test $$? != 0; then \ mkpdf_options="$$mkpdf_options --imgdir=$$part"; \ fi; \ done; \ fi; \ gtkdoc-mkpdf --path="$(abs_srcdir)" $$mkpdf_options $(DOC_MODULE) $(DOC_MAIN_SGML_FILE) $(MKPDF_OPTIONS) $(AM_V_at)touch pdf-build.stamp ############## clean-local: @rm -f *~ *.bak @rm -rf .libs @if echo $(SCAN_OPTIONS) | grep -q "\-\-rebuild-types" ; then \ rm -f $(DOC_MODULE).types; \ fi @if echo $(SCAN_OPTIONS) | grep -q "\-\-rebuild-sections" ; then \ rm -f $(DOC_MODULE)-sections.txt; \ fi distclean-local: @rm -rf xml html $(REPORT_FILES) $(DOC_MODULE).pdf \ $(DOC_MODULE)-decl-list.txt $(DOC_MODULE)-decl.txt @if test "$(abs_srcdir)" != "$(abs_builddir)" ; then \ rm -f $(SETUP_FILES) $(DOC_MODULE).types; \ fi maintainer-clean-local: @rm -rf xml html install-data-local: @installfiles=`echo $(builddir)/html/*`; \ if test "$$installfiles" = '$(builddir)/html/*'; \ then echo 1>&2 'Nothing to install' ; \ else \ if test -n "$(DOC_MODULE_VERSION)"; then \ installdir="$(DESTDIR)$(TARGET_DIR)-$(DOC_MODULE_VERSION)"; \ else \ installdir="$(DESTDIR)$(TARGET_DIR)"; \ fi; \ $(mkinstalldirs) $${installdir} ; \ for i in $$installfiles; do \ echo ' $(INSTALL_DATA) '$$i ; \ $(INSTALL_DATA) $$i $${installdir}; \ done; \ if test -n "$(DOC_MODULE_VERSION)"; then \ mv -f $${installdir}/$(DOC_MODULE).devhelp2 \ $${installdir}/$(DOC_MODULE)-$(DOC_MODULE_VERSION).devhelp2; \ fi; \ $(GTKDOC_REBASE) --relative --dest-dir=$(DESTDIR) --html-dir=$${installdir}; \ fi uninstall-local: @if test -n "$(DOC_MODULE_VERSION)"; then \ installdir="$(DESTDIR)$(TARGET_DIR)-$(DOC_MODULE_VERSION)"; \ else \ installdir="$(DESTDIR)$(TARGET_DIR)"; \ fi; \ rm -rf $${installdir} # # Require gtk-doc when making dist # @HAVE_GTK_DOC_TRUE@dist-check-gtkdoc: docs @HAVE_GTK_DOC_FALSE@dist-check-gtkdoc: @HAVE_GTK_DOC_FALSE@ @echo "*** gtk-doc is needed to run 'make dist'. ***" @HAVE_GTK_DOC_FALSE@ @echo "*** gtk-doc was not found when 'configure' ran. ***" @HAVE_GTK_DOC_FALSE@ @echo "*** please install gtk-doc and rerun 'configure'. ***" @HAVE_GTK_DOC_FALSE@ @false dist-hook: dist-check-gtkdoc all-gtk-doc dist-hook-local @mkdir $(distdir)/html @cp ./html/* $(distdir)/html @-cp ./$(DOC_MODULE).pdf $(distdir)/ @-cp ./$(DOC_MODULE).types $(distdir)/ @-cp ./$(DOC_MODULE)-sections.txt $(distdir)/ @cd $(distdir) && rm -f $(DISTCLEANFILES) @$(GTKDOC_REBASE) --online --relative --html-dir=$(distdir)/html .PHONY : dist-hook-local docs # Comment this out if you want your docs-status tested during 'make check' #TESTS = $(GTKDOC_CHECK) # 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: libinfinity-0.7.1/docs/reference/libinfinoted-plugin-manager/PaxHeaders.26529/Makefile.am0000644000000000000000000000013212400102201026055 xustar0030 mtime=1409320065.091132986 30 atime=1409320065.091132986 30 ctime=1488261619.888070514 libinfinity-0.7.1/docs/reference/libinfinoted-plugin-manager/Makefile.am0000644000175000017500000000750612400102201026617 0ustar00arminarmin00000000000000## Process this file with automake to produce Makefile.in # We require automake 1.6 at least. AUTOMAKE_OPTIONS = 1.6 # This is a blank Makefile.am for using gtk-doc. # Copy this to your project's API docs directory and modify the variables to # suit your project. See the GTK+ Makefiles in gtk+/docs/reference for examples # of using the various options. # The name of the module, e.g. 'glib'. DOC_MODULE=libinfinoted-plugin-manager-$(LIBINFINITY_API_VERSION) # The top-level SGML file. You can change this if you want to. DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml # The directory containing the source code. Relative to $(srcdir). # gtk-doc will search all .c & .h files beneath here for inline comments # documenting the functions and macros. # e.g. DOC_SOURCE_DIR=../../../gtk DOC_SOURCE_DIR=$(top_srcdir)/infinoted # Extra options to pass to gtkdoc-scangobj. Not normally needed. SCANGOBJ_OPTIONS= # Extra options to supply to gtkdoc-scan. # e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED" SCAN_OPTIONS=--rebuild-types # Extra options to supply to gtkdoc-mkdb. # e.g. MKDB_OPTIONS=--sgml-mode --output-format=xml MKDB_OPTIONS=--sgml-mode --output-format=xml # Extra options to supply to gtkdoc-mktmpl # e.g. MKTMPL_OPTIONS=--only-section-tmpl MKTMPL_OPTIONS= # Extra options to supply to gtkdoc-fixref. Not normally needed. # e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html FIXXREF_OPTIONS = \ --extra-dir=../libinfinity/html # Used for dependencies. The docs will be rebuilt if any of these change. # e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h # e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c HFILE_GLOB = \ $(top_srcdir)/infinoted/infinoted-log.h \ $(top_srcdir)/infinoted/infinoted-parameter.h \ $(top_srcdir)/infinoted/infinoted-plugin-manager.h \ $(top_srcdir)/infinoted/infinoted-util.h CFILE_GLOB = \ $(top_srcdir)/infinoted/infinoted-log.c \ $(top_srcdir)/infinoted/infinoted-parameter.c \ $(top_srcdir)/infinoted/infinoted-plugin-manager.c \ $(top_srcdir)/infinoted/infinoted-util.c # Header files to ignore when scanning. # e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h IGNORE_HFILES = \ infinoted-config-reload.h \ infinoted-dh-params.h \ infinoted-options.h \ infinoted-pam.h \ infinoted-run.h \ infinoted-signal.h \ infinoted-startup.h \ infinoted-plugin-util-navigate-browser.h # Images to copy into HTML directory. # e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png HTML_IMAGES= # Extra SGML files that are included by $(DOC_MAIN_SGML_FILE). # e.g. content_files=running.sgml building.sgml changes-2.0.sgml content_files = \ ../version.xml # SGML files where gtk-doc abbrevations (#GtkWidget) are expanded # These files must be listed here *and* in content_files # e.g. expand_content_files=running.sgml expand_content_files= # CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library. # Only needed if you are using gtkdoc-scangobj to dynamically query widget # signals and properties. # e.g. INCLUDES=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS) # e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib) AM_CPPFLAGS=$(infinoted_CFLAGS) GTKDOC_LIBS = \ $(top_builddir)/infinoted/libinfinoted-plugin-manager-$(LIBINFINITY_API_VERSION).la \ $(top_builddir)/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la\ $(infinoted_LIBS) \ $(libdaemon_LIBS) # This includes the standard gtk-doc make rules, copied by gtkdocize. include $(top_srcdir)/gtk-doc.make # Other files to distribute # e.g. EXTRA_DIST += version.xml.in EXTRA_DIST += # Files not to distribute # for --rebuild-types in $(SCAN_OPTIONS), e.g. $(DOC_MODULE).types # for --rebuild-sections in $(SCAN_OPTIONS) e.g. $(DOC_MODULE)-sections.txt DISTCLEANFILES = libinfinoted-plugin-manager-$(LIBINFINITY_API_VERSION).types version.xml # Comment this out if you want your docs-status tested during 'make check' #TESTS = $(GTKDOC_CHECK) libinfinity-0.7.1/docs/reference/libinfinoted-plugin-manager/PaxHeaders.26529/libinfinoted-plugin-ma0000644000000000000000000000031213034342512030320 xustar00112 path=libinfinity-0.7.1/docs/reference/libinfinoted-plugin-manager/libinfinoted-plugin-manager-0.7-docs.sgml 30 mtime=1483851082.013718339 30 atime=1483851082.013718339 30 ctime=1488261619.892070505 libinfinity-0.7.1/docs/reference/libinfinoted-plugin-manager/libinfinoted-plugin-manager-0.7-docs.sg0000644000175000017500000000220213034342512033723 0ustar00arminarmin00000000000000 ]> libinfinoted-plugin-manager-&api_version; Reference Manual for libinfinoted-plugin-manager &version;. The latest version of this documentation can be found on-line at http://infinote.0x539.de/libinfinity/API/libinfinoted-plugin-manager/. libinfinoted-plugin-manager API reference libinfinity-0.7.1/docs/reference/libinfinoted-plugin-manager/PaxHeaders.26529/libinfinoted-plugin-ma0000644000000000000000000000031513055210765030332 xustar00115 path=libinfinity-0.7.1/docs/reference/libinfinoted-plugin-manager/libinfinoted-plugin-manager-0.7-sections.txt 30 mtime=1488261621.148067674 30 atime=1483851082.013718339 30 ctime=1488261621.148067674 libinfinity-0.7.1/docs/reference/libinfinoted-plugin-manager/libinfinoted-plugin-manager-0.7-section0000644000175000017500000000436613055210765034053 0ustar00arminarmin00000000000000
infinoted-log InfinotedLog InfinotedLog InfinotedLogClass infinoted_log_new infinoted_log_open infinoted_log_close infinoted_log_log infinoted_log_info infinoted_log_warning infinoted_log_error INFINOTED_IS_LOG INFINOTED_IS_LOG_CLASS INFINOTED_LOG INFINOTED_LOG_CLASS INFINOTED_LOG_GET_CLASS INFINOTED_TYPE_LOG infinoted_log_get_type
infinoted-parameter InfinotedParameterType InfinotedParameterFlags InfinotedParameterValue InfinotedParameterTypedValue InfinotedParameterConvertFunc InfinotedParameterInfo InfinotedParameterError infinoted_parameter_typed_value_new infinoted_parameter_typed_value_copy infinoted_parameter_typed_value_free infinoted_parameter_error_quark infinoted_parameter_load_from_key_file infinoted_parameter_convert_boolean infinoted_parameter_convert_filename infinoted_parameter_convert_nonnegative infinoted_parameter_convert_port infinoted_parameter_convert_positive infinoted_parameter_convert_security_policy infinoted_parameter_convert_string infinoted_parameter_convert_string_list infinoted_parameter_convert_flags infinoted_parameter_convert_ip_address INFINOTED_PARAMETER_TYPED_VALUE_TYPE infinoted_parameter_typed_value_get_type
infinoted-plugin-manager InfinotedPluginManager InfinotedPluginManager InfinotedPluginManagerClass InfinotedPlugin InfinotedPluginManagerError infinoted_plugin_manager_new infinoted_plugin_manager_load infinoted_plugin_manager_get_directory infinoted_plugin_manager_get_io infinoted_plugin_manager_get_log infinoted_plugin_manager_get_credentials infinoted_plugin_manager_get_connection_info infinoted_plugin_manager_get_session_info infinoted_plugin_manager_error_quark INFINOTED_IS_PLUGIN_MANAGER INFINOTED_IS_PLUGIN_MANAGER_CLASS INFINOTED_PLUGIN_MANAGER INFINOTED_PLUGIN_MANAGER_CLASS INFINOTED_PLUGIN_MANAGER_GET_CLASS INFINOTED_TYPE_PLUGIN_MANAGER infinoted_plugin_manager_get_type
infinoted-util infinoted_util_create_dirname infinoted_util_set_errno_error infinoted_util_daemon_set_global_pid_file_proc infinoted_util_daemon_set_local_pid_file_proc infinoted_util_daemon_pid_file_kill
libinfinity-0.7.1/docs/reference/libinfinoted-plugin-manager/PaxHeaders.26529/libinfinoted-plugin-ma0000644000000000000000000000031612401204471030322 xustar00116 path=libinfinity-0.7.1/docs/reference/libinfinoted-plugin-manager/libinfinoted-plugin-manager-0.7-overrides.txt 30 mtime=1409616185.958246005 30 atime=1409616185.958246005 30 ctime=1488261619.896070496 libinfinity-0.7.1/docs/reference/libinfinoted-plugin-manager/libinfinoted-plugin-manager-0.7-overrid0000644000175000017500000000000012401204471034025 0ustar00arminarmin00000000000000libinfinity-0.7.1/docs/reference/PaxHeaders.26529/libinftext0000644000000000000000000000013213055210756020570 xustar0030 mtime=1488261614.088083542 30 atime=1488261610.920090629 30 ctime=1488261614.088083542 libinfinity-0.7.1/docs/reference/libinftext/0000755000175000017500000000000013055210756021377 5ustar00arminarmin00000000000000libinfinity-0.7.1/docs/reference/libinftext/PaxHeaders.26529/libinftext-0.7-sections.txt0000644000000000000000000000013213055210756025705 xustar0030 mtime=1488261614.084083552 30 atime=1483851082.013718339 30 ctime=1488261614.084083552 libinfinity-0.7.1/docs/reference/libinftext/libinftext-0.7-sections.txt0000644000175000017500000001555413055210756026451 0ustar00arminarmin00000000000000
inf-text-default-delete-operation InfTextDefaultDeleteOperation InfTextDefaultDeleteOperation InfTextDefaultDeleteOperationClass inf_text_default_delete_operation_new inf_text_default_delete_operation_get_chunk INF_TEXT_DEFAULT_DELETE_OPERATION INF_TEXT_IS_DEFAULT_DELETE_OPERATION INF_TEXT_TYPE_DEFAULT_DELETE_OPERATION inf_text_default_delete_operation_get_type INF_TEXT_DEFAULT_DELETE_OPERATION_CLASS INF_TEXT_IS_DEFAULT_DELETE_OPERATION_CLASS INF_TEXT_DEFAULT_DELETE_OPERATION_GET_CLASS
inf-text-insert-operation InfTextInsertOperation InfTextInsertOperationInterface inf_text_insert_operation_get_position inf_text_insert_operation_get_length inf_text_insert_operation_need_concurrency_id inf_text_insert_operation_transform_insert inf_text_insert_operation_transform_delete INF_TEXT_INSERT_OPERATION INF_TEXT_IS_INSERT_OPERATION INF_TEXT_TYPE_INSERT_OPERATION inf_text_insert_operation_get_type INF_TEXT_INSERT_OPERATION_GET_IFACE
inf-text-remote-delete-operation InfTextRemoteDeleteOperation InfTextRemoteDeleteOperation InfTextRemoteDeleteOperationClass inf_text_remote_delete_operation_new INF_TEXT_REMOTE_DELETE_OPERATION INF_TEXT_IS_REMOTE_DELETE_OPERATION INF_TEXT_TYPE_REMOTE_DELETE_OPERATION inf_text_remote_delete_operation_get_type INF_TEXT_REMOTE_DELETE_OPERATION_CLASS INF_TEXT_IS_REMOTE_DELETE_OPERATION_CLASS INF_TEXT_REMOTE_DELETE_OPERATION_GET_CLASS
inf-text-session InfTextSessionError InfTextOperationError InfTextSession InfTextSession InfTextSessionClass inf_text_session_new inf_text_session_new_with_user_table inf_text_session_set_user_color inf_text_session_flush_requests_for_user inf_text_session_join_user INF_TEXT_SESSION INF_TEXT_IS_SESSION INF_TEXT_TYPE_SESSION inf_text_session_get_type INF_TEXT_SESSION_CLASS INF_TEXT_IS_SESSION_CLASS INF_TEXT_SESSION_GET_CLASS
inf-text-undo-grouping InfTextUndoGrouping InfTextUndoGrouping InfTextUndoGroupingClass inf_text_undo_grouping_new INF_TEXT_UNDO_GROUPING INF_TEXT_IS_UNDO_GROUPING INF_TEXT_TYPE_UNDO_GROUPING inf_text_undo_grouping_get_type INF_TEXT_UNDO_GROUPING_CLASS INF_TEXT_IS_UNDO_GROUPING_CLASS INF_TEXT_UNDO_GROUPING_GET_CLASS
inf-text-user InfTextUser InfTextUser InfTextUserClass inf_text_user_new inf_text_user_get_caret_position inf_text_user_get_selection_length inf_text_user_set_selection inf_text_user_get_hue INF_TEXT_USER INF_TEXT_IS_USER INF_TEXT_TYPE_USER inf_text_user_get_type INF_TEXT_USER_CLASS INF_TEXT_IS_USER_CLASS INF_TEXT_USER_GET_CLASS
inf-text-default-insert-operation InfTextDefaultInsertOperation InfTextDefaultInsertOperation InfTextDefaultInsertOperationClass inf_text_default_insert_operation_new inf_text_default_insert_operation_get_chunk INF_TEXT_DEFAULT_INSERT_OPERATION INF_TEXT_IS_DEFAULT_INSERT_OPERATION INF_TEXT_TYPE_DEFAULT_INSERT_OPERATION inf_text_default_insert_operation_get_type INF_TEXT_DEFAULT_INSERT_OPERATION_CLASS INF_TEXT_IS_DEFAULT_INSERT_OPERATION_CLASS INF_TEXT_DEFAULT_INSERT_OPERATION_GET_CLASS
inf-text-delete-operation InfTextDeleteOperation InfTextDeleteOperationInterface inf_text_delete_operation_get_position inf_text_delete_operation_get_length inf_text_delete_operation_need_concurrency_id inf_text_delete_operation_transform_insert inf_text_delete_operation_transform_delete INF_TEXT_DELETE_OPERATION INF_TEXT_IS_DELETE_OPERATION INF_TEXT_TYPE_DELETE_OPERATION inf_text_delete_operation_get_type INF_TEXT_DELETE_OPERATION_GET_IFACE
inf-text-buffer InfTextBuffer InfTextBufferInterface InfTextBufferIter inf_text_buffer_get_encoding inf_text_buffer_get_length inf_text_buffer_get_slice inf_text_buffer_insert_text inf_text_buffer_insert_chunk inf_text_buffer_erase_text inf_text_buffer_create_begin_iter inf_text_buffer_create_end_iter inf_text_buffer_destroy_iter inf_text_buffer_iter_next inf_text_buffer_iter_prev inf_text_buffer_iter_get_text inf_text_buffer_iter_get_offset inf_text_buffer_iter_get_length inf_text_buffer_iter_get_bytes inf_text_buffer_iter_get_author inf_text_buffer_text_inserted inf_text_buffer_text_erased INF_TEXT_BUFFER INF_TEXT_IS_BUFFER INF_TEXT_TYPE_BUFFER inf_text_buffer_get_type INF_TEXT_BUFFER_GET_IFACE
inf-text-default-buffer InfTextDefaultBuffer InfTextDefaultBuffer InfTextDefaultBufferClass inf_text_default_buffer_new INF_TEXT_DEFAULT_BUFFER INF_TEXT_IS_DEFAULT_BUFFER INF_TEXT_TYPE_DEFAULT_BUFFER inf_text_default_buffer_get_type INF_TEXT_DEFAULT_BUFFER_CLASS INF_TEXT_IS_DEFAULT_BUFFER_CLASS INF_TEXT_DEFAULT_BUFFER_GET_CLASS
inf-text-fixline-buffer InfTextFixlineBuffer InfTextFixlineBuffer InfTextFixlineBufferClass inf_text_fixline_buffer_new INF_TEXT_FIXLINE_BUFFER INF_TEXT_IS_FIXLINE_BUFFER INF_TEXT_TYPE_FIXLINE_BUFFER inf_text_fixline_buffer_get_type INF_TEXT_FIXLINE_BUFFER_CLASS INF_TEXT_IS_FIXLINE_BUFFER_CLASS INF_TEXT_FIXLINE_BUFFER_GET_CLASS
inf-text-move-operation InfTextMoveOperation InfTextMoveOperation InfTextMoveOperationClass inf_text_move_operation_new inf_text_move_operation_get_position inf_text_move_operation_get_length inf_text_move_operation_transform_insert inf_text_move_operation_transform_delete INF_TEXT_MOVE_OPERATION INF_TEXT_IS_MOVE_OPERATION INF_TEXT_TYPE_MOVE_OPERATION inf_text_move_operation_get_type INF_TEXT_MOVE_OPERATION_CLASS INF_TEXT_IS_MOVE_OPERATION_CLASS INF_TEXT_MOVE_OPERATION_GET_CLASS
inf-text-chunk InfTextChunk InfTextChunkIter inf_text_chunk_iter_copy inf_text_chunk_iter_free inf_text_chunk_new inf_text_chunk_copy inf_text_chunk_free inf_text_chunk_get_encoding inf_text_chunk_get_length inf_text_chunk_substring inf_text_chunk_insert_text inf_text_chunk_insert_chunk inf_text_chunk_erase inf_text_chunk_get_text inf_text_chunk_equal inf_text_chunk_iter_init_begin inf_text_chunk_iter_init_end inf_text_chunk_iter_next inf_text_chunk_iter_prev inf_text_chunk_iter_get_text inf_text_chunk_iter_get_offset inf_text_chunk_iter_get_length inf_text_chunk_iter_get_bytes inf_text_chunk_iter_get_author INF_TEXT_TYPE_CHUNK_ITER INF_TEXT_TYPE_CHUNK inf_text_chunk_iter_get_type inf_text_chunk_get_type
inf-text-filesystem-format InfTextFilesystemFormat InfTextFilesystemFormatError inf_text_filesystem_format_read inf_text_filesystem_format_write
libinfinity-0.7.1/docs/reference/libinftext/PaxHeaders.26529/html0000644000000000000000000000013213055210756021534 xustar0030 mtime=1488261614.120083471 30 atime=1488261614.076083569 30 ctime=1488261614.120083471 libinfinity-0.7.1/docs/reference/libinftext/html/0000755000175000017500000000000013055210756022343 5ustar00arminarmin00000000000000libinfinity-0.7.1/docs/reference/libinftext/html/PaxHeaders.26529/left-insensitive.png0000644000000000000000000000012713055210756025613 xustar0029 mtime=1488261614.08008356 29 atime=1488261614.08008356 29 ctime=1488261614.08008356 libinfinity-0.7.1/docs/reference/libinftext/html/left-insensitive.png0000644000175000017500000000061313055210756026341 0ustar00arminarmin00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEà 4ÓkMIDAT8ËÍ’­NQ…¿éö†…@¡p üdsÛÀÖ`*š4Á@ò„W@ A!ÈÔ†@6Ü^ƒ 5hxèIH R`sQpäÌ™339þBÊó|Ês¤ªKEQTÛíöK°@·ÛÎià¦^¯Ï~îWʆ½÷‹ÀÕûðå`0˜åTJ6·Tõ˜‘cYn6›AÞû Æ€½~¿ß±Ö>}Ç­Žœs;ªº ¨ˆlYkwËÞürˆ¼†ºó£ Þû5U= °/"›ÖÚç  ¬µ‡"ÒuU=ɲlü×ArÎÕDä˜zÃáp5I’ûà4^E+ÀP3Æœçàq_«êp Ì¥iñ¯ðUY¥‚p=#IEND®B`‚libinfinity-0.7.1/docs/reference/libinftext/html/PaxHeaders.26529/InfTextUndoGrouping.html0000644000000000000000000000012713055210756026425 xustar0029 mtime=1488261614.11608348 29 atime=1488261614.11608348 29 ctime=1488261614.11608348 libinfinity-0.7.1/docs/reference/libinftext/html/InfTextUndoGrouping.html0000644000175000017500000001624113055210756027157 0ustar00arminarmin00000000000000 InfTextUndoGrouping: libinftext-0.7 Reference Manual

InfTextUndoGrouping

InfTextUndoGrouping — Undo grouping for text operations

Types and Values

Object Hierarchy

    GObject
    ╰── InfAdoptedUndoGrouping
        ╰── InfTextUndoGrouping

Includes

#include <libinftext/inf-text-undo-grouping.h>

Description

InfTextUndoGrouping handles undo grouping for text operations. It makes sure many insert or delete operations occuring in a row can be undone simultaneousely, taking into account that other users might have issued requests inbetween.

Using this class you don't need to connect to “group-requests†to perform the grouping.

Functions

inf_text_undo_grouping_new ()

InfTextUndoGrouping *
inf_text_undo_grouping_new (void);

Creates a new InfTextUndoGrouping.

[constructor]

Returns

A new InfTextUndoGrouping. To be freed with g_object_unref().

[transfer full]

Types and Values

struct InfTextUndoGrouping

struct InfTextUndoGrouping;

InfTextUndoGrouping is an opaque data type. You should only access it via the public API functions.


struct InfTextUndoGroupingClass

struct InfTextUndoGroupingClass {
};

libinfinity-0.7.1/docs/reference/libinftext/html/PaxHeaders.26529/InfTextUser.html0000644000000000000000000000012713055210756024723 xustar0029 mtime=1488261614.11608348 29 atime=1488261614.11608348 29 ctime=1488261614.11608348 libinfinity-0.7.1/docs/reference/libinftext/html/InfTextUser.html0000644000175000017500000005442213055210756025460 0ustar00arminarmin00000000000000 InfTextUser: libinftext-0.7 Reference Manual

InfTextUser

InfTextUser

Properties

guint caret-position Read / Write / Construct
gdouble hue Read / Write / Construct
gint selection-length Read / Write / Construct

Types and Values

Object Hierarchy

    GObject
    ╰── InfUser
        ╰── InfAdoptedUser
            ╰── InfTextUser

Description

Functions

inf_text_user_new ()

InfTextUser *
inf_text_user_new (guint id,
                   const gchar *name,
                   InfAdoptedStateVector *vector,
                   double hue);

Creates a new InfTextUser. id should be unique for all users working together. InfUserTable will refuse to add users with duplicate id. If vector is NULL, then the vector with all components zero is used.

[constructor]

Parameters

id

The user ID for this user.

 

name

The user's name.

 

vector

The state at which the user is at, or NULL.

[allow-none]

hue

The hue value of the user's color.

 

Returns

A new InfTextUser. Free with g_object_unref() when no longer needed.

[transfer full]


inf_text_user_get_caret_position ()

guint
inf_text_user_get_caret_position (InfTextUser *user);

Returns the position of user 's caret.

Parameters

user

A InfTextUser.

 

Returns

user 's caret position.


inf_text_user_get_selection_length ()

gint
inf_text_user_get_selection_length (InfTextUser *user);

Returns the number of characters this user has selected, starting from the caret position. Negative number mean selection towards the beginning of the buffer.

Parameters

user

A InfTextUser.

 

Returns

user 's selection length in characters.


inf_text_user_set_selection ()

void
inf_text_user_set_selection (InfTextUser *user,
                             guint position,
                             gint length,
                             gboolean by_request);

Changes user 's selection (i.e. caret position and selection length). The by_request parameter should be set to TRUE if the selection change was requested explicitly, for example by the user actively moving the cursor using the mouse or the keyboard. If the cursor position changes only because another user inserted text at a position before the user's cursor and this results in a change of the selection position, the by_request parameter should be set to FALSE.

Parameters

user

A InfTextUser.

 

position

The new position for the user's caret.

 

length

The number of characters to select. Negative numbers mean selection towards the beginning.

 

by_request

TRUE if explicitly requested or FALSE when just an effect of another operation.

 

inf_text_user_get_hue ()

gdouble
inf_text_user_get_hue (InfTextUser *user);

Returns the hue of the user's color as a double ranging from 0 to 1. The other components (saturation and lightness) are not specific to the user and may be chosen indivudually to optimize the actual visual display.

Parameters

user

A InfTextUser.

 

Returns

The hue of the user 's color.

Types and Values

struct InfTextUser

struct InfTextUser;


struct InfTextUserClass

struct InfTextUserClass {
  InfAdoptedUserClass parent_class;

  void(*selection_changed)(InfTextUser* user,
                           guint position,
                           guint length,
                           gboolean by_request);
};

Property Details

The “caret-position†property

  “caret-position†          guint

The position of this user's caret.

Flags: Read / Write / Construct

Default value: 0


The “hue†property

  “hue†                     gdouble

The hue value of the user's color. saturation and lightness are set by each client individually.

Flags: Read / Write / Construct

Allowed values: [0,1]

Default value: 0


The “selection-length†property

  “selection-length†        gint

The number of characters of this user's selection.

Flags: Read / Write / Construct

Default value: 0

Signal Details

The “selection-changed†signal

void
user_function (InfTextUser *inftextuser,
               guint        arg1,
               gint         arg2,
               gboolean     arg3,
               gpointer     user_data)

Parameters

inftextuser

the object which received the signal.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last

libinfinity-0.7.1/docs/reference/libinftext/html/PaxHeaders.26529/InfTextMoveOperation.html0000644000000000000000000000012713055210756026574 xustar0029 mtime=1488261614.11608348 29 atime=1488261614.11608348 29 ctime=1488261614.11608348 libinfinity-0.7.1/docs/reference/libinftext/html/InfTextMoveOperation.html0000644000175000017500000005060513055210756027330 0ustar00arminarmin00000000000000 InfTextMoveOperation: libinftext-0.7 Reference Manual

InfTextMoveOperation

InfTextMoveOperation

Properties

gint length Read / Write / Construct Only
guint position Read / Write / Construct Only

Types and Values

Object Hierarchy

    GObject
    ╰── InfTextMoveOperation

Implemented Interfaces

InfTextMoveOperation implements InfAdoptedOperation.

Description

Functions

inf_text_move_operation_new ()

InfTextMoveOperation *
inf_text_move_operation_new (guint position,
                             gint length);

Creates a new move operation that, when applied, changes the caret and selection of the applying user.

[constructor]

Parameters

position

The position to place the user's caret at.

 

length

The number of characters to select. Negative means selection towards the beginning of the buffer.

 

Returns

A new InfTextMoveOperation.

[transfer full]


inf_text_move_operation_get_position ()

guint
inf_text_move_operation_get_position (InfTextMoveOperation *operation);

Returns the position at which operation places the user's cursor.

Parameters

operation

A InfTextMoveOperation.

 

Returns

The position of operation .


inf_text_move_operation_get_length ()

gint
inf_text_move_operation_get_length (InfTextMoveOperation *operation);

Returns the length to which operation changes the user's selection. Negative means selection towards the beginning of the buffer.

Parameters

operation

A InfTextMoveOperation.

 

Returns

The length of operation .


inf_text_move_operation_transform_insert ()

void
inf_text_move_operation_transform_insert
                               (guint insert_position,
                                guint insert_length,
                                guint *move_position,
                                gint *move_length,
                                gboolean left_gravity);

Changes *move_position and *move_length so that they point to the same region when insert_length characters are inserted at insert_position .

If text is inserted at the same position as move_position , then move_position is kept at the position it currently is if left_gravity is TRUE, otherwise it is shifted to the right.

If *move_length is nonzero, then the selection length is never enlarged if text is inserted at the selection bounds, not depending on whether left_gravity is set or not.

Parameters

insert_position

The position at which text is inserted.

 

insert_length

The number of inserted characters.

 

move_position

Points to the character offset to which the caret is moved.

[inout]

move_length

Points to the number of characters selected. Negative means towards the beginning.

[inout]

left_gravity

Whether the move position and length have left gravity.

 

inf_text_move_operation_transform_delete ()

void
inf_text_move_operation_transform_delete
                               (guint delete_position,
                                guint delete_length,
                                guint *move_position,
                                gint *move_length);

Changes *move_position and *move_length so that they point to the same region when delete_length characters are deleted starting from delete_position .

Parameters

delete_position

The position at which text is deleted.

 

delete_length

The number of deleted characters.

 

move_position

Points to the character offset to which the caret is moved.

[inout]

move_length

Points to the number of characters selected. Negative means towards the beginning.

[inout]

Types and Values

struct InfTextMoveOperation

struct InfTextMoveOperation;


struct InfTextMoveOperationClass

struct InfTextMoveOperationClass {
  GObjectClass parent_class;
};

Property Details

The “length†property

  “length†                  gint

The number of characters of the selected text.

Flags: Read / Write / Construct Only

Default value: 0


The “position†property

  “position†                guint

Position where to place the user's caret at.

Flags: Read / Write / Construct Only

Default value: 0

libinfinity-0.7.1/docs/reference/libinftext/html/PaxHeaders.26529/InfTextRemoteDeleteOperation.html0000644000000000000000000000012713055210756030244 xustar0029 mtime=1488261614.11608348 29 atime=1488261614.11608348 29 ctime=1488261614.11608348 libinfinity-0.7.1/docs/reference/libinftext/html/InfTextRemoteDeleteOperation.html0000644000175000017500000002507013055210756030776 0ustar00arminarmin00000000000000 InfTextRemoteDeleteOperation: libinftext-0.7 Reference Manual

InfTextRemoteDeleteOperation

InfTextRemoteDeleteOperation

Properties

guint length Read / Write / Construct Only
guint position Read / Write / Construct Only

Object Hierarchy

    GObject
    ╰── InfTextRemoteDeleteOperation

Implemented Interfaces

InfTextRemoteDeleteOperation implements InfAdoptedOperation and InfTextDeleteOperation.

Description

Functions

inf_text_remote_delete_operation_new ()

InfTextRemoteDeleteOperation *
inf_text_remote_delete_operation_new (guint position,
                                      guint length);

Creates a new delete operation that, when applied, deletes length characters starting from position position . Note that this operation is not reversible because it does not know the text to delete and is therefore only used to transmit a delete operation through the network to reduce bandwidth usage. The remote part can then reconstruct the deleted text using inf_adopted_operation_apply_transformed().

However, it is easier to just use InfTextDefaultDeleteOperation if you want the operation to be reversible.

[constructor]

Parameters

position

The position at which to delete text.

 

length

The number of characters to delete.

 

Returns

A new InfTextRemoteDeleteOperation.

[transfer full]

Types and Values

struct InfTextRemoteDeleteOperation

struct InfTextRemoteDeleteOperation;


struct InfTextRemoteDeleteOperationClass

struct InfTextRemoteDeleteOperationClass {
  GObjectClass parent_class;
};

Property Details

The “length†property

  “length†                  guint

The length of the deleted text.

Flags: Read / Write / Construct Only

Default value: 0


The “position†property

  “position†                guint

Position where to start deleting characters.

Flags: Read / Write / Construct Only

Default value: 0

libinfinity-0.7.1/docs/reference/libinftext/html/PaxHeaders.26529/libinftext-0.7-inf-text-insert-ope0000644000000000000000000000012713055210756030031 xustar0029 mtime=1488261614.11608348 29 atime=1488261614.11608348 29 ctime=1488261614.11608348 libinfinity-0.7.1/docs/reference/libinftext/html/libinftext-0.7-inf-text-insert-operation.html0000644000175000017500000004676213055210756032756 0ustar00arminarmin00000000000000 inf-text-insert-operation: libinftext-0.7 Reference Manual

inf-text-insert-operation

inf-text-insert-operation

Object Hierarchy

    GInterface
    ╰── InfTextInsertOperation

Prerequisites

InfTextInsertOperation requires InfAdoptedOperation and GObject.

Known Implementations

InfTextInsertOperation is implemented by InfTextDefaultInsertOperation.

Description

Functions

inf_text_insert_operation_get_position ()

guint
inf_text_insert_operation_get_position
                               (InfTextInsertOperation *operation);

Returns the position at which operation inserts text.

Parameters

operation

A InfTextInsertOperation.

 

Returns

The position to insert text.


inf_text_insert_operation_get_length ()

guint
inf_text_insert_operation_get_length (InfTextInsertOperation *operation);

Returns the length of the text inserted by operation .

Parameters

operation

A InfTextInsertOperation.

 

Returns

The length of operation .


inf_text_insert_operation_need_concurrency_id ()

gboolean
inf_text_insert_operation_need_concurrency_id
                               (InfTextInsertOperation *op,
                                InfAdoptedOperation *against);

Returns whether transforming op against against requires a concurrency ID (see inf_adopted_operation_need_concurrency_id() for further information).

Parameters

op

A InfTextInsertOperation.

 

against

Another InfAdoptedOperation.

 

Returns

Whether transforming op against against requires a concurrency ID.


inf_text_insert_operation_transform_insert ()

InfAdoptedOperation *
inf_text_insert_operation_transform_insert
                               (InfTextInsertOperation *operation,
                                InfTextInsertOperation *against,
                                InfTextInsertOperation *op_lcs,
                                InfTextInsertOperation *ag_lcs,
                                InfAdoptedConcurrencyId cid);

Returns a new operation that includes the effect of against into operation .

Parameters

operation

A InfTextInsertOperation.

 

against

Another InfTextInsertOperation.

 

op_lcs

The given operation in a previous state, or NULL.

 

ag_lcs

The against operation in a previous state, or NULL.

 

cid

The concurrency ID for the transformation.

 

Returns

A new InfAdoptedOperation.

[transfer full]


inf_text_insert_operation_transform_delete ()

InfAdoptedOperation *
inf_text_insert_operation_transform_delete
                               (InfTextInsertOperation *operation,
                                InfTextDeleteOperation *against);

Returns a new operation that includes the effect of against into operation .

Parameters

operation

A InfTextInsertOperation.

 

against

A InfTextDeleteOperation.

 

Returns

A new InfAdoptedOperation.

[transfer full]

Types and Values

InfTextInsertOperation

typedef struct _InfTextInsertOperation InfTextInsertOperation;

InfTextInsertOperation is an opaque data type. You should only access it via the public API functions.


struct InfTextInsertOperationInterface

struct InfTextInsertOperationInterface {
  GTypeInterface parent;

  /* Virtual table */
  guint(*get_position)(InfTextInsertOperation* operation);

  guint(*get_length)(InfTextInsertOperation* operation);

  InfTextInsertOperation*(*transform_position)(InfTextInsertOperation* op,
                                               guint position);
};

libinfinity-0.7.1/docs/reference/libinftext/html/PaxHeaders.26529/annotation-glossary.html0000644000000000000000000000012713055210756026516 xustar0029 mtime=1488261614.11608348 29 atime=1488261614.11608348 29 ctime=1488261614.11608348 libinfinity-0.7.1/docs/reference/libinftext/html/annotation-glossary.html0000644000175000017500000001225013055210756027244 0ustar00arminarmin00000000000000 Annotation Glossary: libinftext-0.7 Reference Manual

Annotation Glossary

A

allow-none

NULL is OK, both for passing and for returning.

array

Parameter points to an array of items.

C

constructor

This symbol is a constructor, not a static method.

I

inout

Parameter for input and for returning results. Default is transfer full.

O

out

Parameter for returning results. Default is transfer full.

S

scope async

The callback is valid until first called.

T

transfer full

Free data after the code is done.

transfer none

Don't free data after the code is done.

type

Override the parsed C type with given type.

U

Unstable

Unstable interfaces are experimental or transitional. They are typically used to give outside developers early access to new or rapidly changing technology, or to provide an interim solution to a problem where a more general solution is anticipated. No claims are made about either source or binary compatibility from one minor release to the next. The Unstable interface level is a warning that these interfaces are subject to change without warning and should not be used in unbundled products. Given such caveats, customer impact need not be a factor when considering incompatible changes to an Unstable interface in a major or minor release. Nonetheless, when such changes are introduced, the changes should still be mentioned in the release notes for the affected release.

libinfinity-0.7.1/docs/reference/libinftext/html/PaxHeaders.26529/up-insensitive.png0000644000000000000000000000012713055210756025305 xustar0029 mtime=1488261614.08008356 29 atime=1488261614.08008356 29 ctime=1488261614.08008356 libinfinity-0.7.1/docs/reference/libinftext/html/up-insensitive.png0000644000175000017500000000056613055210756026042 0ustar00arminarmin00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEà 4ÓkMIDAT8Ëí’?/QÅÏ™?[êu$¾€V³î›ÑâHTD³ø”ÛˆBM+¡!™ÂÌ<ˆDã+èô[mdÞ\…·bø{º{sÎ/97˜ªSÖÚ£º®»<ìTõ8ŒcÌÉ¿UU­‘¼‡•WÕÍ,Ë®ÿ”e¹EÑ €žªîÉSïmÛ®æy~û+À9·è½¿0`hŒ9u†ªº`Çñr¿ßùpÎÍ{ïÌ8‘m’ ªJkí€-o$—Dä¢  išË¾'¹; ‡ Jr‡äCð\¨*¿HΑ|JÓtCDÆßo#"ã$IÖ<«êBQ½é£êêÉ]•TKúIEND®B`‚libinfinity-0.7.1/docs/reference/libinftext/html/PaxHeaders.26529/InfTextDefaultBuffer.html0000644000000000000000000000012713055210756026523 xustar0029 mtime=1488261614.11608348 29 atime=1488261614.11608348 29 ctime=1488261614.11608348 libinfinity-0.7.1/docs/reference/libinftext/html/InfTextDefaultBuffer.html0000644000175000017500000002032213055210756027250 0ustar00arminarmin00000000000000 InfTextDefaultBuffer: libinftext-0.7 Reference Manual

InfTextDefaultBuffer

InfTextDefaultBuffer

Properties

gchar * encoding Read / Write / Construct Only

Types and Values

Object Hierarchy

    GObject
    ╰── InfTextDefaultBuffer

Implemented Interfaces

InfTextDefaultBuffer implements InfBuffer and InfTextBuffer.

Description

Functions

inf_text_default_buffer_new ()

InfTextDefaultBuffer *
inf_text_default_buffer_new (const gchar *encoding);

Creates a new, empty InfTextDefaultBuffer.

[constructor]

Parameters

encoding

The character encoding to use for the buffer.

 

Returns

A InfTextDefaultBuffer.

[transfer full]

Types and Values

struct InfTextDefaultBuffer

struct InfTextDefaultBuffer;


struct InfTextDefaultBufferClass

struct InfTextDefaultBufferClass {
  GObjectClass parent_class;
};

Property Details

The “encoding†property

  “encoding†                gchar *

The character encoding of the text buffer.

Flags: Read / Write / Construct Only

Default value: NULL

libinfinity-0.7.1/docs/reference/libinftext/html/PaxHeaders.26529/InfTextDefaultDeleteOperation.html0000644000000000000000000000012713055210756030375 xustar0029 mtime=1488261614.11608348 29 atime=1488261614.11608348 29 ctime=1488261614.11608348 libinfinity-0.7.1/docs/reference/libinftext/html/InfTextDefaultDeleteOperation.html0000644000175000017500000003032113055210756031122 0ustar00arminarmin00000000000000 InfTextDefaultDeleteOperation: libinftext-0.7 Reference Manual

InfTextDefaultDeleteOperation

InfTextDefaultDeleteOperation

Properties

InfTextChunk * chunk Read / Write / Construct Only
guint position Read / Write / Construct Only

Object Hierarchy

    GObject
    ╰── InfTextDefaultDeleteOperation

Implemented Interfaces

InfTextDefaultDeleteOperation implements InfAdoptedOperation and InfTextDeleteOperation.

Description

Functions

inf_text_default_delete_operation_new ()

InfTextDefaultDeleteOperation *
inf_text_default_delete_operation_new (guint position,
                                       InfTextChunk *chunk);

Creates a new delete operation that, when applied, deletes the text chunk that starts at character offset position in the buffer. The operation cannot be applied, if there is some other text at that position in the buffer.

[constructor]

Parameters

position

The position at which to delete text.

 

chunk

The text to delete.

 

Returns

A new InfTextDefaultDeleteOperation.

[transfer full]


inf_text_default_delete_operation_get_chunk ()

InfTextChunk *
inf_text_default_delete_operation_get_chunk
                               (InfTextDefaultDeleteOperation *operation);

Returns the text deleted by operation .

Parameters

operation

A InfTextDefaultDeleteOperation.

 

Returns

A InfTextChunk, owned by the operation.

[transfer none]

Types and Values

struct InfTextDefaultDeleteOperation

struct InfTextDefaultDeleteOperation;


struct InfTextDefaultDeleteOperationClass

struct InfTextDefaultDeleteOperationClass {
  GObjectClass parent_class;
};

Property Details

The “chunk†property

  “chunk†                   InfTextChunk *

The deleted text.

Flags: Read / Write / Construct Only


The “position†property

  “position†                guint

Position where to start deleting characters.

Flags: Read / Write / Construct Only

Default value: 0

libinfinity-0.7.1/docs/reference/libinftext/html/PaxHeaders.26529/index.html0000644000000000000000000000012713055210756023612 xustar0029 mtime=1488261614.11608348 29 atime=1488261614.11608348 29 ctime=1488261614.11608348 libinfinity-0.7.1/docs/reference/libinftext/html/index.html0000644000175000017500000000746513055210756024354 0ustar00arminarmin00000000000000 libinftext-0.7 Reference Manual: libinftext-0.7 Reference Manual

for libinftext 0.7.0. The latest version of this documentation can be found on-line at http://infinote.0x539.de/libinfinity/API/libinftext/.


libinftext API reference
InfTextSession
InfTextBuffer — Interface for the text storage of an InfTextSession
InfTextUser
InfTextChunk — A chunk of text written by various authors
InfTextDefaultBuffer
InfTextFixlineBuffer — Keep a fixed number of trailing lines
InfTextUndoGrouping — Undo grouping for text operations
inf-text-insert-operation
InfTextDeleteOperation — Interface for an operation erasing text
InfTextDefaultDeleteOperation
InfTextDefaultInsertOperation
InfTextRemoteDeleteOperation
InfTextMoveOperation
Storage of text sessions on the file system — Utility functions to deal with storing InfTextSessions in filesystem storage
Annotation Glossary
libinfinity-0.7.1/docs/reference/libinftext/html/PaxHeaders.26529/libinftext-0.7-InfTextFilesystemFo0000644000000000000000000000013213055210756030117 xustar0030 mtime=1488261614.120083471 30 atime=1488261614.120083471 30 ctime=1488261614.120083471 libinfinity-0.7.1/docs/reference/libinftext/html/libinftext-0.7-InfTextFilesystemFormat.html0000644000175000017500000004077713055210756032517 0ustar00arminarmin00000000000000 Storage of text sessions on the file system: libinftext-0.7 Reference Manual

Storage of text sessions on the file system

Storage of text sessions on the file system — Utility functions to deal with storing InfTextSessions in filesystem storage

Stability Level

Unstable, unless otherwise indicated

Types and Values

Includes

#include <libinftext/inf-text-filesystem-storage.h>

Description

The functions in this section are utility functions that can be used when implementing a InfdNotePlugin to handle InfTextSessions. These functions implement reading and writing the content of an InfTextSession to an XML file in the storage.

Functions

inf_text_filesystem_format_read ()

gboolean
inf_text_filesystem_format_read (InfdFilesystemStorage *storage,
                                 const gchar *path,
                                 InfUserTable *user_table,
                                 InfTextBuffer *buffer,
                                 GError **error);

Reads a text session from path in storage . The file is expected to have been saved with inf_text_filesystem_format_write() before. The user_table parameter should be an empty user table that will be used for the session, and the buffer parameter should be an empty InfTextBuffer, and the document will be written into this buffer. If the function succeeds, the user table and buffer can be used to create an InfTextSession with inf_text_session_new_with_user_table(). If the function fails, FALSE is returned and error is set.

Parameters

storage

A InfdFilesystemStorage.

 

path

Storage path to retrieve the session from.

 

user_table

An empty InfUserTable to use as the new session's user table.

 

buffer

An empty InfTextBuffer to use as the new session's buffer.

 

error

Location to store error information, if any, or NULL.

 

Returns

TRUE on success or FALSE on error.


inf_text_filesystem_format_write ()

gboolean
inf_text_filesystem_format_write (InfdFilesystemStorage *storage,
                                  const gchar *path,
                                  InfUserTable *user_table,
                                  InfTextBuffer *buffer,
                                  GError **error);

Writes the given user table and buffer into the filesystem storage at path . If successful, the session can then be read back with inf_text_filesystem_format_read(). If the function fails, FALSE is returned and error is set.

Parameters

storage

A InfdFilesystemStorage.

 

path

Storage path where to write the session to.

 

user_table

The InfUserTable to write.

 

buffer

The InfTextBuffer to write.

 

error

Location to store error information, if any, or NULL.

 

Returns

TRUE on success or FALSE on error.

Types and Values

enum InfTextFilesystemFormatError

Errors that can occur when reading a InfTextSession from a InfdFilesystemStorage.

Members

INF_TEXT_FILESYSTEM_FORMAT_ERROR_NOT_A_TEXT_SESSION

The file to be read is not a serialized text session.

 

INF_TEXT_FILESYSTEM_FORMAT_ERROR_USER_EXISTS

The user table of the session contains users with duplicate ID or duplicate name.

 

INF_TEXT_FILESYSTEM_FORMAT_ERROR_NO_SUCH_USER

A segment of the text document is written by a user which does not exist.

 
libinfinity-0.7.1/docs/reference/libinftext/html/PaxHeaders.26529/libinftext-0.7-inf-text-session.ht0000644000000000000000000000013213055210756030035 xustar0030 mtime=1488261614.120083471 30 atime=1488261614.120083471 30 ctime=1488261614.120083471 libinfinity-0.7.1/docs/reference/libinftext/html/libinftext-0.7-inf-text-session.html0000644000175000017500000010145113055210756031122 0ustar00arminarmin00000000000000 InfTextSession: libinftext-0.7 Reference Manual

InfTextSession

InfTextSession

Properties

guint caret-update-interval Read / Write / Construct

Object Hierarchy

    GObject
    ╰── InfSession
        ╰── InfAdoptedSession
            ╰── InfTextSession

Implemented Interfaces

InfTextSession implements InfCommunicationObject.

Description

Functions

inf_text_session_new ()

InfTextSession *
inf_text_session_new (InfCommunicationManager *manager,
                      InfTextBuffer *buffer,
                      InfIo *io,
                      InfSessionStatus status,
                      InfCommunicationGroup *sync_group,
                      InfXmlConnection *sync_connection);

Creates a new InfTextSession. The communication manager is used to send and receive requests from subscription and synchronization. buffer will be set to be initially empty if the session is initially synchronized (see below). io is required to trigger timeouts.

If status is INF_SESSION_PRESYNC or INF_SESSION_SYNCHRONIZING, then the session will initially be sychronized, meaning the initial content is retrieved from sync_connection . If you are subscribed to the session, set the subscription group via inf_session_set_subscription_group().

[constructor]

Parameters

manager

A InfCommunicationManager.

 

buffer

An initial InfTextBuffer.

 

io

A InfIo object.

 

status

The initial status of the session.

 

sync_group

A group in which the session is synchronized. Ignored if status is INF_SESSION_RUNNING.

[allow-none]

sync_connection

A connection to synchronize the session from. Ignored if status is INF_SESSION_RUNNING.

[allow-none]

Returns

A new InfTextSession.

[transfer full]


inf_text_session_new_with_user_table ()

InfTextSession *
inf_text_session_new_with_user_table (InfCommunicationManager *manager,
                                      InfTextBuffer *buffer,
                                      InfIo *io,
                                      InfUserTable *user_table,
                                      InfSessionStatus status,
                                      InfCommunicationGroup *sync_group,
                                      InfXmlConnection *sync_connection);

Creates a new InfTextSession. The connection manager is used to send and receive requests from subscription and synchronization. buffer will be set to be initially empty if the session is initially synchronized (see below). io is required to trigger timeouts.

If status is INF_SESSION_PRESYNC or INF_SESSION_SYNCHRONIZING, then the session will initially be sychronized, meaning the initial content is retrieved from sync_connection . If you are subscribed to the session, set the subscription group via inf_session_set_subscription_group().

user_table is used as an initial user table. The user table should only contain unavailable users, if any, that may rejoin during the session. If there was an available user in the user table, it would probably belong to another session, but different sessions cannot share the same user object.

[constructor]

Parameters

manager

A InfCommunicationManager.

 

buffer

An initial InfTextBuffer.

 

io

A InfIo object.

 

user_table

A InfUserTable.

 

status

The initial status for the session.

 

sync_group

A group in which the session is synchronized. Ignored if status is INF_SESSION_RUNNING.

[allow-none]

sync_connection

A connection to synchronize the session from. Ignored if status is INF_SESSION_RUNNING.

[allow-none]

Returns

A new InfTextSession.

[transfer full]


inf_text_session_set_user_color ()

void
inf_text_session_set_user_color (InfTextSession *session,
                                 InfTextUser *user,
                                 gdouble hue);

Changes the user color of user . user must have the INF_USER_LOCAL flag set.

Parameters

session

A InfTextSession.

 

user

A local InfTextUser from session 's user table.

 

hue

New hue value for user 's color. Ranges from 0.0 (red) to 1.0 (red).

 

inf_text_session_flush_requests_for_user ()

void
inf_text_session_flush_requests_for_user
                               (InfTextSession *session,
                                InfTextUser *user);

This function sends all pending requests for user immediately. Requests that modify the buffer are not queued normally, but cursor movement requests are delayed in case are issued frequently, to save bandwidth.

The main purpose of this function is to send all pending requests before changing a user's status to inactive or unavailable since inactive users are automatically activated as soon as they issue a request.

TODO: We should probably detect this automatically, without requiring people to call this function, i.e. flush requests for local users just before they become inactive.

user must have the INF_USER_LOCAL flag set.

Parameters

session

A InfTextSession.

 

user

The InfTextUser for which to flush messages.

 

inf_text_session_join_user ()

InfRequest *
inf_text_session_join_user (InfSessionProxy *proxy,
                            const gchar *name,
                            InfUserStatus status,
                            gdouble hue,
                            guint caret_position,
                            int selection_length,
                            InfRequestFunc func,
                            gpointer user_data);

This functions creates a user join request for an InfTextSession. This is a shortcut for inf_session_proxy_join_user().

Parameters

proxy

A InfSessionProxy with a InfTextSession session.

 

name

The name of the user to join.

 

status

The initial status of the user to join. Must not be INF_USER_UNAVAILABLE .

 

hue

The user color of the user to join.

 

caret_position

The initial position of the new user's cursor.

 

selection_length

The initial length of the new user's selection.

 

func

Function to call after completion of the request, or NULL.

[scope async]

user_data

Additional data to pass to func .

 

Returns

A InfRequest, or NULL.

[transfer full]

Types and Values

enum InfTextSessionError

Members

INF_TEXT_SESSION_ERROR_INVALID_HUE

   

INF_TEXT_SESSION_ERROR_FAILED

   

enum InfTextOperationError

Error codes that can occur when applying a InfTextInsertOperation, InfTextDeleteOperation or InfTextMoveOperation to the buffer.

Members

INF_TEXT_OPERATION_ERROR_INVALID_INSERT

A InfTextInsertOperation attempted to insert text after the end of the buffer.

 

INF_TEXT_OPERATION_ERROR_INVALID_DELETE

A InfTextDeleteOperation attempted to delete text from after the end of the buffer.

 

INF_TEXT_OPERATION_ERROR_INVALID_MOVE

A InfTextMoveOperation attempted to move the cursor of a user behind the end of the buffer.

 

INF_TEXT_OPERATION_ERROR_FAILED

No further specified error code.

 

struct InfTextSession

struct InfTextSession;


struct InfTextSessionClass

struct InfTextSessionClass {
  InfAdoptedSessionClass parent_class;
};

Property Details

The “caret-update-interval†property

  “caret-update-interval†   guint

Minimum number of milliseconds between caret update broadcasts.

Flags: Read / Write / Construct

Default value: 500

libinfinity-0.7.1/docs/reference/libinftext/html/PaxHeaders.26529/InfTextChunk.html0000644000000000000000000000013213055210756025051 xustar0030 mtime=1488261614.120083471 30 atime=1488261614.120083471 30 ctime=1488261614.120083471 libinfinity-0.7.1/docs/reference/libinftext/html/InfTextChunk.html0000644000175000017500000015514213055210756025613 0ustar00arminarmin00000000000000 InfTextChunk: libinftext-0.7 Reference Manual

InfTextChunk

InfTextChunk — A chunk of text written by various authors

Stability Level

Unstable, unless otherwise indicated

Types and Values

Object Hierarchy

    GBoxed
    ├── InfTextChunk
    ╰── InfTextChunkIter

Includes

#include <libinftext/inf-text-chunk.h>

Description

InfTextChunk represents a chunk of text where different parts of it can be written by different authors. The InfTextChunk API can be used like a normal string API, except that apart from the text itself it also stores the author information.

An InfTextChunk is made up of segments, where each segment represents a contiguous piece of text which is written by the same user. The InfTextChunkIter functionality can be used to iterate over the segments of a chunk.

The InfTextChunk API works with characters, not bytes, i.e. all offsets are given in number of characters. This ensures that unicode strings cannot be torn apart in the middle of a multibyte sequence. The encoding of an InfTextChunk is not fixed, but it can be freely chosen. InfTextChunk then uses iconv to convert between bytes and character offsets where necessary. For a small set of selected encodings which are very popular, most notably UTF-8, there exist more optimized code paths to do the conversion.

Functions

inf_text_chunk_iter_copy ()

InfTextChunkIter *
inf_text_chunk_iter_copy (const InfTextChunkIter *iter);

Makes a dynamically-allocated copy of iter . This is typically not needed because InfTextChunkIter can be copied by value, however it might be useful to language bindings.

Parameters

iter

A InfTextChunkIter.

 

Returns

A copy of iter . Free with inf_text_chunk_iter_free().

[transfer full]


inf_text_chunk_iter_free ()

void
inf_text_chunk_iter_free (InfTextChunkIter *iter);

Frees all resources allocated with inf_text_chunk_iter_copy(). Must not be used with stack-allocated InfTextChunkIters.

Parameters

iter

The InfTextChunkIter to free.

 

inf_text_chunk_new ()

InfTextChunk *
inf_text_chunk_new (const gchar *encoding);

Creates a new InfTextChunk with no initial content that holds text in the given encoding. TODO: Allow binary data with NULL encoding.

[constructor]

Parameters

encoding

A content encoding, such as "UTF-8" or "LATIN1".

 

Returns

A new InfTextChunk.

[transfer full]


inf_text_chunk_copy ()

InfTextChunk *
inf_text_chunk_copy (InfTextChunk *self);

Returns a copy of self .

Parameters

self

A InfTextChunk.

 

Returns

A new InfTextChunk.

[transfer full]


inf_text_chunk_free ()

void
inf_text_chunk_free (InfTextChunk *self);

Frees a InfTextChunk allocated with inf_text_chunk_new(), inf_text_chunk_copy() or inf_text_chunk_substring().

Parameters

self

A InfTextChunk.

 

inf_text_chunk_get_encoding ()

const gchar *
inf_text_chunk_get_encoding (InfTextChunk *self);

Returns the character encoding in which the content of self is encoded.

Parameters

self

A InfTextChunk.

 

Returns

The encoding of self .


inf_text_chunk_get_length ()

guint
inf_text_chunk_get_length (InfTextChunk *self);

Returns the number of characters contained in self .

Parameters

self

A InfTextChunk.

 

Returns

The number of characters of self .


inf_text_chunk_substring ()

InfTextChunk *
inf_text_chunk_substring (InfTextChunk *self,
                          guint begin,
                          guint length);

Returns a new InfTextChunk containing a substring of self , beginning at character offset begin and length characters long.

Parameters

self

A InfTextChunk.

 

begin

A character offset into self .

 

length

The length of the text to extract.

 

Returns

A new InfTextChunk.

[transfer full]


inf_text_chunk_insert_text ()

void
inf_text_chunk_insert_text (InfTextChunk *self,
                            guint offset,
                            gconstpointer text,
                            gsize bytes,
                            guint length,
                            guint author);

Inserts text written by author into self . text is expected to be in the chunk's encoding.

Parameters

self

A InfTextChunk.

 

offset

Character offset at which to insert text text (type const guint8*) (array length=bytes) (transfer none): Text to insert.

 

bytes

Number of bytes of text .

 

length

Number of characters contained in text .

 

author

User that wrote text .

 

inf_text_chunk_insert_chunk ()

void
inf_text_chunk_insert_chunk (InfTextChunk *self,
                             guint offset,
                             InfTextChunk *text);

Inserts text into self at position offset . text and self must have the same encoding.

Parameters

self

A InfTextChunk.

 

offset

Character offset at which to insert text.

 

text

Chunk to insert into self .

[transfer none]

inf_text_chunk_erase ()

void
inf_text_chunk_erase (InfTextChunk *self,
                      guint begin,
                      guint length);

Removes length characters of self , starting from character offset begin .

Parameters

self

A InfTextChunk.

 

begin

A character offset into self .

 

length

Number of characters to erase.

 

inf_text_chunk_get_text ()

gpointer
inf_text_chunk_get_text (InfTextChunk *self,
                         gsize *length);

Returns the content of self as an array. The text is encoded in self 's encoding. length is set to the number of bytes in the returned buffer, if non-NULL. The result is _not_ zero-terminated.

Parameters

self

A InfTextChunk.

 

length

Location to write the number of bytes to, or NULL.

[out]

Returns

Content of self . Free with g_free() if no longer in use.

[type guint8*][array length=length][transfer full]


inf_text_chunk_equal ()

gboolean
inf_text_chunk_equal (InfTextChunk *self,
                      InfTextChunk *other);

Returns whether the two text chunks contain the same text and the same segments were written by the same authors.

Parameters

self

A InfTextChunk.

 

other

Another InfTextChunk.

 

Returns

Whether the two chunks are equal.


inf_text_chunk_iter_init_begin ()

gboolean
inf_text_chunk_iter_init_begin (InfTextChunk *self,
                                InfTextChunkIter *iter);

Sets iter to point to the first segment of self . If there are no segments (i.e. self is empty), iter is left untouched and the function returns FALSE.

Parameters

self

A InfTextChunk.

 

iter

A InfTextChunkIter.

[out]

Returns

Whether iter was set.


inf_text_chunk_iter_init_end ()

gboolean
inf_text_chunk_iter_init_end (InfTextChunk *self,
                              InfTextChunkIter *iter);

Sets iter to point to the last segment of self . If there are no segments (i.e. self is empty), iter is left untouched and the function returns FALSE.

Parameters

self

A InfTextChunk.

 

iter

A InfTextChunkIter.

[out]

Returns

Whether iter was set.


inf_text_chunk_iter_next ()

gboolean
inf_text_chunk_iter_next (InfTextChunkIter *iter);

Sets iter to point to the next segment. If iter already points to the last segment, the function returns FALSE.

Parameters

iter

An initialized InfTextChunkIter.

 

Returns

Whether iter was set.


inf_text_chunk_iter_prev ()

gboolean
inf_text_chunk_iter_prev (InfTextChunkIter *iter);

Sets iter to point to the previous segment. If iter already points to the first segment, the function returns FALSE.

Parameters

iter

An initialized InfTextChunkIter.

 

Returns

Whether iter has changed.


inf_text_chunk_iter_get_text ()

gconstpointer
inf_text_chunk_iter_get_text (InfTextChunkIter *iter);

Returns the text of the segment iter points to. The text is in the underlaying InfTextChunk's encoding.

Parameters

iter

An initialized InfTextChunkIter.

 

Returns

The text of the segment iter points to.

[transfer none]


inf_text_chunk_iter_get_offset ()

guint
inf_text_chunk_iter_get_offset (InfTextChunkIter *iter);

Returns the offset of the first character in the segment iter points to.

Parameters

iter

An initialized InfTextChunkIter.

 

Returns

The offset of the first characters in the segment iter points to.


inf_text_chunk_iter_get_length ()

guint
inf_text_chunk_iter_get_length (InfTextChunkIter *iter);

Returns the number of characters in the segment iter points to.

Parameters

iter

An initialized InfTextChunkIter.

 

Returns

The number of characters in the segment iter points to.


inf_text_chunk_iter_get_bytes ()

gsize
inf_text_chunk_iter_get_bytes (InfTextChunkIter *iter);

Returns the number of bytes in the segment iter points to.

Parameters

iter

An initialized InfTextChunkIter.

 

Returns

The number of bytes in the segment iter points to.


inf_text_chunk_iter_get_author ()

guint
inf_text_chunk_iter_get_author (InfTextChunkIter *iter);

Returns the user ID of the author of the segment iter points to.

Parameters

iter

An initialized InfTextChunkIter.

 

Returns

The user ID of the author of the segment iter points to.

Types and Values

InfTextChunk

typedef struct _InfTextChunk InfTextChunk;

InfTextChunk is an opaque data type. You should only access it via the public API functions.


struct InfTextChunkIter

struct InfTextChunkIter {
};

InfTextChunkIter is an opaque data type. You should only access it via the public API functions.

InfTextChunkIter can be safely allocated on the stack and copied by value. Use inf_text_chunk_iter_init_begin() or inf_text_chunk_iter_init_end() to initialize a InfTextChunkIter. There is no deinitialization required. A InfTextChunkIter is valid as long as the chunk is not modified.

See Also

InfTextBuffer

libinfinity-0.7.1/docs/reference/libinftext/html/PaxHeaders.26529/libinftext-0.7.devhelp20000644000000000000000000000012713055210756025722 xustar0029 mtime=1488261614.08008356 29 atime=1488261614.08008356 29 ctime=1488261614.08008356 libinfinity-0.7.1/docs/reference/libinftext/html/libinftext-0.7.devhelp20000644000175000017500000005441113055210756026455 0ustar00arminarmin00000000000000 libinfinity-0.7.1/docs/reference/libinftext/html/PaxHeaders.26529/InfTextBuffer.html0000644000000000000000000000013213055210756025212 xustar0030 mtime=1488261614.120083471 30 atime=1488261614.120083471 30 ctime=1488261614.120083471 libinfinity-0.7.1/docs/reference/libinftext/html/InfTextBuffer.html0000644000175000017500000021607013055210756025752 0ustar00arminarmin00000000000000 InfTextBuffer: libinftext-0.7 Reference Manual

InfTextBuffer

InfTextBuffer — Interface for the text storage of an InfTextSession

Stability Level

Unstable, unless otherwise indicated

Types and Values

Object Hierarchy

    GInterface
    ╰── InfTextBuffer

Prerequisites

InfTextBuffer requires InfBuffer and GObject.

Known Implementations

InfTextBuffer is implemented by InfTextDefaultBuffer and InfTextFixlineBuffer.

Includes

#include <libinftext/inf-text-buffer.h>

Description

InfTextBuffer is an interface on top of InfBuffer which represents a text buffer in a similar way as GtkTextBuffer. InfTextBuffer can be used as the buffer of an InfTextSession, allowing the session to insert text written by remote users and access text written by local users and send it to everyone else.

See InfTextDefaultBuffer for a simple implementation based on InfTextChunk. However, in GUI collaborative editing clients this interface should be implemented in a more sophisticated way, such that the text of a document is not stored twice in memory. InfTextGtkBuffer does this for GTK+ based user interfaces.

Functions

inf_text_buffer_get_encoding ()

const gchar *
inf_text_buffer_get_encoding (InfTextBuffer *buffer);

Returns the character encoding that the buffer uses. This means that all InfTextChunk return values are encoded in this encoding and all InfTextChunk parameters are expected to be encoded in that encoding.

Parameters

buffer

A InfTextBuffer.

 

Returns

The character encoding for buffer .


inf_text_buffer_get_length ()

guint
inf_text_buffer_get_length (InfTextBuffer *buffer);

Returns the number of characters in buffer .

Parameters

buffer

A InfTextBuffer.

 

Returns

The length of buffer .


inf_text_buffer_get_slice ()

InfTextChunk *
inf_text_buffer_get_slice (InfTextBuffer *buffer,
                           guint pos,
                           guint len);

Reads len characters, starting at pos , from the buffer, and returns them as a InfTextChunk.

Parameters

buffer

A InfTextBuffer.

 

pos

Character offset of where to start extracting.

 

len

Number of characters to extract.

 

Returns

A InfTextChunk.

[transfer full]


inf_text_buffer_insert_text ()

void
inf_text_buffer_insert_text (InfTextBuffer *buffer,
                             guint pos,
                             gconstpointer text,
                             gsize bytes,
                             guint len,
                             InfUser *user);

Inserts text into buffer as written by author . text must be encoded in the character encoding of the buffer, see inf_text_buffer_get_encoding().

Parameters

buffer

A InfTextBuffer.

 

pos

A character offset into buffer . text (type=guint8*) (array length=bytes) (transfer none): A pointer to the text to insert.

 

bytes

The length (in bytes) of text .

 

len

The length (in characters) of text .

 

user

A InfUser that has inserted the new text, or NULL.

[allow-none]

inf_text_buffer_insert_chunk ()

void
inf_text_buffer_insert_chunk (InfTextBuffer *buffer,
                              guint pos,
                              InfTextChunk *chunk,
                              InfUser *user);

Inserts a InfTextChunk into buffer . user must not necessarily be the author of chunk (chunk may even consist of multiple segments). This happens when undoing a delete operation that erased another user's text.

Parameters

buffer

A InfTextBuffer.

 

pos

A character offset into buffer .

 

chunk

A InfTextChunk.

[transfer none]

user

A InfUser inserting chunk , or NULL.

[allow-none]

inf_text_buffer_erase_text ()

void
inf_text_buffer_erase_text (InfTextBuffer *buffer,
                            guint pos,
                            guint len,
                            InfUser *user);

Erases characters from the text buffer.

Parameters

buffer

A InfTextBuffer.

 

pos

The position to begin deleting characters from.

 

len

The amount of characters to delete.

 

user

A InfUser that erases the text, or NULL.

[allow-none]

inf_text_buffer_create_begin_iter ()

InfTextBufferIter *
inf_text_buffer_create_begin_iter (InfTextBuffer *buffer);

Creates a InfTextBufferIter pointing to the first segment of buffer . A InfTextBufferIter is used to traverse the buffer contents in steps of so-called segments each of which is written by the same user. The function returns NULL if there are no segments (i.e. the buffer is empty).

The iterator stays valid as long as the buffer remains unmodified and must be freed with inf_text_buffer_destroy_iter() before.

Parameters

buffer

A InfTextBuffer.

 

Returns

A InfTextBufferIter to be freed by inf_text_buffer_destroy_iter() when done using it, or NULL.

[transfer full][allow-none]


inf_text_buffer_create_end_iter ()

InfTextBufferIter *
inf_text_buffer_create_end_iter (InfTextBuffer *buffer);

Creates a InfTextBufferIter pointing to the last segment of buffer . A InfTextBufferIter is used to traverse the buffer contents in steps of so-called segments each of which is written by the same user. The function returns NULL if there are no segments (i.e. the buffer is empty).

The iterator stays valid as long as the buffer remains unmodified and must be freed with inf_text_buffer_destroy_iter() before.

Parameters

buffer

A InfTextBuffer.

 

Returns

A InfTextBufferIter to be freed by inf_text_buffer_destroy_iter() when done using it, or NULL.

[transfer full][allow-none]


inf_text_buffer_destroy_iter ()

void
inf_text_buffer_destroy_iter (InfTextBuffer *buffer,
                              InfTextBufferIter *iter);

Destroys a InfTextBufferIter created by inf_text_buffer_create_begin_iter() or inf_text_buffer_create_end_iter().

Parameters

buffer

A InfTextBuffer.

 

iter

A InfTextBufferIter pointing into buffer .

[transfer full]

inf_text_buffer_iter_next ()

gboolean
inf_text_buffer_iter_next (InfTextBuffer *buffer,
                           InfTextBufferIter *iter);

Moves iter to point to the next segment in the buffer. If iter already points to the last segment, iter is left unmodified and the function returns FALSE.

Parameters

buffer

A InfTextBuffer.

 

iter

A InfTextBufferIter pointing into buffer .

 

Returns

Whether iter was moved.


inf_text_buffer_iter_prev ()

gboolean
inf_text_buffer_iter_prev (InfTextBuffer *buffer,
                           InfTextBufferIter *iter);

Moves iter to point to the previous segment in the buffer. If iter already points to the first segment, iter is left unmodified and the function returns FALSE.

Parameters

buffer

A InfTextBuffer.

 

iter

A InfTextBufferIter pointing into buffer .

 

Returns

Whether iter was moved.


inf_text_buffer_iter_get_text ()

gpointer
inf_text_buffer_iter_get_text (InfTextBuffer *buffer,
                               InfTextBufferIter *iter);

Returns the text of the segment iter points to. It is encoded in buffer 's encoding (see inf_text_buffer_get_encoding()).

Parameters

buffer

A InfTextBuffer.

 

iter

A InfTextBufferIter pointing into buffer .

 

Returns

The text of the segment iter points to. Free with g_free() when done using it.

[transfer full]


inf_text_buffer_iter_get_offset ()

guint
inf_text_buffer_iter_get_offset (InfTextBuffer *buffer,
                                 InfTextBufferIter *iter);

Returns the offset of the first character in the segment iter points to, in characters.

Parameters

buffer

A InfTextBuffer.

 

iter

A InfTextBufferIter pointing into buffer .

 

Returns

The offset of the first character in the segment iter points to.


inf_text_buffer_iter_get_length ()

guint
inf_text_buffer_iter_get_length (InfTextBuffer *buffer,
                                 InfTextBufferIter *iter);

Returns the length of the segment iter points to, in characters.

Parameters

buffer

A InfTextBuffer.

 

iter

A InfTextBufferIter pointing into buffer .

 

Returns

The number of characters of the segment iter points to.


inf_text_buffer_iter_get_bytes ()

gsize
inf_text_buffer_iter_get_bytes (InfTextBuffer *buffer,
                                InfTextBufferIter *iter);

Returns the length of the segment iter points to, in bytes.

Parameters

buffer

A InfTextBuffer.

 

iter

A InfTextBufferIter pointing into buffer .

 

Returns

The number of bytes of the segment iter points to.


inf_text_buffer_iter_get_author ()

guint
inf_text_buffer_iter_get_author (InfTextBuffer *buffer,
                                 InfTextBufferIter *iter);

Returns the user ID of the user that has written the segment iter points to.

Parameters

buffer

A InfTextBuffer.

 

iter

A InfTextBufferIter pointing into buffer .

 

Returns

The user ID of the user that wrote the segment iter points to.


inf_text_buffer_text_inserted ()

void
inf_text_buffer_text_inserted (InfTextBuffer *buffer,
                               guint pos,
                               InfTextChunk *chunk,
                               InfUser *user);

Emits the “text-inserted†signal. This is meant to be used by interface implementations in their insert_text function, or when text was inserted by other means.

Parameters

buffer

A InfTextBuffer.

 

pos

A character offset into buffer .

 

chunk

A InfTextChunk.

 

user

A InfUser inserting chunk , or NULL.

[allow-none]

inf_text_buffer_text_erased ()

void
inf_text_buffer_text_erased (InfTextBuffer *buffer,
                             guint pos,
                             InfTextChunk *chunk,
                             InfUser *user);

Emits the “text-erased†signal. This is meant to be used by interface implementations in their erase_text function, or when text was erased by other means.

Parameters

buffer

A InfTextBuffer.

 

pos

The position to begin deleting characters from.

 

chunk

A InfTextChunk containing the erased text.

 

user

A InfUser that erases the text, or NULL.

[allow-none]

Types and Values

InfTextBuffer

typedef struct _InfTextBuffer InfTextBuffer;

InfTextBuffer is an opaque data type. You should only access it via the public API functions.


struct InfTextBufferInterface

struct InfTextBufferInterface {
  /* Virtual table */
  const gchar* (*get_encoding)(InfTextBuffer* buffer);

  guint(*get_length)(InfTextBuffer* buffer);

  InfTextChunk*(*get_slice)(InfTextBuffer* buffer,
                            guint pos,
                            guint len);

  void(*insert_text)(InfTextBuffer* buffer,
                     guint pos,
                     InfTextChunk* chunk,
                     InfUser* user);

  void(*erase_text)(InfTextBuffer* buffer,
                    guint pos,
                    guint len,
                    InfUser* user);

  InfTextBufferIter*(*create_begin_iter)(InfTextBuffer* buffer);

  InfTextBufferIter*(*create_end_iter)(InfTextBuffer* buffer);

  void(*destroy_iter)(InfTextBuffer* buffer,
                      InfTextBufferIter* iter);

  gboolean(*iter_next)(InfTextBuffer* buffer,
                       InfTextBufferIter* iter);
  
  gboolean(*iter_prev)(InfTextBuffer* buffer,
                       InfTextBufferIter* iter);

  gpointer(*iter_get_text)(InfTextBuffer* buffer,
                           InfTextBufferIter* iter);

  guint(*iter_get_offset)(InfTextBuffer* buffer,
                          InfTextBufferIter* iter);

  guint(*iter_get_length)(InfTextBuffer* buffer,
                          InfTextBufferIter* iter);

  gsize(*iter_get_bytes)(InfTextBuffer* buffer,
                         InfTextBufferIter* iter);

  guint(*iter_get_author)(InfTextBuffer* buffer,
                          InfTextBufferIter* iter);

  /* Signals */
  void(*text_inserted)(InfTextBuffer* buffer,
                       guint pos,
                       InfTextChunk* chunk,
                       InfUser* user);

  void(*text_erased)(InfTextBuffer* buffer,
                     guint pos,
                     InfTextChunk* chunk,
                     InfUser* user);
};

This structure contains virtual functions and signal handlers of the InfTextBuffer interface.

Members

get_encoding ()

Virtual function which returns the character coding of the buffer.

 

get_length ()

Virtual function to return the total length of the text in the buffer, in characters.

 

get_slice ()

Virtual function to extract a slice of text from the buffer.

 

insert_text ()

Virtual function to insert text into the buffer.

 

erase_text ()

Virtual function to remove text from the buffer.

 

create_begin_iter ()

Virtual function to create a InfTextBufferIter at the beginning of the buffer, used for traversing through buffer segments.

 

create_end_iter ()

Virtual function to create a InfTextBufferIter at the end of the buffer, used for traversing through buffer segments.

 

destroy_iter ()

Virtual function to destroy an iterator created with the create_begin_iter and create_end_iter functions.

 

iter_next ()

Virtual function to advance a InfTextBufferIter to the next segment.

 

iter_prev ()

Virtual function to retreat a InfTextBufferIter to the previous segment.

 

iter_get_text ()

Virtual function to obtain the text of a segment a InfTextBufferIter points to.

 

iter_get_offset ()

Virtual function to obtain the offset of the first character in the segment a InfTextBufferIter points to.

 

iter_get_length ()

Virtual function to obtain the length of a segment a InfTextBufferIter points to.

 

iter_get_bytes ()

Virtual function to obtain the number of bytes in a segment a InfTextBufferIter points to.

 

iter_get_author ()

Virtual function to obtain the author of the segment a InfTextBufferIter points to.

 

text_inserted ()

Default signal handler of the “text-inserted†signal.

 

text_erased ()

Default signal handler of the “text-erased†signal.

 

InfTextBufferIter

typedef struct _InfTextBufferIter InfTextBufferIter;

InfTextBufferIter is an opaque data type. You should only access it via the public API functions.

Signal Details

The “text-erased†signal

void
user_function (InfTextBuffer *inftextbuffer,
               guint          arg1,
               InfTextChunk  *arg2,
               InfUser       *arg3,
               gpointer       user_data)

Parameters

inftextbuffer

the object which received the signal.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run First


The “text-inserted†signal

void
user_function (InfTextBuffer *inftextbuffer,
               guint          arg1,
               InfTextChunk  *arg2,
               InfUser       *arg3,
               gpointer       user_data)

Parameters

inftextbuffer

the object which received the signal.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run First

libinfinity-0.7.1/docs/reference/libinftext/html/PaxHeaders.26529/ch01.html0000644000000000000000000000013213055210756023232 xustar0030 mtime=1488261614.120083471 30 atime=1488261614.120083471 30 ctime=1488261614.120083471 libinfinity-0.7.1/docs/reference/libinftext/html/ch01.html0000644000175000017500000000774513055210756024001 0ustar00arminarmin00000000000000 libinftext API reference: libinftext-0.7 Reference Manual

libinftext API reference

InfTextSession
InfTextBuffer — Interface for the text storage of an InfTextSession
InfTextUser
InfTextChunk — A chunk of text written by various authors
InfTextDefaultBuffer
InfTextFixlineBuffer — Keep a fixed number of trailing lines
InfTextUndoGrouping — Undo grouping for text operations
inf-text-insert-operation
InfTextDeleteOperation — Interface for an operation erasing text
InfTextDefaultDeleteOperation
InfTextDefaultInsertOperation
InfTextRemoteDeleteOperation
InfTextMoveOperation
Storage of text sessions on the file system — Utility functions to deal with storing InfTextSessions in filesystem storage
libinfinity-0.7.1/docs/reference/libinftext/html/PaxHeaders.26529/InfTextDeleteOperation.html0000644000000000000000000000013213055210756027064 xustar0030 mtime=1488261614.120083471 30 atime=1488261614.120083471 30 ctime=1488261614.120083471 libinfinity-0.7.1/docs/reference/libinftext/html/InfTextDeleteOperation.html0000644000175000017500000005554613055210756027635 0ustar00arminarmin00000000000000 InfTextDeleteOperation: libinftext-0.7 Reference Manual

InfTextDeleteOperation

InfTextDeleteOperation — Interface for an operation erasing text

Stability Level

Unstable, unless otherwise indicated

Object Hierarchy

    GInterface
    ╰── InfTextDeleteOperation

Prerequisites

InfTextDeleteOperation requires InfAdoptedOperation and GObject.

Known Implementations

InfTextDeleteOperation is implemented by InfTextDefaultDeleteOperation and InfTextRemoteDeleteOperation.

Includes

#include <libinftext/inf-text-delete-operation.h>

Description

InfTextDeleteOperation is an interface for an operation removing text from the document. It implements the transformation logic for transformation against other delete operations or insert operations.

This interface does not make any assumption on what kind of text is removed, it works only with character offsets and lengths. This information is enough to perform transformation of this operation or other operations against this operation. Whether the actual operation only knows about the offsets, too, or actually knows the text that is being erased (and if so, in what representation), is up to the implementation.

Functions

inf_text_delete_operation_get_position ()

guint
inf_text_delete_operation_get_position
                               (InfTextDeleteOperation *operation);

Returns the position at which operation starts to delete dext.

Parameters

operation

A InfTextDeleteOperation.

 

Returns

The position of operation .


inf_text_delete_operation_get_length ()

guint
inf_text_delete_operation_get_length (InfTextDeleteOperation *operation);

Returns the number of characters deleted by operation .

Parameters

operation

A InfTextDeleteOperation.

 

Returns

The length of operation .


inf_text_delete_operation_need_concurrency_id ()

gboolean
inf_text_delete_operation_need_concurrency_id
                               (InfTextDeleteOperation *op,
                                InfAdoptedOperation *against);

Returns whether transforming op against against requires a concurrency ID (see inf_adopted_operation_need_concurrency_id() for further information).

Parameters

op

A InfTextDeleteOperation.

 

against

Another InfAdoptedOperation.

 

Returns

Whether transforming op against against requires a concurrency ID.


inf_text_delete_operation_transform_insert ()

InfAdoptedOperation *
inf_text_delete_operation_transform_insert
                               (InfTextDeleteOperation *operation,
                                InfTextInsertOperation *against);

Returns a new operation that includes the effect of against into operation .

Parameters

operation

A InfTextDeleteOperation.

 

against

A InfTextInsertOperation.

 

Returns

A new InfAdoptedOperation.

[transfer full]


inf_text_delete_operation_transform_delete ()

InfAdoptedOperation *
inf_text_delete_operation_transform_delete
                               (InfTextDeleteOperation *operation,
                                InfTextDeleteOperation *against);

Returns a new operation that includes the effect of against into operation .

Parameters

operation

A InfTextDeleteOperation.

 

against

Another InfTextDeleteOperation.

 

Returns

A new InfAdoptedOperation.

[transfer full]

Types and Values

InfTextDeleteOperation

typedef struct _InfTextDeleteOperation InfTextDeleteOperation;

InfTextDeleteOperation is an opaque data type. You should only access it via the public API functions.


struct InfTextDeleteOperationInterface

struct InfTextDeleteOperationInterface {
  /* Virtual table */
  guint(*get_position)(InfTextDeleteOperation* operation);

  guint(*get_length)(InfTextDeleteOperation* operation);

  InfTextDeleteOperation*(*transform_position)(InfTextDeleteOperation* op,
                                               guint position);

  InfTextDeleteOperation*(*transform_overlap)(InfTextDeleteOperation* op,
                                              InfTextDeleteOperation* other,
                                              guint position,
                                              guint begin,
                                              guint other_begin,
                                              guint length);

  InfAdoptedSplitOperation*(*transform_split)(InfTextDeleteOperation* op,
                                              guint split_pos,
                                              guint split_length);
};

This structure contains virtual methods of the InfTextDeleteOperation interface.

Members

get_position ()

Virtual function to retrieve the start position of the delete operation.

 

get_length ()

Virtual function to retrieve the end position of the number of characters removed by the delete operation.

 

transform_position ()

Virtual function to transform the operation such that the start position of the operation changes.

 

transform_overlap ()

Virtual function to transform the operation against another delete operation with overlapping regions.

 

transform_split ()

Virtual function to transform the operation against an insert operation such that this operation needs to be split in two.

 
libinfinity-0.7.1/docs/reference/libinftext/html/PaxHeaders.26529/up.png0000644000000000000000000000012713055210756022747 xustar0029 mtime=1488261614.08008356 29 atime=1488261614.08008356 29 ctime=1488261614.08008356 libinfinity-0.7.1/docs/reference/libinftext/html/up.png0000644000175000017500000000040413055210756023473 0ustar00arminarmin00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEà 4ÓkM‘IDAT8Ëí’1 ƒ@DŸ•¶{ƒxa™ƒØÄ;$]r =JR´È1,Ë øSd„-©}0°ÌŸÙÏÂÂÎàüo¹L:m-˜¤QÞOäÀ[› Éäåkå T¸zþMÞ Lè¬Ì,š:ךuÀ!tÁK;æ ðP¦õÌôÀp Ot@£l¼ÿò/̵*á§l}IEND®B`‚libinfinity-0.7.1/docs/reference/libinftext/html/PaxHeaders.26529/home.png0000644000000000000000000000013213055210756023247 xustar0030 mtime=1488261614.076083569 30 atime=1488261614.076083569 30 ctime=1488261614.076083569 libinfinity-0.7.1/docs/reference/libinftext/html/home.png0000644000175000017500000000040013055210756023773 0ustar00arminarmin00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEà 4ÓkMIDAT8ËÝÒ½ AÅñßž¦f`n v`6`/¶`Y€š˜Ü¡`f&k$,Ëá}˜ˆ ÌüßÀ0ü§bŒ+Ô¸aQW~bæ ËOà e˜{‡y N°Á£üö[LáØÌ}.pÇiÀ­÷¨BzüžÆmm Šoæ·.I]7Ì^[úÃô;%:å†ÁVIEND®B`‚libinfinity-0.7.1/docs/reference/libinftext/html/PaxHeaders.26529/right-insensitive.png0000644000000000000000000000012713055210756025776 xustar0029 mtime=1488261614.08008356 29 atime=1488261614.08008356 29 ctime=1488261614.08008356 libinfinity-0.7.1/docs/reference/libinftext/html/right-insensitive.png0000644000175000017500000000056513055210756026532 0ustar00arminarmin00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEà 4ÓkMIDAT8ËÍ’±JÃ`…¿ ‚“‹³«/ S’_$ÄÁÁAqrÐÙW(>€“à‚®©“m¥"]\œ„è(‘49.NÚdÒ3¸ß9Ü{á¯eM#MSI‡Î¹·E¯iHz|3{̲l½3 ,K˜k’ž†ÃáV'@EŸEQlwÀŠçyišî·Äqüçù‘™]KÀíh4:mµÄ¦²,;“t˜¤sç\aƒÆR5/¬7'¹W×õp”’Žs×­I’,Kº1³=àËÌÂ0´j0Wg³ÙØ>€Ý ¦­¯PUÕýïð»¤0 §]?qCÒ«™ùιgþ½~œÉkÄAâ…_IEND®B`‚libinfinity-0.7.1/docs/reference/libinftext/html/PaxHeaders.26529/right.png0000644000000000000000000000012713055210756023440 xustar0029 mtime=1488261614.08008356 29 atime=1488261614.08008356 29 ctime=1488261614.08008356 libinfinity-0.7.1/docs/reference/libinftext/html/right.png0000644000175000017500000000040513055210756024165 0ustar00arminarmin00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEà 4ÓkM’IDAT8ËÕÒ¯aÇñ?›M´½IdErš,¾Ù-¸ÑhîAâIl’Í ¯r’äy§ž}¿ç·s¿X6èæ ö!9¢Ÿ#èD‚ Œr$-¬BrÃ$GÒÀ"$”¹;™á‰æŸÍú—WZêä&–!¸cš·±øŠq \`ðÃÔ軀Oä¾ò=QouføòIEND®B`‚libinfinity-0.7.1/docs/reference/libinftext/html/PaxHeaders.26529/InfTextDefaultInsertOperation.html0000644000000000000000000000013213055210756030433 xustar0030 mtime=1488261614.120083471 30 atime=1488261614.120083471 30 ctime=1488261614.120083471 libinfinity-0.7.1/docs/reference/libinftext/html/InfTextDefaultInsertOperation.html0000644000175000017500000003006613055210756031172 0ustar00arminarmin00000000000000 InfTextDefaultInsertOperation: libinftext-0.7 Reference Manual

InfTextDefaultInsertOperation

InfTextDefaultInsertOperation

Properties

InfTextChunk * chunk Read / Write / Construct Only
guint position Read / Write / Construct Only

Object Hierarchy

    GObject
    ╰── InfTextDefaultInsertOperation

Implemented Interfaces

InfTextDefaultInsertOperation implements InfAdoptedOperation and InfTextInsertOperation.

Description

Functions

inf_text_default_insert_operation_new ()

InfTextDefaultInsertOperation *
inf_text_default_insert_operation_new (guint pos,
                                       InfTextChunk *chunk);

Creates a new insert operation that, when applied, inserts chunk at pos .

[constructor]

Parameters

pos

The position at which to insert text.

 

chunk

The text to insert.

 

Returns

A new InfTextDefaultInsertOperation.

[transfer full]


inf_text_default_insert_operation_get_chunk ()

InfTextChunk *
inf_text_default_insert_operation_get_chunk
                               (InfTextDefaultInsertOperation *operation);

Returns the text inserted by operation .

Parameters

operation

A InfTextDefaultInsertOperation.

 

Returns

A InfTextChunk, owned by the operation.

[transfer none]

Types and Values

struct InfTextDefaultInsertOperation

struct InfTextDefaultInsertOperation;


struct InfTextDefaultInsertOperationClass

struct InfTextDefaultInsertOperationClass {
  GObjectClass parent_class;
};

Property Details

The “chunk†property

  “chunk†                   InfTextChunk *

The text to insert.

Flags: Read / Write / Construct Only


The “position†property

  “position†                guint

Insertion position.

Flags: Read / Write / Construct Only

Default value: 0

libinfinity-0.7.1/docs/reference/libinftext/html/PaxHeaders.26529/style.css0000644000000000000000000000012713055210756023467 xustar0029 mtime=1488261614.08008356 29 atime=1488261614.08008356 29 ctime=1488261614.08008356 libinfinity-0.7.1/docs/reference/libinftext/html/style.css0000644000175000017500000002115413055210756024220 0ustar00arminarmin00000000000000body { font-family: cantarell, sans-serif; } .synopsis, .classsynopsis { /* tango:aluminium 1/2 */ background: #eeeeec; background: rgba(238, 238, 236, 0.5); border: solid 1px rgb(238, 238, 236); padding: 0.5em; } .programlisting { /* tango:sky blue 0/1 */ /* fallback for no rgba support */ background: #e6f3ff; border: solid 1px #729fcf; background: rgba(114, 159, 207, 0.1); border: solid 1px rgba(114, 159, 207, 0.2); padding: 0.5em; } .variablelist { padding: 4px; margin-left: 3em; } .variablelist td:first-child { vertical-align: top; } div.gallery-float { float: left; padding: 10px; } div.gallery-float img { border-style: none; } div.gallery-spacer { clear: both; } a, a:visited { text-decoration: none; /* tango:sky blue 2 */ color: #3465a4; } a:hover { text-decoration: underline; /* tango:sky blue 1 */ color: #729fcf; } div.informaltable table { border-collapse: separate; border-spacing: 1em 0.3em; border: none; } div.informaltable table td, div.informaltable table th { vertical-align: top; } .function_type, .variable_type, .property_type, .signal_type, .parameter_name, .struct_member_name, .union_member_name, .define_keyword, .datatype_keyword, .typedef_keyword { text-align: right; } /* dim non-primary columns */ .c_punctuation, .function_type, .variable_type, .property_type, .signal_type, .define_keyword, .datatype_keyword, .typedef_keyword, .property_flags, .signal_flags, .parameter_annotations, .enum_member_annotations, .struct_member_annotations, .union_member_annotations { color: #888a85; } .function_type a, .function_type a:visited, .function_type a:hover, .property_type a, .property_type a:visited, .property_type a:hover, .signal_type a, .signal_type a:visited, .signal_type a:hover, .signal_flags a, .signal_flags a:visited, .signal_flags a:hover { color: #729fcf; } td p { margin: 0.25em; } div.table table { border-collapse: collapse; border-spacing: 0px; /* tango:aluminium 3 */ border: solid 1px #babdb6; } div.table table td, div.table table th { /* tango:aluminium 3 */ border: solid 1px #babdb6; padding: 3px; vertical-align: top; } div.table table th { /* tango:aluminium 2 */ background-color: #d3d7cf; } h4 { color: #555753; margin-top: 1em; margin-bottom: 1em; } hr { /* tango:aluminium 1 */ color: #d3d7cf; background: #d3d7cf; border: none 0px; height: 1px; clear: both; margin: 2.0em 0em 2.0em 0em; } dl.toc dt { padding-bottom: 0.25em; } dl.toc > dt { padding-top: 0.25em; padding-bottom: 0.25em; font-weight: bold; } dl.toc > dl { padding-bottom: 0.5em; } .parameter { font-style: normal; } .footer { padding-top: 3.5em; /* tango:aluminium 3 */ color: #babdb6; text-align: center; font-size: 80%; } .informalfigure, .figure { margin: 1em; } .informalexample, .example { margin-top: 1em; margin-bottom: 1em; } .warning { /* tango:orange 0/1 */ background: #ffeed9; background: rgba(252, 175, 62, 0.1); border-color: #ffb04f; border-color: rgba(252, 175, 62, 0.2); } .note { /* tango:chameleon 0/0.5 */ background: #d8ffb2; background: rgba(138, 226, 52, 0.1); border-color: #abf562; border-color: rgba(138, 226, 52, 0.2); } div.blockquote { border-color: #eeeeec; } .note, .warning, div.blockquote { padding: 0.5em; border-width: 1px; border-style: solid; margin: 2em; } .note p, .warning p { margin: 0; } div.warning h3.title, div.note h3.title { display: none; } p + div.section { margin-top: 1em; } div.refnamediv, div.refsynopsisdiv, div.refsect1, div.refsect2, div.toc, div.section { margin-bottom: 1em; } /* blob links */ h2 .extralinks, h3 .extralinks { float: right; /* tango:aluminium 3 */ color: #babdb6; font-size: 80%; font-weight: normal; } .lineart { color: #d3d7cf; font-weight: normal; } .annotation { /* tango:aluminium 5 */ color: #555753; font-weight: normal; } .structfield { font-style: normal; font-weight: normal; } acronym,abbr { border-bottom: 1px dotted gray; } /* code listings */ .listing_code .programlisting .normal, .listing_code .programlisting .normal a, .listing_code .programlisting .number, .listing_code .programlisting .cbracket, .listing_code .programlisting .symbol { color: #555753; } .listing_code .programlisting .comment, .listing_code .programlisting .linenum { color: #babdb6; } /* tango: aluminium 3 */ .listing_code .programlisting .function, .listing_code .programlisting .function a, .listing_code .programlisting .preproc { color: #204a87; } /* tango: sky blue 3 */ .listing_code .programlisting .string { color: #ad7fa8; } /* tango: plum */ .listing_code .programlisting .keyword, .listing_code .programlisting .usertype, .listing_code .programlisting .type, .listing_code .programlisting .type a { color: #4e9a06; } /* tango: chameleon 3 */ .listing_frame { /* tango:sky blue 1 */ border: solid 1px #729fcf; border: solid 1px rgba(114, 159, 207, 0.2); padding: 0px; } .listing_lines, .listing_code { margin-top: 0px; margin-bottom: 0px; padding: 0.5em; } .listing_lines { /* tango:sky blue 0.5 */ background: #a6c5e3; background: rgba(114, 159, 207, 0.2); /* tango:aluminium 6 */ color: #2e3436; } .listing_code { /* tango:sky blue 0 */ background: #e6f3ff; background: rgba(114, 159, 207, 0.1); } .listing_code .programlisting { /* override from previous */ border: none 0px; padding: 0px; background: none; } .listing_lines pre, .listing_code pre { margin: 0px; } @media screen { /* these have a as a first child, but since there are no parent selectors * we can't use that. */ a.footnote { position: relative; top: 0em ! important; } /* this is needed so that the local anchors are displayed below the naviagtion */ div.footnote a[name], div.refnamediv a[name], div.refsect1 a[name], div.refsect2 a[name], div.index a[name], div.glossary a[name], div.sect1 a[name] { display: inline-block; position: relative; top:-5em; } /* this seems to be a bug in the xsl style sheets when generating indexes */ div.index div.index { top: 0em; } /* make space for the fixed navigation bar and add space at the bottom so that * link targets appear somewhat close to top */ body { padding-top: 2.5em; padding-bottom: 500px; max-width: 60em; } p { max-width: 60em; } /* style and size the navigation bar */ table.navigation#top { position: fixed; background: #e2e2e2; border-bottom: solid 1px #babdb6; border-spacing: 5px; margin-top: 0; margin-bottom: 0; top: 0; left: 0; z-index: 10; } table.navigation#top td { padding-left: 6px; padding-right: 6px; } .navigation a, .navigation a:visited { /* tango:sky blue 3 */ color: #204a87; } .navigation a:hover { /* tango:sky blue 2 */ color: #3465a4; } td.shortcuts { /* tango:sky blue 2 */ color: #3465a4; font-size: 80%; white-space: nowrap; } td.shortcuts .dim { color: #babdb6; } .navigation .title { font-size: 80%; max-width: none; margin: 0px; font-weight: normal; } } @media screen and (min-width: 60em) { /* screen larger than 60em */ body { margin: auto; } } @media screen and (max-width: 60em) { /* screen less than 60em */ #nav_hierarchy { display: none; } #nav_interfaces { display: none; } #nav_prerequisites { display: none; } #nav_derived_interfaces { display: none; } #nav_implementations { display: none; } #nav_child_properties { display: none; } #nav_style_properties { display: none; } #nav_index { display: none; } #nav_glossary { display: none; } .gallery_image { display: none; } .property_flags { display: none; } .signal_flags { display: none; } .parameter_annotations { display: none; } .enum_member_annotations { display: none; } .struct_member_annotations { display: none; } .union_member_annotations { display: none; } /* now that a column is hidden, optimize space */ col.parameters_name { width: auto; } col.parameters_description { width: auto; } col.struct_members_name { width: auto; } col.struct_members_description { width: auto; } col.enum_members_name { width: auto; } col.enum_members_description { width: auto; } col.union_members_name { width: auto; } col.union_members_description { width: auto; } .listing_lines { display: none; } } @media print { table.navigation { visibility: collapse; display: none; } div.titlepage table.navigation { visibility: visible; display: table; background: #e2e2e2; border: solid 1px #babdb6; margin-top: 0; margin-bottom: 0; top: 0; left: 0; height: 3em; } } libinfinity-0.7.1/docs/reference/libinftext/html/PaxHeaders.26529/left.png0000644000000000000000000000012713055210756023255 xustar0029 mtime=1488261614.08008356 29 atime=1488261614.08008356 29 ctime=1488261614.08008356 libinfinity-0.7.1/docs/reference/libinftext/html/left.png0000644000175000017500000000040613055210756024003 0ustar00arminarmin00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEà 4ÓkM“IDAT8ËÕÒ¯Áa‡ñ?ÁDAPY‘\‚$‹º[p¢+ÐÜIÐIªMlfü('Úì}MpâÙyží{Îá_ª…ž¨¤ÂÞ¥Â}œ^£‘q xZ <Æ=àYjî) <0ù4\~Ó+Púöl#Ü"ÂÕÉ—,QÏ‘ôp ÉÍIÇlswÒÆ>÷•[/]_i0‘3ÃIEND®B`‚libinfinity-0.7.1/docs/reference/libinftext/html/PaxHeaders.26529/InfTextFixlineBuffer.html0000644000000000000000000000013213055210756026531 xustar0030 mtime=1488261614.120083471 30 atime=1488261614.120083471 30 ctime=1488261614.120083471 libinfinity-0.7.1/docs/reference/libinftext/html/InfTextFixlineBuffer.html0000644000175000017500000003141613055210756027270 0ustar00arminarmin00000000000000 InfTextFixlineBuffer: libinftext-0.7 Reference Manual

InfTextFixlineBuffer

InfTextFixlineBuffer — Keep a fixed number of trailing lines

Stability Level

Unstable, unless otherwise indicated

Properties

InfTextBuffer * buffer Read / Write / Construct Only
InfIo * io Read / Write / Construct Only
guint lines Read / Write / Construct Only

Types and Values

Object Hierarchy

    GObject
    ╰── InfTextFixlineBuffer

Implemented Interfaces

InfTextFixlineBuffer implements InfBuffer and InfTextBuffer.

Includes

#include <libinftext/inf-text-fixline-buffer.h>

Description

This class is a wrapper around another InfTextBuffer. It makes sure that the number of trailing empty lines in the underlying buffer is always fixed to a given number while it itself keeps track of the missing or additional lines. This can be used for example to keep the number of empty lines fixed on the client side even if lines are added and removed within a text session.

Functions

inf_text_fixline_buffer_new ()

InfTextFixlineBuffer *
inf_text_fixline_buffer_new (InfIo *io,
                             InfTextBuffer *buffer,
                             guint n_lines);

Creates a new InfTextFixlineBuffer which keeps the number of trailing lines of the given underlying buffer fixed to n_lines .

[constructor]

Parameters

io

A InfIo object to schedule timeouts.

 

buffer

The underlying buffer for which to keep a fixed line count.

 

n_lines

The number of lines to be kept fixed.

 

Returns

A InfTextFixlineBuffer.

[transfer full]

Types and Values

struct InfTextFixlineBuffer

struct InfTextFixlineBuffer;

InfTextFixlineBuffer is an opaque data type. You should only access it via the public API functions.


struct InfTextFixlineBufferClass

struct InfTextFixlineBufferClass {
  GObjectClass parent_class;
};

This structure does not contain any public fields.

Property Details

The “buffer†property

  “buffer†                  InfTextBuffer *

The buffer for which to keep a fixed line count.

Flags: Read / Write / Construct Only


The “io†property

  “io†                      InfIo *

The I/O object used to schedule line keeping.

Flags: Read / Write / Construct Only


The “lines†property

  “lines†                   guint

The number of lines to keep in the underlying buffer.

Flags: Read / Write / Construct Only

Default value: 0

libinfinity-0.7.1/docs/reference/libinftext/PaxHeaders.26529/Makefile.in0000644000000000000000000000013213051241007022677 xustar0030 mtime=1487225351.765148612 30 atime=1487225351.765148612 30 ctime=1488261611.652088993 libinfinity-0.7.1/docs/reference/libinftext/Makefile.in0000644000175000017500000006675413051241007023453 0ustar00arminarmin00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 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@ # -*- mode: makefile -*- #################################### # Everything below here is generic # #################################### VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) 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@ subdir = docs/reference/libinftext ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/gtk-doc.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/libinfinity/inf-config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/gtk-doc.make DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ 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@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIRNAME = @DATADIRNAME@ 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@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ GTKDOC_CHECK = @GTKDOC_CHECK@ GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ GTKDOC_MKPDF = @GTKDOC_MKPDF@ GTKDOC_REBASE = @GTKDOC_REBASE@ HTML_DIR = @HTML_DIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INSTOBJEXT = @INSTOBJEXT@ INTLLIBS = @INTLLIBS@ INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBINFINITY_API_VERSION = @LIBINFINITY_API_VERSION@ LIBINFINITY_LIBTOOL_VERSION = @LIBINFINITY_LIBTOOL_VERSION@ LIBINFINITY_VERSION = @LIBINFINITY_VERSION@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGFMT_OPTS = @MSGFMT_OPTS@ 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@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ 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@ avahi_CFLAGS = @avahi_CFLAGS@ avahi_LIBS = @avahi_LIBS@ 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@ gio_CFLAGS = @gio_CFLAGS@ gio_LIBS = @gio_LIBS@ gtk_requirement = @gtk_requirement@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infgtk_CFLAGS = @infgtk_CFLAGS@ infgtk_LIBS = @infgtk_LIBS@ infinity_CFLAGS = @infinity_CFLAGS@ infinity_LIBS = @infinity_LIBS@ infinoted_CFLAGS = @infinoted_CFLAGS@ infinoted_LIBS = @infinoted_LIBS@ infodir = @infodir@ inftext_CFLAGS = @inftext_CFLAGS@ inftext_LIBS = @inftext_LIBS@ inftextgtk_CFLAGS = @inftextgtk_CFLAGS@ inftextgtk_LIBS = @inftextgtk_LIBS@ install_sh = @install_sh@ libdaemon_CFLAGS = @libdaemon_CFLAGS@ libdaemon_LIBS = @libdaemon_LIBS@ 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@ runstatedir = @runstatedir@ 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@ # We require automake 1.6 at least. AUTOMAKE_OPTIONS = 1.6 # This is a blank Makefile.am for using gtk-doc. # Copy this to your project's API docs directory and modify the variables to # suit your project. See the GTK+ Makefiles in gtk+/docs/reference for examples # of using the various options. # The name of the module, e.g. 'glib'. DOC_MODULE = libinftext-$(LIBINFINITY_API_VERSION) # The top-level SGML file. You can change this if you want to. DOC_MAIN_SGML_FILE = $(DOC_MODULE)-docs.sgml # The directory containing the source code. Relative to $(srcdir). # gtk-doc will search all .c & .h files beneath here for inline comments # documenting the functions and macros. # e.g. DOC_SOURCE_DIR=../../../gtk DOC_SOURCE_DIR = $(top_srcdir)/libinftext # Extra options to pass to gtkdoc-scangobj. Not normally needed. SCANGOBJ_OPTIONS = # Extra options to supply to gtkdoc-scan. # e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED" SCAN_OPTIONS = --rebuild-types # Extra options to supply to gtkdoc-mkdb. # e.g. MKDB_OPTIONS=--sgml-mode --output-format=xml MKDB_OPTIONS = --sgml-mode --output-format=xml # Extra options to supply to gtkdoc-mktmpl # e.g. MKTMPL_OPTIONS=--only-section-tmpl MKTMPL_OPTIONS = # Extra options to supply to gtkdoc-fixref. Not normally needed. # e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html FIXXREF_OPTIONS = \ --extra-dir=../libinfinity/html # Used for dependencies. The docs will be rebuilt if any of these change. # e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h # e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c HFILE_GLOB = \ $(top_srcdir)/libinftext/*.h CFILE_GLOB = \ $(top_srcdir)/libinftext/*.c # Header files to ignore when scanning. # e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h IGNORE_HFILES = # Images to copy into HTML directory. # e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png HTML_IMAGES = # Extra SGML files that are included by $(DOC_MAIN_SGML_FILE). # e.g. content_files=running.sgml building.sgml changes-2.0.sgml content_files = \ ../version.xml # SGML files where gtk-doc abbrevations (#GtkWidget) are expanded # These files must be listed here *and* in content_files # e.g. expand_content_files=running.sgml expand_content_files = # CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library. # Only needed if you are using gtkdoc-scangobj to dynamically query widget # signals and properties. # e.g. INCLUDES=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS) # e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib) #INCLUDES=$(inftext_CFLAGS) AM_CPPFLAGS = $(inftext_CFLAGS) GTKDOC_LIBS = \ $(inftext_LIBS) \ $(top_builddir)/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(top_builddir)/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la @GTK_DOC_USE_LIBTOOL_FALSE@GTKDOC_CC = $(CC) $(INCLUDES) $(GTKDOC_DEPS_CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) @GTK_DOC_USE_LIBTOOL_TRUE@GTKDOC_CC = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(INCLUDES) $(GTKDOC_DEPS_CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) @GTK_DOC_USE_LIBTOOL_FALSE@GTKDOC_LD = $(CC) $(GTKDOC_DEPS_LIBS) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) @GTK_DOC_USE_LIBTOOL_TRUE@GTKDOC_LD = $(LIBTOOL) --tag=CC --mode=link $(CC) $(GTKDOC_DEPS_LIBS) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) @GTK_DOC_USE_LIBTOOL_FALSE@GTKDOC_RUN = @GTK_DOC_USE_LIBTOOL_TRUE@GTKDOC_RUN = $(LIBTOOL) --mode=execute # We set GPATH here; this gives us semantics for GNU make # which are more like other make's VPATH, when it comes to # whether a source that is a target of one rule is then # searched for in VPATH/GPATH. # GPATH = $(srcdir) TARGET_DIR = $(HTML_DIR)/$(DOC_MODULE) SETUP_FILES = \ $(content_files) \ $(expand_content_files) \ $(DOC_MAIN_SGML_FILE) \ $(DOC_MODULE)-sections.txt \ $(DOC_MODULE)-overrides.txt # This includes the standard gtk-doc make rules, copied by gtkdocize. # Other files to distribute # e.g. EXTRA_DIST += version.xml.in EXTRA_DIST = $(HTML_IMAGES) $(SETUP_FILES) DOC_STAMPS = setup-build.stamp scan-build.stamp sgml-build.stamp \ html-build.stamp pdf-build.stamp \ sgml.stamp html.stamp pdf.stamp SCANOBJ_FILES = \ $(DOC_MODULE).args \ $(DOC_MODULE).hierarchy \ $(DOC_MODULE).interfaces \ $(DOC_MODULE).prerequisites \ $(DOC_MODULE).signals REPORT_FILES = \ $(DOC_MODULE)-undocumented.txt \ $(DOC_MODULE)-undeclared.txt \ $(DOC_MODULE)-unused.txt CLEANFILES = $(SCANOBJ_FILES) $(REPORT_FILES) $(DOC_STAMPS) gtkdoc-check.test @GTK_DOC_BUILD_HTML_FALSE@HTML_BUILD_STAMP = @GTK_DOC_BUILD_HTML_TRUE@HTML_BUILD_STAMP = html-build.stamp @GTK_DOC_BUILD_PDF_FALSE@PDF_BUILD_STAMP = @GTK_DOC_BUILD_PDF_TRUE@PDF_BUILD_STAMP = pdf-build.stamp #### setup #### GTK_DOC_V_SETUP = $(GTK_DOC_V_SETUP_$(V)) GTK_DOC_V_SETUP_ = $(GTK_DOC_V_SETUP_$(AM_DEFAULT_VERBOSITY)) GTK_DOC_V_SETUP_0 = @echo " DOC Preparing build"; #### scan #### GTK_DOC_V_SCAN = $(GTK_DOC_V_SCAN_$(V)) GTK_DOC_V_SCAN_ = $(GTK_DOC_V_SCAN_$(AM_DEFAULT_VERBOSITY)) GTK_DOC_V_SCAN_0 = @echo " DOC Scanning header files"; GTK_DOC_V_INTROSPECT = $(GTK_DOC_V_INTROSPECT_$(V)) GTK_DOC_V_INTROSPECT_ = $(GTK_DOC_V_INTROSPECT_$(AM_DEFAULT_VERBOSITY)) GTK_DOC_V_INTROSPECT_0 = @echo " DOC Introspecting gobjects"; #### xml #### GTK_DOC_V_XML = $(GTK_DOC_V_XML_$(V)) GTK_DOC_V_XML_ = $(GTK_DOC_V_XML_$(AM_DEFAULT_VERBOSITY)) GTK_DOC_V_XML_0 = @echo " DOC Building XML"; #### html #### GTK_DOC_V_HTML = $(GTK_DOC_V_HTML_$(V)) GTK_DOC_V_HTML_ = $(GTK_DOC_V_HTML_$(AM_DEFAULT_VERBOSITY)) GTK_DOC_V_HTML_0 = @echo " DOC Building HTML"; GTK_DOC_V_XREF = $(GTK_DOC_V_XREF_$(V)) GTK_DOC_V_XREF_ = $(GTK_DOC_V_XREF_$(AM_DEFAULT_VERBOSITY)) GTK_DOC_V_XREF_0 = @echo " DOC Fixing cross-references"; #### pdf #### GTK_DOC_V_PDF = $(GTK_DOC_V_PDF_$(V)) GTK_DOC_V_PDF_ = $(GTK_DOC_V_PDF_$(AM_DEFAULT_VERBOSITY)) GTK_DOC_V_PDF_0 = @echo " DOC Building PDF"; # Files not to distribute # for --rebuild-types in $(SCAN_OPTIONS), e.g. $(DOC_MODULE).types # for --rebuild-sections in $(SCAN_OPTIONS) e.g. $(DOC_MODULE)-sections.txt DISTCLEANFILES = libinftext-$(LIBINFINITY_API_VERSION).types version.xml all: all-am .SUFFIXES: $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/gtk-doc.make $(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) --foreign docs/reference/libinftext/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign docs/reference/libinftext/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_srcdir)/gtk-doc.make $(am__empty): $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs tags TAGS: ctags CTAGS: cscope cscopelist: 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 $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-hook check-am: all-am check: check-am @ENABLE_GTK_DOC_FALSE@all-local: all-am: Makefile all-local installdirs: install: 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) -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic distclean-local dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-data-local install-dvi: install-dvi-am install-dvi-am: install-exec-am: 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 -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic \ maintainer-clean-local mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-local .MAKE: install-am install-strip .PHONY: all all-am all-local check check-am clean clean-generic \ clean-libtool clean-local cscopelist-am ctags-am dist-hook \ distclean distclean-generic distclean-libtool distclean-local \ distdir dvi dvi-am html html-am info info-am install \ install-am install-data install-data-am install-data-local \ 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-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ maintainer-clean-local mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \ uninstall-am uninstall-local .PRECIOUS: Makefile gtkdoc-check.test: Makefile $(AM_V_GEN)echo "#!/bin/sh -e" > $@; \ echo "$(GTKDOC_CHECK_PATH) || exit 1" >> $@; \ chmod +x $@ all-gtk-doc: $(HTML_BUILD_STAMP) $(PDF_BUILD_STAMP) .PHONY: all-gtk-doc @ENABLE_GTK_DOC_TRUE@all-local: all-gtk-doc docs: $(HTML_BUILD_STAMP) $(PDF_BUILD_STAMP) $(REPORT_FILES): sgml-build.stamp setup-build.stamp: -$(GTK_DOC_V_SETUP)if test "$(abs_srcdir)" != "$(abs_builddir)" ; then \ files=`echo $(SETUP_FILES) $(DOC_MODULE).types`; \ if test "x$$files" != "x" ; then \ for file in $$files ; do \ destdir=`dirname $(abs_builddir)/$$file`; \ test -d "$$destdir" || mkdir -p "$$destdir"; \ test -f $(abs_srcdir)/$$file && \ cp -pf $(abs_srcdir)/$$file $(abs_builddir)/$$file || true; \ done; \ fi; \ fi $(AM_V_at)touch setup-build.stamp scan-build.stamp: setup-build.stamp $(HFILE_GLOB) $(CFILE_GLOB) $(GTK_DOC_V_SCAN)_source_dir='' ; \ for i in $(DOC_SOURCE_DIR) ; do \ _source_dir="$${_source_dir} --source-dir=$$i" ; \ done ; \ gtkdoc-scan --module=$(DOC_MODULE) --ignore-headers="$(IGNORE_HFILES)" $${_source_dir} $(SCAN_OPTIONS) $(EXTRA_HFILES) $(GTK_DOC_V_INTROSPECT)if grep -l '^..*$$' $(DOC_MODULE).types > /dev/null 2>&1 ; then \ scanobj_options=""; \ gtkdoc-scangobj 2>&1 --help | grep >/dev/null "\-\-verbose"; \ if test "$$?" = "0"; then \ if test "x$(V)" = "x1"; then \ scanobj_options="--verbose"; \ fi; \ fi; \ CC="$(GTKDOC_CC)" LD="$(GTKDOC_LD)" RUN="$(GTKDOC_RUN)" CFLAGS="$(GTKDOC_CFLAGS) $(CFLAGS)" LDFLAGS="$(GTKDOC_LIBS) $(LDFLAGS)" \ gtkdoc-scangobj $(SCANGOBJ_OPTIONS) $$scanobj_options --module=$(DOC_MODULE); \ else \ for i in $(SCANOBJ_FILES) ; do \ test -f $$i || touch $$i ; \ done \ fi $(AM_V_at)touch scan-build.stamp $(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(DOC_MODULE)-sections.txt $(DOC_MODULE)-overrides.txt: scan-build.stamp @true sgml-build.stamp: setup-build.stamp $(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(HFILE_GLOB) $(CFILE_GLOB) $(DOC_MODULE)-sections.txt $(DOC_MODULE)-overrides.txt $(expand_content_files) xml/gtkdocentities.ent $(GTK_DOC_V_XML)_source_dir='' ; \ for i in $(DOC_SOURCE_DIR) ; do \ _source_dir="$${_source_dir} --source-dir=$$i" ; \ done ; \ gtkdoc-mkdb --module=$(DOC_MODULE) --output-format=xml --expand-content-files="$(expand_content_files)" --main-sgml-file=$(DOC_MAIN_SGML_FILE) $${_source_dir} $(MKDB_OPTIONS) $(AM_V_at)touch sgml-build.stamp sgml.stamp: sgml-build.stamp @true xml/gtkdocentities.ent: Makefile $(GTK_DOC_V_XML)$(MKDIR_P) $(@D) && ( \ echo ""; \ echo ""; \ echo ""; \ echo ""; \ echo ""; \ echo ""; \ echo ""; \ ) > $@ html-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) $(expand_content_files) $(GTK_DOC_V_HTML)rm -rf html && mkdir html && \ mkhtml_options=""; \ gtkdoc-mkhtml 2>&1 --help | grep >/dev/null "\-\-verbose"; \ if test "$$?" = "0"; then \ if test "x$(V)" = "x1"; then \ mkhtml_options="$$mkhtml_options --verbose"; \ fi; \ fi; \ gtkdoc-mkhtml 2>&1 --help | grep >/dev/null "\-\-path"; \ if test "$$?" = "0"; then \ mkhtml_options="$$mkhtml_options --path=\"$(abs_srcdir)\""; \ fi; \ cd html && gtkdoc-mkhtml $$mkhtml_options $(MKHTML_OPTIONS) $(DOC_MODULE) ../$(DOC_MAIN_SGML_FILE) -@test "x$(HTML_IMAGES)" = "x" || \ for file in $(HTML_IMAGES) ; do \ if test -f $(abs_srcdir)/$$file ; then \ cp $(abs_srcdir)/$$file $(abs_builddir)/html; \ fi; \ if test -f $(abs_builddir)/$$file ; then \ cp $(abs_builddir)/$$file $(abs_builddir)/html; \ fi; \ done; $(GTK_DOC_V_XREF)gtkdoc-fixxref --module=$(DOC_MODULE) --module-dir=html --html-dir=$(HTML_DIR) $(FIXXREF_OPTIONS) $(AM_V_at)touch html-build.stamp pdf-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) $(expand_content_files) $(GTK_DOC_V_PDF)rm -f $(DOC_MODULE).pdf && \ mkpdf_options=""; \ gtkdoc-mkpdf 2>&1 --help | grep >/dev/null "\-\-verbose"; \ if test "$$?" = "0"; then \ if test "x$(V)" = "x1"; then \ mkpdf_options="$$mkpdf_options --verbose"; \ fi; \ fi; \ if test "x$(HTML_IMAGES)" != "x"; then \ for img in $(HTML_IMAGES); do \ part=`dirname $$img`; \ echo $$mkpdf_options | grep >/dev/null "\-\-imgdir=$$part "; \ if test $$? != 0; then \ mkpdf_options="$$mkpdf_options --imgdir=$$part"; \ fi; \ done; \ fi; \ gtkdoc-mkpdf --path="$(abs_srcdir)" $$mkpdf_options $(DOC_MODULE) $(DOC_MAIN_SGML_FILE) $(MKPDF_OPTIONS) $(AM_V_at)touch pdf-build.stamp ############## clean-local: @rm -f *~ *.bak @rm -rf .libs @if echo $(SCAN_OPTIONS) | grep -q "\-\-rebuild-types" ; then \ rm -f $(DOC_MODULE).types; \ fi @if echo $(SCAN_OPTIONS) | grep -q "\-\-rebuild-sections" ; then \ rm -f $(DOC_MODULE)-sections.txt; \ fi distclean-local: @rm -rf xml html $(REPORT_FILES) $(DOC_MODULE).pdf \ $(DOC_MODULE)-decl-list.txt $(DOC_MODULE)-decl.txt @if test "$(abs_srcdir)" != "$(abs_builddir)" ; then \ rm -f $(SETUP_FILES) $(DOC_MODULE).types; \ fi maintainer-clean-local: @rm -rf xml html install-data-local: @installfiles=`echo $(builddir)/html/*`; \ if test "$$installfiles" = '$(builddir)/html/*'; \ then echo 1>&2 'Nothing to install' ; \ else \ if test -n "$(DOC_MODULE_VERSION)"; then \ installdir="$(DESTDIR)$(TARGET_DIR)-$(DOC_MODULE_VERSION)"; \ else \ installdir="$(DESTDIR)$(TARGET_DIR)"; \ fi; \ $(mkinstalldirs) $${installdir} ; \ for i in $$installfiles; do \ echo ' $(INSTALL_DATA) '$$i ; \ $(INSTALL_DATA) $$i $${installdir}; \ done; \ if test -n "$(DOC_MODULE_VERSION)"; then \ mv -f $${installdir}/$(DOC_MODULE).devhelp2 \ $${installdir}/$(DOC_MODULE)-$(DOC_MODULE_VERSION).devhelp2; \ fi; \ $(GTKDOC_REBASE) --relative --dest-dir=$(DESTDIR) --html-dir=$${installdir}; \ fi uninstall-local: @if test -n "$(DOC_MODULE_VERSION)"; then \ installdir="$(DESTDIR)$(TARGET_DIR)-$(DOC_MODULE_VERSION)"; \ else \ installdir="$(DESTDIR)$(TARGET_DIR)"; \ fi; \ rm -rf $${installdir} # # Require gtk-doc when making dist # @HAVE_GTK_DOC_TRUE@dist-check-gtkdoc: docs @HAVE_GTK_DOC_FALSE@dist-check-gtkdoc: @HAVE_GTK_DOC_FALSE@ @echo "*** gtk-doc is needed to run 'make dist'. ***" @HAVE_GTK_DOC_FALSE@ @echo "*** gtk-doc was not found when 'configure' ran. ***" @HAVE_GTK_DOC_FALSE@ @echo "*** please install gtk-doc and rerun 'configure'. ***" @HAVE_GTK_DOC_FALSE@ @false dist-hook: dist-check-gtkdoc all-gtk-doc dist-hook-local @mkdir $(distdir)/html @cp ./html/* $(distdir)/html @-cp ./$(DOC_MODULE).pdf $(distdir)/ @-cp ./$(DOC_MODULE).types $(distdir)/ @-cp ./$(DOC_MODULE)-sections.txt $(distdir)/ @cd $(distdir) && rm -f $(DISTCLEANFILES) @$(GTKDOC_REBASE) --online --relative --html-dir=$(distdir)/html .PHONY : dist-hook-local docs # Comment this out if you want your docs-status tested during 'make check' #TESTS = $(GTKDOC_CHECK) # 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: libinfinity-0.7.1/docs/reference/libinftext/PaxHeaders.26529/Makefile.am0000644000000000000000000000013212400102201022653 xustar0030 mtime=1409320065.091132986 30 atime=1409320065.091132986 30 ctime=1488261611.652088993 libinfinity-0.7.1/docs/reference/libinftext/Makefile.am0000644000175000017500000000642112400102201023410 0ustar00arminarmin00000000000000## Process this file with automake to produce Makefile.in # We require automake 1.6 at least. AUTOMAKE_OPTIONS = 1.6 # This is a blank Makefile.am for using gtk-doc. # Copy this to your project's API docs directory and modify the variables to # suit your project. See the GTK+ Makefiles in gtk+/docs/reference for examples # of using the various options. # The name of the module, e.g. 'glib'. DOC_MODULE=libinftext-$(LIBINFINITY_API_VERSION) # The top-level SGML file. You can change this if you want to. DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml # The directory containing the source code. Relative to $(srcdir). # gtk-doc will search all .c & .h files beneath here for inline comments # documenting the functions and macros. # e.g. DOC_SOURCE_DIR=../../../gtk DOC_SOURCE_DIR=$(top_srcdir)/libinftext # Extra options to pass to gtkdoc-scangobj. Not normally needed. SCANGOBJ_OPTIONS= # Extra options to supply to gtkdoc-scan. # e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED" SCAN_OPTIONS=--rebuild-types # Extra options to supply to gtkdoc-mkdb. # e.g. MKDB_OPTIONS=--sgml-mode --output-format=xml MKDB_OPTIONS=--sgml-mode --output-format=xml # Extra options to supply to gtkdoc-mktmpl # e.g. MKTMPL_OPTIONS=--only-section-tmpl MKTMPL_OPTIONS= # Extra options to supply to gtkdoc-fixref. Not normally needed. # e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html FIXXREF_OPTIONS = \ --extra-dir=../libinfinity/html # Used for dependencies. The docs will be rebuilt if any of these change. # e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h # e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c HFILE_GLOB = \ $(top_srcdir)/libinftext/*.h CFILE_GLOB = \ $(top_srcdir)/libinftext/*.c # Header files to ignore when scanning. # e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h IGNORE_HFILES = # Images to copy into HTML directory. # e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png HTML_IMAGES= # Extra SGML files that are included by $(DOC_MAIN_SGML_FILE). # e.g. content_files=running.sgml building.sgml changes-2.0.sgml content_files = \ ../version.xml # SGML files where gtk-doc abbrevations (#GtkWidget) are expanded # These files must be listed here *and* in content_files # e.g. expand_content_files=running.sgml expand_content_files= # CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library. # Only needed if you are using gtkdoc-scangobj to dynamically query widget # signals and properties. # e.g. INCLUDES=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS) # e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib) #INCLUDES=$(inftext_CFLAGS) AM_CPPFLAGS=$(inftext_CFLAGS) GTKDOC_LIBS = \ $(inftext_LIBS) \ $(top_builddir)/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(top_builddir)/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la # This includes the standard gtk-doc make rules, copied by gtkdocize. include $(top_srcdir)/gtk-doc.make # Other files to distribute # e.g. EXTRA_DIST += version.xml.in EXTRA_DIST += # Files not to distribute # for --rebuild-types in $(SCAN_OPTIONS), e.g. $(DOC_MODULE).types # for --rebuild-sections in $(SCAN_OPTIONS) e.g. $(DOC_MODULE)-sections.txt DISTCLEANFILES = libinftext-$(LIBINFINITY_API_VERSION).types version.xml # Comment this out if you want your docs-status tested during 'make check' #TESTS = $(GTKDOC_CHECK) libinfinity-0.7.1/docs/reference/libinftext/PaxHeaders.26529/libinftext-0.7-docs.sgml0000644000000000000000000000013213034342512025122 xustar0030 mtime=1483851082.013718339 30 atime=1483851082.013718339 30 ctime=1488261611.656088984 libinfinity-0.7.1/docs/reference/libinftext/libinftext-0.7-docs.sgml0000644000175000017500000000321713034342512025657 0ustar00arminarmin00000000000000 ]> libinftext-&api_version; Reference Manual for libinftext &version;. The latest version of this documentation can be found on-line at http://infinote.0x539.de/libinfinity/API/libinftext/. libinftext API reference libinfinity-0.7.1/docs/reference/libinftext/PaxHeaders.26529/libinftext-0.7-overrides.txt0000644000000000000000000000013012401204462026045 xustar0029 mtime=1409616178.63426398 29 atime=1409616178.63426398 30 ctime=1488261611.656088984 libinfinity-0.7.1/docs/reference/libinftext/libinftext-0.7-overrides.txt0000644000175000017500000000000012401204462026567 0ustar00arminarmin00000000000000libinfinity-0.7.1/docs/reference/PaxHeaders.26529/libinfgtk0000644000000000000000000000013213055210760020364 xustar0030 mtime=1488261616.860077325 30 atime=1488261614.124083461 30 ctime=1488261616.860077325 libinfinity-0.7.1/docs/reference/libinfgtk/0000755000175000017500000000000013055210760021173 5ustar00arminarmin00000000000000libinfinity-0.7.1/docs/reference/libinfgtk/PaxHeaders.26529/html0000644000000000000000000000013213055210760021330 xustar0030 mtime=1488261616.896077244 30 atime=1488261616.848077351 30 ctime=1488261616.896077244 libinfinity-0.7.1/docs/reference/libinfgtk/html/0000755000175000017500000000000013055210760022137 5ustar00arminarmin00000000000000libinfinity-0.7.1/docs/reference/libinfgtk/html/PaxHeaders.26529/left-insensitive.png0000644000000000000000000000013213055210760025403 xustar0030 mtime=1488261616.852077342 30 atime=1488261616.852077342 30 ctime=1488261616.852077342 libinfinity-0.7.1/docs/reference/libinfgtk/html/left-insensitive.png0000644000175000017500000000061313055210760026135 0ustar00arminarmin00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEà 4ÓkMIDAT8ËÍ’­NQ…¿éö†…@¡p üdsÛÀÖ`*š4Á@ò„W@ A!ÈÔ†@6Ü^ƒ 5hxèIH R`sQpäÌ™339þBÊó|Ês¤ªKEQTÛíöK°@·ÛÎià¦^¯Ï~îWʆ½÷‹ÀÕûðå`0˜åTJ6·Tõ˜‘cYn6›AÞû Æ€½~¿ß±Ö>}Ç­Žœs;ªº ¨ˆlYkwËÞürˆ¼†ºó£ Þû5U= °/"›ÖÚç  ¬µ‡"ÒuU=ɲlü×ArÎÕDä˜zÃáp5I’ûà4^E+ÀP3Æœçàq_«êp Ì¥iñ¯ðUY¥‚p=#IEND®B`‚libinfinity-0.7.1/docs/reference/libinfgtk/html/PaxHeaders.26529/InfGtkBrowserModelSort.html0000644000000000000000000000013213055210760026652 xustar0030 mtime=1488261616.892077253 30 atime=1488261616.892077253 30 ctime=1488261616.892077253 libinfinity-0.7.1/docs/reference/libinfgtk/html/InfGtkBrowserModelSort.html0000644000175000017500000001704613055210760027414 0ustar00arminarmin00000000000000 InfGtkBrowserModelSort: libinfgtk-0.7 Reference Manual

InfGtkBrowserModelSort

InfGtkBrowserModelSort

Types and Values

Object Hierarchy

    GObject
    ╰── GtkTreeModelSort
        ╰── InfGtkBrowserModelSort

Implemented Interfaces

InfGtkBrowserModelSort implements GtkTreeModel, GtkTreeSortable, GtkTreeDragSource and InfGtkBrowserModel.

Description

Functions

inf_gtk_browser_model_sort_new ()

InfGtkBrowserModelSort *
inf_gtk_browser_model_sort_new (InfGtkBrowserModel *child_model);

Creates a new InfGtkBrowserModelSort, sorting child_model .

[constructor]

Parameters

child_model

A InfGtkBrowserModel.

 

Returns

A new InfGtkBrowserModelSort.

[transfer full]

Types and Values

struct InfGtkBrowserModelSort

struct InfGtkBrowserModelSort;


struct InfGtkBrowserModelSortClass

struct InfGtkBrowserModelSortClass {
  GtkTreeModelSortClass parent_class;
};

libinfinity-0.7.1/docs/reference/libinfgtk/html/PaxHeaders.26529/InfGtkAclSheetView.html0000644000000000000000000000013213055210760025721 xustar0030 mtime=1488261616.892077253 30 atime=1488261616.892077253 30 ctime=1488261616.892077253 libinfinity-0.7.1/docs/reference/libinfgtk/html/InfGtkAclSheetView.html0000644000175000017500000010147513055210760026463 0ustar00arminarmin00000000000000 InfGtkAclSheetView: libinfgtk-0.7 Reference Manual

InfGtkAclSheetView

InfGtkAclSheetView — A widget showing a InfAclSheet

Stability Level

Unstable, unless otherwise indicated

Properties

gboolean editable Read / Write / Construct
InfAclMask * permission-mask Read / Write
InfAclSheet * sheet Read / Write / Construct
gboolean show-default Read / Write

Signals

Types and Values

Object Hierarchy

    GObject
    ╰── GInitiallyUnowned
        ╰── GtkWidget
            ╰── GtkContainer
                ╰── GtkGrid
                    ╰── InfGtkAclSheetView

Implemented Interfaces

InfGtkAclSheetView implements AtkImplementorIface, GtkBuildable and GtkOrientable.

Includes

#include <libinfgtk/inf-gtk-acl-sheet-view.h>

Description

InfGtkAclSheetView is a widget that can show a InfAclSheet in the user interface. Optionally, it also allows the user to edit the sheet.

Functions

inf_gtk_acl_sheet_view_new ()

GtkWidget *
inf_gtk_acl_sheet_view_new (void);

Creates a new InfGtkAclSheetView. To show a sheet in the view, call inf_gtk_acl_sheet_view_set_sheet().

[constructor]

Returns

A new InfGtkAclSheetView.

[transfer full]


inf_gtk_acl_sheet_view_set_sheet ()

void
inf_gtk_acl_sheet_view_set_sheet (InfGtkAclSheetView *view,
                                  const InfAclSheet *sheet);

Sets the sheet to be displayed by view .

Parameters

view

A InfGtkAclSheetView.

 

sheet

The InfAclSheet to show, or NULL.

[allow-none]

inf_gtk_acl_sheet_view_get_sheet ()

const InfAclSheet *
inf_gtk_acl_sheet_view_get_sheet (InfGtkAclSheetView *view);

Returns the sheet that is currently being displayed by view , or NULL if there is no sheet displayed.

Parameters

view

A InfGtkAclSheetView.

 

Returns

A InfAclSheet owned by view , or NULL.

[transfer none][allow-none]


inf_gtk_acl_sheet_view_set_editable ()

void
inf_gtk_acl_sheet_view_set_editable (InfGtkAclSheetView *view,
                                     gboolean editable);

Sets whether the sheet being displayed by view can be edited by the user or not.

Parameters

view

A InfGtkAclSheetView.

 

editable

Whether to make the sheet editable or not.

 

inf_gtk_acl_sheet_view_get_editable ()

gboolean
inf_gtk_acl_sheet_view_get_editable (InfGtkAclSheetView *view);

Returns whether the sheet being displayed by view can be edited by the user or not.

Parameters

view

A InfGtkAclSheetView.

 

Returns

TRUE when the sheet can be edited or FALSE otherwise.


inf_gtk_acl_sheet_view_set_show_default ()

void
inf_gtk_acl_sheet_view_set_show_default
                               (InfGtkAclSheetView *view,
                                gboolean show);

Specifies whether the "default" column is shown, and whether it is allowed to change certain permissions to the default value or not. The ACL sheet for the default account of a directory's root node is not allowed to have default permissions. In this case this function should be called to hide the default column from the user interface.

Parameters

view

A InfGtkAclSheetView.

 

show

Whether to show the default column.

 

inf_gtk_acl_sheet_view_get_show_default ()

gboolean
inf_gtk_acl_sheet_view_get_show_default
                               (InfGtkAclSheetView *view);

Returns whether the "default" column is shown.

Parameters

view

A InfGtkAclSheetView.

 

Returns

TRUE if the "default" column is shown or FALSE otherwise.


inf_gtk_acl_sheet_view_set_permission_mask ()

void
inf_gtk_acl_sheet_view_set_permission_mask
                               (InfGtkAclSheetView *view,
                                const InfAclMask *mask);

Sets which permissions of the sheet to show. Only the permissions that are enabled in mask ar being shown. By default all permissions are shown.

Parameters

view

A InfGtkAclSheetView.

 

mask

A InfAclMask with the permissions to show.

 

inf_gtk_acl_sheet_view_get_permission_mask ()

const InfAclMask *
inf_gtk_acl_sheet_view_get_permission_mask
                               (InfGtkAclSheetView *view);

Returns a InfAclMask specifies which permissions are currently being shown by view .

Parameters

view

A InfGtkAclSheetView.

 

Returns

A InfAclMask owned by view . It must not be freed.

[transfer none]

Types and Values

struct InfGtkAclSheetView

struct InfGtkAclSheetView;

InfGtkAclSheetView is an opaque data type. You should only access it via the public API functions.


struct InfGtkAclSheetViewClass

struct InfGtkAclSheetViewClass {
  void (*sheet_changed)(InfGtkAclSheetView* view);
};

This structure contains the default signal handlers for the InfGtkAclSheetView class.

Members

sheet_changed ()

Default signal handler for the “sheet-changed†signal.

 

Property Details

The “editable†property

  “editable†                gboolean

Whether the sheet can be edited by the user or not.

Flags: Read / Write / Construct

Default value: FALSE


The “permission-mask†property

  “permission-mask†         InfAclMask *

Specifies which permissions to show in the sheet view.

Flags: Read / Write


The “sheet†property

  “sheet†                   InfAclSheet *

The ACL sheet the widget is displaying.

Flags: Read / Write / Construct


The “show-default†property

  “show-default†            gboolean

Whether to show the "default" column.

Flags: Read / Write

Default value: TRUE

Signal Details

The “sheet-changed†signal

void
user_function (InfGtkAclSheetView *view,
               gpointer            user_data)

This signal is emitted when the InfAclSheet displayed by view was changed by the user.

Parameters

view

The InfGtkAclSheetView that emitted the signal.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last

libinfinity-0.7.1/docs/reference/libinfgtk/html/PaxHeaders.26529/libinfgtk-0.7.devhelp20000644000000000000000000000013213055210760025313 xustar0030 mtime=1488261616.852077342 30 atime=1488261616.852077342 30 ctime=1488261616.852077342 libinfinity-0.7.1/docs/reference/libinfgtk/html/libinfgtk-0.7.devhelp20000644000175000017500000004311013055210760026044 0ustar00arminarmin00000000000000 libinfinity-0.7.1/docs/reference/libinfgtk/html/PaxHeaders.26529/InfGtkBrowserStore.html0000644000000000000000000000013213055210760026036 xustar0030 mtime=1488261616.892077253 30 atime=1488261616.892077253 30 ctime=1488261616.892077253 libinfinity-0.7.1/docs/reference/libinfgtk/html/InfGtkBrowserStore.html0000644000175000017500000006447013055210760026603 0ustar00arminarmin00000000000000 InfGtkBrowserStore: libinfgtk-0.7 Reference Manual

InfGtkBrowserStore

InfGtkBrowserStore

Properties

InfCommunicationManager * communication-manager Read / Write / Construct Only
InfIo * io Read / Write / Construct Only

Types and Values

Object Hierarchy

    GObject
    ╰── InfGtkBrowserStore

Implemented Interfaces

InfGtkBrowserStore implements GtkTreeModel and InfGtkBrowserModel.

Description

Functions

inf_gtk_browser_store_new ()

InfGtkBrowserStore *
inf_gtk_browser_store_new (InfIo *io,
                           InfCommunicationManager *comm_manager);

Creates a new InfGtkBrowserStore.

[constructor]

Parameters

io

A InfIo object for the created InfcBrowser to schedule timeouts.

 

comm_manager

The InfCommunicationManager with which to explore remote directories.

 

Returns

A new InfGtkBrowserStore.

[transfer full]


inf_gtk_browser_store_add_discovery ()

void
inf_gtk_browser_store_add_discovery (InfGtkBrowserStore *store,
                                     InfDiscovery *discovery);

Adds discovery to model . The model will then show up discovered servers.

Parameters

store

A InfGtkBrowserStore.

 

discovery

A InfDiscovery not yet added to model .

 

inf_gtk_browser_store_add_connection ()

InfBrowser *
inf_gtk_browser_store_add_connection (InfGtkBrowserStore *store,
                                      InfXmlConnection *connection,
                                      const gchar *name);

This function adds a connection to the store . store will show up an item for the connection if there is not already one. This allows to browse the explored parts of the directory of the remote site. If name is NULL, then the “remote-id†of the connection will be used.

The return value is the InfBrowser for the added connection, or an existing browser for the connection, if there is any.

Parameters

store

A InfGtkBrowserStore.

 

connection

A InfXmlConnection.

 

name

Name for the item, or NULL.

[allow-none]

Returns

An InfBrowser for the new connection.

[transfer none]


inf_gtk_browser_store_add_browser ()

void
inf_gtk_browser_store_add_browser (InfGtkBrowserStore *store,
                                   InfBrowser *browser,
                                   const gchar *name);

This function adds a browser to the store . store will show up an item for the browser if there is not already one. This allows to browse the explored part of the browser. The name parameter must not be NULL.

Parameters

store

A InfGtkBrowserStore.

 

browser

A InfBrowser.

 

name

Name for the item.

 

inf_gtk_browser_store_remove_browser ()

void
inf_gtk_browser_store_remove_browser (InfGtkBrowserStore *store,
                                      InfBrowser *browser);

This function removes the entry for the given browser from store .

Parameters

store

A InfGtkBrowserStore

 

browser

A InfBrowser contained in store .

 

inf_gtk_browser_store_remove_connection ()

void
inf_gtk_browser_store_remove_connection
                               (InfGtkBrowserStore *store,
                                InfXmlConnection *connection);

This function removes the entry for the given connection from store .

Parameters

store

A InfGtkBrowserStore.

 

connection

A InfXmlConnection contained in store .

 

inf_gtk_browser_store_clear_connection_error ()

void
inf_gtk_browser_store_clear_connection_error
                               (InfGtkBrowserStore *store,
                                InfXmlConnection *connection);

This function clears the error for the entry which belongs to the given connection.

Parameters

store

A InfGtkBrowserStore.

 

connection

A InfXmlConnection contained in store .

 

inf_gtk_browser_store_set_connection_name ()

void
inf_gtk_browser_store_set_connection_name
                               (InfGtkBrowserStore *store,
                                InfXmlConnection *connection,
                                const gchar *name);

This function sets the name of connection .

Parameters

store

A InfGtkBrowserStore.

 

connection

A InfXmlConnection contained in store .

 

name

The new name to set for the connection.

 

Types and Values

struct InfGtkBrowserStore

struct InfGtkBrowserStore;


struct InfGtkBrowserStoreClass

struct InfGtkBrowserStoreClass {
  GObjectClass parent_class;
};

Property Details

The “communication-manager†property

  “communication-manager†   InfCommunicationManager *

The communication manager used for browsing remote directories.

Flags: Read / Write / Construct Only


The “io†property

  “io†                      InfIo *

The IO object used for the created browsers to schedule timeouts.

Flags: Read / Write / Construct Only

libinfinity-0.7.1/docs/reference/libinfgtk/html/PaxHeaders.26529/InfGtkPermissionsDialog.html0000644000000000000000000000013213055210760027031 xustar0030 mtime=1488261616.892077253 30 atime=1488261616.892077253 30 ctime=1488261616.892077253 libinfinity-0.7.1/docs/reference/libinfgtk/html/InfGtkPermissionsDialog.html0000644000175000017500000004432513055210760027573 0ustar00arminarmin00000000000000 InfGtkPermissionsDialog: libinfgtk-0.7 Reference Manual

InfGtkPermissionsDialog

InfGtkPermissionsDialog — A dialog to view and modify the ACL of a directory node

Stability Level

Unstable, unless otherwise indicated

Properties

InfBrowser * browser Read / Write / Construct Only
InfBrowserIter * browser-iter Read / Write / Construct Only

Types and Values

Object Hierarchy

    GObject
    ╰── GInitiallyUnowned
        ╰── GtkWidget
            ╰── GtkContainer
                ╰── GtkBin
                    ╰── GtkWindow
                        ╰── GtkDialog
                            ╰── InfGtkPermissionsDialog

Implemented Interfaces

InfGtkPermissionsDialog implements AtkImplementorIface and GtkBuildable.

Includes

#include <libinfgtk/inf-gtk-permissions-dialog.h>

Description

InfGtkPermissionsDialog is a dialog widget which allows to view and modify the ACL of a node in a infinote directory. It shows a list of all available users and allows the permissions for each of them to be changed, using a InfGtkAclSheetView widget.

If the "can-query-acl" permission is not granted for the local user, the dialog only shows the permissions for the default user and the local user. The dialog also comes with a status text to inform the user why certain functionality is not available.

The dialog class reacts to changes to the ACL in real time, and also if the node that is being monitored is removed.

Functions

inf_gtk_permissions_dialog_new ()

InfGtkPermissionsDialog *
inf_gtk_permissions_dialog_new (GtkWindow *parent,
                                GtkDialogFlags dialog_flags,
                                InfBrowser *browser,
                                const InfBrowserIter *iter);

Creates a new InfGtkPermissionsDialog, showing the ACL for the node iter points to inside browser . If browser is NULL, iter must be NULL, too. In that case no permissions are shown, and the node to be shown can be set later with inf_gtk_permissions_dialog_set_node().

[constructor]

Parameters

parent

Parent GtkWindow of the dialog.

 

dialog_flags

Flags for the dialog, see GtkDialogFlags.

 

browser

The InfBrowser containing the node to show permissions for, or NULL.

[allow-none]

iter

An iterator pointing to the node to show permissions for, or NULL.

[allow-none]

Returns

A new InfGtkPermissionsDialog. Free with gtk_widget_destroy() when no longer needed.

[transfer full]


inf_gtk_permissions_dialog_set_node ()

void
inf_gtk_permissions_dialog_set_node (InfGtkPermissionsDialog *dialog,
                                     InfBrowser *browser,
                                     const InfBrowserIter *iter);

Changes the node the dialog shows permissions for. To unset the node, both browser and iter should be NULL.

Parameters

dialog

A InfGtkPermissionsDialog.

 

browser

The InfBrowser containing the node to show permissions for, or NULL.

[allow-none]

iter

An iterator pointing to the node to show permissions for, or NULL.

[allow-none]

Types and Values

struct InfGtkPermissionsDialog

struct InfGtkPermissionsDialog;

InfGtkPermissionsDialog is an opaque data type. You should only access it via the public API functions.


struct InfGtkPermissionsDialogClass

struct InfGtkPermissionsDialogClass {
};

This structure does not contain any public fields.

Property Details

The “browser†property

  “browser†                 InfBrowser *

The browser with the node for which to show the permissions.

Flags: Read / Write / Construct Only


The “browser-iter†property

  “browser-iter†            InfBrowserIter *

An iterator pointing to the node inside the browser for which to show the permissions.

Flags: Read / Write / Construct Only

libinfinity-0.7.1/docs/reference/libinfgtk/html/PaxHeaders.26529/annotation-glossary.html0000644000000000000000000000013213055210760026306 xustar0030 mtime=1488261616.892077253 30 atime=1488261616.892077253 30 ctime=1488261616.892077253 libinfinity-0.7.1/docs/reference/libinfgtk/html/annotation-glossary.html0000644000175000017500000001073413055210760027045 0ustar00arminarmin00000000000000 Annotation Glossary: libinfgtk-0.7 Reference Manual

Annotation Glossary

A

allow-none

NULL is OK, both for passing and for returning.

C

constructor

This symbol is a constructor, not a static method.

O

out

Parameter for returning results. Default is transfer full.

T

transfer floating

Alias for transfer none, used for objects with floating refs.

transfer full

Free data after the code is done.

transfer none

Don't free data after the code is done.

type

Override the parsed C type with given type.

U

Unstable

Unstable interfaces are experimental or transitional. They are typically used to give outside developers early access to new or rapidly changing technology, or to provide an interim solution to a problem where a more general solution is anticipated. No claims are made about either source or binary compatibility from one minor release to the next. The Unstable interface level is a warning that these interfaces are subject to change without warning and should not be used in unbundled products. Given such caveats, customer impact need not be a factor when considering incompatible changes to an Unstable interface in a major or minor release. Nonetheless, when such changes are introduced, the changes should still be mentioned in the release notes for the affected release.

libinfinity-0.7.1/docs/reference/libinfgtk/html/PaxHeaders.26529/InfGtkIo.html0000644000000000000000000000013213055210760023745 xustar0030 mtime=1488261616.892077253 30 atime=1488261616.892077253 30 ctime=1488261616.892077253 libinfinity-0.7.1/docs/reference/libinfgtk/html/InfGtkIo.html0000644000175000017500000001323413055210760024502 0ustar00arminarmin00000000000000 InfGtkIo: libinfgtk-0.7 Reference Manual

InfGtkIo

InfGtkIo

Functions

Types and Values

struct InfGtkIo
struct InfGtkIoClass

Object Hierarchy

    GObject
    ╰── InfGtkIo

Implemented Interfaces

InfGtkIo implements InfIo.

Description

Functions

inf_gtk_io_new ()

InfGtkIo *
inf_gtk_io_new (void);

Creates a new InfGtkIo.

[constructor]

Returns

A new InfGtkIo. Free with g_object_unref() when no longer needed.

[transfer full]

Types and Values

struct InfGtkIo

struct InfGtkIo;


struct InfGtkIoClass

struct InfGtkIoClass {
  GObjectClass parent_class;
};

libinfinity-0.7.1/docs/reference/libinfgtk/html/PaxHeaders.26529/up-insensitive.png0000644000000000000000000000013213055210760025075 xustar0030 mtime=1488261616.852077342 30 atime=1488261616.852077342 30 ctime=1488261616.852077342 libinfinity-0.7.1/docs/reference/libinfgtk/html/up-insensitive.png0000644000175000017500000000056613055210760025636 0ustar00arminarmin00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEà 4ÓkMIDAT8Ëí’?/QÅÏ™?[êu$¾€V³î›ÑâHTD³ø”ÛˆBM+¡!™ÂÌ<ˆDã+èô[mdÞ\…·bø{º{sÎ/97˜ªSÖÚ£º®»<ìTõ8ŒcÌÉ¿UU­‘¼‡•WÕÍ,Ë®ÿ”e¹EÑ €žªîÉSïmÛ®æy~û+À9·è½¿0`hŒ9u†ªº`Çñr¿ßùpÎÍ{ïÌ8‘m’ ªJkí€-o$—Dä¢  išË¾'¹; ‡ Jr‡äCð\¨*¿HΑ|JÓtCDÆßo#"ã$IÖ<«êBQ½é£êêÉ]•TKúIEND®B`‚libinfinity-0.7.1/docs/reference/libinfgtk/html/PaxHeaders.26529/libinfgtk-0.7-InfGtkAccountCreation0000644000000000000000000000013213055210760027765 xustar0030 mtime=1488261616.892077253 30 atime=1488261616.892077253 30 ctime=1488261616.892077253 libinfinity-0.7.1/docs/reference/libinfgtk/html/libinfgtk-0.7-InfGtkAccountCreationsDialog.html0000644000175000017500000005245713055210760033002 0ustar00arminarmin00000000000000 InfGtkAccountCreationDialog: libinfgtk-0.7 Reference Manual

InfGtkAccountCreationDialog

InfGtkAccountCreationDialog — A dialog to request a new account on a server.

Stability Level

Unstable, unless otherwise indicated

Properties

InfBrowser * browser Read / Write / Construct
InfIo * io Read / Write / Construct Only

Signals

Object Hierarchy

    GObject
    ╰── GInitiallyUnowned
        ╰── GtkWidget
            ╰── GtkContainer
                ╰── GtkBin
                    ╰── GtkWindow
                        ╰── GtkDialog
                            ╰── InfGtkAccountCreationDialog

Implemented Interfaces

InfGtkAccountCreationDialog implements AtkImplementorIface and GtkBuildable.

Includes

#include <libinfgtk/inf-gtk-account-creation-dialog.h>

Description

InfGtkAccountCreationDialog is a dialog widget which allows to request creation of a new account on an infinote server. If the "can-create-acl-account" permission is not granted, the dialog shows an error message instead.

Functions

inf_gtk_account_creation_dialog_new ()

InfGtkAccountCreationDialog *
inf_gtk_account_creation_dialog_new (GtkWindow *parent,
                                     GtkDialogFlags dialog_flags,
                                     InfIo *io,
                                     InfBrowser *browser);

Creates a new InfGtkAccountCreationDialog, which can be used to generate a new account on the infinote directory represented by the given browser.

[constructor]

Parameters

parent

Parent GtkWindow of the dialog.

 

dialog_flags

Flags for the dialog, see GtkDialogFlags.

 

io

A InfIo object to schedule asynchronous operations.

 

browser

The InfBrowser for which to create a new account.

 

Returns

A new InfGtkAccountCreationDialog. Free with gtk_widget_destroy() when no longer needed.

[transfer full]


inf_gtk_account_creation_dialog_set_browser ()

void
inf_gtk_account_creation_dialog_set_browser
                               (InfGtkAccountCreationDialog *dlg,
                                InfBrowser *browser);

Changes the browser for which to create a new account.

Parameters

dlg

A InfGtkAccountCreationDialog.

 

browser

The InfBrowser for which to create a new account, or NULL.

 

Types and Values

struct InfGtkAccountCreationDialog

struct InfGtkAccountCreationDialog;

InfGtkAccountCreationDialog is an opaque data type. You should only access it via the public API functions.


struct InfGtkAccountCreationDialogClass

struct InfGtkAccountCreationDialogClass {
  void(*account_created)(InfGtkAccountCreationDialog* dialog,
                         gnutls_x509_privkey_t key,
                         InfCertificateChain* chain,
                         const InfAclAccount* account);
};

This structure contains the default signal handlers for the InfGtkAccountCreationDialog class.

Members

account_created ()

Default signal handler for the “account-created†signal.

 

Property Details

The “browser†property

  “browser†                 InfBrowser *

The infinote directory for which to create an account.

Flags: Read / Write / Construct


The “io†property

  “io†                      InfIo *

The InfIo object to schedule asynchronous operations.

Flags: Read / Write / Construct Only

Signal Details

The “account-created†signal

void
user_function (InfGtkAccountCreationDialog *dialog,
               gpointer                     key,
               InfCertificateChain         *certificate,
               InfAclAccount               *account,
               gpointer                     user_data)

This signal is emitted whenever a new account has been created with the dialog. Along with the created account, the login credentials are provided. Note that the private key is owned by the dialog, and will be deleted after the signal was emitted.

Parameters

dialog

The InfGtkAccountCreationDialog emitting the signal.

 

key

A newly generated private key that the user certificate is signed with.

 

certificate

A certificate signed by the server associated to the new account.

 

account

The newly created account.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last

libinfinity-0.7.1/docs/reference/libinfgtk/html/PaxHeaders.26529/index.html0000644000000000000000000000013213055210760023402 xustar0030 mtime=1488261616.892077253 30 atime=1488261616.892077253 30 ctime=1488261616.892077253 libinfinity-0.7.1/docs/reference/libinfgtk/html/index.html0000644000175000017500000000747713055210760024153 0ustar00arminarmin00000000000000 libinfgtk-0.7 Reference Manual: libinfgtk-0.7 Reference Manual

for libinfgtk 0.7.0. The latest version of this documentation can be found on-line at http://infinote.0x539.de/libinfinity/API/libinfgtk/.


libinfgtk API
InfGtkBrowserView
InfGtkBrowserModel — Interface for tree models representing infinote directories
InfGtkBrowserStore
InfGtkBrowserModelFilter
InfGtkBrowserModelSort
InfGtkPermissionsDialog — A dialog to view and modify the ACL of a directory node
InfGtkAccountCreationDialog — A dialog to request a new account on a server.
InfGtkCertificateManager — Verify server certificates and warn the user
InfGtkCertificateDialog — A dialog warning the user about a server's certificate
InfGtkCertificateView
InfGtkConnectionView — A widget showing connection parameters
InfGtkChat — Gtk interface to InfChatSession
InfGtkAclSheetView — A widget showing a InfAclSheet
InfGtkIo
Annotation Glossary
libinfinity-0.7.1/docs/reference/libinfgtk/html/PaxHeaders.26529/InfGtkConnectionView.html0000644000000000000000000000013213055210760026330 xustar0030 mtime=1488261616.892077253 30 atime=1488261616.892077253 30 ctime=1488261616.892077253 libinfinity-0.7.1/docs/reference/libinfgtk/html/InfGtkConnectionView.html0000644000175000017500000003474013055210760027072 0ustar00arminarmin00000000000000 InfGtkConnectionView: libinfgtk-0.7 Reference Manual

InfGtkConnectionView

InfGtkConnectionView — A widget showing connection parameters

Stability Level

Unstable, unless otherwise indicated

Properties

InfXmppConnection * connection Read / Write

Types and Values

Object Hierarchy

    GObject
    ╰── GInitiallyUnowned
        ╰── GtkWidget
            ╰── GtkContainer
                ╰── GtkGrid
                    ╰── InfGtkConnectionView

Implemented Interfaces

InfGtkConnectionView implements AtkImplementorIface, GtkBuildable and GtkOrientable.

Includes

#include <libinfgtk/inf-gtk-connection-view.h>

Description

InfGtkConnectionView is a widget that shows parameters for a given connection such as the name of the remote host, its IP address, and encryption information.

Functions

inf_gtk_connection_view_new ()

GtkWidget *
inf_gtk_connection_view_new (void);

Creates a new InfGtkConnectionView. To show a connection, use inf_gtk_connection_view_set_connection() on the returned widget.

[constructor]

Returns

A new InfGtkConnectionView.

[transfer floating]


inf_gtk_connection_view_new_with_connection ()

GtkWidget *
inf_gtk_connection_view_new_with_connection
                               (InfXmppConnection *connection);

Creates a new InfGtkConnectionView showing the given connection. This is the same as creating a new connection view and calling inf_gtk_connection_view_set_connection() afterwards.

[constructor]

Parameters

connection

The connection to show.

 

Returns

A new InfGtkConnectionView.

[transfer floating]


inf_gtk_connection_view_set_connection ()

void
inf_gtk_connection_view_set_connection
                               (InfGtkConnectionView *view,
                                InfXmppConnection *connection);

Shows the given connection in view .

Parameters

view

A InfGtkConnectionView.

 

connection

The connection to show.

 

Types and Values

struct InfGtkConnectionView

struct InfGtkConnectionView;

InfGtkConnectionView is an opaque data type. You should only access it via the public API functions.


struct InfGtkConnectionViewClass

struct InfGtkConnectionViewClass {
};

This structure does not contain any public fields.

Property Details

The “connection†property

  “connection†              InfXmppConnection *

Connection for which to show parameters.

Flags: Read / Write

libinfinity-0.7.1/docs/reference/libinfgtk/html/PaxHeaders.26529/InfGtkChat.html0000644000000000000000000000013213055210760024255 xustar0030 mtime=1488261616.892077253 30 atime=1488261616.892077253 30 ctime=1488261616.892077253 libinfinity-0.7.1/docs/reference/libinfgtk/html/InfGtkChat.html0000644000175000017500000004717613055210760025026 0ustar00arminarmin00000000000000 InfGtkChat: libinfgtk-0.7 Reference Manual

InfGtkChat

InfGtkChat — Gtk interface to InfChatSession

Stability Level

Unstable, unless otherwise indicated

Properties

InfUser * active-user Read / Write
InfChatSession * session Read / Write

Types and Values

struct InfGtkChat
struct InfGtkChatClass

Object Hierarchy

    GObject
    ╰── GInitiallyUnowned
        ╰── GtkWidget
            ╰── GtkContainer
                ╰── GtkGrid
                    ╰── InfGtkChat

Implemented Interfaces

InfGtkChat implements AtkImplementorIface, GtkBuildable and GtkOrientable.

Includes

#include <libinfgtk/inf-gtk-chat.h>

Description

InfGtkChat is a widget showing a InfChatSession conversation. Use inf_gtk_chat_set_session() to set the session whose conversation to show in the widget. If you have a local user in the session you can also call inf_gtk_chat_set_active_user(). In this case the input text entry is made available and messages are sent via that user.

Functions

inf_gtk_chat_new ()

GtkWidget *
inf_gtk_chat_new (void);

Creates a new InfGtkChat. To show a chat conversation set a session to show via inf_gtk_chat_set_session().

[constructor]

Returns

A new InfGtkChat.

[transfer floating]


inf_gtk_chat_set_session ()

void
inf_gtk_chat_set_session (InfGtkChat *chat,
                          InfChatSession *session);

Sets the chat session to show in the chat widget. If there is a previous session set the chat view will be cleared before showing the new session. If the previous session had an active user set it will be unset. If session is NULL this function just clears the chat view and unsets the active user, if any.

Parameters

chat

A InfGtkChat.

 

session

The InfChatSession to set.

 

inf_gtk_chat_get_active_user ()

InfUser *
inf_gtk_chat_get_active_user (InfGtkChat *chat);

Returns the active user for chat as set with inf_gtk_chat_set_active_user().

Parameters

chat

A InfGtkChat.

 

Returns

The chat's active user, or NULL if there is none.

[transfer none][allow-none]


inf_gtk_chat_set_active_user ()

void
inf_gtk_chat_set_active_user (InfGtkChat *chat,
                              InfUser *user);

Sets the active user for the chat. This must be a user in the chat's session's user table and it must have the INF_USER_LOCAL flag set, i.e. you need to have it joined before using inf_session_proxy_join_user().

If an active user is set the chat's text entry is made sensitive and the user can type chat messages. They are sent to the session as originated by user . If user 's status changes to INF_USER_UNAVAILABLE or the INF_USER_LOCAL flag is removed the active user will be unset automatically.

This cannot be called when the chat has no session set yet. Use inf_gtk_chat_set_session() first.

Parameters

chat

A InfGtkChat.

 

user

A local InfUser which joined chat's session.

 

inf_gtk_chat_get_entry ()

GtkWidget *
inf_gtk_chat_get_entry (InfGtkChat *chat);

Returns the chat's text input entry.

Parameters

chat

A InfGtkChat.

 

Returns

The chat's GtkEntry. This is owned by the chat, so you don't need to free it.

[transfer none]

Types and Values

struct InfGtkChat

struct InfGtkChat;

InfGtkChat is an opaque data type. You should only access it via the public API functions.


struct InfGtkChatClass

struct InfGtkChatClass {
};

This structure does not contain any public fields.

Property Details

The “active-user†property

  “active-user†             InfUser *

The user outgoing messages come from.

Flags: Read / Write


The “session†property

  “session†                 InfChatSession *

The chat session this widget is displaying.

Flags: Read / Write

libinfinity-0.7.1/docs/reference/libinfgtk/html/PaxHeaders.26529/ch01.html0000644000000000000000000000013213055210760023026 xustar0030 mtime=1488261616.892077253 30 atime=1488261616.892077253 30 ctime=1488261616.892077253 libinfinity-0.7.1/docs/reference/libinfgtk/html/ch01.html0000644000175000017500000000773113055210760023570 0ustar00arminarmin00000000000000 libinfgtk API: libinfgtk-0.7 Reference Manual

libinfgtk API

InfGtkBrowserView
InfGtkBrowserModel — Interface for tree models representing infinote directories
InfGtkBrowserStore
InfGtkBrowserModelFilter
InfGtkBrowserModelSort
InfGtkPermissionsDialog — A dialog to view and modify the ACL of a directory node
InfGtkAccountCreationDialog — A dialog to request a new account on a server.
InfGtkCertificateManager — Verify server certificates and warn the user
InfGtkCertificateDialog — A dialog warning the user about a server's certificate
InfGtkCertificateView
InfGtkConnectionView — A widget showing connection parameters
InfGtkChat — Gtk interface to InfChatSession
InfGtkAclSheetView — A widget showing a InfAclSheet
InfGtkIo
libinfinity-0.7.1/docs/reference/libinfgtk/html/PaxHeaders.26529/InfGtkBrowserView.html0000644000000000000000000000013213055210760025654 xustar0030 mtime=1488261616.892077253 30 atime=1488261616.892077253 30 ctime=1488261616.892077253 libinfinity-0.7.1/docs/reference/libinfgtk/html/InfGtkBrowserView.html0000644000175000017500000005064613055210760026421 0ustar00arminarmin00000000000000 InfGtkBrowserView: libinfgtk-0.7 Reference Manual

InfGtkBrowserView

InfGtkBrowserView

Types and Values

Object Hierarchy

    GObject
    ╰── GInitiallyUnowned
        ╰── GtkWidget
            ╰── GtkContainer
                ╰── GtkTreeView
                    ╰── InfGtkBrowserView

Implemented Interfaces

InfGtkBrowserView implements AtkImplementorIface, GtkBuildable and GtkScrollable.

Description

Functions

inf_gtk_browser_view_new ()

GtkWidget *
inf_gtk_browser_view_new (void);

Creates a new InfGtkBrowserView.

[constructor]

Returns

A new InfGtkBrowserView.

[transfer floating]


inf_gtk_browser_view_new_with_model ()

GtkWidget *
inf_gtk_browser_view_new_with_model (InfGtkBrowserModel *model);

Creates a new InfGtkBrowserView showing model .

[constructor]

Parameters

model

A InfGtkBrowserModel.

 

Returns

A new InfGtkBrowserView.

[transfer floating]


inf_gtk_browser_view_get_selected ()

gboolean
inf_gtk_browser_view_get_selected (InfGtkBrowserView *view,
                                   GtkTreeIter *iter);

Sets iter to point to the currently selected row in the browser view. If no row is selected, iter is left untouched and FALSE is returned.

Parameters

view

A InfGtkBrowserView.

 

iter

An uninitialized GtkTreeIter.

[out]

Returns

Whether iter was set.


inf_gtk_browser_view_set_selected ()

void
inf_gtk_browser_view_set_selected (InfGtkBrowserView *view,
                                   GtkTreeIter *iter);

Sets the currently selected row to be iter . If necessary, rows will be expanded so that iter is visible.

Parameters

view

A InfGtkBrowserView.

 

iter

A GtkTreeIter pointing to a row in view .

[transfer none]

Types and Values

struct InfGtkBrowserView

struct InfGtkBrowserView;


struct InfGtkBrowserViewClass

struct InfGtkBrowserViewClass {
  GtkTreeViewClass parent_class;

  /* signals */
  void (*activate)(InfGtkBrowserView* view,
                   GtkTreeIter* iter);

  void (*selection_changed)(InfGtkBrowserView* view,
                            GtkTreeIter* iter);

  void (*populate_popup)(InfGtkBrowserView* view,
                         GtkMenu* menu);

#if ! GTK_CHECK_VERSION(2, 91, 0)
  void (*set_scroll_adjustments)(InfGtkBrowserView* view,
                                 GtkAdjustment* hadjustment,
                                 GtkAdjustment* vadjustment);
#endif
};

Signal Details

The “activate†signal

void
user_function (InfGtkBrowserView *infgtkbrowserview,
               GtkTreeIter       *arg1,
               gpointer           user_data)

Parameters

infgtkbrowserview

the object which received the signal.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last


The “populate-popup†signal

void
user_function (InfGtkBrowserView *infgtkbrowserview,
               GtkMenu           *arg1,
               gpointer           user_data)

Parameters

infgtkbrowserview

the object which received the signal.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last


The “selection-changed†signal

void
user_function (InfGtkBrowserView *infgtkbrowserview,
               GtkTreeIter       *arg1,
               gpointer           user_data)

Parameters

infgtkbrowserview

the object which received the signal.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last

libinfinity-0.7.1/docs/reference/libinfgtk/html/PaxHeaders.26529/InfGtkCertificateDialog.html0000644000000000000000000000013213055210760026740 xustar0030 mtime=1488261616.892077253 30 atime=1488261616.892077253 30 ctime=1488261616.892077253 libinfinity-0.7.1/docs/reference/libinfgtk/html/InfGtkCertificateDialog.html0000644000175000017500000004066713055210760027507 0ustar00arminarmin00000000000000 InfGtkCertificateDialog: libinfgtk-0.7 Reference Manual

InfGtkCertificateDialog

InfGtkCertificateDialog — A dialog warning the user about a server's certificate

Stability Level

Unstable, unless otherwise indicated

Properties

Types and Values

Object Hierarchy

    GObject
    ╰── GInitiallyUnowned
        ╰── GtkWidget
            ╰── GtkContainer
                ╰── GtkBin
                    ╰── GtkWindow
                        ╰── GtkDialog
                            ╰── InfGtkCertificateDialog

Implemented Interfaces

InfGtkCertificateDialog implements AtkImplementorIface and GtkBuildable.

Includes

#include <libinfgtk/inf-gtk-certificate-dialog.h>

Description

InfGtkCertificateDialog is a dialog that can be shown to a user if the validation of the server's certificate cannot be performed automatically. The dialog will present to the user the reason(s) of the validation failure and might ask whether to fully establish the connection to the server or not.

Functions

inf_gtk_certificate_dialog_new ()

InfGtkCertificateDialog *
inf_gtk_certificate_dialog_new (GtkWindow *parent,
                                GtkDialogFlags dialog_flags,
                                InfCertificateVerifyFlags verify_flags,
                                const gchar *hostname,
                                InfCertificateChain *certificate_chain,
                                gnutls_x509_crt_t pinned_certificate);

Creates a new InfGtkCertificateDialog. A InfGtkCertificateDialog shows a warning about a server's certificate to a user, for example when the issuer is not trusted or the hostname does not match what the certificate was issued to.

[constructor]

Parameters

parent

Parent GtkWindow of the dialog.

 

dialog_flags

Flags for the dialog, see GtkDialogFlags.

 

verify_flags

What certificate warnings to show, see InfCertificateVerifyFlags.

 

hostname

The host name of the server that provides the certificate.

 

certificate_chain

The certificate chain provided by the server.

[transfer none]

pinned_certificate

The certificate that we had pinned for this host, or NULL.

[transfer none]

Returns

A new InfGtkCertificateDialog.

[transfer full]

Types and Values

struct InfGtkCertificateDialog

struct InfGtkCertificateDialog;

InfGtkCertificateDialog is an opaque data type. You should only access it via the public API functions.


struct InfGtkCertificateDialogClass

struct InfGtkCertificateDialogClass {
};

This structure does not contain any public fields.

Property Details

The “certificate-chain†property

  “certificate-chain†       InfCertificateChain *

The certificate chain to show in the dialog.

Flags: Read / Write


The “hostname†property

  “hostname†                gchar *

Host name of the server from which the certificate is.

Flags: Read / Write

Default value: NULL


The “pinned-certificate†property

  “pinned-certificate†      gpointer

The certificate that we had pinned for this host.

Flags: Read / Write


The “verify-flags†property

  “verify-flags†            InfCertificateVerifyFlags

What warnings about the certificate to display.

Flags: Read / Write

libinfinity-0.7.1/docs/reference/libinfgtk/html/PaxHeaders.26529/up.png0000644000000000000000000000013213055210760022537 xustar0030 mtime=1488261616.852077342 30 atime=1488261616.852077342 30 ctime=1488261616.852077342 libinfinity-0.7.1/docs/reference/libinfgtk/html/up.png0000644000175000017500000000040413055210760023267 0ustar00arminarmin00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEà 4ÓkM‘IDAT8Ëí’1 ƒ@DŸ•¶{ƒxa™ƒØÄ;$]r =JR´È1,Ë øSd„-©}0°ÌŸÙÏÂÂÎàüo¹L:m-˜¤QÞOäÀ[› Éäåkå T¸zþMÞ Lè¬Ì,š:ךuÀ!tÁK;æ ðP¦õÌôÀp Ot@£l¼ÿò/̵*á§l}IEND®B`‚libinfinity-0.7.1/docs/reference/libinfgtk/html/PaxHeaders.26529/home.png0000644000000000000000000000013213055210760023043 xustar0030 mtime=1488261616.852077342 30 atime=1488261616.852077342 30 ctime=1488261616.852077342 libinfinity-0.7.1/docs/reference/libinfgtk/html/home.png0000644000175000017500000000040013055210760023567 0ustar00arminarmin00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEà 4ÓkMIDAT8ËÝÒ½ AÅñßž¦f`n v`6`/¶`Y€š˜Ü¡`f&k$,Ëá}˜ˆ ÌüßÀ0ü§bŒ+Ô¸aQW~bæ ËOà e˜{‡y N°Á£üö[LáØÌ}.pÇiÀ­÷¨BzüžÆmm Šoæ·.I]7Ì^[úÃô;%:å†ÁVIEND®B`‚libinfinity-0.7.1/docs/reference/libinfgtk/html/PaxHeaders.26529/right-insensitive.png0000644000000000000000000000013213055210760025566 xustar0030 mtime=1488261616.852077342 30 atime=1488261616.852077342 30 ctime=1488261616.852077342 libinfinity-0.7.1/docs/reference/libinfgtk/html/right-insensitive.png0000644000175000017500000000056513055210760026326 0ustar00arminarmin00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEà 4ÓkMIDAT8ËÍ’±JÃ`…¿ ‚“‹³«/ S’_$ÄÁÁAqrÐÙW(>€“à‚®©“m¥"]\œ„è(‘49.NÚdÒ3¸ß9Ü{á¯eM#MSI‡Î¹·E¯iHz|3{̲l½3 ,K˜k’ž†ÃáV'@EŸEQlwÀŠçyišî·Äqüçù‘™]KÀíh4:mµÄ¦²,;“t˜¤sç\aƒÆR5/¬7'¹W×õp”’Žs×­I’,Kº1³=àËÌÂ0´j0Wg³ÙØ>€Ý ¦­¯PUÕýïð»¤0 §]?qCÒ«™ùιgþ½~œÉkÄAâ…_IEND®B`‚libinfinity-0.7.1/docs/reference/libinfgtk/html/PaxHeaders.26529/InfGtkCertificateManager.html0000644000000000000000000000013213055210760027113 xustar0030 mtime=1488261616.896077244 30 atime=1488261616.896077244 30 ctime=1488261616.896077244 libinfinity-0.7.1/docs/reference/libinfgtk/html/InfGtkCertificateManager.html0000644000175000017500000002741713055210760027660 0ustar00arminarmin00000000000000 InfGtkCertificateManager: libinfgtk-0.7 Reference Manual

InfGtkCertificateManager

InfGtkCertificateManager — Verify server certificates and warn the user

Stability Level

Unstable, unless otherwise indicated

Properties

GtkWindow * parent-window Read / Write / Construct Only

Object Hierarchy

    GObject
    ╰── InfCertificateVerify
        ╰── InfGtkCertificateManager

Includes

#include <libinfgtk/inf-gtk-certificate-manager.h>

Description

InfGtkCertificateManager is derived from InfCertificateVerify, and as such it verifies server certificates. This class handles the “check-certificate†signal by showing a InfGtkCertificateDialog to the user to let them decide whether or not to accept the server's certificate.

Functions

inf_gtk_certificate_manager_new ()

InfGtkCertificateManager *
inf_gtk_certificate_manager_new (GtkWindow *parent_window,
                                 InfXmppManager *xmpp_manager,
                                 const gchar *known_hosts_file);

Creates a new InfGtkCertificateManager. See InfCertificateVerify for details about the certificate verification process.

[constructor]

Parameters

parent_window

The GtkWindow to which to make certificate verification dialogs transient to.

 

xmpp_manager

The InfXmppManager whose InfXmppConnections to manage the certificates for.

 

known_hosts_file

Path pointing to a file that contains pinned certificates, or NULL.

[type filename][allow-none]

Returns

A new InfGtkCertificateManager.

[transfer full]

Types and Values

struct InfGtkCertificateManager

struct InfGtkCertificateManager;


struct InfGtkCertificateManagerClass

struct InfGtkCertificateManagerClass {
  InfCertificateVerifyClass parent_class;
};

Property Details

The “parent-window†property

  “parent-window†           GtkWindow *

The parent window for certificate verification dialogs.

Flags: Read / Write / Construct Only

libinfinity-0.7.1/docs/reference/libinfgtk/html/PaxHeaders.26529/right.png0000644000000000000000000000013213055210760023230 xustar0030 mtime=1488261616.852077342 30 atime=1488261616.852077342 30 ctime=1488261616.852077342 libinfinity-0.7.1/docs/reference/libinfgtk/html/right.png0000644000175000017500000000040513055210760023761 0ustar00arminarmin00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEà 4ÓkM’IDAT8ËÕÒ¯aÇñ?›M´½IdErš,¾Ù-¸ÑhîAâIl’Í ¯r’äy§ž}¿ç·s¿X6èæ ö!9¢Ÿ#èD‚ Œr$-¬BrÃ$GÒÀ"$”¹;™á‰æŸÍú—WZêä&–!¸cš·±øŠq \`ðÃÔ軀Oä¾ò=QouføòIEND®B`‚libinfinity-0.7.1/docs/reference/libinfgtk/html/PaxHeaders.26529/InfGtkBrowserModel.html0000644000000000000000000000013213055210760026002 xustar0030 mtime=1488261616.896077244 30 atime=1488261616.896077244 30 ctime=1488261616.896077244 libinfinity-0.7.1/docs/reference/libinfgtk/html/InfGtkBrowserModel.html0000644000175000017500000010440513055210760026540 0ustar00arminarmin00000000000000 InfGtkBrowserModel: libinfgtk-0.7 Reference Manual

InfGtkBrowserModel

InfGtkBrowserModel — Interface for tree models representing infinote directories

Stability Level

Unstable, unless otherwise indicated

Signals

Object Hierarchy

    GEnum
    ╰── InfGtkBrowserModelStatus
    GInterface
    ╰── InfGtkBrowserModel

Prerequisites

InfGtkBrowserModel requires GtkTreeModel and GObject.

Known Implementations

InfGtkBrowserModel is implemented by InfGtkBrowserModelFilter, InfGtkBrowserModelSort and InfGtkBrowserStore.

Includes

#include <libinfgtk/inf-gtk-browser-model.h>

Description

InfGtkBrowserModel provides an interface for tree models that are used to show the contents of infinote directories. All implementations of InfGtkBrowserModel also need to implement GtkTreeModel and can then by displayed in a GtkTreeView.

InfGtkBrowserStore is a reference implementation of this interface, allowing to add discoveries and browsers to it which it then manages. Other implementations include InfGtkBrowserModelSort and InfGtkBrowserModelFilter which can be used to sort or filter the list.

Functions

inf_gtk_browser_model_set_browser ()

void
inf_gtk_browser_model_set_browser (InfGtkBrowserModel *model,
                                   GtkTreePath *path,
                                   GtkTreeIter *iter,
                                   InfBrowser *old_browser,
                                   InfBrowser *new_browser);

Emits the “set-browser†signal. This is supposed to only be called by implementations of InfGtkBrowserModel whenever they set or unset a browser on a row.

Parameters

model

A InfGtkBrowserModel.

 

path

A GtkTreePath to a top-level row.

 

iter

A GtkTreeIter pointing to the same row.

 

old_browser

The browser which was set at this row before.

 

new_browser

The new InfBrowser to set for this row.

 

inf_gtk_browser_model_resolve ()

void
inf_gtk_browser_model_resolve (InfGtkBrowserModel *model,
                               InfDiscovery *discovery,
                               InfDiscoveryInfo *info);

Resolves info and adds the resulting connection to the model. If that connection is already contained, the original (newly resolved) entry is removed in favor of the existing entry whose browser might already have explored (parts of) the server's directory.

Parameters

model

A InfGtkBrowserModel.

 

discovery

A InfDiscovery added to store .

 

info

A InfDiscoveryInfo discovered by discovery .

 

inf_gtk_browser_model_browser_iter_to_tree_iter ()

gboolean
inf_gtk_browser_model_browser_iter_to_tree_iter
                               (InfGtkBrowserModel *model,
                                InfBrowser *browser,
                                const InfBrowserIter *iter,
                                GtkTreeIter *tree_iter);

Sets tree_iter to point to the same node iter refers to within the model. If browser is not known to model , i.e. its connection was never added to model , then the function returns FALSE and tree_iter is left untouched.

If iter is NULL, the function sets tree_iter to point to the top level entry representing browser .

Parameters

model

A InfGtkBrowserModel.

 

browser

A InfBrowser.

 

iter

A InfBrowserIter pointing into browser , or NULL.

 

tree_iter

A GtkTreeIter that will be set by this function.

[out]

Returns

Whether tree_iter was set.

Types and Values

INF_GTK_TYPE_BROWSER_MODEL_STATUS

#define INF_GTK_TYPE_BROWSER_MODEL_STATUS          (inf_gtk_browser_model_status_get_type())


InfGtkBrowserModel

typedef struct _InfGtkBrowserModel InfGtkBrowserModel;

InfGtkBrowserModel is an opaque data type. You should only access it via the public API functions.


struct InfGtkBrowserModelInterface

struct InfGtkBrowserModelInterface {
  /* signals */
  void(*set_browser)(InfGtkBrowserModel* model,
                     GtkTreePath* path,
                     GtkTreeIter* iter,
                     InfBrowser* old_browser,
                     InfBrowser* new_browser);

  /* virtual functions */
  void(*resolve)(InfGtkBrowserModel* model,
                 InfDiscovery* discovery,
                 InfDiscoveryInfo* info);

  gboolean(*browser_iter_to_tree_iter)(InfGtkBrowserModel* model,
                                       InfBrowser* browser,
                                       const InfBrowserIter* iter,
                                       GtkTreeIter* tree_iter);
};

This structure contains virtual functions and signal handlers of the InfGtkBrowserModel interface.

Members

set_browser ()

Default signal handler of the “set-browser†signal.

 

resolve ()

Virtual function for resolving a discovered infinote service.

 

browser_iter_to_tree_iter ()

Virtual function for converting a InfBrowserIter to a GtkTreeIter.

 

enum InfGtkBrowserModelStatus

The different statuses an item in the InfGtkBrowserModel can have. The status of an item is only defined for toplevel items in the tree.

Members

INF_GTK_BROWSER_MODEL_INVALID

Invalid state. A healthy item should not have this status.

 

INF_GTK_BROWSER_MODEL_DISCOVERED

The item was discovered with a InfDiscovery, but no attempt has been made at connecting to it.

 

INF_GTK_BROWSER_MODEL_RESOLVING

The item was discovered with a InfDiscovery and is currently being resolved, see inf_discovery_resolve().

 

INF_GTK_BROWSER_MODEL_DISCONNECTED

A connection attempt to the remote site was not successful, or the connection was lost. The connection parameters are known, but currently no connection is established.

 

INF_GTK_BROWSER_MODEL_CONNECTING

A connection attempt to the remote site is currently in progress.

 

INF_GTK_BROWSER_MODEL_CONNECTED

A connection to the remote site has been established and its directory can be browsed.

 

INF_GTK_BROWSER_MODEL_ERROR

An error has occured with this item. The column with index INF_GTK_BROWSER_MODEL_COL_ERROR has more information about the error that occurred.

 

enum InfGtkBrowserModelColumn

The various GtkTreeModel columns that a tree model implementing InfGtkBrowserModel must support.

Members

INF_GTK_BROWSER_MODEL_COL_DISCOVERY_INFO

The InfDiscoveryInfo of a discovered toplevel item, or NULL if the item was not discovered.

 

INF_GTK_BROWSER_MODEL_COL_DISCOVERY

The InfDiscovery object that the item has been discovered with, if any.

 

INF_GTK_BROWSER_MODEL_COL_BROWSER

The InfBrowser with which this item is being browsed, or NULL if no browser is available.

 

INF_GTK_BROWSER_MODEL_COL_STATUS

The status of this item. This column is only valid for toplevel items, i.e. for connections to directories.

 

INF_GTK_BROWSER_MODEL_COL_NAME

The name of the item as a simple string.

 

INF_GTK_BROWSER_MODEL_COL_ERROR

If an error has occurred with the item, for example the connection failed, or a node exploration failed, this column contains a GError with more error information.

 

INF_GTK_BROWSER_MODEL_COL_NODE

The InfBrowserIter pointing to the corresponding node of the InfBrowser.

 

INF_GTK_BROWSER_MODEL_NUM_COLS

The total number of columns of a InfGtkBrowserModel.

 

Signal Details

The “set-browser†signal

void
user_function (InfGtkBrowserModel *model,
               GtkTreePath        *path,
               GtkTreeIter        *iter,
               InfBrowser         *old_browser,
               InfBrowser         *new_browser,
               gpointer            user_data)

This signal is emitted every time the InfBrowser for one of the model's top-level entries change. This means either that a completely new item was inserted, that an item providing only a discovery has been resolved (see inf_gtk_browser_model_resolve()), or that a top-level entry has been removed.

During emission of the signal the actual value in the model might either be the old or the new browser.

Parameters

model

The InfGtkBrowserModel emitting the signal.

 

path

A GtkTreePath pointing to the item with a new browesr.

 

iter

A GtkTreeIter pointing to the item with a new browser.

 

old_browser

The previous InfBrowser.

 

new_browser

The new InfBrowser.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last

libinfinity-0.7.1/docs/reference/libinfgtk/html/PaxHeaders.26529/style.css0000644000000000000000000000013213055210760023257 xustar0030 mtime=1488261616.852077342 30 atime=1488261616.852077342 30 ctime=1488261616.852077342 libinfinity-0.7.1/docs/reference/libinfgtk/html/style.css0000644000175000017500000002115413055210760024014 0ustar00arminarmin00000000000000body { font-family: cantarell, sans-serif; } .synopsis, .classsynopsis { /* tango:aluminium 1/2 */ background: #eeeeec; background: rgba(238, 238, 236, 0.5); border: solid 1px rgb(238, 238, 236); padding: 0.5em; } .programlisting { /* tango:sky blue 0/1 */ /* fallback for no rgba support */ background: #e6f3ff; border: solid 1px #729fcf; background: rgba(114, 159, 207, 0.1); border: solid 1px rgba(114, 159, 207, 0.2); padding: 0.5em; } .variablelist { padding: 4px; margin-left: 3em; } .variablelist td:first-child { vertical-align: top; } div.gallery-float { float: left; padding: 10px; } div.gallery-float img { border-style: none; } div.gallery-spacer { clear: both; } a, a:visited { text-decoration: none; /* tango:sky blue 2 */ color: #3465a4; } a:hover { text-decoration: underline; /* tango:sky blue 1 */ color: #729fcf; } div.informaltable table { border-collapse: separate; border-spacing: 1em 0.3em; border: none; } div.informaltable table td, div.informaltable table th { vertical-align: top; } .function_type, .variable_type, .property_type, .signal_type, .parameter_name, .struct_member_name, .union_member_name, .define_keyword, .datatype_keyword, .typedef_keyword { text-align: right; } /* dim non-primary columns */ .c_punctuation, .function_type, .variable_type, .property_type, .signal_type, .define_keyword, .datatype_keyword, .typedef_keyword, .property_flags, .signal_flags, .parameter_annotations, .enum_member_annotations, .struct_member_annotations, .union_member_annotations { color: #888a85; } .function_type a, .function_type a:visited, .function_type a:hover, .property_type a, .property_type a:visited, .property_type a:hover, .signal_type a, .signal_type a:visited, .signal_type a:hover, .signal_flags a, .signal_flags a:visited, .signal_flags a:hover { color: #729fcf; } td p { margin: 0.25em; } div.table table { border-collapse: collapse; border-spacing: 0px; /* tango:aluminium 3 */ border: solid 1px #babdb6; } div.table table td, div.table table th { /* tango:aluminium 3 */ border: solid 1px #babdb6; padding: 3px; vertical-align: top; } div.table table th { /* tango:aluminium 2 */ background-color: #d3d7cf; } h4 { color: #555753; margin-top: 1em; margin-bottom: 1em; } hr { /* tango:aluminium 1 */ color: #d3d7cf; background: #d3d7cf; border: none 0px; height: 1px; clear: both; margin: 2.0em 0em 2.0em 0em; } dl.toc dt { padding-bottom: 0.25em; } dl.toc > dt { padding-top: 0.25em; padding-bottom: 0.25em; font-weight: bold; } dl.toc > dl { padding-bottom: 0.5em; } .parameter { font-style: normal; } .footer { padding-top: 3.5em; /* tango:aluminium 3 */ color: #babdb6; text-align: center; font-size: 80%; } .informalfigure, .figure { margin: 1em; } .informalexample, .example { margin-top: 1em; margin-bottom: 1em; } .warning { /* tango:orange 0/1 */ background: #ffeed9; background: rgba(252, 175, 62, 0.1); border-color: #ffb04f; border-color: rgba(252, 175, 62, 0.2); } .note { /* tango:chameleon 0/0.5 */ background: #d8ffb2; background: rgba(138, 226, 52, 0.1); border-color: #abf562; border-color: rgba(138, 226, 52, 0.2); } div.blockquote { border-color: #eeeeec; } .note, .warning, div.blockquote { padding: 0.5em; border-width: 1px; border-style: solid; margin: 2em; } .note p, .warning p { margin: 0; } div.warning h3.title, div.note h3.title { display: none; } p + div.section { margin-top: 1em; } div.refnamediv, div.refsynopsisdiv, div.refsect1, div.refsect2, div.toc, div.section { margin-bottom: 1em; } /* blob links */ h2 .extralinks, h3 .extralinks { float: right; /* tango:aluminium 3 */ color: #babdb6; font-size: 80%; font-weight: normal; } .lineart { color: #d3d7cf; font-weight: normal; } .annotation { /* tango:aluminium 5 */ color: #555753; font-weight: normal; } .structfield { font-style: normal; font-weight: normal; } acronym,abbr { border-bottom: 1px dotted gray; } /* code listings */ .listing_code .programlisting .normal, .listing_code .programlisting .normal a, .listing_code .programlisting .number, .listing_code .programlisting .cbracket, .listing_code .programlisting .symbol { color: #555753; } .listing_code .programlisting .comment, .listing_code .programlisting .linenum { color: #babdb6; } /* tango: aluminium 3 */ .listing_code .programlisting .function, .listing_code .programlisting .function a, .listing_code .programlisting .preproc { color: #204a87; } /* tango: sky blue 3 */ .listing_code .programlisting .string { color: #ad7fa8; } /* tango: plum */ .listing_code .programlisting .keyword, .listing_code .programlisting .usertype, .listing_code .programlisting .type, .listing_code .programlisting .type a { color: #4e9a06; } /* tango: chameleon 3 */ .listing_frame { /* tango:sky blue 1 */ border: solid 1px #729fcf; border: solid 1px rgba(114, 159, 207, 0.2); padding: 0px; } .listing_lines, .listing_code { margin-top: 0px; margin-bottom: 0px; padding: 0.5em; } .listing_lines { /* tango:sky blue 0.5 */ background: #a6c5e3; background: rgba(114, 159, 207, 0.2); /* tango:aluminium 6 */ color: #2e3436; } .listing_code { /* tango:sky blue 0 */ background: #e6f3ff; background: rgba(114, 159, 207, 0.1); } .listing_code .programlisting { /* override from previous */ border: none 0px; padding: 0px; background: none; } .listing_lines pre, .listing_code pre { margin: 0px; } @media screen { /* these have a as a first child, but since there are no parent selectors * we can't use that. */ a.footnote { position: relative; top: 0em ! important; } /* this is needed so that the local anchors are displayed below the naviagtion */ div.footnote a[name], div.refnamediv a[name], div.refsect1 a[name], div.refsect2 a[name], div.index a[name], div.glossary a[name], div.sect1 a[name] { display: inline-block; position: relative; top:-5em; } /* this seems to be a bug in the xsl style sheets when generating indexes */ div.index div.index { top: 0em; } /* make space for the fixed navigation bar and add space at the bottom so that * link targets appear somewhat close to top */ body { padding-top: 2.5em; padding-bottom: 500px; max-width: 60em; } p { max-width: 60em; } /* style and size the navigation bar */ table.navigation#top { position: fixed; background: #e2e2e2; border-bottom: solid 1px #babdb6; border-spacing: 5px; margin-top: 0; margin-bottom: 0; top: 0; left: 0; z-index: 10; } table.navigation#top td { padding-left: 6px; padding-right: 6px; } .navigation a, .navigation a:visited { /* tango:sky blue 3 */ color: #204a87; } .navigation a:hover { /* tango:sky blue 2 */ color: #3465a4; } td.shortcuts { /* tango:sky blue 2 */ color: #3465a4; font-size: 80%; white-space: nowrap; } td.shortcuts .dim { color: #babdb6; } .navigation .title { font-size: 80%; max-width: none; margin: 0px; font-weight: normal; } } @media screen and (min-width: 60em) { /* screen larger than 60em */ body { margin: auto; } } @media screen and (max-width: 60em) { /* screen less than 60em */ #nav_hierarchy { display: none; } #nav_interfaces { display: none; } #nav_prerequisites { display: none; } #nav_derived_interfaces { display: none; } #nav_implementations { display: none; } #nav_child_properties { display: none; } #nav_style_properties { display: none; } #nav_index { display: none; } #nav_glossary { display: none; } .gallery_image { display: none; } .property_flags { display: none; } .signal_flags { display: none; } .parameter_annotations { display: none; } .enum_member_annotations { display: none; } .struct_member_annotations { display: none; } .union_member_annotations { display: none; } /* now that a column is hidden, optimize space */ col.parameters_name { width: auto; } col.parameters_description { width: auto; } col.struct_members_name { width: auto; } col.struct_members_description { width: auto; } col.enum_members_name { width: auto; } col.enum_members_description { width: auto; } col.union_members_name { width: auto; } col.union_members_description { width: auto; } .listing_lines { display: none; } } @media print { table.navigation { visibility: collapse; display: none; } div.titlepage table.navigation { visibility: visible; display: table; background: #e2e2e2; border: solid 1px #babdb6; margin-top: 0; margin-bottom: 0; top: 0; left: 0; height: 3em; } } libinfinity-0.7.1/docs/reference/libinfgtk/html/PaxHeaders.26529/InfGtkCertificateView.html0000644000000000000000000000013213055210760026453 xustar0030 mtime=1488261616.896077244 30 atime=1488261616.896077244 30 ctime=1488261616.896077244 libinfinity-0.7.1/docs/reference/libinfgtk/html/InfGtkCertificateView.html0000644000175000017500000003373313055210760027216 0ustar00arminarmin00000000000000 InfGtkCertificateView: libinfgtk-0.7 Reference Manual

InfGtkCertificateView

InfGtkCertificateView

Properties

gpointer certificate Read / Write

Types and Values

Object Hierarchy

    GObject
    ╰── GInitiallyUnowned
        ╰── GtkWidget
            ╰── GtkContainer
                ╰── GtkGrid
                    ╰── InfGtkCertificateView

Implemented Interfaces

InfGtkCertificateView implements AtkImplementorIface, GtkBuildable and GtkOrientable.

Description

Functions

inf_gtk_certificate_view_new ()

GtkWidget *
inf_gtk_certificate_view_new (void);

Creates a new InfGtkCertificateView. To show a certificate, use inf_gtk_certificate_view_set_certificate() on the returned widget.

[constructor]

Returns

A new InfGtkCertificateView.

[transfer floating]


inf_gtk_certificate_view_new_with_certificate ()

GtkWidget *
inf_gtk_certificate_view_new_with_certificate
                               (gnutls_x509_crt_t cert);

Creates a new InfGtkCertificateView showing the given certificate. This is the same as creating a new certificate view and calling inf_gtk_certificate_view_set_certificate() afterwards.

cert must not be freed as long as the certificate view is showing it. You can make the view not showing it anymore by calling inf_gtk_certificate_view_set_certificate() with NULL as certificate.

[constructor]

Parameters

cert

The certificate to show.

 

Returns

A new InfGtkCertificateView.

[transfer floating]


inf_gtk_certificate_view_set_certificate ()

void
inf_gtk_certificate_view_set_certificate
                               (InfGtkCertificateView *view,
                                gnutls_x509_crt_t cert);

Shows the given certificate in view .

cert must not be freed as long as the certificate view is showing it. You can make the view not showing it anymore by calling inf_gtk_certificate_view_set_certificate() with NULL as certificate.

Parameters

view

A InfGtkCertificateView.

 

cert

The certificate to show.

 

Types and Values

struct InfGtkCertificateView

struct InfGtkCertificateView;


struct InfGtkCertificateViewClass

struct InfGtkCertificateViewClass {
  GtkGridClass parent_class;
};

Property Details

The “certificate†property

  “certificate†             gpointer

The certificate to show.

Flags: Read / Write

libinfinity-0.7.1/docs/reference/libinfgtk/html/PaxHeaders.26529/left.png0000644000000000000000000000013213055210760023045 xustar0030 mtime=1488261616.852077342 30 atime=1488261616.852077342 30 ctime=1488261616.852077342 libinfinity-0.7.1/docs/reference/libinfgtk/html/left.png0000644000175000017500000000040613055210760023577 0ustar00arminarmin00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEà 4ÓkM“IDAT8ËÕÒ¯Áa‡ñ?ÁDAPY‘\‚$‹º[p¢+ÐÜIÐIªMlfü('Úì}MpâÙyží{Îá_ª…ž¨¤ÂÞ¥Â}œ^£‘q xZ <Æ=àYjî) <0ù4\~Ó+Púöl#Ü"ÂÕÉ—,QÏ‘ôp ÉÍIÇlswÒÆ>÷•[/]_i0‘3ÃIEND®B`‚libinfinity-0.7.1/docs/reference/libinfgtk/html/PaxHeaders.26529/InfGtkBrowserModelFilter.html0000644000000000000000000000013213055210760027150 xustar0030 mtime=1488261616.896077244 30 atime=1488261616.896077244 30 ctime=1488261616.896077244 libinfinity-0.7.1/docs/reference/libinfgtk/html/InfGtkBrowserModelFilter.html0000644000175000017500000001703313055210760027706 0ustar00arminarmin00000000000000 InfGtkBrowserModelFilter: libinfgtk-0.7 Reference Manual

InfGtkBrowserModelFilter

InfGtkBrowserModelFilter

Object Hierarchy

    GObject
    ╰── GtkTreeModelFilter
        ╰── InfGtkBrowserModelFilter

Implemented Interfaces

InfGtkBrowserModelFilter implements GtkTreeModel, GtkTreeDragSource and InfGtkBrowserModel.

Description

Functions

inf_gtk_browser_model_filter_new ()

InfGtkBrowserModelFilter *
inf_gtk_browser_model_filter_new (InfGtkBrowserModel *child_model);

Creates a new InfGtkBrowserModelFilter, filtering child_model .

[constructor]

Parameters

child_model

A InfGtkBrowserModel.

 

Returns

A new InfGtkBrowserModelFilter.

[transfer full]

Types and Values

struct InfGtkBrowserModelFilter

struct InfGtkBrowserModelFilter;


struct InfGtkBrowserModelFilterClass

struct InfGtkBrowserModelFilterClass {
  GtkTreeModelFilterClass parent_class;
};

libinfinity-0.7.1/docs/reference/libinfgtk/PaxHeaders.26529/Makefile.in0000644000000000000000000000013213051241007022500 xustar0030 mtime=1487225351.661148281 30 atime=1487225351.661148281 30 ctime=1488261614.952081606 libinfinity-0.7.1/docs/reference/libinfgtk/Makefile.in0000644000175000017500000006676213051241007023253 0ustar00arminarmin00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 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@ # -*- mode: makefile -*- #################################### # Everything below here is generic # #################################### VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) 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@ subdir = docs/reference/libinfgtk ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/gtk-doc.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/libinfinity/inf-config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/gtk-doc.make DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ 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@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIRNAME = @DATADIRNAME@ 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@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ GTKDOC_CHECK = @GTKDOC_CHECK@ GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ GTKDOC_MKPDF = @GTKDOC_MKPDF@ GTKDOC_REBASE = @GTKDOC_REBASE@ HTML_DIR = @HTML_DIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INSTOBJEXT = @INSTOBJEXT@ INTLLIBS = @INTLLIBS@ INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBINFINITY_API_VERSION = @LIBINFINITY_API_VERSION@ LIBINFINITY_LIBTOOL_VERSION = @LIBINFINITY_LIBTOOL_VERSION@ LIBINFINITY_VERSION = @LIBINFINITY_VERSION@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGFMT_OPTS = @MSGFMT_OPTS@ 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@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ 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@ avahi_CFLAGS = @avahi_CFLAGS@ avahi_LIBS = @avahi_LIBS@ 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@ gio_CFLAGS = @gio_CFLAGS@ gio_LIBS = @gio_LIBS@ gtk_requirement = @gtk_requirement@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infgtk_CFLAGS = @infgtk_CFLAGS@ infgtk_LIBS = @infgtk_LIBS@ infinity_CFLAGS = @infinity_CFLAGS@ infinity_LIBS = @infinity_LIBS@ infinoted_CFLAGS = @infinoted_CFLAGS@ infinoted_LIBS = @infinoted_LIBS@ infodir = @infodir@ inftext_CFLAGS = @inftext_CFLAGS@ inftext_LIBS = @inftext_LIBS@ inftextgtk_CFLAGS = @inftextgtk_CFLAGS@ inftextgtk_LIBS = @inftextgtk_LIBS@ install_sh = @install_sh@ libdaemon_CFLAGS = @libdaemon_CFLAGS@ libdaemon_LIBS = @libdaemon_LIBS@ 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@ runstatedir = @runstatedir@ 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@ # We require automake 1.6 at least. AUTOMAKE_OPTIONS = 1.6 # This is a blank Makefile.am for using gtk-doc. # Copy this to your project's API docs directory and modify the variables to # suit your project. See the GTK+ Makefiles in gtk+/docs/reference for examples # of using the various options. # The name of the module, e.g. 'glib'. DOC_MODULE = libinfgtk-$(LIBINFINITY_API_VERSION) # The top-level SGML file. You can change this if you want to. DOC_MAIN_SGML_FILE = $(DOC_MODULE)-docs.sgml # The directory containing the source code. Relative to $(srcdir). # gtk-doc will search all .c & .h files beneath here for inline comments # documenting the functions and macros. # e.g. DOC_SOURCE_DIR=../../../gtk DOC_SOURCE_DIR = $(top_srcdir)/libinfgtk # Extra options to pass to gtkdoc-scangobj. Not normally needed. SCANGOBJ_OPTIONS = # Extra options to supply to gtkdoc-scan. # e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED" SCAN_OPTIONS = --rebuild-types # Extra options to supply to gtkdoc-mkdb. # e.g. MKDB_OPTIONS=--sgml-mode --output-format=xml MKDB_OPTIONS = --sgml-mode --output-format=xml # Extra options to supply to gtkdoc-mktmpl # e.g. MKTMPL_OPTIONS=--only-section-tmpl MKTMPL_OPTIONS = # Extra options to supply to gtkdoc-fixref. Not normally needed. # e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html FIXXREF_OPTIONS = \ --extra-dir=../libinfinity/html # Used for dependencies. The docs will be rebuilt if any of these change. # e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h # e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c HFILE_GLOB = \ $(top_srcdir)/libinfgtk/*.h CFILE_GLOB = \ $(top_srcdir)/libinfgtk/*.c # Header files to ignore when scanning. # e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h IGNORE_HFILES = inf-gtk-resources.h # Images to copy into HTML directory. # e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png HTML_IMAGES = # Extra SGML files that are included by $(DOC_MAIN_SGML_FILE). # e.g. content_files=running.sgml building.sgml changes-2.0.sgml content_files = \ ../version.xml # SGML files where gtk-doc abbrevations (#GtkWidget) are expanded # These files must be listed here *and* in content_files # e.g. expand_content_files=running.sgml expand_content_files = # CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library. # Only needed if you are using gtkdoc-scangobj to dynamically query widget # signals and properties. # e.g. INCLUDES=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS) # e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib) #INCLUDES=$(infgtk_CFLAGS) AM_CPPFLAGS = $(infgtk_CFLAGS) GTKDOC_LIBS = \ $(infgtk_LIBS) \ $(top_builddir)/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(top_builddir)/libinfgtk/libinfgtk-$(LIBINFINITY_API_VERSION).la @GTK_DOC_USE_LIBTOOL_FALSE@GTKDOC_CC = $(CC) $(INCLUDES) $(GTKDOC_DEPS_CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) @GTK_DOC_USE_LIBTOOL_TRUE@GTKDOC_CC = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(INCLUDES) $(GTKDOC_DEPS_CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) @GTK_DOC_USE_LIBTOOL_FALSE@GTKDOC_LD = $(CC) $(GTKDOC_DEPS_LIBS) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) @GTK_DOC_USE_LIBTOOL_TRUE@GTKDOC_LD = $(LIBTOOL) --tag=CC --mode=link $(CC) $(GTKDOC_DEPS_LIBS) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) @GTK_DOC_USE_LIBTOOL_FALSE@GTKDOC_RUN = @GTK_DOC_USE_LIBTOOL_TRUE@GTKDOC_RUN = $(LIBTOOL) --mode=execute # We set GPATH here; this gives us semantics for GNU make # which are more like other make's VPATH, when it comes to # whether a source that is a target of one rule is then # searched for in VPATH/GPATH. # GPATH = $(srcdir) TARGET_DIR = $(HTML_DIR)/$(DOC_MODULE) SETUP_FILES = \ $(content_files) \ $(expand_content_files) \ $(DOC_MAIN_SGML_FILE) \ $(DOC_MODULE)-sections.txt \ $(DOC_MODULE)-overrides.txt # This includes the standard gtk-doc make rules, copied by gtkdocize. # Other files to distribute # e.g. EXTRA_DIST += version.xml.in EXTRA_DIST = $(HTML_IMAGES) $(SETUP_FILES) DOC_STAMPS = setup-build.stamp scan-build.stamp sgml-build.stamp \ html-build.stamp pdf-build.stamp \ sgml.stamp html.stamp pdf.stamp SCANOBJ_FILES = \ $(DOC_MODULE).args \ $(DOC_MODULE).hierarchy \ $(DOC_MODULE).interfaces \ $(DOC_MODULE).prerequisites \ $(DOC_MODULE).signals REPORT_FILES = \ $(DOC_MODULE)-undocumented.txt \ $(DOC_MODULE)-undeclared.txt \ $(DOC_MODULE)-unused.txt CLEANFILES = $(SCANOBJ_FILES) $(REPORT_FILES) $(DOC_STAMPS) gtkdoc-check.test @GTK_DOC_BUILD_HTML_FALSE@HTML_BUILD_STAMP = @GTK_DOC_BUILD_HTML_TRUE@HTML_BUILD_STAMP = html-build.stamp @GTK_DOC_BUILD_PDF_FALSE@PDF_BUILD_STAMP = @GTK_DOC_BUILD_PDF_TRUE@PDF_BUILD_STAMP = pdf-build.stamp #### setup #### GTK_DOC_V_SETUP = $(GTK_DOC_V_SETUP_$(V)) GTK_DOC_V_SETUP_ = $(GTK_DOC_V_SETUP_$(AM_DEFAULT_VERBOSITY)) GTK_DOC_V_SETUP_0 = @echo " DOC Preparing build"; #### scan #### GTK_DOC_V_SCAN = $(GTK_DOC_V_SCAN_$(V)) GTK_DOC_V_SCAN_ = $(GTK_DOC_V_SCAN_$(AM_DEFAULT_VERBOSITY)) GTK_DOC_V_SCAN_0 = @echo " DOC Scanning header files"; GTK_DOC_V_INTROSPECT = $(GTK_DOC_V_INTROSPECT_$(V)) GTK_DOC_V_INTROSPECT_ = $(GTK_DOC_V_INTROSPECT_$(AM_DEFAULT_VERBOSITY)) GTK_DOC_V_INTROSPECT_0 = @echo " DOC Introspecting gobjects"; #### xml #### GTK_DOC_V_XML = $(GTK_DOC_V_XML_$(V)) GTK_DOC_V_XML_ = $(GTK_DOC_V_XML_$(AM_DEFAULT_VERBOSITY)) GTK_DOC_V_XML_0 = @echo " DOC Building XML"; #### html #### GTK_DOC_V_HTML = $(GTK_DOC_V_HTML_$(V)) GTK_DOC_V_HTML_ = $(GTK_DOC_V_HTML_$(AM_DEFAULT_VERBOSITY)) GTK_DOC_V_HTML_0 = @echo " DOC Building HTML"; GTK_DOC_V_XREF = $(GTK_DOC_V_XREF_$(V)) GTK_DOC_V_XREF_ = $(GTK_DOC_V_XREF_$(AM_DEFAULT_VERBOSITY)) GTK_DOC_V_XREF_0 = @echo " DOC Fixing cross-references"; #### pdf #### GTK_DOC_V_PDF = $(GTK_DOC_V_PDF_$(V)) GTK_DOC_V_PDF_ = $(GTK_DOC_V_PDF_$(AM_DEFAULT_VERBOSITY)) GTK_DOC_V_PDF_0 = @echo " DOC Building PDF"; # Files not to distribute # for --rebuild-types in $(SCAN_OPTIONS), e.g. $(DOC_MODULE).types # for --rebuild-sections in $(SCAN_OPTIONS) e.g. $(DOC_MODULE)-sections.txt DISTCLEANFILES = libinfgtk-$(LIBINFINITY_API_VERSION).types version.xml all: all-am .SUFFIXES: $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/gtk-doc.make $(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) --foreign docs/reference/libinfgtk/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign docs/reference/libinfgtk/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_srcdir)/gtk-doc.make $(am__empty): $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs tags TAGS: ctags CTAGS: cscope cscopelist: 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 $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-hook check-am: all-am check: check-am @ENABLE_GTK_DOC_FALSE@all-local: all-am: Makefile all-local installdirs: install: 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) -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic distclean-local dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-data-local install-dvi: install-dvi-am install-dvi-am: install-exec-am: 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 -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic \ maintainer-clean-local mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-local .MAKE: install-am install-strip .PHONY: all all-am all-local check check-am clean clean-generic \ clean-libtool clean-local cscopelist-am ctags-am dist-hook \ distclean distclean-generic distclean-libtool distclean-local \ distdir dvi dvi-am html html-am info info-am install \ install-am install-data install-data-am install-data-local \ 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-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ maintainer-clean-local mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \ uninstall-am uninstall-local .PRECIOUS: Makefile gtkdoc-check.test: Makefile $(AM_V_GEN)echo "#!/bin/sh -e" > $@; \ echo "$(GTKDOC_CHECK_PATH) || exit 1" >> $@; \ chmod +x $@ all-gtk-doc: $(HTML_BUILD_STAMP) $(PDF_BUILD_STAMP) .PHONY: all-gtk-doc @ENABLE_GTK_DOC_TRUE@all-local: all-gtk-doc docs: $(HTML_BUILD_STAMP) $(PDF_BUILD_STAMP) $(REPORT_FILES): sgml-build.stamp setup-build.stamp: -$(GTK_DOC_V_SETUP)if test "$(abs_srcdir)" != "$(abs_builddir)" ; then \ files=`echo $(SETUP_FILES) $(DOC_MODULE).types`; \ if test "x$$files" != "x" ; then \ for file in $$files ; do \ destdir=`dirname $(abs_builddir)/$$file`; \ test -d "$$destdir" || mkdir -p "$$destdir"; \ test -f $(abs_srcdir)/$$file && \ cp -pf $(abs_srcdir)/$$file $(abs_builddir)/$$file || true; \ done; \ fi; \ fi $(AM_V_at)touch setup-build.stamp scan-build.stamp: setup-build.stamp $(HFILE_GLOB) $(CFILE_GLOB) $(GTK_DOC_V_SCAN)_source_dir='' ; \ for i in $(DOC_SOURCE_DIR) ; do \ _source_dir="$${_source_dir} --source-dir=$$i" ; \ done ; \ gtkdoc-scan --module=$(DOC_MODULE) --ignore-headers="$(IGNORE_HFILES)" $${_source_dir} $(SCAN_OPTIONS) $(EXTRA_HFILES) $(GTK_DOC_V_INTROSPECT)if grep -l '^..*$$' $(DOC_MODULE).types > /dev/null 2>&1 ; then \ scanobj_options=""; \ gtkdoc-scangobj 2>&1 --help | grep >/dev/null "\-\-verbose"; \ if test "$$?" = "0"; then \ if test "x$(V)" = "x1"; then \ scanobj_options="--verbose"; \ fi; \ fi; \ CC="$(GTKDOC_CC)" LD="$(GTKDOC_LD)" RUN="$(GTKDOC_RUN)" CFLAGS="$(GTKDOC_CFLAGS) $(CFLAGS)" LDFLAGS="$(GTKDOC_LIBS) $(LDFLAGS)" \ gtkdoc-scangobj $(SCANGOBJ_OPTIONS) $$scanobj_options --module=$(DOC_MODULE); \ else \ for i in $(SCANOBJ_FILES) ; do \ test -f $$i || touch $$i ; \ done \ fi $(AM_V_at)touch scan-build.stamp $(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(DOC_MODULE)-sections.txt $(DOC_MODULE)-overrides.txt: scan-build.stamp @true sgml-build.stamp: setup-build.stamp $(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(HFILE_GLOB) $(CFILE_GLOB) $(DOC_MODULE)-sections.txt $(DOC_MODULE)-overrides.txt $(expand_content_files) xml/gtkdocentities.ent $(GTK_DOC_V_XML)_source_dir='' ; \ for i in $(DOC_SOURCE_DIR) ; do \ _source_dir="$${_source_dir} --source-dir=$$i" ; \ done ; \ gtkdoc-mkdb --module=$(DOC_MODULE) --output-format=xml --expand-content-files="$(expand_content_files)" --main-sgml-file=$(DOC_MAIN_SGML_FILE) $${_source_dir} $(MKDB_OPTIONS) $(AM_V_at)touch sgml-build.stamp sgml.stamp: sgml-build.stamp @true xml/gtkdocentities.ent: Makefile $(GTK_DOC_V_XML)$(MKDIR_P) $(@D) && ( \ echo ""; \ echo ""; \ echo ""; \ echo ""; \ echo ""; \ echo ""; \ echo ""; \ ) > $@ html-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) $(expand_content_files) $(GTK_DOC_V_HTML)rm -rf html && mkdir html && \ mkhtml_options=""; \ gtkdoc-mkhtml 2>&1 --help | grep >/dev/null "\-\-verbose"; \ if test "$$?" = "0"; then \ if test "x$(V)" = "x1"; then \ mkhtml_options="$$mkhtml_options --verbose"; \ fi; \ fi; \ gtkdoc-mkhtml 2>&1 --help | grep >/dev/null "\-\-path"; \ if test "$$?" = "0"; then \ mkhtml_options="$$mkhtml_options --path=\"$(abs_srcdir)\""; \ fi; \ cd html && gtkdoc-mkhtml $$mkhtml_options $(MKHTML_OPTIONS) $(DOC_MODULE) ../$(DOC_MAIN_SGML_FILE) -@test "x$(HTML_IMAGES)" = "x" || \ for file in $(HTML_IMAGES) ; do \ if test -f $(abs_srcdir)/$$file ; then \ cp $(abs_srcdir)/$$file $(abs_builddir)/html; \ fi; \ if test -f $(abs_builddir)/$$file ; then \ cp $(abs_builddir)/$$file $(abs_builddir)/html; \ fi; \ done; $(GTK_DOC_V_XREF)gtkdoc-fixxref --module=$(DOC_MODULE) --module-dir=html --html-dir=$(HTML_DIR) $(FIXXREF_OPTIONS) $(AM_V_at)touch html-build.stamp pdf-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) $(expand_content_files) $(GTK_DOC_V_PDF)rm -f $(DOC_MODULE).pdf && \ mkpdf_options=""; \ gtkdoc-mkpdf 2>&1 --help | grep >/dev/null "\-\-verbose"; \ if test "$$?" = "0"; then \ if test "x$(V)" = "x1"; then \ mkpdf_options="$$mkpdf_options --verbose"; \ fi; \ fi; \ if test "x$(HTML_IMAGES)" != "x"; then \ for img in $(HTML_IMAGES); do \ part=`dirname $$img`; \ echo $$mkpdf_options | grep >/dev/null "\-\-imgdir=$$part "; \ if test $$? != 0; then \ mkpdf_options="$$mkpdf_options --imgdir=$$part"; \ fi; \ done; \ fi; \ gtkdoc-mkpdf --path="$(abs_srcdir)" $$mkpdf_options $(DOC_MODULE) $(DOC_MAIN_SGML_FILE) $(MKPDF_OPTIONS) $(AM_V_at)touch pdf-build.stamp ############## clean-local: @rm -f *~ *.bak @rm -rf .libs @if echo $(SCAN_OPTIONS) | grep -q "\-\-rebuild-types" ; then \ rm -f $(DOC_MODULE).types; \ fi @if echo $(SCAN_OPTIONS) | grep -q "\-\-rebuild-sections" ; then \ rm -f $(DOC_MODULE)-sections.txt; \ fi distclean-local: @rm -rf xml html $(REPORT_FILES) $(DOC_MODULE).pdf \ $(DOC_MODULE)-decl-list.txt $(DOC_MODULE)-decl.txt @if test "$(abs_srcdir)" != "$(abs_builddir)" ; then \ rm -f $(SETUP_FILES) $(DOC_MODULE).types; \ fi maintainer-clean-local: @rm -rf xml html install-data-local: @installfiles=`echo $(builddir)/html/*`; \ if test "$$installfiles" = '$(builddir)/html/*'; \ then echo 1>&2 'Nothing to install' ; \ else \ if test -n "$(DOC_MODULE_VERSION)"; then \ installdir="$(DESTDIR)$(TARGET_DIR)-$(DOC_MODULE_VERSION)"; \ else \ installdir="$(DESTDIR)$(TARGET_DIR)"; \ fi; \ $(mkinstalldirs) $${installdir} ; \ for i in $$installfiles; do \ echo ' $(INSTALL_DATA) '$$i ; \ $(INSTALL_DATA) $$i $${installdir}; \ done; \ if test -n "$(DOC_MODULE_VERSION)"; then \ mv -f $${installdir}/$(DOC_MODULE).devhelp2 \ $${installdir}/$(DOC_MODULE)-$(DOC_MODULE_VERSION).devhelp2; \ fi; \ $(GTKDOC_REBASE) --relative --dest-dir=$(DESTDIR) --html-dir=$${installdir}; \ fi uninstall-local: @if test -n "$(DOC_MODULE_VERSION)"; then \ installdir="$(DESTDIR)$(TARGET_DIR)-$(DOC_MODULE_VERSION)"; \ else \ installdir="$(DESTDIR)$(TARGET_DIR)"; \ fi; \ rm -rf $${installdir} # # Require gtk-doc when making dist # @HAVE_GTK_DOC_TRUE@dist-check-gtkdoc: docs @HAVE_GTK_DOC_FALSE@dist-check-gtkdoc: @HAVE_GTK_DOC_FALSE@ @echo "*** gtk-doc is needed to run 'make dist'. ***" @HAVE_GTK_DOC_FALSE@ @echo "*** gtk-doc was not found when 'configure' ran. ***" @HAVE_GTK_DOC_FALSE@ @echo "*** please install gtk-doc and rerun 'configure'. ***" @HAVE_GTK_DOC_FALSE@ @false dist-hook: dist-check-gtkdoc all-gtk-doc dist-hook-local @mkdir $(distdir)/html @cp ./html/* $(distdir)/html @-cp ./$(DOC_MODULE).pdf $(distdir)/ @-cp ./$(DOC_MODULE).types $(distdir)/ @-cp ./$(DOC_MODULE)-sections.txt $(distdir)/ @cd $(distdir) && rm -f $(DISTCLEANFILES) @$(GTKDOC_REBASE) --online --relative --html-dir=$(distdir)/html .PHONY : dist-hook-local docs # Comment this out if you want your docs-status tested during 'make check' #TESTS = $(GTKDOC_CHECK) # 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: libinfinity-0.7.1/docs/reference/libinfgtk/PaxHeaders.26529/libinfgtk-0.7-docs.sgml0000644000000000000000000000013213034342512024524 xustar0030 mtime=1483851082.013718339 30 atime=1483851082.013718339 30 ctime=1488261614.956081597 libinfinity-0.7.1/docs/reference/libinfgtk/libinfgtk-0.7-docs.sgml0000644000175000017500000000317113034342512025260 0ustar00arminarmin00000000000000 ]> libinfgtk-&api_version; Reference Manual for libinfgtk &version;. The latest version of this documentation can be found on-line at http://infinote.0x539.de/libinfinity/API/libinfgtk/. libinfgtk API libinfinity-0.7.1/docs/reference/libinfgtk/PaxHeaders.26529/Makefile.am0000644000000000000000000000013213034342512022473 xustar0030 mtime=1483851082.013718339 30 atime=1483851082.013718339 30 ctime=1488261614.952081606 libinfinity-0.7.1/docs/reference/libinfgtk/Makefile.am0000644000175000017500000000643013034342512023230 0ustar00arminarmin00000000000000## Process this file with automake to produce Makefile.in # We require automake 1.6 at least. AUTOMAKE_OPTIONS = 1.6 # This is a blank Makefile.am for using gtk-doc. # Copy this to your project's API docs directory and modify the variables to # suit your project. See the GTK+ Makefiles in gtk+/docs/reference for examples # of using the various options. # The name of the module, e.g. 'glib'. DOC_MODULE=libinfgtk-$(LIBINFINITY_API_VERSION) # The top-level SGML file. You can change this if you want to. DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml # The directory containing the source code. Relative to $(srcdir). # gtk-doc will search all .c & .h files beneath here for inline comments # documenting the functions and macros. # e.g. DOC_SOURCE_DIR=../../../gtk DOC_SOURCE_DIR=$(top_srcdir)/libinfgtk # Extra options to pass to gtkdoc-scangobj. Not normally needed. SCANGOBJ_OPTIONS= # Extra options to supply to gtkdoc-scan. # e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED" SCAN_OPTIONS=--rebuild-types # Extra options to supply to gtkdoc-mkdb. # e.g. MKDB_OPTIONS=--sgml-mode --output-format=xml MKDB_OPTIONS=--sgml-mode --output-format=xml # Extra options to supply to gtkdoc-mktmpl # e.g. MKTMPL_OPTIONS=--only-section-tmpl MKTMPL_OPTIONS= # Extra options to supply to gtkdoc-fixref. Not normally needed. # e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html FIXXREF_OPTIONS= \ --extra-dir=../libinfinity/html # Used for dependencies. The docs will be rebuilt if any of these change. # e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h # e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c HFILE_GLOB = \ $(top_srcdir)/libinfgtk/*.h CFILE_GLOB = \ $(top_srcdir)/libinfgtk/*.c # Header files to ignore when scanning. # e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h IGNORE_HFILES = inf-gtk-resources.h # Images to copy into HTML directory. # e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png HTML_IMAGES= # Extra SGML files that are included by $(DOC_MAIN_SGML_FILE). # e.g. content_files=running.sgml building.sgml changes-2.0.sgml content_files = \ ../version.xml # SGML files where gtk-doc abbrevations (#GtkWidget) are expanded # These files must be listed here *and* in content_files # e.g. expand_content_files=running.sgml expand_content_files= # CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library. # Only needed if you are using gtkdoc-scangobj to dynamically query widget # signals and properties. # e.g. INCLUDES=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS) # e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib) #INCLUDES=$(infgtk_CFLAGS) AM_CPPFLAGS=$(infgtk_CFLAGS) GTKDOC_LIBS = \ $(infgtk_LIBS) \ $(top_builddir)/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(top_builddir)/libinfgtk/libinfgtk-$(LIBINFINITY_API_VERSION).la # This includes the standard gtk-doc make rules, copied by gtkdocize. include $(top_srcdir)/gtk-doc.make # Other files to distribute # e.g. EXTRA_DIST += version.xml.in EXTRA_DIST += # Files not to distribute # for --rebuild-types in $(SCAN_OPTIONS), e.g. $(DOC_MODULE).types # for --rebuild-sections in $(SCAN_OPTIONS) e.g. $(DOC_MODULE)-sections.txt DISTCLEANFILES=libinfgtk-$(LIBINFINITY_API_VERSION).types version.xml # Comment this out if you want your docs-status tested during 'make check' #TESTS = $(GTKDOC_CHECK) libinfinity-0.7.1/docs/reference/libinfgtk/PaxHeaders.26529/libinfgtk-0.7-sections.txt0000644000000000000000000000013213055210760025302 xustar0030 mtime=1488261616.856077334 30 atime=1483851082.013718339 30 ctime=1488261616.856077334 libinfinity-0.7.1/docs/reference/libinfgtk/libinfgtk-0.7-sections.txt0000644000175000017500000001524613055210760026044 0ustar00arminarmin00000000000000
inf-gtk-browser-store InfGtkBrowserStore InfGtkBrowserStore InfGtkBrowserStoreClass inf_gtk_browser_store_new inf_gtk_browser_store_add_discovery inf_gtk_browser_store_add_connection inf_gtk_browser_store_add_browser inf_gtk_browser_store_remove_browser inf_gtk_browser_store_remove_connection inf_gtk_browser_store_clear_connection_error inf_gtk_browser_store_set_connection_name INF_GTK_BROWSER_STORE INF_GTK_IS_BROWSER_STORE INF_GTK_TYPE_BROWSER_STORE inf_gtk_browser_store_get_type INF_GTK_BROWSER_STORE_CLASS INF_GTK_IS_BROWSER_STORE_CLASS INF_GTK_BROWSER_STORE_GET_CLASS
inf-gtk-browser-model-filter InfGtkBrowserModelFilter InfGtkBrowserModelFilter InfGtkBrowserModelFilterClass inf_gtk_browser_model_filter_new INF_GTK_BROWSER_MODEL_FILTER INF_GTK_IS_BROWSER_MODEL_FILTER INF_GTK_TYPE_BROWSER_MODEL_FILTER inf_gtk_browser_model_filter_get_type INF_GTK_BROWSER_MODEL_FILTER_CLASS INF_GTK_IS_BROWSER_MODEL_FILTER_CLASS INF_GTK_BROWSER_MODEL_FILTER_GET_CLASS
inf-gtk-browser-model INF_GTK_TYPE_BROWSER_MODEL_STATUS InfGtkBrowserModel InfGtkBrowserModelInterface InfGtkBrowserModelStatus InfGtkBrowserModelColumn inf_gtk_browser_model_set_browser inf_gtk_browser_model_resolve inf_gtk_browser_model_browser_iter_to_tree_iter inf_gtk_browser_model_get_type INF_GTK_BROWSER_MODEL INF_GTK_IS_BROWSER_MODEL INF_GTK_TYPE_BROWSER_MODEL inf_gtk_browser_model_status_get_type INF_GTK_BROWSER_MODEL_GET_IFACE
inf-gtk-browser-model-sort InfGtkBrowserModelSort InfGtkBrowserModelSort InfGtkBrowserModelSortClass inf_gtk_browser_model_sort_new INF_GTK_BROWSER_MODEL_SORT INF_GTK_IS_BROWSER_MODEL_SORT INF_GTK_TYPE_BROWSER_MODEL_SORT inf_gtk_browser_model_sort_get_type INF_GTK_BROWSER_MODEL_SORT_CLASS INF_GTK_IS_BROWSER_MODEL_SORT_CLASS INF_GTK_BROWSER_MODEL_SORT_GET_CLASS
inf-gtk-browser-view InfGtkBrowserView InfGtkBrowserView InfGtkBrowserViewClass inf_gtk_browser_view_new inf_gtk_browser_view_new_with_model inf_gtk_browser_view_get_selected inf_gtk_browser_view_set_selected INF_GTK_BROWSER_VIEW INF_GTK_IS_BROWSER_VIEW INF_GTK_TYPE_BROWSER_VIEW inf_gtk_browser_view_get_type INF_GTK_BROWSER_VIEW_CLASS INF_GTK_IS_BROWSER_VIEW_CLASS INF_GTK_BROWSER_VIEW_GET_CLASS INF_GTK_TYPE_BROWSER_VIEW_STATUS
inf-gtk-io InfGtkIo InfGtkIo InfGtkIoClass inf_gtk_io_new INF_GTK_IO INF_GTK_IS_IO INF_GTK_TYPE_IO inf_gtk_io_get_type INF_GTK_IO_CLASS INF_GTK_IS_IO_CLASS INF_GTK_IO_GET_CLASS
inf-gtk-account-creation-dialog InfGtkAccountCreationsDialog InfGtkAccountCreationDialog InfGtkAccountCreationDialogClass inf_gtk_account_creation_dialog_new inf_gtk_account_creation_dialog_set_browser INF_GTK_ACCOUNT_CREATION_DIALOG INF_GTK_ACCOUNT_CREATION_DIALOG_CLASS INF_GTK_ACCOUNT_CREATION_DIALOG_GET_CLASS INF_GTK_IS_ACCOUNT_CREATION_DIALOG INF_GTK_IS_ACCOUNT_CREATION_DIALOG_CLASS INF_GTK_TYPE_ACCOUNT_CREATION_DIALOG inf_gtk_account_creation_dialog_get_type
inf-gtk-permissions-dialog InfGtkPermissionsDialog InfGtkPermissionsDialog InfGtkPermissionsDialogClass inf_gtk_permissions_dialog_new inf_gtk_permissions_dialog_set_node INF_GTK_PERMISSIONS_DIALOG INF_GTK_PERMISSIONS_DIALOG_CLASS INF_GTK_PERMISSIONS_DIALOG_GET_CLASS INF_GTK_IS_PERMISSIONS_DIALOG INF_GTK_IS_PERMISSIONS_DIALOG_CLASS INF_GTK_TYPE_PERMISSIONS_DIALOG inf_gtk_permissions_dialog_get_type
inf-gtk-certificate-dialog InfGtkCertificateDialog InfGtkCertificateDialog InfGtkCertificateDialogClass inf_gtk_certificate_dialog_new INF_GTK_CERTIFICATE_DIALOG INF_GTK_CERTIFICATE_DIALOG_CLASS INF_GTK_CERTIFICATE_DIALOG_GET_CLASS INF_GTK_IS_CERTIFICATE_DIALOG INF_GTK_IS_CERTIFICATE_DIALOG_CLASS INF_GTK_TYPE_CERTIFICATE_DIALOG inf_gtk_certificate_dialog_get_type
inf-gtk-certificate-manager InfGtkCertificateManager InfGtkCertificateManager InfGtkCertificateManagerClass inf_gtk_certificate_manager_new INF_GTK_CERTIFICATE_MANAGER INF_GTK_CERTIFICATE_MANAGER_CLASS INF_GTK_CERTIFICATE_MANAGER_GET_CLASS INF_GTK_IS_CERTIFICATE_MANAGER INF_GTK_IS_CERTIFICATE_MANAGER_CLASS INF_GTK_TYPE_CERTIFICATE_MANAGER inf_gtk_certificate_manager_get_type
inf-gtk-connection-view InfGtkConnectionView InfGtkConnectionView InfGtkConnectionViewClass inf_gtk_connection_view_new inf_gtk_connection_view_new_with_connection inf_gtk_connection_view_set_connection INF_GTK_CONNECTION_VIEW INF_GTK_CONNECTION_VIEW_CLASS INF_GTK_CONNECTION_VIEW_GET_CLASS INF_GTK_IS_CONNECTION_VIEW INF_GTK_IS_CONNECTION_VIEW_CLASS INF_GTK_TYPE_CONNECTION_VIEW INF_GTK_TYPE_CONNECTION_VIEW_FLAGS inf_gtk_connection_view_get_type
inf-gtk-certificate-view InfGtkCertificateView InfGtkCertificateView InfGtkCertificateViewClass inf_gtk_certificate_view_new inf_gtk_certificate_view_new_with_certificate inf_gtk_certificate_view_set_certificate INF_GTK_CERTIFICATE_VIEW INF_GTK_CERTIFICATE_VIEW_CLASS INF_GTK_CERTIFICATE_VIEW_GET_CLASS INF_GTK_IS_CERTIFICATE_VIEW INF_GTK_IS_CERTIFICATE_VIEW_CLASS INF_GTK_TYPE_CERTIFICATE_VIEW INF_GTK_TYPE_CERTIFICATE_VIEW_FLAGS inf_gtk_certificate_view_get_type
inf-gtk-chat InfGtkChat InfGtkChat InfGtkChatClass inf_gtk_chat_new inf_gtk_chat_set_session inf_gtk_chat_get_active_user inf_gtk_chat_set_active_user inf_gtk_chat_get_entry INF_GTK_CHAT INF_GTK_IS_CHAT INF_GTK_TYPE_CHAT inf_gtk_chat_get_type INF_GTK_CHAT_CLASS INF_GTK_IS_CHAT_CLASS INF_GTK_CHAT_GET_CLASS
inf-gtk-acl-sheet-view InfGtkAclSheetView InfGtkAclSheetView InfGtkAclSheetViewClass inf_gtk_acl_sheet_view_new inf_gtk_acl_sheet_view_set_sheet inf_gtk_acl_sheet_view_get_sheet inf_gtk_acl_sheet_view_set_editable inf_gtk_acl_sheet_view_get_editable inf_gtk_acl_sheet_view_set_show_default inf_gtk_acl_sheet_view_get_show_default inf_gtk_acl_sheet_view_set_permission_mask inf_gtk_acl_sheet_view_get_permission_mask INF_GTK_ACL_SHEET_VIEW INF_GTK_IS_ACL_SHEET_VIEW INF_GTK_TYPE_ACL_SHEET_VIEW inf_gtk_acl_sheet_view_get_type INF_GTK_ACL_SHEET_VIEW_CLASS INF_GTK_IS_ACL_SHEET_VIEW_CLASS INF_GTK_ACL_SHEET_VIEW_GET_CLASS
libinfinity-0.7.1/docs/reference/libinfgtk/PaxHeaders.26529/libinfgtk-0.7-overrides.txt0000644000000000000000000000013212401204465025454 xustar0030 mtime=1409616181.538256853 30 atime=1409616181.538256853 30 ctime=1488261614.960081588 libinfinity-0.7.1/docs/reference/libinfgtk/libinfgtk-0.7-overrides.txt0000644000175000017500000000000012401204465026174 0ustar00arminarmin00000000000000libinfinity-0.7.1/docs/reference/PaxHeaders.26529/api_version.xml.in.in0000644000000000000000000000013212400102201022521 xustar0030 mtime=1409320065.087133093 30 atime=1409320065.087133093 30 ctime=1488261589.980136922 libinfinity-0.7.1/docs/reference/api_version.xml.in.in0000644000175000017500000000003212400102201023246 0ustar00arminarmin00000000000000@LIBINFINITY_API_VERSION@ libinfinity-0.7.1/docs/reference/PaxHeaders.26529/libinfinity0000644000000000000000000000013213055210752020734 xustar0030 mtime=1488261610.844090798 30 atime=1488261589.984136914 30 ctime=1488261610.844090798 libinfinity-0.7.1/docs/reference/libinfinity/0000755000175000017500000000000013055210752021543 5ustar00arminarmin00000000000000libinfinity-0.7.1/docs/reference/libinfinity/PaxHeaders.26529/html0000644000000000000000000000013213055210752021700 xustar0030 mtime=1488261610.916090637 30 atime=1488261610.828090834 30 ctime=1488261610.916090637 libinfinity-0.7.1/docs/reference/libinfinity/html/0000755000175000017500000000000013055210752022507 5ustar00arminarmin00000000000000libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfAdoptedStateVector.html0000644000000000000000000000013213055210752027044 xustar0030 mtime=1488261610.872090736 30 atime=1488261610.872090736 30 ctime=1488261610.872090736 libinfinity-0.7.1/docs/reference/libinfinity/html/InfAdoptedStateVector.html0000644000175000017500000014172313055210752027606 0ustar00arminarmin00000000000000 InfAdoptedStateVector: libinfinity-0.7 Reference Manual

InfAdoptedStateVector

InfAdoptedStateVector — Represents a state in the interaction model

Stability Level

Unstable, unless otherwise indicated

Object Hierarchy

    GBoxed
    ╰── InfAdoptedStateVector

Includes

#include <libinfinity/adopted/inf-adopted-state-vector.h>

Description

The InfAdoptedStateVector represents a state in the current state space. It basically maps user IDs to operation counts and states how many operations of the corresponding user have already been performed.

Functions

InfAdoptedStateVectorForeachFunc ()

void
(*InfAdoptedStateVectorForeachFunc) (guint id,
                                     guint value,
                                     gpointer user_data);

This function is called for every component in the state vector during the invocation of inf_adopted_state_vector_foreach().

Parameters

id

The ID of the entry.

 

value

The value of the entry.

 

user_data

The user data passed to inf_adopted_state_vector_foreach().

 

inf_adopted_state_vector_error_quark ()

GQuark
inf_adopted_state_vector_error_quark (void);

The domain for InfAdoptedStateVectorError errors.

Returns

A GQuark for that domain.


inf_adopted_state_vector_new ()

InfAdoptedStateVector *
inf_adopted_state_vector_new (void);

Returns a new state vector with all components set to zero.

[constructor]

Returns

A new InfAdoptedStateVector.

[transfer full]


inf_adopted_state_vector_copy ()

InfAdoptedStateVector *
inf_adopted_state_vector_copy (InfAdoptedStateVector *vec);

Returns a copy of vec .

Parameters

vec

The InfAdoptedStateVector to copy

 

Returns

A copy of vec .

[transfer full]


inf_adopted_state_vector_free ()

void
inf_adopted_state_vector_free (InfAdoptedStateVector *vec);

Frees a state vector allocated by inf_adopted_state_vector_new() or inf_adopted_state_vector_copy().

Parameters

vec

A InfAdoptedStateVector.

 

inf_adopted_state_vector_get ()

guint
inf_adopted_state_vector_get (const InfAdoptedStateVector *vec,
                              guint id);

Returns the timestamp for the given component. Implicitely, all IDs that the vector does not contain are assigned the timestamp 0.

Parameters

vec

A InfAdoptedStateVector.

 

id

The component whose timestamp to look for.

 

Returns

The component 'th entry in the vector.


inf_adopted_state_vector_set ()

void
inf_adopted_state_vector_set (InfAdoptedStateVector *vec,
                              guint id,
                              guint value);

Sets the given component of vec to value .

Parameters

vec

A InfAdoptedStateVector.

 

id

The component to change.

 

value

The value to set the component to.

 

inf_adopted_state_vector_add ()

void
inf_adopted_state_vector_add (InfAdoptedStateVector *vec,
                              guint id,
                              gint value);

Adds value to the current value of component . value may be negative in which case the current value is actually decreased. Make sure to not drop below zero this way.

Parameters

vec

A InfAdoptedStateVector.

 

id

The component to change.

 

value

The value by which to change the component.

 

inf_adopted_state_vector_foreach ()

void
inf_adopted_state_vector_foreach (const InfAdoptedStateVector *vec,
                                  InfAdoptedStateVectorForeachFunc func,
                                  gpointer user_data);

Calls func for each component in vec . Note that there may be users for which func will not be called if their timestamp is 0.

Parameters

vec

A InfAdoptedStateVector.

 

func

The function to call.

[scope call]

user_data

Additional data to pass to func .

 

inf_adopted_state_vector_compare ()

int
inf_adopted_state_vector_compare (const InfAdoptedStateVector *first,
                                  const InfAdoptedStateVector *second);

Performs a comparison suited for strict-weak ordering so that state vectors can be sorted. This function returns -1 if first compares before second , 0 if they compare equal and 1 if first compares after second .

Parameters

first

A InfAdoptedStateVector.

 

second

Another InfAdoptedStateVector.

 

Returns

-1, 0 or 1.


inf_adopted_state_vector_causally_before ()

gboolean
inf_adopted_state_vector_causally_before
                               (const InfAdoptedStateVector *first,
                                const InfAdoptedStateVector *second);

Checks whether an event that occured at time second is causally dependant on an event that occured at time first , that is all components of first are less or equal to the corresponding component in second .

Parameters

first

A InfAdoptedStateVector.

 

second

Another InfAdoptedStateVector.

 

Returns

Whether second depends on first .


inf_adopted_state_vector_causally_before_inc ()

gboolean
inf_adopted_state_vector_causally_before_inc
                               (const InfAdoptedStateVector *first,
                                const InfAdoptedStateVector *second,
                                guint inc_component);

This function does the equivalent of

1
2
3
4
inf_adopted_state_vector_add(first, inc_component, 1);
gboolean result = inf_adopted_state_vector_causally_before(first, second);
inf_adopted_state_vector_add(first, inc_component, -1);
return result;

But it is more efficient.

Parameters

first

A InfAdoptedStateVector.

 

second

Another InfAdoptedStateVector.

 

inc_component

The component to increment before comparing.

 

Returns

Whether second depends on first with the inc_component th component increased by one.


inf_adopted_state_vector_vdiff ()

guint
inf_adopted_state_vector_vdiff (const InfAdoptedStateVector *first,
                                const InfAdoptedStateVector *second);

This function returns the sum of the differences between each component of first and second . This function can only be called if inf_adopted_state_vector_causally_before() returns TRUE.

Parameters

first

A InfAdoptedStateVector.

 

second

Another InfAdoptedStateVector.

 

Returns

The sum of the differences between each component of first and second .


inf_adopted_state_vector_to_string ()

gchar *
inf_adopted_state_vector_to_string (const InfAdoptedStateVector *vec);

Returns a string representation of vec .

Parameters

vec

A InfAdoptedStateVector.

 

Returns

A newly-allocated string to be freed by the caller.

[transfer full]


inf_adopted_state_vector_from_string ()

InfAdoptedStateVector *
inf_adopted_state_vector_from_string (const gchar *str,
                                      GError **error);

Recreates the InfAdoptedStateVector from its string representation. If an error occurs, the function returns NULL and error is set.

Parameters

str

A string representation of a InfAdoptedStateVector.

 

error

Location to place an error, if any.

 

Returns

A new InfAdoptedStateVector, or NULL.

[transfer full]


inf_adopted_state_vector_to_string_diff ()

gchar *
inf_adopted_state_vector_to_string_diff
                               (const InfAdoptedStateVector *vec,
                                const InfAdoptedStateVector *orig);

Returns the string representation of a diff between orig and vec . This is possibly smaller than the representation created by inf_adopted_state_vector_to_string(), but the same orig vector is needed to recreate vec from the string representation. Additionally, inf_adopted_state_vector_causally_before(orig , vec ) must hold.

Parameters

vec

A InfAdoptedStateVector.

 

orig

Another InfAdoptedStateVector.

 

Returns

A newly allocated string to be freed by the caller.

[transfer full]


inf_adopted_state_vector_from_string_diff ()

InfAdoptedStateVector *
inf_adopted_state_vector_from_string_diff
                               (const gchar *str,
                                const InfAdoptedStateVector *orig,
                                GError **error);

Recreates a vector from its string representation diff and the original vector. If an error returns, the function returns NULL and error is set.

Parameters

str

A string representation of a diff between state vectors.

 

orig

The state vector used to create str in inf_adopted_state_vector_to_string_diff().

 

error

Location to place an error, if any.

 

Returns

The created state vector, or NULL on error. Free with inf_adopted_state_vector_free() when no longer needed.

[transfer full]

Types and Values

InfAdoptedStateVector

typedef struct _InfAdoptedStateVector InfAdoptedStateVector;

InfAdoptedStateVector is an opaque data type. You should only access it via the public API functions.


enum InfAdoptedStateVectorError

Error codes for InfAdoptedStateVector.

Members

INF_ADOPTED_STATE_VECTOR_BAD_FORMAT

A string representation of an InfAdoptedStateVector as required by inf_adopted_state_vector_from_string() or inf_adopted_state_vector_from_string_diff() is invalid.

 

INF_ADOPTED_STATE_VECTOR_FAILED

No further specified error code.

 
libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfLocalPublisher.html0000644000000000000000000000013213055210752026210 xustar0030 mtime=1488261610.872090736 30 atime=1488261610.872090736 30 ctime=1488261610.872090736 libinfinity-0.7.1/docs/reference/libinfinity/html/InfLocalPublisher.html0000644000175000017500000003307713055210752026754 0ustar00arminarmin00000000000000 InfLocalPublisher: libinfinity-0.7 Reference Manual

InfLocalPublisher

InfLocalPublisher — Publish services on the local network

Object Hierarchy

    GInterface
    ╰── InfLocalPublisher

Prerequisites

InfLocalPublisher requires GObject.

Known Implementations

InfLocalPublisher is implemented by InfDiscoveryAvahi.

Includes

#include <libinfinity/common/inf-local-publisher.h>

Description

InfLocalPublisher provides a common interface to publish services on the local network.

Functions

inf_local_publisher_publish ()

InfLocalPublisherItem *
inf_local_publisher_publish (InfLocalPublisher *publisher,
                             const gchar *type,
                             const gchar *name,
                             guint port);

Publishes a service through publisher so that it can be discovered with an appropriate InfDiscovery.

Parameters

publisher

A InfLocalPublisher.

 

type

The service type to publish, such as _http._tcp.

 

name

The name of the service.

 

port

The port the service is listening on.

 

Returns

A InfLocalPublisherItem that can be used to unpublish the service again.

[transfer none]


inf_local_publisher_unpublish ()

void
inf_local_publisher_unpublish (InfLocalPublisher *publisher,
                               InfLocalPublisherItem *item);

Unpublishes item so that it can no longer be found in the network.

Parameters

publisher

A InfLocalPublisher.

 

item

A published item obtained from inf_local_publisher_publish().

 

Types and Values

InfLocalPublisher

typedef struct _InfLocalPublisher InfLocalPublisher;

InfLocalPublisher is an opaque data type. You should only access it via the public API functions.


struct InfLocalPublisherInterface

struct InfLocalPublisherInterface {
  InfLocalPublisherItem* (*publish)(InfLocalPublisher* publisher,
                                    const gchar* type,
                                    const gchar* name,
                                    guint port);

  void (*unpublish)(InfLocalPublisher* publisher,
                    InfLocalPublisherItem* item);
};

Virtual functions for InfLocalPublisher.

Members

publish ()

Virtual function to announce a service of the given type with the given name on the given port. The returned InfLocalPublisherItem is valid as long as the service is published and the InfLocalPublisher is alive. It can be used to unpublish the service again using the unpublish function.

 

unpublish ()

Virtual function to unpublish a previously published service.

 

InfLocalPublisherItem

typedef struct _InfLocalPublisherItem InfLocalPublisherItem;

InfLocalPublisherItem is an opaque data type. You should only access it via the public API functions.

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfIo.html0000644000000000000000000000013213055210752023647 xustar0030 mtime=1488261610.872090736 30 atime=1488261610.872090736 30 ctime=1488261610.872090736 libinfinity-0.7.1/docs/reference/libinfinity/html/InfIo.html0000644000175000017500000012606413055210752024412 0ustar00arminarmin00000000000000 InfIo: libinfinity-0.7 Reference Manual

InfIo

InfIo — Event loop abstraction

Stability Level

Unstable, unless otherwise indicated

Types and Values

Object Hierarchy

    GFlags
    ╰── InfIoEvent
    GInterface
    ╰── InfIo

Prerequisites

InfIo requires GObject.

Known Implementations

InfIo is implemented by InfStandaloneIo.

Includes

#include <libinfinity/common/inf-io.h>

Description

The InfIo interface is used to schedule timeouts and to watch sockets for events to occur. An actual implementation usually integrates this into the application main loop, such as GMainLoop. There is also a standalone implementation, InfStandaloneIo, that can directly be used as the application's main loop.

Every object in Libinfinity that needs to schedule timeouts or watches sockets uses a InfIo to do so. This allows to use libinfinity with different main event loops, not only Glib's one.

InfIo is guaranteed to be thread-safe. All functions can be called from any thread at any time. However, all callback functions are always called from the same thread (normally the one running the main loop).

Functions

InfIoWatchFunc ()

void
(*InfIoWatchFunc) (InfNativeSocket *socket,
                   InfIoEvent event,
                   gpointer user_data);

Callback function that is called when an event occurs on a watched socket.

Parameters

socket

The socket on which an event occured.

[array fixed-size=1]

event

A bitmask of the events that occured.

 

user_data

User-defined data specified in inf_io_add_watch().

 

InfIoTimeoutFunc ()

void
(*InfIoTimeoutFunc) (gpointer user_data);

Callback function that is called when a timeout has elapsed.

Parameters

user_data

User-defined data specified in inf_io_add_timeout().

 

InfIoDispatchFunc ()

void
(*InfIoDispatchFunc) (gpointer user_data);

Callback function that is called when a dispatch is executed by the thread that runs InfIo.

Parameters

user_data

User-defined data specified in inf_io_add_dispatch().

 

inf_io_add_watch ()

InfIoWatch *
inf_io_add_watch (InfIo *io,
                  InfNativeSocket *socket,
                  InfIoEvent events,
                  InfIoWatchFunc func,
                  gpointer user_data,
                  GDestroyNotify notify);

Monitors the given socket for activity and calls func if one of the events specified in events occurs.

Parameters

io

A InfIo.

 

socket

The socket to watch.

 

events

Events to watch for.

 

func

Function to be called when one of the events occurs.

 

user_data

Extra data to pass to func .

 

notify

A GDestroyNotify that is called when user_data is no longer needed, or NULL.

 

Returns

A InfIoWatch that can be used to update or remove the watch.

[transfer none]


inf_io_add_watch_from_fd ()

InfIoWatch *
inf_io_add_watch_from_fd (InfIo *io,
                          int fd,
                          InfIoEvent events,
                          InfIoWatchFunc func,
                          gpointer user_data,
                          GDestroyNotify notify);

Monitors the given file descriptor for activity and calls func if one of the events specified in events occurs. This is equivalent to inf_io_add_watch() for a socket that represents the given file descriptor, but takes care of the memory management of the file descriptor. This function is especially intended for language bindings. It is only available on unix-like operating systems.

Parameters

io

A InfIo.

 

fd

The file descriptor to watch.

 

events

Events to watch for.

 

func

Function to be called when one of the events occurs.

 

user_data

Extra data to pass to func .

 

notify

A GDestroyNotify that is called when user_data is no longer needed, or NULL.

 

Returns

A InfIoWatch that can be used to update or remove the watch.

[transfer none]


inf_io_update_watch ()

void
inf_io_update_watch (InfIo *io,
                     InfIoWatch *watch,
                     InfIoEvent events);

Changes the events that the socket bound to watch is being watched for. The callback of watch will only be called if one of the newly watched for events occurs.

Parameters

io

A InfIo.

 

watch

The watch to update, as returned by inf_io_add_watch().

 

events

The new events to watch for.

 

inf_io_remove_watch ()

void
inf_io_remove_watch (InfIo *io,
                     InfIoWatch *watch);

Removes watch from io and releases all resources allocated for the watch. Events are no longer looked for on the socket.

Parameters

io

A InfIo.

 

watch

The watch to remove, as returned by inf_io_add_watch().

 

inf_io_add_timeout ()

InfIoTimeout *
inf_io_add_timeout (InfIo *io,
                    guint msecs,
                    InfIoTimeoutFunc func,
                    gpointer user_data,
                    GDestroyNotify notify);

Calls func after at least msecs milliseconds have elapsed. The timeout is removed after it has elapsed.

Parameters

io

A InfIo.

 

msecs

Number of milliseconds after which the timeout should be elapsed.

 

func

Function to be called when the timeout elapsed.

 

user_data

Extra data to pass to func .

 

notify

A GDestroyNotify that is called when user_data is no longer needed, or NULL.

 

Returns

A timeout handle that can be used to remove the timeout.

[transfer none]


inf_io_remove_timeout ()

void
inf_io_remove_timeout (InfIo *io,
                       InfIoTimeout *timeout);

Removes the given timeout.

Parameters

io

A InfIo.

 

timeout

A timeout handle obtained from inf_io_add_timeout().

 

inf_io_add_dispatch ()

InfIoDispatch *
inf_io_add_dispatch (InfIo *io,
                     InfIoDispatchFunc func,
                     gpointer user_data,
                     GDestroyNotify notify);

Schedules func to be called by the thread io runs in. This function can be used from a different thread to communicate to io 's thread.

Parameters

io

A InfIo.

 

func

Function to be called when the function is dispatched.

 

user_data

Extra data to pass to func .

 

notify

A GDestroyNotify that is called when user_data is no longer needed, or NULL.

 

Returns

A dispatch handle that can be used to stop the dispatched function from being called as long as it has not yet been called.

[transfer none]


inf_io_remove_dispatch ()

void
inf_io_remove_dispatch (InfIo *io,
                        InfIoDispatch *dispatch);

Removes the given dispatch from io so that it is not called.

Parameters

io

A InfIo.

 

dispatch

A dispatch handle obtained from inf_io_add_dispatch().

 

Types and Values

InfIo

typedef struct _InfIo InfIo;

InfIo is an opaque data type. You should only access it via the public API functions.


struct InfIoInterface

struct InfIoInterface {
  InfIoWatch* (*add_watch)(InfIo* io,
                           InfNativeSocket* socket,
                           InfIoEvent events,
                           InfIoWatchFunc func,
                           gpointer user_data,
                           GDestroyNotify notify);

  void (*update_watch)(InfIo* io,
                       InfIoWatch* watch,
                       InfIoEvent events);

  void (*remove_watch)(InfIo* io,
                       InfIoWatch* watch);

  InfIoTimeout* (*add_timeout)(InfIo* io,
                               guint msecs,
                               InfIoTimeoutFunc func,
                               gpointer user_data,
                               GDestroyNotify notify);

  void (*remove_timeout)(InfIo* io,
                         InfIoTimeout* timeout);

  InfIoDispatch* (*add_dispatch)(InfIo* io,
                                 InfIoDispatchFunc func,
                                 gpointer user_data,
                                 GDestroyNotify notify);

  void (*remove_dispatch)(InfIo* io,
                          InfIoDispatch* dispatch);
};

The virtual methods of InfIo. These allow to set up socket watches, timeouts and function dispatchers. All of these functions need to be thread-safe.

Members

add_watch ()

Watches a socket for events to occur in which case func is called.

 

update_watch ()

Updates a watch on a socket so that a different set of events is watched for.

 

remove_watch ()

Removes a watch on a socket.

 

add_timeout ()

Schedules func to be called at least msecs milliseconds in the future.

 

remove_timeout ()

Removes a scheduled timeout again. The timeout is removed automatically when it has elapsed, so there is no need to call this function in that case.

 

add_dispatch ()

Schedules func to be called by the thread the InfIo runs in.

 

remove_dispatch ()

Removes a scheduled dispatch. This can be called as long as the scheduled function has not yet been called.

 

enum InfIoEvent

This enumeration specifies events that can be watched.

Members

INF_IO_INCOMING

Data can be read from the socket without blocking, or the connection has been closed (which is the case when recv() returns 0).

 

INF_IO_OUTGOING

Data can be sent without blocking.

 

INF_IO_ERROR

An error with the socket occured, or the connection has been closed. Use getsockopt() to read the SO_ERROR option to find out what the problem is.

 

InfIoWatch

typedef struct _InfIoWatch InfIoWatch;

InfIoWatch represents a watch on a InfNativeSocket for events to occur. It is an opaque data type. You should only access it via the public API functions.


InfIoTimeout

typedef struct _InfIoTimeout InfIoTimeout;

InfIoTimeout represents a timer which will call a specified function in the future. It is an opaque data type. You should only access it via the public API functions.


InfIoDispatch

typedef struct _InfIoDispatch InfIoDispatch;

InfIoDispatch represents a function to be called by the thread executing the InfIo object. It is an opaque data type. You should only access it via the public API functions.

See Also

InfStandaloneIo

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfCommunicationJoinedGroup.html0000644000000000000000000000013213055210752030253 xustar0030 mtime=1488261610.872090736 30 atime=1488261610.872090736 30 ctime=1488261610.872090736 libinfinity-0.7.1/docs/reference/libinfinity/html/InfCommunicationJoinedGroup.html0000644000175000017500000003532213055210752031012 0ustar00arminarmin00000000000000 InfCommunicationJoinedGroup: libinfinity-0.7 Reference Manual

InfCommunicationJoinedGroup

InfCommunicationJoinedGroup — Communication group opened by a remote host

Stability Level

Unstable, unless otherwise indicated

Properties

gchar * method Read / Write / Construct Only
InfXmlConnection * publisher Read / Write / Construct Only

Object Hierarchy

    GObject
    ╰── InfCommunicationGroup
        ╰── InfCommunicationJoinedGroup

Includes

#include <libinfinity/communication/inf-communication-joined-group.h>

Description

InfCommunicationJoinedGroup represents membership of the local host on a InfCommunicationGroup opened on a remote host.

There is no API to add a member to a joined group. This is because new members can only join via the group's publisher. It is the job of the InfCommunicationMethod to tell the joined group about the new member in which case, the “member-added†signal will be emitted.

Functions

inf_communication_joined_group_remove_member ()

void
inf_communication_joined_group_remove_member
                               (InfCommunicationJoinedGroup *grp,
                                InfXmlConnection *connection);

Removes connection as grp 's member. On the remote site, the corresponding InfCommunicationGroup needs to be freed (which may be a InfCommunicationJoinedGroup or a InfCommunicationHostedGroup).

Parameters

grp

A InfCommunicationJoinedGroup.

 

connection

A connection to a member of grp .

 

inf_communication_joined_group_get_publisher ()

InfXmlConnection *
inf_communication_joined_group_get_publisher
                               (InfCommunicationJoinedGroup *g);

Returns a InfXmlConnection to the group's publisher, or NULL if the publisher is no longer a group member.

Parameters

Returns

A InfXmlConnection, or NULL.

[transfer none][allow-none]

Types and Values

struct InfCommunicationJoinedGroup

struct InfCommunicationJoinedGroup;

InfCommunicationJoinedGroup is an opaque data type. You should only access it via the public API functions.


struct InfCommunicationJoinedGroupClass

struct InfCommunicationJoinedGroupClass {
};

This structure does not contain any public fields.

Property Details

The “method†property

  “method†                  gchar *

The communication method to use for this group.

Flags: Read / Write / Construct Only

Default value: NULL


The “publisher†property

  “publisher†               InfXmlConnection *

A connection to the group's publisher.

Flags: Read / Write / Construct Only

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfdTcpServer.html0000644000000000000000000000013213055210752025361 xustar0030 mtime=1488261610.872090736 30 atime=1488261610.872090736 30 ctime=1488261610.872090736 libinfinity-0.7.1/docs/reference/libinfinity/html/InfdTcpServer.html0000644000175000017500000006221213055210752026116 0ustar00arminarmin00000000000000 InfdTcpServer: libinfinity-0.7 Reference Manual

InfdTcpServer

InfdTcpServer

Properties

InfIo * io Read / Write / Construct Only
InfKeepalive * keepalive Read / Write
InfIpAddress * local-address Read / Write
guint local-port Read / Write
InfdTcpServerStatus status Read

Types and Values

Object Hierarchy

    GEnum
    ╰── InfdTcpServerStatus
    GObject
    ╰── InfdTcpServer

Description

Functions

infd_tcp_server_bind ()

gboolean
infd_tcp_server_bind (InfdTcpServer *server,
                      GError **error);

Binds the server to the address and port given by the “local-address†and “local-port†properties. If the former is NULL, it will bind on all interfaces on IPv4. If the latter is 0, a random available port will be assigned. If the function fails, FALSE is returned and an error is set.

server must be in INFD_TCP_SERVER_CLOSED state for this function to be called.

Parameters

server

A InfdTcpServer.

 

error

Location to store error information, if any.

 

Returns

TRUE on success, or FALSE if an error occured.


infd_tcp_server_open ()

gboolean
infd_tcp_server_open (InfdTcpServer *server,
                      GError **error);

Attempts to open server . This means binding its local address and port if not already (see infd_tcp_server_bind()) and accepting incoming connections.

server needs to be in INFD_TCP_SERVER_CLOSED or INFD_TCP_SERVER_BOUND status for this function to be called. If server 's status is INFD_TCP_SERVER_CLOSED, then infd_tcp_server_bind() is called before actually opening the server.

Parameters

server

A InfdTcpServer.

 

error

Location to store error information.

 

Returns

TRUE on success, or FALSE if an error occured.


infd_tcp_server_close ()

void
infd_tcp_server_close (InfdTcpServer *server);

Closes a TCP server that is open or bound.

Parameters

server

A InfdTcpServer.

 

infd_tcp_server_set_keepalive ()

void
infd_tcp_server_set_keepalive (InfdTcpServer *server,
                               const InfKeepalive *keepalive);

Sets the keepalive settings for new connections accepted by the server.

Parameters

server

A InfdTcpServer.

 

keepalive

The keepalive settings for accepted connections.

 

infd_tcp_server_get_keepalive ()

const InfKeepalive *
infd_tcp_server_get_keepalive (InfdTcpServer *server);

Obtains the current keepalive settings for accepted connections.

Parameters

server

A InfdTcpServer.

 

Returns

A InfKeepalive representing the keepalive configuration for accepted connections, owned by server .

Types and Values

enum InfdTcpServerStatus

Members

INFD_TCP_SERVER_CLOSED

   

INFD_TCP_SERVER_BOUND

   

INFD_TCP_SERVER_OPEN

   

struct InfdTcpServer

struct InfdTcpServer;


struct InfdTcpServerClass

struct InfdTcpServerClass {
  GObjectClass parent_class;

  /* Signals */
  void (*new_connection)(InfdTcpServer* server,
                         InfTcpConnection* connection);

  void (*error)(InfdTcpServer* server,
                GError* error);
};

Property Details

The “io†property

  “io†                      InfIo *

I/O handler.

Flags: Read / Write / Construct Only


The “keepalive†property

  “keepalive†               InfKeepalive *

Keepalive settings for accepted connections.

Flags: Read / Write


The “local-address†property

  “local-address†           InfIpAddress *

Address to bind to.

Flags: Read / Write


The “local-port†property

  “local-port†              guint

Port to bind to.

Flags: Read / Write

Allowed values: <= 65535

Default value: 0


The “status†property

  “status†                  InfdTcpServerStatus

Status of the TCP server.

Flags: Read

Default value: INFD_TCP_SERVER_CLOSED

Signal Details

The “error†signal

void
user_function (InfdTcpServer *infdtcpserver,
               GError        *arg1,
               gpointer       user_data)

Parameters

infdtcpserver

the object which received the signal.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last


The “new-connection†signal

void
user_function (InfdTcpServer    *infdtcpserver,
               InfTcpConnection *arg1,
               gpointer          user_data)

Parameters

infdtcpserver

the object which received the signal.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfcRequestManager.html0000644000000000000000000000013213055210752026366 xustar0030 mtime=1488261610.876090727 30 atime=1488261610.876090727 30 ctime=1488261610.876090727 libinfinity-0.7.1/docs/reference/libinfinity/html/InfcRequestManager.html0000644000175000017500000015460613055210752027134 0ustar00arminarmin00000000000000 InfcRequestManager: libinfinity-0.7 Reference Manual

InfcRequestManager

InfcRequestManager — Keeps track of pending asynchronous requests

Stability Level

Unstable, unless otherwise indicated

Properties

guint sequence-id Read / Write / Construct Only

Types and Values

Object Hierarchy

    GObject
    ╰── InfcRequestManager

Includes

#include <libinfinity/client/infc-request-manager.h>

Description

This class keeps track of requests sent by InfcBrowser and InfcSessionProxy (typically via the InfBrowser and InfSessionProxy APIs). It is used internally by InfcBrowser and InfcSessionProxy, and usually end-users of the libinfinity API do not need to use this class directly.

Requests can be added with the infc_request_manager_add_request() and infc_request_manager_add_request_valist() methods and retrieved back via their unique seq number with infc_request_manager_get_request_by_seq(). In addition to this basic API, there are various convenience functions available as well.

Functions

InfcRequestManagerForeachFunc ()

void
(*InfcRequestManagerForeachFunc) (InfcRequest *request,
                                  gpointer user_data);

This signature specifies the callback type when iterating over all requests of the request manager.

Parameters

request

The current request.

 

user_data

Additional data passed to infc_request_manager_foreach_request() or infc_request_manager_foreach_named_request().

 

infc_request_manager_new ()

InfcRequestManager *
infc_request_manager_new (guint seq_id);

Creates a new InfcRequestManager.

[constructor]

Parameters

seq_id

The local sequence ID.

 

Returns

A newly allocated InfcRequestManager.

[transfer full]


infc_request_manager_add_request ()

InfcRequest *
infc_request_manager_add_request (InfcRequestManager *manager,
                                  GType request_type,
                                  const gchar *request_name,
                                  GCallback callback,
                                  gpointer user_data,
                                  const gchar *first_property_name,
                                  ...);

Adds a request to the request manager. A new signal handler for the request's "finished" signal will be installed and made to invoke the given callback.

Parameters

manager

A InfcRequestManager.

 

request_type

The type of request to add, such as InfcProgressRequest.

 

request_name

The name of the request, such as "explore-node" or "subscribe-session".

 

callback

A GCallback that will be called when the request has completed, or NULL.

[scope async]

user_data

Additional data passed to the callback.

 

first_property_name

The first property name apart from name and seq to set for the new request.

 

...

The value of the first property, followed optionally by more name/value pairs, followed by NULL.

 

Returns

The generated InfcRequest (actually of type request_type ).

[transfer none]


infc_request_manager_add_request_valist ()

InfcRequest *
infc_request_manager_add_request_valist
                               (InfcRequestManager *manager,
                                GType request_type,
                                const gchar *request_name,
                                GCallback callback,
                                gpointer user_data,
                                const gchar *first_property_name,
                                va_list arglist);

Adds a request to the request manager. A new signal handler for the request's "finished" signal will be installed and made to invoke the given callback.

Parameters

manager

A InfcRequestManager.

 

request_type

The type of request to add, such as InfcProgressRequest.

 

request_name

The name of the request, such as "explore-node" or "subscribe-session"

 

callback

A GCallback that will be called when the request has completed, or NULL.

[scope async]

user_data

Additional data passed to the callback.

 

first_property_name

The first property name apart from name and seq to set for the new request.

 

arglist

The value of the first property, followed optionally by more name/value pairs, followed by NULL.

 

Returns

The generated InfcRequest (actually of type request_type ).

[transfer none]


infc_request_manager_remove_request ()

void
infc_request_manager_remove_request (InfcRequestManager *manager,
                                     InfcRequest *request);

Removes a request from the request manager.

Parameters

manager

A InfcRequestManager.

 

request

A InfcRequest that has previously been added to manager .

 

infc_request_manager_finish_request ()

void
infc_request_manager_finish_request (InfcRequestManager *manager,
                                     InfcRequest *request,
                                     InfRequestResult *result);

Marks request as finished using inf_request_finish() and then removes the request from the manager. The function takes ownership of result .

Parameters

manager

A InfcRequestManager.

 

request

A InfcRequest that has previously been added to manager .

 

result

The request result.

[transfer full]

infc_request_manager_fail_request ()

void
infc_request_manager_fail_request (InfcRequestManager *manager,
                                   InfcRequest *request,
                                   const GError *error);

Marks request as failed using inf_request_fail() and then removes the request from the manager.

Parameters

manager

A InfcRequestManager.

 

request

A InfcRequest that has previously been added to manager .

 

error

Error information why the request failed.

 

infc_request_manager_clear ()

void
infc_request_manager_clear (InfcRequestManager *manager);

Removes all the requests in manager .

Parameters

manager

A InfcRequestManager.

 

infc_request_manager_get_request_by_seq ()

InfcRequest *
infc_request_manager_get_request_by_seq
                               (InfcRequestManager *manager,
                                guint seq);

Returns a previously-added request that has the given seq.

Parameters

manager

A InfcRequestManager.

 

seq

The sequence number to which the request should be retrieved.

 

Returns

The request with the given seq, or NULL if there is no such request.

[transfer none][allow-none]


infc_request_manager_get_request_by_xml ()

InfcRequest *
infc_request_manager_get_request_by_xml
                               (InfcRequestManager *manager,
                                const gchar *name,
                                xmlNodePtr xml,
                                GError **error);

Looks whether there is a "seq" attribute in xml . If not, the function returns NULL (without setting error ). Otherwise, it returns the request with the given seq and name, if the sequence ID matches. If the "seq" attribute is set but the actual request is not present (or has another name), the function returns NULL and error is set.

Parameters

manager

A InfcRequestManager.

 

name

Name of the expected request. May be NULL to allow all requests.

 

xml

XML node that is supposed to contain a "seq" attribute.

 

error

Location to store error information.

 

Returns

The resulting request, or NULL if the "seq" attribute was not present or an error occured.

[transfer none][allow-none]


infc_request_manager_get_request_by_xml_required ()

InfcRequest *
infc_request_manager_get_request_by_xml_required
                               (InfcRequestManager *manager,
                                const gchar *name,
                                xmlNodePtr xml,
                                GError **error);

Looks whether there is a "seq" attribute in xml . If so, it returns the request with the given seq and name, if the sequence ID matches. If the "seq" attribute is not set or the actual request is not present (or has another name), the function returns NULL and error is set.

Parameters

manager

A InfcRequestManager.

 

name

Name of the expected request. May be NULL to allow all requests.

 

xml

XML node that is supposed to contain a "seq" attribute.

 

error

Location to store error information.

 

Returns

The resulting request, or NULL if an error occured.

[transfer none]


infc_request_manager_foreach_request ()

void
infc_request_manager_foreach_request (InfcRequestManager *manager,
                                      InfcRequestManagerForeachFunc func,
                                      gpointer user_data);

Calls the given function for each request that has been added to the request manager.

Parameters

manager

A InfcRequestManager.

 

func

The function to be called.

[scope call]

user_data

Arbitrary data to be passed to func .

 

infc_request_manager_foreach_named_request ()

void
infc_request_manager_foreach_named_request
                               (InfcRequestManager *manager,
                                const gchar *name,
                                InfcRequestManagerForeachFunc func,
                                gpointer user_data);

Calls the given function for each request that has been added to the request manager that has the name name .

Parameters

manager

A InfcRequestManager.

 

name

The name of the request to look for.

 

func

The function to be called.

[scope call]

user_data

Arbitrary data to be passed to func .

 

Types and Values

struct InfcRequestManager

struct InfcRequestManager;

InfcRequestManager is an opaque data type. You should only access it via the public API functions.


struct InfcRequestManagerClass

struct InfcRequestManagerClass {
  void (*request_add)(InfcRequestManager* manager,
                      InfcRequest* request);
  void (*request_remove)(InfcRequestManager* manager,
                         InfcRequest* request);
};

This structure contains the default signal handlers of the InfcRequestManager class.

Members

request_add ()

Default signal handler for the “request-add†signal.

 

request_remove ()

Default signal handler for the “request-remove†signal.

 

Property Details

The “sequence-id†property

  “sequence-id†             guint

The local sequence identifier.

Flags: Read / Write / Construct Only

Default value: 0

Signal Details

The “request-add†signal

void
user_function (InfcRequestManager *manager,
               InfcRequest        *request,
               gpointer            user_data)

This signal is emitted whenever a request was added to the request manager.

Parameters

manager

The InfcRequestManager emitting the signal.

 

request

The InfcRequest that was added.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last


The “request-remove†signal

void
user_function (InfcRequestManager *manager,
               InfcRequest        *request,
               gpointer            user_data)

This signal is emitted whenever a request was removed from the request manager. Typically this happens when the request has finished (either successfully or unsuccessfully). It can also happen when the client is disconnected from the server while a request was still pending.

Parameters

manager

The InfcRequestManager emitting the signal.

 

request

The InfcRequest that was removed.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfSessionProxy.html0000644000000000000000000000013213055210752025765 xustar0030 mtime=1488261610.876090727 30 atime=1488261610.876090727 30 ctime=1488261610.876090727 libinfinity-0.7.1/docs/reference/libinfinity/html/InfSessionProxy.html0000644000175000017500000003704313055210752026526 0ustar00arminarmin00000000000000 InfSessionProxy: libinfinity-0.7 Reference Manual

InfSessionProxy

InfSessionProxy — Joining users into a session

Stability Level

Unstable, unless otherwise indicated

Properties

InfSession * session Read / Write / Construct Only

Types and Values

Object Hierarchy

    GInterface
    ╰── InfSessionProxy

Prerequisites

InfSessionProxy requires GObject.

Known Implementations

InfSessionProxy is implemented by InfcSessionProxy and InfdSessionProxy.

Includes

#include <libinfinity/common/inf-session_proxy.h>

Description

A InfSessionProxy is a network-architecture-aware layer on top of a InfSession. A InfSession has no idea about what kind of network it is in, all it has is a possibility to send messages to one user or to all users.

A InfSessionProxy implements the part of the infinote protocol which depends on whether the session is at an infinote server or an infinote client. This interface provides a method to join a user into a session so that it does not need to be known to the caller whether the session at hand is on a server or a client.

Functions

inf_session_proxy_join_user ()

InfRequest *
inf_session_proxy_join_user (InfSessionProxy *proxy,
                             guint n_params,
                             const GParameter *params,
                             InfRequestFunc func,
                             gpointer user_data);

Requests a user join for a user with the given properties (which must not include “id†or “flags†since these are chosen by the session proxy). The “status†property is optional and defaults to INF_USER_ACTIVE if not given. It must not be INF_USER_UNAVAILABLE.

The request might either finish during the call to this function, in which case func will be called and NULL being returned. If the request does not finish within the function call, a InfRequest object is returned, where func has been installed for the “finished†signal, so that it is called as soon as the request finishes.

Parameters

proxy

A InfSessionProxy.

 

n_params

Number of parameters.

 

params

Construction properties for the InfUser (or derived) object.

[array length=n_params]

func

Function to be called on completion of the user join, or NULL.

[scope async]

user_data

Additional data to be passed to func .

 

Returns

A InfRequest object that may be used to get notified when the request finishes, or NULL.

[transfer none]

Types and Values

InfSessionProxy

typedef struct _InfSessionProxy InfSessionProxy;

InfSessionProxy is an opaque data type. You should only access it via the public API functions.


struct InfSessionProxyInterface

struct InfSessionProxyInterface {
  InfRequest* (*join_user)(InfSessionProxy* proxy,
                           guint n_params,
                           const GParameter* params,
                           InfRequestFunc func,
                           gpointer user_data);
};

Virtual functions for the InfSessionProxy interface.

Members

join_user ()

Virtual function to join a user into the proxy's session.

 

Property Details

The “session†property

  “session†                 InfSession *

The underlying session object.

Flags: Read / Write / Construct Only

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfcProgressRequest.html0000644000000000000000000000013213055210752026620 xustar0030 mtime=1488261610.876090727 30 atime=1488261610.876090727 30 ctime=1488261610.876090727 libinfinity-0.7.1/docs/reference/libinfinity/html/InfcProgressRequest.html0000644000175000017500000003342113055210752027355 0ustar00arminarmin00000000000000 InfcProgressRequest: libinfinity-0.7 Reference Manual

InfcProgressRequest

InfcProgressRequest — Asynchronous request with dynamic progress.

Stability Level

Unstable, unless otherwise indicated

Properties

guint current Read
guint total Read

Types and Values

Object Hierarchy

    GObject
    ╰── InfcRequest
        ╰── InfcProgressRequest

Implemented Interfaces

InfcProgressRequest implements InfRequest.

Includes

#include <libinfinity/client/infc-progress-request.h>

Description

This class represents a request which consists of multiple steps and for which progress on the overall operation is reported.

Functions

infc_progress_request_initiated ()

void
infc_progress_request_initiated (InfcProgressRequest *request,
                                 guint total);

Initiates the request. A progress request is considered initiated as soon as the total number of items is known.

Parameters

request

An InfcProgressRequest.

 

total

The total number of items.

 

infc_progress_request_get_initiated ()

gboolean
infc_progress_request_get_initiated (InfcProgressRequest *request);

Returns whether the request was initiated, i.e. the total number of items is known.

Parameters

request

A InfcProgressRequest.

 

Returns

Whether the request was initiated.


infc_progress_request_progress ()

void
infc_progress_request_progress (InfcProgressRequest *request);

Indicates that one more operation has been performed and changes the “current†property accordingly. The request must be initiated before this function can be called.

Parameters

request

A InfcProgressRequest.

 

Types and Values

struct InfcProgressRequest

struct InfcProgressRequest;

InfcProgressRequest is an opaque data type. You should only access it via the public API functions.


struct InfcProgressRequestClass

struct InfcProgressRequestClass {
};

This structure does not contain any public fields.

Property Details

The “current†property

  “current†                 guint

The current number of finished operations.

Flags: Read

Default value: 0


The “total†property

  “total†                   guint

The total number of operations.

Flags: Read

Default value: 0

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/left-insensitive.png0000644000000000000000000000013213055210752025753 xustar0030 mtime=1488261610.832090825 30 atime=1488261610.832090825 30 ctime=1488261610.832090825 libinfinity-0.7.1/docs/reference/libinfinity/html/left-insensitive.png0000644000175000017500000000061313055210752026505 0ustar00arminarmin00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEà 4ÓkMIDAT8ËÍ’­NQ…¿éö†…@¡p üdsÛÀÖ`*š4Á@ò„W@ A!ÈÔ†@6Ü^ƒ 5hxèIH R`sQpäÌ™339þBÊó|Ês¤ªKEQTÛíöK°@·ÛÎià¦^¯Ï~îWʆ½÷‹ÀÕûðå`0˜åTJ6·Tõ˜‘cYn6›AÞû Æ€½~¿ß±Ö>}Ç­Žœs;ªº ¨ˆlYkwËÞürˆ¼†ºó£ Þû5U= °/"›ÖÚç  ¬µ‡"ÒuU=ɲlü×ArÎÕDä˜zÃáp5I’ûà4^E+ÀP3Æœçàq_«êp Ì¥iñ¯ðUY¥‚p=#IEND®B`‚libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfIpAddress.html0000644000000000000000000000013213055210752025156 xustar0030 mtime=1488261610.876090727 30 atime=1488261610.876090727 30 ctime=1488261610.876090727 libinfinity-0.7.1/docs/reference/libinfinity/html/InfIpAddress.html0000644000175000017500000006327713055210752025727 0ustar00arminarmin00000000000000 InfIpAddress: libinfinity-0.7 Reference Manual

InfIpAddress

InfIpAddress — IPv4 and IPv6 addresses

Stability Level

Unstable, unless otherwise indicated

Types and Values

Object Hierarchy

    GBoxed
    ╰── InfIpAddress
    GEnum
    ╰── InfIpAddressFamily

Includes

#include <libinfinity/common/inf-ip-address.h>

Description

A InfIpAddress represents an IPv4 or an IPv6 network address. Use inf_ip_address_get_family() to find out the type of a specific address.

Functions

inf_ip_address_new_raw4 ()

InfIpAddress *
inf_ip_address_new_raw4 (guint32 address);

Creates a new IPv4 address.

[constructor]

Parameters

address

An IPv4 address in network byte order.

 

Returns

A new InfIpAddress.

[transfer full]


inf_ip_address_new_loopback4 ()

InfIpAddress *
inf_ip_address_new_loopback4 (void);

Creates a new IPv4 address that contains the local host's IP address ("127.0.0.1").

[constructor]

Returns

A new InfIpAddress.

[transfer full]


inf_ip_address_new_raw6 ()

InfIpAddress *
inf_ip_address_new_raw6 (const guint8 address[16]);

Creates a new IPv6 address.

[constructor]

Parameters

address

An IPv6 address in network bype order.

 

Returns

A new InfIpAddress.

[transfer full]


inf_ip_address_new_loopback6 ()

InfIpAddress *
inf_ip_address_new_loopback6 (void);

Creates a new IPv6 address that contains the local host's IP address ("::1").

[constructor]

Returns

A new InfIpAddress.

[transfer full]


inf_ip_address_new_from_string ()

InfIpAddress *
inf_ip_address_new_from_string (const gchar *str);

Creates a new IP address (either IPv4 or IPv6) from the given string.

[constructor]

Parameters

str

A string containing an IPv4 or IPv6 address in standard dots notation.

 

Returns

A new InfIpAddress, or NULL.

[transfer full]


inf_ip_address_copy ()

InfIpAddress *
inf_ip_address_copy (const InfIpAddress *address);

Creates a new InfIpAddress that contains the same address as address .

Parameters

address

A InfIpAddress.

 

Returns

A new InfIpAddress.


inf_ip_address_free ()

void
inf_ip_address_free (InfIpAddress *address);

Frees address .

Parameters

address

A InfIpAddress.

 

inf_ip_address_get_family ()

InfIpAddressFamily
inf_ip_address_get_family (const InfIpAddress *address);

Returns the address family of address .

Parameters

address

A InfIpAddress.

 

Returns

A InfIpAddressFamily.


inf_ip_address_get_raw ()

gconstpointer
inf_ip_address_get_raw (const InfIpAddress *address);

Returns either 32 bit (IPv4) or 128 bit (IPv6) raw address data in host byte order of address .

Parameters

address

A InfIpAddress.

 

Returns

The raw address.

[transfer none]


inf_ip_address_to_string ()

gchar *
inf_ip_address_to_string (const InfIpAddress *address);

Returns a string representation of address in standard dots format (like "192.168.0.1" or "::1").

Parameters

address

A InfIpAddress.

 

Returns

A newly-allocated string. Free with g_free().

[transfer full]


inf_ip_address_collate ()

int
inf_ip_address_collate (const InfIpAddress *address1,
                        const InfIpAddress *address2);

Compares the two addresses for sorting.

Parameters

address1

First address.

 

address2

Second address.

 

Returns

-1 if address1 compares before, 0 if it compares equal or 1 if it compares after address .

Types and Values

InfIpAddress

typedef struct _InfIpAddress InfIpAddress;

InfIpAddress is an opaque data type. You should only access it via the public API functions.


enum InfIpAddressFamily

This enumeration specifies different types of IP addresses.

Members

INF_IP_ADDRESS_IPV4

This specifies an IPv4 address.

 

INF_IP_ADDRESS_IPV6

This specifies an IPv6 address.

 

See Also

InfTcpConnection

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfChatBuffer.html0000644000000000000000000000013213055210752025311 xustar0030 mtime=1488261610.876090727 30 atime=1488261610.876090727 30 ctime=1488261610.876090727 libinfinity-0.7.1/docs/reference/libinfinity/html/InfChatBuffer.html0000644000175000017500000012420213055210752026044 0ustar00arminarmin00000000000000 InfChatBuffer: libinfinity-0.7 Reference Manual

InfChatBuffer

InfChatBuffer — A ring buffer for chat messages

Stability Level

Unstable, unless otherwise indicated

Properties

guint size Read / Write / Construct Only

Signals

Object Hierarchy

    GBoxed
    ╰── InfChatBufferMessage
    GEnum
    ╰── InfChatBufferMessageType
    GFlags
    ╰── InfChatBufferMessageFlags
    GObject
    ╰── InfChatBuffer

Implemented Interfaces

InfChatBuffer implements InfBuffer.

Includes

#include <libinfinity/common/inf-chat-buffer.h>

Description

InfChatBuffer contains the chat messages for a InfChatSession.

Functions

inf_chat_buffer_message_copy ()

InfChatBufferMessage *
inf_chat_buffer_message_copy (const InfChatBufferMessage *message);

Creates a copy of the given message.

Parameters

message

The InfChatBufferMessage to copy.

 

Returns

A new InfChatBufferMessage. Free with inf_chat_buffer_message_free() when no longer needed.

[transfer full]


inf_chat_buffer_message_free ()

void
inf_chat_buffer_message_free (InfChatBufferMessage *message);

Frees the given InfChatBufferMessage which must have been created with inf_chat_buffer_message_copy().

Parameters

message

A InfChatBufferMessage.

 

inf_chat_buffer_new ()

InfChatBuffer *
inf_chat_buffer_new (guint size);

Creates a new InfChatBuffer which contains no initial messages. size specifies how many messages to store before dropping old messages.

[constructor]

Parameters

size

The number of messages to store.

 

Returns

A new InfChatBuffer.

[transfer full]


inf_chat_buffer_add_message ()

void
inf_chat_buffer_add_message (InfChatBuffer *buffer,
                             InfUser *by,
                             const gchar *message,
                             gsize length,
                             time_t time,
                             InfChatBufferMessageFlags flags);

Adds a new message to the chat buffer. If the buffer is full (meaning the number of messages in the buffer equals its size), then an old message will get discarded. If the message to be added is older than all other messages in the buffer, then it will not be added at all.

Parameters

buffer

A InfChatBuffer.

 

by

A InfUser who wrote the message.

 

message

The message text.

[array length=length]

length

The length of message , in bytes.

 

time

The time at which the user has written the message.

 

flags

Flags to set for the message to add.

 

inf_chat_buffer_add_emote_message ()

void
inf_chat_buffer_add_emote_message (InfChatBuffer *buffer,
                                   InfUser *by,
                                   const gchar *message,
                                   gsize length,
                                   time_t time,
                                   InfChatBufferMessageFlags flags);

Adds a new emote message to the chat buffer. If the buffer is full (meaning the number of messages in the buffer equals its size), then an old message will get discarded. If the message to be added is older than all other messages in the buffer, then it will not be added at all.

Parameters

buffer

A InfChatBuffer.

 

by

A InfUser who wrote the message.

 

message

The message text.

[array length=length]

length

The length of message , in bytes.

 

time

The time at which the user has written the message.

 

flags

Flags to set for the message to add.

 

inf_chat_buffer_add_userjoin_message ()

void
inf_chat_buffer_add_userjoin_message (InfChatBuffer *buffer,
                                      InfUser *user,
                                      time_t time,
                                      InfChatBufferMessageFlags flags);

Adds a new userjoin message to the chat buffer. If the buffer is full (meaning the number of messages in the buffer equals its size), then an old message will get discarded. If the message to be added is older than all other messages in the buffer, then it will not be added at all.

Parameters

buffer

A InfChatBuffer.

 

user

A InfUser who wrote the message.

 

time

The time at which the user has written the message.

 

flags

Flags to set for the message to add.

 

inf_chat_buffer_add_userpart_message ()

void
inf_chat_buffer_add_userpart_message (InfChatBuffer *buffer,
                                      InfUser *user,
                                      time_t time,
                                      InfChatBufferMessageFlags flags);

Adds a new userpart message to the chat buffer. If the buffer is full (meaning the number of messages in the buffer equals its size), then an old message will get discarded. If the message to be added is older than all other messages in the buffer, then it will not be added at all.

Parameters

buffer

A InfChatBuffer.

 

user

A InfUser who wrote the message.

 

time

The time at which the user has written the message.

 

flags

Flags to set for the message to add.

 

inf_chat_buffer_get_message ()

const InfChatBufferMessage *
inf_chat_buffer_get_message (InfChatBuffer *buffer,
                             guint n);

Returns the message with the given index from the buffer. The oldest message in the buffer has index 0, and the most recent one has index inf_chat_buffer_get_n_messages() - 1.

Parameters

buffer

A InfChatBuffer.

 

n

The index of the message to obtain.

 

Returns

The InfChatBufferMessage with the given index.


inf_chat_buffer_get_n_messages ()

guint
inf_chat_buffer_get_n_messages (InfChatBuffer *buffer);

Returns the number of messages in the buffer.

Parameters

buffer

A InfChatBuffer.

 

Returns

The number of messages in the buffer.


inf_chat_buffer_get_size ()

guint
inf_chat_buffer_get_size (InfChatBuffer *buffer);

Returns the size of the chat buffer, which is the maximum number of messages that can be stored in the buffer.

Parameters

buffer

A InfChatBuffer.

 

Returns

The number of messages in the chat buffer.

Types and Values

enum InfChatBufferMessageType

Possible chat message types.

Members

INF_CHAT_BUFFER_MESSAGE_NORMAL

A normal chat message.

 

INF_CHAT_BUFFER_MESSAGE_EMOTE

An emote chat message (/me is doing something).

 

INF_CHAT_BUFFER_MESSAGE_USERJOIN

A user join notification.

 

INF_CHAT_BUFFER_MESSAGE_USERPART

A user part notification.

 

enum InfChatBufferMessageFlags

Possible chat message flags.

Members

INF_CHAT_BUFFER_MESSAGE_BACKLOG

The message is a backlog message, i.e. it originated in a previous session.

 

struct InfChatBufferMessage

struct InfChatBufferMessage {
  InfChatBufferMessageType type;
  InfUser* user;
  gchar* text;
  gsize length;
  time_t time;
  InfChatBufferMessageFlags flags;
};

Represents a chat message.

Members

InfChatBufferMessageType type;

The InfChatBufferMessageType of the message.

 

InfUser *user;

The InfUser that issued the message.

 

gchar *text;

The UTF-8 encoded text of the message.

 

gsize length;

The length of the message, in bytes.

 

time_t time;

The time at which the message was received.

 

InfChatBufferMessageFlags flags;

Additional flags for the message, see InfChatBufferMessageFlags.

 

struct InfChatBuffer

struct InfChatBuffer;

InfChatBuffer is an opaque data type. You should only access it via the public API functions.


struct InfChatBufferClass

struct InfChatBufferClass {
  void (*add_message)(InfChatBuffer* buffer,
                      const InfChatBufferMessage* message);
};

This structure contains default signal handlers for InfChatBuffer.

Members

add_message ()

Default signal handler for the “add-message†signal.

 

Property Details

The “size†property

  “size†                    guint

The maxmimum number of messages saved.

Flags: Read / Write / Construct Only

Default value: 256

Signal Details

The “add-message†signal

void
user_function (InfChatBuffer        *buffer,
               InfChatBufferMessage *message,
               gpointer              user_data)

This signal is emitted whenever a message has been added to buffer .

Parameters

buffer

The InfChatBuffer that is receiving a message.

 

message

The InfChatBufferMessage that was received.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfStandaloneIo.html0000644000000000000000000000013213055210752025660 xustar0030 mtime=1488261610.876090727 30 atime=1488261610.876090727 30 ctime=1488261610.876090727 libinfinity-0.7.1/docs/reference/libinfinity/html/InfStandaloneIo.html0000644000175000017500000004176413055210752026426 0ustar00arminarmin00000000000000 InfStandaloneIo: libinfinity-0.7 Reference Manual

InfStandaloneIo

InfStandaloneIo — Simple event loop implementation

Stability Level

Unstable, unless otherwise indicated

Types and Values

Object Hierarchy

    GObject
    ╰── InfStandaloneIo

Implemented Interfaces

InfStandaloneIo implements InfIo.

Includes

#include <libinfinity/common/inf-standalone-io.h>

Description

InfStandaloneIo is a simple implementation of the InfIo interface. It implements a basic application event loop with support for listening on sockets, scheduling timeouts and inter-thread notifications. The class is fully thread-safe.

This class can be perfectly used for all functions in libinfinity that require a InfIo object to wait for events. If, on top of that more functionality is required, or the main loop needs to be integrated with another library such as a UI toolkit, a custom class should be created instead which implements the InfIo interface. For the GTK+ toolkit, there is InfGtkIo in the libinfgtk library, to integrate with the Glib main loop.

Functions

inf_standalone_io_new ()

InfStandaloneIo *
inf_standalone_io_new (void);

Creates a new InfStandaloneIo.

[constructor]

Returns

A new InfStandaloneIo. Free with g_object_unref() when no longer needed.

[transfer full]


inf_standalone_io_iteration ()

void
inf_standalone_io_iteration (InfStandaloneIo *io);

Performs a single iteration of io . The call will block until a first event has occured. Then, it will process that event and return.

Parameters

io

A InfStandaloneIo.

 

inf_standalone_io_iteration_timeout ()

void
inf_standalone_io_iteration_timeout (InfStandaloneIo *io,
                                     guint timeout);

Performs a single iteration of io . The call will block until either an event occured or timeout milliseconds have elapsed. If an event occured, the event will be processed before returning.

Parameters

io

A InfStandaloneIo.

 

timeout

Maximum number of milliseconds to block.

 

inf_standalone_io_loop ()

void
inf_standalone_io_loop (InfStandaloneIo *io);

This call will cause io to wait for events and process them, but not return until inf_standalone_io_loop_quit() is called.

Parameters

io

A InfStandaloneIo.

 

inf_standalone_io_loop_quit ()

void
inf_standalone_io_loop_quit (InfStandaloneIo *io);

Exits a loop in which io is running through a call to inf_standalone_io_loop().

Parameters

io

A InfStandaloneIo.

 

inf_standalone_io_loop_running ()

gboolean
inf_standalone_io_loop_running (InfStandaloneIo *io);

Returns whether io runs currently in a loop initiated with inf_standalone_io_loop().

Parameters

io

A InfStandaloneIo.

 

Returns

Whether io runs in a loop.

Types and Values

struct InfStandaloneIo

struct InfStandaloneIo;

InfStandaloneIo is an opaque data type. You should only access it via the public API functions.


struct InfStandaloneIoClass

struct InfStandaloneIoClass {
};

This structure does not contain any public fields.

See Also

InfIo

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfKeepalive.html0000644000000000000000000000013213055210752025205 xustar0030 mtime=1488261610.876090727 30 atime=1488261610.876090727 30 ctime=1488261610.876090727 libinfinity-0.7.1/docs/reference/libinfinity/html/InfKeepalive.html0000644000175000017500000004735513055210752025755 0ustar00arminarmin00000000000000 InfKeepalive: libinfinity-0.7 Reference Manual

InfKeepalive

InfKeepalive — Platform-independent configuration of TCP keep-alive probes

Stability Level

Unstable, unless otherwise indicated

Types and Values

Object Hierarchy

    GBoxed
    ╰── InfKeepalive
    GFlags
    ╰── InfKeepaliveMask

Includes

#include <libinfinity/common/inf-keepalive.h>

Description

The functions in this section can be used to enable and configure TCP keepalives in a platform-independent way. This allows to detect inactive connections, and to maintain some activity in case a firewall is dropping the connection after some inactivity.

Typically, these functions do not need to be called directly, but the keep-alive settings can be configured with inf_tcp_connection_set_keepalive(), infd_tcp_server_set_keepalive() and inf_discovery_avahi_set_keepalive().

The InfKeepalive structure can be safely allocated on the stack and copied by value.

Functions

inf_keepalive_copy ()

InfKeepalive *
inf_keepalive_copy (const InfKeepalive *keepalive);

Makes a dynamically allocated copy of keepalive . This is typically not needed, since the structure can be copied by value, but might prove useful for language bindings.

Parameters

keepalive

The InfKeepalive to copy.

 

Returns

A copy of keepalive . Free with inf_keepalive_free().

[transfer full]


inf_keepalive_free ()

void
inf_keepalive_free (InfKeepalive *keepalive);

Frees a InfKeepalive obtained with inf_keepalive_copy().

Parameters

keepalive

A dynamically allocated InfKeepalive.

 

inf_keepalive_apply ()

gboolean
inf_keepalive_apply (const InfKeepalive *keepalive,
                     InfNativeSocket *socket,
                     InfKeepaliveMask current_mask,
                     GError **error);

Sets the keepalive settings of keepalive for the socket socket . This function abstracts away the platform-dependent configuration of keepalives.

If current_mask is not INF_KEEPALIVE_ALL, it can help this function to not do some unneccessary system calls.

Parameters

keepalive

A InfKeepalive.

 

socket

The socket to which to apply the keepalive settings.

[in]

current_mask

The mask of currently applied keepalive settings on the socket, or INF_KEEPALIVE_ALL if unknown.

 

error

Location for error information, if any, or NULL.

 

Returns

TRUE on success or FALSE if an error occurred.


inf_keepalive_load_default ()

void
inf_keepalive_load_default (InfKeepalive *keepalive,
                            InfKeepaliveMask mask);

This function attempts to obtain the default keepalive settings from the system. If it cannot obtain the default settings, the documented standard values for the host platform are used.

Only the values specified in mask are obtained, and other fields in keepalive are left untouched.

Parameters

keepalive

A InfKeepalive.

[inout]

mask

A mask that specifies which values to obtain.

 

Types and Values

enum InfKeepaliveMask

This bitmask specifies which of the fields in InfKeepalive override the system defaults. For fields that are not enabled in the bitmask, the system default value is taken, and the corresponding field in InfKeepalive is ignored.

Members

INF_KEEPALIVE_ENABLED

Whether the keepalive mechanism is explicitly enabled or disabled.

 

INF_KEEPALIVE_TIME

Whether the keepalive time is overriding the system default.

 

INF_KEEPALIVE_INTERVAL

Whether the keepalive interval is overriding the system default.

 

INF_KEEPALIVE_ALL

All previous values combined.

 

struct InfKeepalive

struct InfKeepalive {
  InfKeepaliveMask mask;
  gboolean enabled;
  guint time;
  guint interval;
};

This structure contains the settings to configure keep-alive on TCP connections.

Members

InfKeepaliveMask mask;

Which of the following settings are enabled. If a setting is disabled, then the system default is taken.

 

gboolean enabled;

Whether sending keep-alive probes is enabled or not.

 

guint time;

Time in seconds after which to send keep-alive probes.

 

guint interval;

Time in seconds between keep-alive probes.

 
libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfRequestResult.html0000644000000000000000000000013213055210752026127 xustar0030 mtime=1488261610.880090717 30 atime=1488261610.880090717 30 ctime=1488261610.880090717 libinfinity-0.7.1/docs/reference/libinfinity/html/InfRequestResult.html0000644000175000017500000033531713055210752026675 0ustar00arminarmin00000000000000 Result of an asynchronous request: libinfinity-0.7 Reference Manual

Result of an asynchronous request

Result of an asynchronous request — Request results for the infinote requests

Stability Level

Unstable, unless otherwise indicated

Functions

InfRequestResult * inf_request_result_new ()
InfRequestResult * inf_request_result_copy ()
void inf_request_result_free ()
gconstpointer inf_request_result_get ()
InfRequestResult * inf_request_result_make_add_node ()
void inf_request_result_get_add_node ()
InfRequestResult * inf_request_result_make_remove_node ()
void inf_request_result_get_remove_node ()
InfRequestResult * inf_request_result_make_explore_node ()
void inf_request_result_get_explore_node ()
InfRequestResult * inf_request_result_make_save_session ()
void inf_request_result_get_save_session ()
InfRequestResult * inf_request_result_make_subscribe_session ()
void inf_request_result_get_subscribe_session ()
InfRequestResult * inf_request_result_make_subscribe_chat ()
void inf_request_result_get_subscribe_chat ()
InfRequestResult * inf_request_result_make_query_acl_account_list ()
void inf_request_result_get_query_acl_account_list ()
InfRequestResult * inf_request_result_make_lookup_acl_accounts ()
void inf_request_result_get_lookup_acl_accounts ()
InfRequestResult * inf_request_result_make_create_acl_account ()
void inf_request_result_get_create_acl_account ()
InfRequestResult * inf_request_result_make_remove_acl_account ()
void inf_request_result_get_remove_acl_account ()
InfRequestResult * inf_request_result_make_query_acl ()
void inf_request_result_get_query_acl ()
InfRequestResult * inf_request_result_make_set_acl ()
void inf_request_result_get_set_acl ()
InfRequestResult * inf_request_result_make_join_user ()
void inf_request_result_get_join_user ()

Types and Values

Object Hierarchy

    GBoxed
    ╰── InfRequestResult

Includes

#include <libinfinity/common/inf-request-result.h>

Description

These functions allow to create InfRequestResult objects and to extract the resulting values from them. In general, all objects in a InfRequestResult are not referenced and must point to an existing reference which is guaranteed to live as long as the InfRequestResult object stays alive. This is typically the case for the primary use case of InfRequestResult, which is to serve as a common parameter for the “finished†signal.

Functions

inf_request_result_new ()

InfRequestResult *
inf_request_result_new (gpointer data,
                        gsize len);

This function creates a new InfRequestResult with the given data. The function takes ownership of the data which must have been allocated with g_malloc(). The memory segment at data must not hold any object references or require deinitialization in a way other than with g_free().

Under normal circumstances, this function should not be used, and instead one of the inf_request_result_make_*() functions should be used.

[constructor]

Parameters

data

The data representing the result of the request.

 

len

The length of the data.

 

Returns

A new InfRequestResult. Free with inf_request_result_free().

[transfer full]


inf_request_result_copy ()

InfRequestResult *
inf_request_result_copy (const InfRequestResult *result);

Creates a copy of result .

Parameters

result

A InfRequestResult.

 

Returns

A new InfRequestResult. Free with inf_request_result_free().

[transfer full]


inf_request_result_free ()

void
inf_request_result_free (InfRequestResult *result);

Releases all resources associated with result .

Parameters

result

A InfRequestResult.

 

inf_request_result_get ()

gconstpointer
inf_request_result_get (const InfRequestResult *result,
                        gsize *length);

Returns the data of result , as given to inf_request_result_new(). The length of the data is stored in length . Normally this function does not need to be used and one of the inf_request_result_get_*() functions should be used instead.

Parameters

result

A InfRequestResult.

 

length

An output parameter for the length of the result data, or NULL.

[out][allow-none]

Returns

A pointer to the request data.

[transfer none][type guint8][array length=length]


inf_request_result_make_add_node ()

InfRequestResult *
inf_request_result_make_add_node (InfBrowser *browser,
                                  const InfBrowserIter *iter,
                                  const InfBrowserIter *new_node);

Creates a new InfRequestResult for an "add-node" request, see inf_browser_add_note() or inf_browser_add_subdirectory(). The InfRequestResult object is only valid as long as the caller maintains a reference to browser .

Parameters

browser

A InfBrowser.

 

iter

An iterator pointing to the node to which a node has been added.

 

new_node

An iterator pointing to the new node.

 

Returns

A new InfRequestResult. Free with inf_request_result_free().

[transfer full]


inf_request_result_get_add_node ()

void
inf_request_result_get_add_node (const InfRequestResult *result,
                                 InfBrowser **browser,
                                 const InfBrowserIter **iter,
                                 const InfBrowserIter **new_node);

Decomposes result into its components. The object must have been created with inf_request_result_make_add_node().

Parameters

result

A InfRequestResult:

 

browser

Output value of the browser that made the request, or NULL.

[out][allow-none][transfer none]

iter

Output value for the node to which a node has been added, or NULL.

[out][allow-none][transfer none]

new_node

Output value for the new node, or NULL.

[out][allow-none][transfer none]

inf_request_result_make_remove_node ()

InfRequestResult *
inf_request_result_make_remove_node (InfBrowser *browser,
                                     const InfBrowserIter *iter);

Creates a new InfRequestResult for an "remove-node" request, see inf_browser_remove_node(). The InfRequestResult object is only valid as long as the caller maintains a reference to browser .

Parameters

browser

A InfBrowser.

 

iter

An iterator pointing to the node to which was removed.

 

Returns

A new InfRequestResult. Free with inf_request_result_free().

[transfer full]


inf_request_result_get_remove_node ()

void
inf_request_result_get_remove_node (const InfRequestResult *result,
                                    InfBrowser **browser,
                                    const InfBrowserIter **iter);

Decomposes result into its components. The object must have been created with inf_request_result_make_remove_node().

Parameters

result

A InfRequestResult:

 

browser

Output value of the browser that made the request, or NULL.

[out][allow-none][transfer none]

iter

Output value for the node that has been removed, or NULL.

[out][allow-none][transfer none]

inf_request_result_make_explore_node ()

InfRequestResult *
inf_request_result_make_explore_node (InfBrowser *browser,
                                      const InfBrowserIter *iter);

Creates a new InfRequestResult for an "explore-node" request, see inf_browser_explore(). The InfRequestResult object is only valid as long as the caller maintains a reference to browser .

Parameters

browser

A InfBrowser.

 

iter

An iterator pointing to the node to which was explored.

 

Returns

A new InfRequestResult. Free with inf_request_result_free().

[transfer full]


inf_request_result_get_explore_node ()

void
inf_request_result_get_explore_node (const InfRequestResult *result,
                                     InfBrowser **browser,
                                     const InfBrowserIter **iter);

Decomposes result into its components. The object must have been created with inf_request_result_make_explore_node().

Parameters

result

A InfRequestResult:

 

browser

Output value of the browser that made the request, or NULL.

[out][allow-none][transfer none]

iter

Output value for the node that has been explored, or NULL.

[out][allow-none][transfer none]

inf_request_result_make_save_session ()

InfRequestResult *
inf_request_result_make_save_session (InfBrowser *browser,
                                      const InfBrowserIter *iter);

Creates a new InfRequestResult for a "save-session" request, see infc_browser_iter_save_session(). The InfRequestResult object is only valid as long as the caller maintains a reference to browser .

Parameters

browser

A InfBrowser.

 

iter

An iterator pointing to the node to which was saved.

 

Returns

A new InfRequestResult. Free with inf_request_result_free().

[transfer full]


inf_request_result_get_save_session ()

void
inf_request_result_get_save_session (const InfRequestResult *result,
                                     InfBrowser **browser,
                                     const InfBrowserIter **iter);

Decomposes result into its components. The object must have been created with inf_request_result_make_save_session().

Parameters

result

A InfRequestResult:

 

browser

Output value of the browser that made the request, or NULL.

[out][allow-none][transfer none]

iter

Output value for the node that has been saved, or NULL.

[out][allow-none][transfer none]

inf_request_result_make_subscribe_session ()

InfRequestResult *
inf_request_result_make_subscribe_session
                               (InfBrowser *browser,
                                const InfBrowserIter *iter,
                                InfSessionProxy *proxy);

Creates a new InfRequestResult for a "subscribe-session" request, see inf_browser_subscribe(). The InfRequestResult object is only valid as long as the caller maintains a reference to browser and proxy .

Parameters

browser

A InfBrowser.

 

iter

An iterator pointing to the node to which a subscription was made.

 

proxy

The InfSessionProxy for the subscription.

 

Returns

A new InfRequestResult. Free with inf_request_result_free().

[transfer full]


inf_request_result_get_subscribe_session ()

void
inf_request_result_get_subscribe_session
                               (const InfRequestResult *result,
                                InfBrowser **browser,
                                const InfBrowserIter **iter,
                                InfSessionProxy **proxy);

Decomposes result into its components. The object must have been created with inf_request_result_make_subscribe_session().

Parameters

result

A InfRequestResult:

 

browser

Output value of the browser that made the request, or NULL.

[out][allow-none][transfer none]

iter

Output value for the node that has been subscribed to, or NULL.

[out][allow-none][transfer none]

proxy

Output value for the subscribed session's proxy, or NULL.

[out][allow-none][transfer none]

inf_request_result_make_subscribe_chat ()

InfRequestResult *
inf_request_result_make_subscribe_chat
                               (InfBrowser *browser,
                                InfSessionProxy *proxy);

Creates a new InfRequestResult for a "subscribe-chat" request, see infc_browser_subscribe_chat(). The InfRequestResult object is only valid as long as the caller maintains a reference to browser and proxy .

Parameters

browser

A InfBrowser.

 

proxy

The InfSessionProxy for the subscribed session.

 

Returns

A new InfRequestResult. Free with inf_request_result_free().

[transfer full]


inf_request_result_get_subscribe_chat ()

void
inf_request_result_get_subscribe_chat (const InfRequestResult *result,
                                       InfBrowser **browser,
                                       InfSessionProxy **proxy);

Decomposes result into its components. The object must have been created with inf_request_result_make_subscribe_chat().

Parameters

result

A InfRequestResult:

 

browser

Output value of the browser that made the request, or NULL.

[out][allow-none][transfer none]

proxy

Output value for the subscribed session's proxy, or NULL.

[out][allow-none][transfer none]

inf_request_result_make_query_acl_account_list ()

InfRequestResult *
inf_request_result_make_query_acl_account_list
                               (InfBrowser *browser,
                                const InfAclAccount *accounts,
                                guint n_accounts,
                                gboolean does_notifications);

Creates a new InfRequestResult for a "query-acl-account-list" request, see inf_browser_query_acl_account_list(). The InfRequestResult object is only valid as long as the caller maintains a reference to browser .

Parameters

browser

A InfBrowser.

 

accounts

The list of accounts.

[array length=n_accounts]

n_accounts

The number of items in the account list.

 

does_notifications

Whether the server notifies the clients about added or removed accounts.

 

Returns

A new InfRequestResult. Free with inf_request_result_free().

[transfer full]


inf_request_result_get_query_acl_account_list ()

void
inf_request_result_get_query_acl_account_list
                               (const InfRequestResult *result,
                                InfBrowser **browser,
                                const InfAclAccount **accounts,
                                guint *n_accounts,
                                gboolean *does_notifications);

Decomposes result into its components. The object must have been created with inf_request_result_make_query_acl_account_list().

Parameters

result

A InfRequestResult:

 

browser

Output value of the browser that made the request, or NULL.

[out][transfer none][allow-none]

accounts

Output value for the list of accounts, or NULL.

[out][array length=n_accounts][transfer none][allow-none]

n_accounts

Output value for the size of the account list, or NULL.

[out][transfer none][allow-none]

does_notifications

Output value for the flag whether the server notifies the client about added or removed accounts, or NULL.

 

inf_request_result_make_lookup_acl_accounts ()

InfRequestResult *
inf_request_result_make_lookup_acl_accounts
                               (InfBrowser *browser,
                                const InfAclAccount *accounts,
                                guint n_accounts);

Creates a new InfRequestResult for a "lookup-acl-accounts" request, see inf_browser_lookup_acl_accounts(). The InfRequestResult object is only valid as long as the caller maintains a reference to browser .

Parameters

browser

A InfBrowser.

 

accounts

The list of accounts.

[array length=n_accounts]

n_accounts

The number of entries in the account list.

 

Returns

A new InfRequestResult. Free with inf_request_result_free().

[transfer full]


inf_request_result_get_lookup_acl_accounts ()

void
inf_request_result_get_lookup_acl_accounts
                               (const InfRequestResult *result,
                                InfBrowser **browser,
                                const InfAclAccount **accounts,
                                guint *n_accounts);

Decomposes result into its components. The object must have been created with inf_request_result_make_lookup_acl_accounts().

Parameters

result

A InfRequestResult:

 

browser

Output value of the browser that made the request, or NULL.

[out][transfer none][allow-none]

accounts

Output value for the list of accounts, or NULL.

[out][transfer none][allow-none][array length=n_accounts]

n_accounts

Output value for the size of the account list, or NULL.

[out][transfer none][allow-none]

inf_request_result_make_create_acl_account ()

InfRequestResult *
inf_request_result_make_create_acl_account
                               (InfBrowser *browser,
                                const InfAclAccount *account,
                                InfCertificateChain *certificate);

Creates a new InfRequestResult for a "create-acl-account" request, see inf_browser_create_acl_account(). The InfRequestResult object is only valid as long as the caller maintains a reference to browser .

Parameters

browser

A InfBrowser.

 

account

The created InfAclAccount.

 

certificate

The certificate which can be used to log into account .

[transfer none]

Returns

A new InfRequestResult. Free with inf_request_result_free().

[transfer full]


inf_request_result_get_create_acl_account ()

void
inf_request_result_get_create_acl_account
                               (const InfRequestResult *result,
                                InfBrowser **browser,
                                const InfAclAccount **account,
                                InfCertificateChain **certificate);

Decomposes result into its components. The object must have been created with inf_request_result_make_create_acl_account().

Parameters

result

A InfRequestResult:

 

browser

Output value of the browser that made the request, or NULL.

[out][transfer none][allow-none]

account

Output value for the created InfAclAccount, or NULL.

[out][transfer none][allow-none]

certificate

Output value for the certificate which can be used to log into the account, or NULL.

[out][transfer none][allow-none]

inf_request_result_make_remove_acl_account ()

InfRequestResult *
inf_request_result_make_remove_acl_account
                               (InfBrowser *browser,
                                const InfAclAccount *account);

Creates a new InfRequestResult for a "remove-acl-account" request, see inf_browser_remove_acl_account(). The InfRequestResult object is only valid as long as the caller maintains a reference to browser .

Parameters

browser

A InfBrowser.

 

account

The removed InfAclAccount.

 

Returns

A new InfRequestResult. Free with inf_request_result_free().

[transfer full]


inf_request_result_get_remove_acl_account ()

void
inf_request_result_get_remove_acl_account
                               (const InfRequestResult *result,
                                InfBrowser **browser,
                                const InfAclAccount **account);

Decomposes result into its components. The object must have been created with inf_request_result_make_remove_acl_account().

Parameters

result

A InfRequestResult:

 

browser

Output value of the browser that made the request, or NULL.

[out][transfer none][allow-none]

account

Output value for the removed InfAclAccount, or NULL.

[out][transfer none][allow-none]

inf_request_result_make_query_acl ()

InfRequestResult *
inf_request_result_make_query_acl (InfBrowser *browser,
                                   const InfBrowserIter *iter,
                                   const InfAclSheetSet *sheet_set);

Creates a new InfRequestResult for a "query-acl" request, see inf_browser_query_acl(). The InfRequestResult object is only valid as long as the caller maintains a reference to browser and proxy .

Parameters

browser

A InfBrowser.

 

iter

An iterator pointing to the node whose ACL was queried.

 

sheet_set

The sheet set for the queried node.

 

Returns

A new InfRequestResult. Free with inf_request_result_free().

[transfer full]


inf_request_result_get_query_acl ()

void
inf_request_result_get_query_acl (const InfRequestResult *result,
                                  InfBrowser **browser,
                                  const InfBrowserIter **iter,
                                  const InfAclSheetSet **sheet_set);

Decomposes result into its components. The object must have been created with inf_request_result_make_query_acl().

Parameters

result

A InfRequestResult:

 

browser

Output value of the browser that made the request, or NULL.

[out][transfer none][allow-none]

iter

Output value for the node whose ACL was queried.

[out][transfer none][allow-none]

sheet_set

Output value for the node's ACL sheets.

[out][transfer none][allow-none]

inf_request_result_make_set_acl ()

InfRequestResult *
inf_request_result_make_set_acl (InfBrowser *browser,
                                 const InfBrowserIter *iter);

Creates a new InfRequestResult for a "set-acl" request, see inf_browser_set_acl(). The InfRequestResult object is only valid as long as the caller maintains a reference to browser and proxy .

Parameters

browser

A InfBrowser.

 

iter

An iterator pointing to the node whose ACL was set.

 

Returns

A new InfRequestResult. Free with inf_request_result_free().

[transfer full]


inf_request_result_get_set_acl ()

void
inf_request_result_get_set_acl (const InfRequestResult *result,
                                InfBrowser **browser,
                                const InfBrowserIter **iter);

Decomposes result into its components. The object must have been created with inf_request_result_make_set_acl().

Parameters

result

A InfRequestResult:

 

browser

Output value of the browser that made the request, or NULL.

[out][transfer none][allow-none]

iter

Output value for the node whose ACL was set.

[out][transfer none][allow-none]

inf_request_result_make_join_user ()

InfRequestResult *
inf_request_result_make_join_user (InfSessionProxy *proxy,
                                   InfUser *user);

Creates a new InfRequestResult for a "join-user" request, see inf_session_proxy_join_user(). The InfRequestResult object is only valid as long as the caller maintains a reference to proxy .

Parameters

proxy

A InfSessionProxy.

 

user

The joined user.

 

Returns

A new InfRequestResult. Free with inf_request_result_free().

[transfer full]


inf_request_result_get_join_user ()

void
inf_request_result_get_join_user (const InfRequestResult *result,
                                  InfSessionProxy **proxy,
                                  InfUser **user);

Decomposes result into its components. The object must have been created with inf_request_result_make_join_user().

Parameters

result

A InfRequestResult:

 

proxy

Output value of the session proxy that made the request, or NULL.

[out][transfer none][allow-none]

user

Output value for the joined user.

[out][transfer none][allow-none]

Types and Values

InfRequestResult

typedef struct _InfRequestResult InfRequestResult;

InfRequestResult is an opaque data type. You should only access it via the public API functions.

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/ch03.html0000644000000000000000000000013213055210752023400 xustar0030 mtime=1488261610.880090717 30 atime=1488261610.880090717 30 ctime=1488261610.880090717 libinfinity-0.7.1/docs/reference/libinfinity/html/ch03.html0000644000175000017500000000754713055210752024147 0ustar00arminarmin00000000000000 Libinfinity's adOPTed implementation: libinfinity-0.7 Reference Manual

Libinfinity's adOPTed implementation

InfAdoptedSession — Session handling concurrency control via the adOPTed algorithm.
InfAdoptedSessionRecord — Create a record of a session
InfAdoptedSessionReplay — Replay a record of a session
InfAdoptedUndoGrouping — Grouping of requests to be undone simultaneously
InfAdoptedAlgorithm — adOPTed implementation
InfAdoptedRequestLog — History of requests
InfAdoptedRequest — Request processed by InfAdoptedAlgorithm.
InfAdoptedOperation — Operation that can be processed by InfAdoptedAlgorithm.
InfAdoptedNoOperation — An operation not doing anything.
InfAdoptedSplitOperation — Operation wrapping two operations
InfAdoptedUser — User in a InfAdoptedUser.
InfAdoptedStateVector — Represents a state in the interaction model
libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfAdoptedNoOperation.html0000644000000000000000000000013213055210752027036 xustar0030 mtime=1488261610.880090717 30 atime=1488261610.880090717 30 ctime=1488261610.880090717 libinfinity-0.7.1/docs/reference/libinfinity/html/InfAdoptedNoOperation.html0000644000175000017500000002120113055210752027564 0ustar00arminarmin00000000000000 InfAdoptedNoOperation: libinfinity-0.7 Reference Manual

InfAdoptedNoOperation

InfAdoptedNoOperation — An operation not doing anything.

Stability Level

Unstable, unless otherwise indicated

Types and Values

Object Hierarchy

    GObject
    ╰── InfAdoptedNoOperation

Implemented Interfaces

InfAdoptedNoOperation implements InfAdoptedOperation.

Includes

#include <libinfinity/adopted/inf-adopted-no-operation.h>

Description

InfAdoptedNoOperation is an operation that does nothing when applied to the buffer. This might be the result of an operation transformation, for example if a request is received that is supposed to delete text that was already deleted by the local site. It is also used by InfAdoptedSession to send the current state to other users in case the user being idle, so that others keep knowing the current state of that user (this is especially required for cleanup of request logs and caches).

Functions

inf_adopted_no_operation_new ()

InfAdoptedNoOperation *
inf_adopted_no_operation_new (void);

Creates a new InfAdoptedNoOperation. A no operation is an operation that does nothing, but might be the result of a transformation.

[constructor]

Returns

A new InfAdoptedNoOperation.

[transfer full]

Types and Values

struct InfAdoptedNoOperation

struct InfAdoptedNoOperation;

InfAdoptedNoOperation is an opaque data type. You should only access it via the public API functions.


struct InfAdoptedNoOperationClass

struct InfAdoptedNoOperationClass {
};

This structure does not contain any public fields.

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfAdoptedOperation.html0000644000000000000000000000013213055210752026541 xustar0030 mtime=1488261610.880090717 30 atime=1488261610.880090717 30 ctime=1488261610.880090717 libinfinity-0.7.1/docs/reference/libinfinity/html/InfAdoptedOperation.html0000644000175000017500000012663113055210752027304 0ustar00arminarmin00000000000000 InfAdoptedOperation: libinfinity-0.7 Reference Manual

InfAdoptedOperation

InfAdoptedOperation — Operation that can be processed by InfAdoptedAlgorithm.

Stability Level

Unstable, unless otherwise indicated

Object Hierarchy

    GEnum
    ╰── InfAdoptedConcurrencyId
    GFlags
    ╰── InfAdoptedOperationFlags
    GInterface
    ╰── InfAdoptedOperation

Prerequisites

InfAdoptedOperation requires GObject.

Known Implementations

InfAdoptedOperation is implemented by InfAdoptedNoOperation and InfAdoptedSplitOperation.

Includes

#include <libinfinity/adopted/inf-adopted-operation.h>

Description

The InfAdoptedOperation interface must be implemented by operations that are supposed to be used by InfAdoptedAlgorithm. They basically need to define transformation rules for transformation against other operations.

Functions

inf_adopted_operation_need_concurrency_id ()

gboolean
inf_adopted_operation_need_concurrency_id
                               (InfAdoptedOperation *operation,
                                InfAdoptedOperation *against);

This function returns whether transforming operation against against is not defined unambiguously. In that case, transformation requires a so-called concurrency ID which determines which of the two operations is transformed.

Parameters

operation

The InfAdoptedOperation to transform.

 

against

The operation to transform against.

 

Returns

Whether transformation of operation against against requires a concurrency ID to be defined.


inf_adopted_operation_transform ()

InfAdoptedOperation *
inf_adopted_operation_transform (InfAdoptedOperation *operation,
                                 InfAdoptedOperation *against,
                                 InfAdoptedOperation *operation_lcs,
                                 InfAdoptedOperation *against_lcs,
                                 gint concurrency_id);

Performs an inclusion transformation of operation against against , meaning that the effect of against is included in operation .

If inf_adopted_operation_need_concurrency_id() returns TRUE for operation and against , then operation_lcs and against_lcs must not be NULL. In this case they must be the same operations as operation and against at the earlierst state to which both of them can be transformed. This information can then be used to resolve any conflicts in the transformation of operation against against .

The concurrency_id parameter is used if inf_adopted_operation_need_concurrency_id() returns TRUE and no conflict resolution can be deduced from operation_lcs and against_lcs . In this case concurrency_id defines a unique way to transform the two operations. Usually, this is derived from the user IDs of the users who issued the two conflicting operations.

Parameters

operation

The InfAdoptedOperation to transform.

 

against

The operation to transform against.

 

operation_lcs

The operation at a previous state, or NULL.

 

against_lcs

The against operation at a previous state, or NULL.

 

concurrency_id

The concurrency ID for the transformation.

 

Returns

The transformed InfAdoptedOperation, or NULL if the transformation failed.

[transfer full][allow-none]


inf_adopted_operation_copy ()

InfAdoptedOperation *
inf_adopted_operation_copy (InfAdoptedOperation *operation);

Returns a copy of operation .

Parameters

operation

The InfAdoptedOperation to copy.

 

Returns

A copy of operation .

[transfer full]


inf_adopted_operation_get_flags ()

InfAdoptedOperationFlags
inf_adopted_operation_get_flags (InfAdoptedOperation *operation);

Returns the flags for operation .

Parameters

operation

A InfAdoptedOperation.

 

Returns

InfAdoptedOperationFlags for operation .


inf_adopted_operation_apply ()

gboolean
inf_adopted_operation_apply (InfAdoptedOperation *operation,
                             InfAdoptedUser *by,
                             InfBuffer *buffer,
                             GError **error);

Applies operation to buffer . The operation is considered to be applied by user by . If the operation cannot be applied then error is set and the function returns FALSE.

Parameters

operation

A InfAdoptedOperation.

 

by

A InfAdoptedUser.

 

buffer

The InfBuffer to apply the operation to.

 

error

Location to store error information, if any, or NULL.

 

Returns

TRUE on success or FALSE on error.


inf_adopted_operation_apply_transformed ()

InfAdoptedOperation *
inf_adopted_operation_apply_transformed
                               (InfAdoptedOperation *operation,
                                InfAdoptedOperation *transformed,
                                InfAdoptedUser *by,
                                InfBuffer *buffer,
                                GError **error);

Applies transformed to buffer . The operation is considered to be applied by user by . The operation transformed must have originated from operation by transformation with inf_adopted_operation_transform().

If operation is reversible or does not affect the buffer (see InfAdoptedOperationFlags), this function is equivalent to

inf_adopted_operation_apply(transformed, by, buffer), with

the exception of the return value. In that case the return value will be operation itself, with a reference added.

However, if operation is not reversible and affects the buffer, the function attempts to construct an operation which is identical to operation , but reversible, and returns it. The function can use information from the transformed operation and the buffer to construct the reversible operation. If a reversible operation cannot be constructed, the function returns an additional reference on operation , and still applies the transformed operation to the buffer.

For example, an operation that deletes text in a text editor would be transmitting only the position and the length of the text to delete over the network. From that information alone, the operation cannot be made reversible. However, when the operation is applied to the buffer, the actual text that is being removed can be restored by looking it up in the buffer, making the operation reversible.

Parameters

operation

A InfAdoptedOperation.

 

transformed

A transformed version of operation .

 

by

The InfAdoptedUser applying the operation.

 

buffer

The InfBuffer to apply the operation to.

 

error

Location to store error information, if any, or NULL.

 

Returns

A InfAdoptedOperation, or NULL on error. Free with g_object_unref() when no longer needed.

[transfer full]


inf_adopted_operation_is_reversible ()

gboolean
inf_adopted_operation_is_reversible (InfAdoptedOperation *operation);

Returns whether operation is reversible.

Parameters

operation

A InfAdoptedOperation.

 

Returns

Whether operation is reversible.


inf_adopted_operation_revert ()

InfAdoptedOperation *
inf_adopted_operation_revert (InfAdoptedOperation *operation);

Returns a new InfAdoptedOperation that undoes the effect of operation . If operation and then its reverse operation are applied to a buffer (in that order), the buffer remains unchanged.

operation must be reversible for this function to be called (i.e. inf_adopted_operation_is_reversible() must return TRUE).

Parameters

operation

A InfAdoptedOperation.

 

Returns

The reverse operation of operation .

[transfer full]

Types and Values

InfAdoptedOperation

typedef struct _InfAdoptedOperation InfAdoptedOperation;

InfAdoptedOperation is an opaque data type. You should only access it via the public API functions.


struct InfAdoptedOperationInterface

struct InfAdoptedOperationInterface {
  gboolean (*need_concurrency_id)(InfAdoptedOperation* operation,
                                  InfAdoptedOperation* against);

  InfAdoptedOperation* (*transform)(InfAdoptedOperation* operation,
                                    InfAdoptedOperation* against,
                                    InfAdoptedOperation* operation_lcs,
                                    InfAdoptedOperation* against_lcs,
                                    InfAdoptedConcurrencyId concurrency_id);

  InfAdoptedOperation* (*copy)(InfAdoptedOperation* operation);

  InfAdoptedOperationFlags (*get_flags)(InfAdoptedOperation* operation);

  gboolean (*apply)(InfAdoptedOperation* operation,
                    InfAdoptedUser* by,
                    InfBuffer* buffer,
                    GError** error);

  InfAdoptedOperation* (*apply_transformed)(InfAdoptedOperation* operation,
                                            InfAdoptedOperation* transformed,
                                            InfAdoptedUser* by,
                                            InfBuffer* buffer,
                                            GError** error);

  InfAdoptedOperation* (*revert)(InfAdoptedOperation* operation);
};

The virtual methods that need to be implemented by an operation to be used with InfAdoptedAlgorithm.

Members

need_concurrency_id ()

Virtual function to determine whether a concurrency ID is required to transform operation against against .

 

transform ()

Virtual function that transform operation against against and returns a new InfAdoptedOperation as the result of the transformation. concurrency_id is either 1 or -1 and can be used to make a decision in case there is no other criteria to decide how to do the transformation, for example when both operation and against are inserting text at the same position in the buffer.

 

copy ()

Virtual function that returns a copy of the operation.

 

get_flags ()

Virtual function that returns the flags of the operation, see InfAdoptedOperationFlags.

 

apply ()

Virtual function that applies the operation to the buffer. by is the user that applies the operation.

 

apply_transformed ()

Virtual function that applies a transformed version of the operation to the buffer. It attempts to use information from the buffer to make the original operation reversible, if it is not already. The implementation of this function is optional, and only needs to be implemented if the operation is not reversible but can be made reversible with additional information from the buffer or the transformed operation.

 

revert ()

Virtual function that creates a new operation that undoes the effect of the operation. If get_flags does never return the INF_ADOPTED_OPERATION_REVERSIBLE flag set, then this is allowed to be NULL.

 

enum InfAdoptedOperationFlags

Various flags for InfAdoptedOperation.

Members

INF_ADOPTED_OPERATION_AFFECTS_BUFFER

The operation changes the content of the buffer.

 

INF_ADOPTED_OPERATION_REVERSIBLE

The operation is reversible, which means that inf_adopted_operation_revert() can be called to generate an operation that undoes the effect of the operation.

 

enum InfAdoptedConcurrencyId

A concurrency ID is used to determine which operation to transform in case two similar operations are transformed against each other.

Members

INF_ADOPTED_CONCURRENCY_SELF

Transform the operation itself.

 

INF_ADOPTED_CONCURRENCY_NONE

Unspecified which operation to transform.

 

INF_ADOPTED_CONCURRENCY_OTHER

Transform the other operation.

 
libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/ch05.html0000644000000000000000000000013213055210752023402 xustar0030 mtime=1488261610.880090717 30 atime=1488261610.880090717 30 ctime=1488261610.880090717 libinfinity-0.7.1/docs/reference/libinfinity/html/ch05.html0000644000175000017500000000755613055210752024151 0ustar00arminarmin00000000000000 Libinfinity server side API: libinfinity-0.7 Reference Manual

Libinfinity server side API

InfdDirectory — Directory of published documents
InfdNotePlugin
infd-storage
InfdAccountStorage — Interface to user account database
InfdFilesystemStorage
InfdFilesystemAccountStorage — Standalone account storage backend
Storage of chat sessions on the file system — Utility functions to deal with storing InfChatSessions in filesystem storage
InfdSessionProxy — Server-side session management
InfdRequest — Asynchronous request on the server side
InfdProgressRequest — Watch progress of node exploration
InfdTcpServer
InfdXmlServer
InfdXmppServer
InfdServerPool
libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfCommunicationCentralFactory.ht0000644000000000000000000000013213055210752030415 xustar0030 mtime=1488261610.880090717 30 atime=1488261610.880090717 30 ctime=1488261610.880090717 libinfinity-0.7.1/docs/reference/libinfinity/html/InfCommunicationCentralFactory.html0000644000175000017500000002137713055210752031512 0ustar00arminarmin00000000000000 InfCommunicationCentralFactory: libinfinity-0.7 Reference Manual

InfCommunicationCentralFactory

InfCommunicationCentralFactory — Factory for InfCommunicationCentralMethod methods

Stability Level

Unstable, unless otherwise indicated

Object Hierarchy

    GObject
    ╰── InfCommunicationCentralFactory

Implemented Interfaces

InfCommunicationCentralFactory implements InfCommunicationFactory.

Includes

#include <libinfinity/communication/inf-communication-central-factory.h>

Description

InfCommunicationCentralFactory implements InfCommunicationFactory. It supports the "central" method on all networks by instantiating InfCommunicationCentralMethod.

Functions

inf_communication_central_factory_get_default ()

InfCommunicationFactory *
inf_communication_central_factory_get_default
                               (void);

Returns the default InfCommunicationCentralFactory.

Returns

A InfCommunicationCentralFactory. It should not be unrefed or freed.

[transfer none]

Types and Values

struct InfCommunicationCentralFactory

struct InfCommunicationCentralFactory;

InfCommunicationCentralFactory is an opaque data type. You should only access it * via the public API functions.


struct InfCommunicationCentralFactoryClass

struct InfCommunicationCentralFactoryClass {
};

This structure does not contain any public fields.

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfChatSession.html0000644000000000000000000000013213055210752025523 xustar0030 mtime=1488261610.880090717 30 atime=1488261610.880090717 30 ctime=1488261610.880090717 libinfinity-0.7.1/docs/reference/libinfinity/html/InfChatSession.html0000644000175000017500000006334713055210752026272 0ustar00arminarmin00000000000000 InfChatSession: libinfinity-0.7 Reference Manual

InfChatSession

InfChatSession — Simple standalone chat

Stability Level

Unstable, unless otherwise indicated

Properties

gchar * log-file Read / Write

Types and Values

Object Hierarchy

    GObject
    ╰── InfSession
        ╰── InfChatSession

Implemented Interfaces

InfChatSession implements InfCommunicationObject.

Includes

#include <libinfinity/common/inf-chat-session.h>

Description

InfChatSession represents a chat session. Normally, there is one chat session per server, and it can be enabled via infd_directory_enable_chat(). Clients can subscribe to the chat session via infc_browser_subscribe_chat().

Functions

inf_chat_session_new ()

InfChatSession *
inf_chat_session_new (InfCommunicationManager *manager,
                      InfChatBuffer *buffer,
                      InfSessionStatus status,
                      InfCommunicationGroup *sync_group,
                      InfXmlConnection *sync_connection);

Creates a new InfChatSession with the messages contained in buffer as initial messages. The communication manager is used to send and receive requests from subscription and synchronization.

If status is INF_SESSION_PRESYNC or INF_SESSION_SYNCHRONIZING, then the session will initially be synchronized, meaning an initial backlog is retrieved from sync_connection (which must not be NULL in this case). If you are subscribed to the session, set the subscription group via inf_session_set_subscription_group().

[constructor]

Parameters

manager

A InfCommunicationManager.

 

buffer

The InfChatBuffer to use for the session.

 

status

Initial status of the session. If this is INF_SESSION_SYNCHRONIZING or INF_SESSION_PRESYNC, then sync_group and sync_connection need to be set.

 

sync_group

A group in which the session is synchronized. Ignored if status is INF_SESSION_RUNNING.

 

sync_connection

A connection to synchronize the session from. Ignored if status is INF_SESSION_RUNNING.

 

Returns

A new InfChatSession.

[transfer full]


inf_chat_session_set_log_file ()

gboolean
inf_chat_session_set_log_file (InfChatSession *session,
                               const gchar *log_file,
                               GError **error);

Sets a file onto which all received messages are appended. The file is created if it does not exist. If a previous log file was set, then it is closed before opening the new file.

Backlog messages received upon synchronization are not logged.

Parameters

session

A InfChatSession.

 

log_file

A filename to store all received messages into.

[type filename]

error

Location to store error information, if any.

 

Returns

TRUE if the log file could be opened, FALSE otherwise (in which case error is set).

Types and Values

struct InfChatSession

struct InfChatSession;

InfChatSession is an opaque data type. You should only access it via the public API functions.


struct InfChatSessionClass

struct InfChatSessionClass {
  void (*receive_message)(InfChatSession* session,
                          const InfChatBufferMessage* message);
  void (*send_message)(InfChatSession* session,
                       const InfChatBufferMessage* message);
};

This structure contains default signal handlers for InfChatSession.

Members

receive_message ()

Default signal handler for the “receive-message†signal.

 

send_message ()

Default signal handler for the “send-message†signal.

 

enum InfChatSessionError

Errors that can occur with a chat session, especially in the process_xml_sync and process_xml_run vfunc implementations.

Members

INF_CHAT_SESSION_ERROR_TYPE_INVALID

An invalid message type was sent.

 

INF_CHAT_SESSION_ERROR_NO_SUCH_USER

A message referred to a nonexisting user.

 

INF_CHAT_SESSION_ERROR_FAILED

Generic error code when no further reason of failure is known.

 

Property Details

The “log-file†property

  “log-file†                gchar *

The file into which to store all received messages.

Flags: Read / Write

Default value: NULL

Signal Details

The “receive-message†signal

void
user_function (InfChatSession       *session,
               InfChatBufferMessage *message,
               gpointer              user_data)

This signal is emitted whenever a message has been received. If the session is in INF_SESSION_SYNCHRONIZING state the received message was a backlog message.

Parameters

session

The InfChatSession that is receiving a message.

 

message

The InfChatBufferMessage that was received.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last


The “send-message†signal

void
user_function (InfChatSession       *session,
               InfChatBufferMessage *message,
               gpointer              user_data)

This signal is emitted whenever a message is sent. Messages can be sent by calling inf_chat_buffer_add_message() or inf_chat_buffer_add_emote_message() on the session's InfChatBuffer. Messages of type INF_CHAT_BUFFER_MESSAGE_USERJOIN or INF_CHAT_BUFFER_MESSAGE_USERPART can not be sent explicitely, so this signal will never be emitted for such messages.

Parameters

session

The InfChatSession that is sending a message.

 

message

The InfChatBufferMessage that is sent.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/libinfinity-0.7-InfError.html0000644000000000000000000000013213055210752027211 xustar0030 mtime=1488261610.880090717 30 atime=1488261610.880090717 30 ctime=1488261610.880090717 libinfinity-0.7.1/docs/reference/libinfinity/html/libinfinity-0.7-InfError.html0000644000175000017500000013263513055210752027755 0ustar00arminarmin00000000000000 InfError: libinfinity-0.7 Reference Manual

InfError

InfError — Common error codes

Stability Level

Unstable, unless otherwise indicated

Includes

#include <libinfinity/common/inf-error.h>

Description

This section defines some common error codes that are used on both client and server side in infinote, and maps these to GErrors.

Functions

inf_request_error_quark ()

GQuark
inf_request_error_quark (void);

Error domain for request errors. Errors in this domain will be from the InfRequestError enumeration. See GError for information on error domains.

Returns

A GQuark.


inf_request_strerror ()

const gchar *
inf_request_strerror (InfRequestError code);

Returns a human-readable string for the given error code.

Parameters

code

An error code from the InfRequestError enumeration.

 

Returns

A static string that must not be freed.


inf_user_error_quark ()

GQuark
inf_user_error_quark (void);

Error domain for user-related errors. Errors in this domain will be from the InfUserError enumeration. See GError for information on error domains.

Returns

A GQuark.


inf_user_strerror ()

const gchar *
inf_user_strerror (InfUserError code);

Returns a human-readable string for the given error code.

Parameters

code

An error code from the InfUserError enumeration.

 

Returns

A static string that must not be freed.


inf_directory_error_quark ()

GQuark
inf_directory_error_quark (void);

Error domain for directory errors. Errors in this domain will be from the InfDirectoryError enumeration. See GError for information on error domains.

Returns

A GQuark.


inf_directory_strerror ()

const gchar *
inf_directory_strerror (InfDirectoryError code);

Returns a human-readable string for the given error code.

Parameters

code

An error code from the InfDirectoryError enumeration.

 

Returns

A static string that must not be freed.


inf_authentication_detail_error_quark ()

GQuark
inf_authentication_detail_error_quark (void);

Error domain for further information on authentication errors. Errors in this domain will be from the InfAuthenticationDetailError enumeration. See GError for information on error domains.

Returns

A GQuark.


inf_authentication_detail_strerror ()

const gchar *
inf_authentication_detail_strerror (InfAuthenticationDetailError code);

Returns a human-readable string for the given error code.

Parameters

code

An error code from the InfAuthenticationDetailError enumeration.

 

Returns

A static string that must not be freed.


inf_gnutls_error_quark ()

GQuark
inf_gnutls_error_quark (void);

Error domain for GnuTLS errors. Errors in this domain will be GnuTLS error codes. See GError for information on error domains.

Returns

A GQuark.


inf_gnutls_set_error ()

void
inf_gnutls_set_error (GError **error,
                      int error_code);

Sets a GError from a GnuTLS error code. If error is NULL, does nothing.

Parameters

error

Location to store the error, or NULL.

 

error_code

A GnuTLS error code.

 

inf_gnutls_certificate_verification_error_quark ()

GQuark
inf_gnutls_certificate_verification_error_quark
                               (void);

Error domain for GnuTLS certificate verification errors. Errors in this domain will be GnuTLS certificate verification results as returned by gnutls_certificate_verify_peers2(). See GError for information on error domains.

Returns

A GQuark.


inf_gnutls_certificate_verification_set_error ()

void
inf_gnutls_certificate_verification_set_error
                               (GError **error,
                                int verify);

Sets a GError from a certificate verification result. If error is NULL, does nothing.

Parameters

error

Location to store the error, or NULL.

 

verify

A GnuTLS certificate verification code.

 

inf_gsasl_error_quark ()

GQuark
inf_gsasl_error_quark (void);

Error domain for GNU SASL errors. Errors in this domain will be GNU SASL error codes. See GError for information on error domains.

Returns

A GQuark.


inf_gsasl_set_error ()

void
inf_gsasl_set_error (GError **error,
                     int error_code);

Sets a GError from a GNU SASL error code. If error is NULL, does nothing.

Parameters

error

Location to store the error, or NULL.

 

error_code

A GNU SASL error code.

 

Types and Values

enum InfRequestError

These are general request errors that all InfcRequests can fail with. Specific requests may also fail with more errors, such as InfDirectoryError.

Members

INF_REQUEST_ERROR_UNKNOWN_DOMAIN

The server sent <request-failed/> with an unknown error domain.

 

INF_REQUEST_ERROR_REPLY_UNPROCESSED

An error occured while processing the server reply for a request.

 

INF_REQUEST_ERROR_INVALID_SEQ

The server sent an invalid sequence number in a reply to a request.

 

INF_REQUEST_ERROR_NO_SUCH_ATTRIBUTE

A request did not contain a XML attribute that is required to complete the request.

 

INF_REQUEST_ERROR_INVALID_ATTRIBUTE

A request contains an XML attribute with unexpected content.

 

INF_REQUEST_ERROR_INVALID_NUMBER

A number in a request was invalid. Either it was not numerical, or it produced an underflow or an overflow.

 

INF_REQUEST_ERROR_NOT_AUTHORIZED

The requesting host is not authorized to perform the requested action.

 

INF_REQUEST_ERROR_FAILED

Generic error code when no further reason of failure is known.

 

enum InfUserError

These are errors related to users. They may occur during user join or during processing a user-related message, such as a user status change message in an InfSession.

Members

INF_USER_ERROR_NAME_IN_USE

The requested name is already in use by another user.

 

INF_USER_ERROR_ID_PROVIDED

The client provided a user ID field in a user join request, but it's the server's job to find an ID.

 

INF_USER_ERROR_NO_SUCH_USER

A request referred to a user ID that no user is associated with.

 

INF_USER_ERROR_STATUS_UNAVAILABLE

The initial user status was given as unavailable during user join or rejoin.

 

INF_USER_ERROR_NOT_JOINED

The user did not join from the connection the request comes from. For example, a user status change can only be requested from the same connection that joined the user.

 

INF_USER_ERROR_INVALID_STATUS

An invalid status was used in a XML request. Allowed status values are "unavailable", "inactive" or "active".

 

INF_USER_ERROR_FAILED

Generic error code when no further reason of failure is known.

 

enum InfDirectoryError

These are errors related to the directory of documents. These errors can be reason why requests created by InfcBrowser fail.

Members

INF_DIRECTORY_ERROR_NO_WELCOME_MESSAGE

A client did not receive the directory's initial welcome message.

 

INF_DIRECTORY_ERROR_VERSION_MISMATCH

The server and client use different versions of the protocol.

 

INF_DIRECTORY_ERROR_NODE_EXISTS

A node with the given name exists already in that subdirectory (in response to node creation requests).

 

INF_DIRECTORY_ERROR_INVALID_NAME

A node with an invalid name was attempted to be created.

 

INF_DIRECTORY_ERROR_NO_SUCH_NODE

The node refered to in a request does not exist in the directory (anymore).

 

INF_DIRECTORY_ERROR_NO_SUCH_SUBSCRIPTION_REQUEST

A <subscribe-ack> or <subscribe-nack> has been received without a previous request.

 

INF_DIRECTORY_ERROR_CHAT_DISABLED

A client attempted to subscribe to a server's chat, but the chat is disabled on the server side.

 

INF_DIRECTORY_ERROR_NOT_A_SUBDIRECTORY

The node refered to in a request is not a subdirectory node, but the requested operation requires one.

 

INF_DIRECTORY_ERROR_NOT_A_NOTE

The node refered to in a request is not a note (non-subdirectory) node, but the requested operations requires one.

 

INF_DIRECTORY_ERROR_NOTE_TYPE_UNSUPPORTED

The node type is not supported by the server.

 

INF_DIRECTORY_ERROR_ROOT_NODE_REMOVE_ATTEMPT

A <remove-node> request attempted to remove a directory's root node, which is not allowed.

 

INF_DIRECTORY_ERROR_NOT_EXPLORED

An operation cannot be performed because the corresponding node is not explored.

 

INF_DIRECTORY_ERROR_ALREADY_EXPLORED

The node given in an exploration request has already been explored earlier.

 

INF_DIRECTORY_ERROR_NOT_INITIATED

Exploration has begun before the client was told how many entries to expect.

 

INF_DIRECTORY_ERROR_TOO_MANY_CHILDREN

Exploration yields more children than announced at the beginning of the exploration.

 

INF_DIRECTORY_ERROR_TOO_FEW_CHILDREN

Exploration yields less children than announced at the beginning of the exploration.

 

INF_DIRECTORY_ERROR_TYPE_UNKNOWN

The type of a note is not known.

 

INF_DIRECTORY_ERROR_ALREADY_SUBSCRIBED

The connection already subscribed to the node refered to, but the requested operation requires it to be unsubscribed.

 

INF_DIRECTORY_ERROR_UNSUBSCRIBED

The connection is not subscribed to the node refered to, but the requested operation requires it to be subscribed.

 

INF_DIRECTORY_ERROR_NETWORK_UNSUPPORTED

The server does not support the network of the incoming connection for the requested operation. For example, subscribing to a session might require a network that has a peer-to-peer communication method, but there is no implementation of that method for the connection's network.

 

INF_DIRECTORY_ERROR_METHOD_UNSUPPORTED

The server requested a communaction method for subscription or synchronization that is not supported by the client.

 

INF_DIRECTORY_ERROR_OPERATION_UNSUPPORTED

The requested operation is not supported by the server.

 

INF_DIRECTORY_ERROR_UNEXPECTED_SYNC_IN

A client received a <sync-in/> without having requested one. The client has no data to sync to the server.

 

INF_DIRECTORY_ERROR_SUBSCRIPTION_REJECTED

A client replied with <subscribe-nack> on an attempt to subscribe it to a session.

 

INF_DIRECTORY_ERROR_UNEXPECTED_MESSAGE

A message that is not understood was received.

 

INF_DIRECTORY_ERROR_NO_STORAGE

A node cannot be stored permanently on the server since it has no storage backend attached.

 

INF_DIRECTORY_ERROR_INVALID_CERTIFICATE

An invalid certificate or certificate request have been sent.

 

INF_DIRECTORY_ERROR_ACCOUNT_LIST_ALREADY_QUERIED

The account list has already been queried before.

 

INF_DIRECTORY_ERROR_ACCOUNT_LIST_NOT_QUERIED

The account list has not been queried.

 

INF_DIRECTORY_ERROR_DUPLICATE_ACCOUNT

When adding a new account the new account ID exists already in the account list.

 

INF_DIRECTORY_ERROR_NO_SUCH_ACCOUNT

There is no such account with the given ID.

 

INF_DIRECTORY_ERROR_ACL_ALREADY_QUERIED

The ACL for a node has already been queried before.

 

INF_DIRECTORY_ERROR_ACL_NOT_QUERIED

The ACL for a node has not yet been queried, but is required to perform the operation.

 

INF_DIRECTORY_ERROR_FAILED

Generic error code when no further reason of failure is known.

 

enum InfAuthenticationDetailError

These errors can give an additional hint why the SASL authentication failed.

Members

INF_AUTHENTICATION_DETAIL_ERROR_AUTHENTICATION_FAILED

User did not provide valid credentials.

 

INF_AUTHENTICATION_DETAIL_ERROR_USER_NOT_AUTHORIZED

User is not permitted to connect to this server.

 

INF_AUTHENTICATION_DETAIL_ERROR_TRY_AGAIN

Authentication was temporarily interrupted on the server side.

 

INF_AUTHENTICATION_DETAIL_ERROR_SERVER_ERROR

An error occured while checking user permissions.

 
libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfSimulatedConnection.html0000644000000000000000000000013213055210752027247 xustar0030 mtime=1488261610.880090717 30 atime=1488261610.880090717 30 ctime=1488261610.880090717 libinfinity-0.7.1/docs/reference/libinfinity/html/InfSimulatedConnection.html0000644000175000017500000006171713055210752030015 0ustar00arminarmin00000000000000 InfSimulatedConnection: libinfinity-0.7 Reference Manual

InfSimulatedConnection

InfSimulatedConnection — Simulated network connection

Stability Level

Unstable, unless otherwise indicated

Properties

InfIo * io Read / Write / Construct Only
InfSimulatedConnectionMode mode Read / Write / Construct
InfSimulatedConnection * target Read / Write

Object Hierarchy

    GEnum
    ╰── InfSimulatedConnectionMode
    GObject
    ╰── InfSimulatedConnection

Implemented Interfaces

InfSimulatedConnection implements InfXmlConnection.

Includes

#include <libinfinity/common/inf-simulated-connection.h>

Description

InfSimulatedConnection simulates a connection and can be used everywhere where a InfXmlConnection is expected. Use inf_simulated_connection_connect() to connect two such connections so that data sent through one is received by the other.

Functions

inf_simulated_connection_new ()

InfSimulatedConnection *
inf_simulated_connection_new (void);

Creates a new InfSimulatedConnection. A connection created this way cannot be switched to INF_SIMULATED_CONNECTION_IO_CONTROLLED mode. Use inf_simulated_connection_new_with_io() instead if you intend to do that.

[constructor]

Returns

A new InfSimulatedConnection.

[transfer full]


inf_simulated_connection_new_with_io ()

InfSimulatedConnection *
inf_simulated_connection_new_with_io (InfIo *io);

Creates a new InfSimulatedConnection with the given InfIo. This connection can be used with INF_SIMULATED_CONNECTION_IO_CONTROLLED mode. If you don't intend to use that mode then using inf_simulated_connection_new() is also good enough since the InfIo object is not required in that case.

[constructor]

Parameters

io

The main loop to be used for INF_SIMULATED_CONNECTION_IO_CONTROLLED mode.

 

Returns

A new InfSimulatedConnection.

[transfer full]


inf_simulated_connection_connect ()

void
inf_simulated_connection_connect (InfSimulatedConnection *connection,
                                  InfSimulatedConnection *to);

Connects two simulated connections, so that data sent through one of them is received by the other one and vice versa. So one call to this function connects both InfSimulatedConnections to each other. There is no need to call this function once for each connection.

If one or both of the connections already have another target, then the simulated connection between those is closed first.

Parameters

connection

A InfSimulatedConnection.

 

to

The target connection.

 

inf_simulated_connection_set_mode ()

void
inf_simulated_connection_set_mode (InfSimulatedConnection *connection,
                                   InfSimulatedConnectionMode mode);

Sets the mode of the simulated connection.

In INF_SIMULATED_CONNECTION_IMMEDIATE mode, messages sent through the connection are received by the target during the call to inf_xml_connection_send().

In INF_SIMULATED_CONNECTION_DELAYED mode, messages sent are queued and received by the target when inf_simulated_connection_flush() is called.

In INF_SIMULATED_CONNECTION_IO_CONTROLLED mode, messages are queued and received by the target as soon as a dispatch handler (see inf_io_add_dispatch()) installed on the main loop is called.

When changing the mode from INF_SIMULATED_CONNECTION_DELAYED or INF_SIMULATED_CONNECTION_IO_CONTROLLED to INF_SIMULATED_CONNECTION_IMMEDIATE, then the queue is flushed, too.

Parameters

connection

A InfSimulatedConnection.

 

mode

The new mode to set.

 

inf_simulated_connection_flush ()

void
inf_simulated_connection_flush (InfSimulatedConnection *connection);

When connection 's mode is INF_SIMULATED_CONNECTION_DELAYED or INF_SIMULATED_CONNECTION_IO_CONTROLLED, then calling this function makes the target connection receive all the queued messages.

Parameters

connection

A InfSimulatedConnection.

 

Types and Values

struct InfSimulatedConnection

struct InfSimulatedConnection;

InfSimulatedConnection is an opaque data type. You should only access it via the public API functions.


struct InfSimulatedConnectionClass

struct InfSimulatedConnectionClass {
};

This structure does not contain any public fields.


enum InfSimulatedConnectionMode

The mode of a simulated connection defines when sent messages arrive at the target connection.

Members

INF_SIMULATED_CONNECTION_IMMEDIATE

Messages are received directly by the target site when calling inf_xml_connection_send().

 

INF_SIMULATED_CONNECTION_DELAYED

Messages are queued, and delivered to the target site when inf_simulated_connection_flush() is called.

 

INF_SIMULATED_CONNECTION_IO_CONTROLLED

Messages are queued and delivered once the application main loop regains control. This requires the simulated connection to have been created with inf_simulated_connection_new_with_io().

 

Property Details

The “io†property

  “io†                      InfIo *

The main loop to be used for IO_CONTROLLED mode.

Flags: Read / Write / Construct Only


The “mode†property

  “mode†                    InfSimulatedConnectionMode

The mode of the simulated connection.

Flags: Read / Write / Construct

Default value: INF_SIMULATED_CONNECTION_IMMEDIATE


The “target†property

  “target†                  InfSimulatedConnection *

The simulated connection receiving data sent through this connection.

Flags: Read / Write

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfCommunicationMethod.html0000644000000000000000000000013213055210752027246 xustar0030 mtime=1488261610.884090709 30 atime=1488261610.884090709 30 ctime=1488261610.884090709 libinfinity-0.7.1/docs/reference/libinfinity/html/InfCommunicationMethod.html0000644000175000017500000011707713055210752030015 0ustar00arminarmin00000000000000 InfCommunicationMethod: libinfinity-0.7 Reference Manual

InfCommunicationMethod

InfCommunicationMethod — Network communication method

Stability Level

Unstable, unless otherwise indicated

Object Hierarchy

    GInterface
    ╰── InfCommunicationMethod

Prerequisites

InfCommunicationMethod requires GObject.

Known Implementations

InfCommunicationMethod is implemented by InfCommunicationCentralMethod.

Includes

#include <libinfinity/communication/inf-communication-method.h>

Description

A InfCommunicationMethod specifies how messages are transferred between group members on the same network. So one method handles all connections on a specific network for the group.

Functions

inf_communication_method_add_member ()

void
inf_communication_method_add_member (InfCommunicationMethod *method,
                                     InfXmlConnection *connection);

Adds a new connection to the group. The network of connection must match the network the method is handling, and connection must not already be a member of the group (see inf_communication_method_is_member()).

Parameters

method

A InfCommunicationMethod.

 

connection

The InfXmlConnection to add.

 

inf_communication_method_remove_member ()

void
inf_communication_method_remove_member
                               (InfCommunicationMethod *method,
                                InfXmlConnection *connection);

Removes a connection from the group. connection needs to be a member of the group (see inf_communication_method_is_member()).

Parameters

method

A InfCommunicationMethod.

 

connection

The InfXmlConnection to remove.

 

inf_communication_method_is_member ()

gboolean
inf_communication_method_is_member (InfCommunicationMethod *method,
                                    InfXmlConnection *connection);

Returns whether connection was added to the group via inf_communication_method_add_member().

Parameters

method

A InfCommunicationMethod.

 

connection

A InfXmlConnection.

 

Returns

Whether connection is a member of the group.


inf_communication_method_send_single ()

void
inf_communication_method_send_single (InfCommunicationMethod *method,
                                      InfXmlConnection *connection,
                                      xmlNodePtr xml);

Sends an XML message to connection . This function takes ownership of xml .

Parameters

method

A InfCommunicationMethod.

 

connection

A InfXmlConnection that is a group member.

 

xml

The message to send.

[transfer full]

inf_communication_method_send_all ()

void
inf_communication_method_send_all (InfCommunicationMethod *method,
                                   xmlNodePtr xml);

Sends an XML message to all group members on this network. This function takes ownership of xml .

Parameters

method

A InfCommunicationMethod.

 

xml

The message to send.

[transfer full]

inf_communication_method_cancel_messages ()

void
inf_communication_method_cancel_messages
                               (InfCommunicationMethod *method,
                                InfXmlConnection *connection);

This function stops all messages to be sent to connection that have not yet been sent.

Parameters

method

A InfCommunicationMethod.

 

connection

A InfXmlConnection that is a group member.

 

inf_communication_method_received ()

InfCommunicationScope
inf_communication_method_received (InfCommunicationMethod *method,
                                   InfXmlConnection *connection,
                                   xmlNodePtr xml);

This function is called by the InfCommunicationRegistry if data has been received on registered connections (see inf_communication_registry_register()).

This function returns the scope of the message. If the scope is INF_COMMUNICATION_SCOPE_GROUP then the registry relays the message to other connections on different networks (if any).

Parameters

method

A InfCommunicationMethod.

 

connection

A InfXmlConnection that is a group member.

 

xml

The received message.

 

Returns

The scope of the message.


inf_communication_method_enqueued ()

void
inf_communication_method_enqueued (InfCommunicationMethod *method,
                                   InfXmlConnection *connection,
                                   xmlNodePtr xml);

This function is called by the InfCommunicationRegistry if data has been enqueued on registered connections (see inf_communication_registry_register()).

Parameters

method

A InfCommunicationMethod.

 

connection

A InfXmlConnection.

 

xml

The enqueued message.

 

inf_communication_method_sent ()

void
inf_communication_method_sent (InfCommunicationMethod *method,
                               InfXmlConnection *connection,
                               xmlNodePtr xml);

This function is called by the InfCommunicationRegistry if data has been sent on registered connections (see inf_communication_registry_register()).

Parameters

method

A InfCommunicationMethod.

 

connection

A InfXmlConnection.

 

xml

The sent message.

 

Types and Values

InfCommunicationMethod

typedef struct _InfCommunicationMethod InfCommunicationMethod;

InfCommunicationMethod is an opaque data type. You should only access it via the public API functions.


struct InfCommunicationMethodInterface

struct InfCommunicationMethodInterface {
  /* Signals */
  void (*add_member)(InfCommunicationMethod* method,
                     InfXmlConnection* connection);
  void (*remove_member)(InfCommunicationMethod* method,
                        InfXmlConnection* connection);

  /* Virtual functions */
  gboolean (*is_member)(InfCommunicationMethod* method,
                        InfXmlConnection* connection);

  void (*send_single)(InfCommunicationMethod* method,
                      InfXmlConnection* connection,
                      xmlNodePtr xml);
  void (*send_all)(InfCommunicationMethod* method,
                   xmlNodePtr xml);
  void (*cancel_messages)(InfCommunicationMethod* method,
                          InfXmlConnection* connection);

  InfCommunicationScope (*received)(InfCommunicationMethod* method,
                                    InfXmlConnection* connection,
                                    xmlNodePtr xml);
  void (*enqueued)(InfCommunicationMethod* method,
                   InfXmlConnection* connection,
                   xmlNodePtr xml);
  void (*sent)(InfCommunicationMethod* method,
               InfXmlConnection* connection,
               xmlNodePtr xml);
};

The default signal handlers of virtual methods of InfCommunicationMethod. These implement communication within a InfCommunicationGroup.

Members

add_member ()

Default signal handler of the “add-member†signal.

 

remove_member ()

Default signal handler of the “remove-member†signal.

 

is_member ()

Returns whether the given connection is a member of the group.

 

send_single ()

Sends a message to a single connection. Takes ownership of xml .

 

send_all ()

Sends a message to all group members, except except . Takes ownership of xml .

 

cancel_messages ()

Cancel sending messages that have not yet been sent to the given connection.

 

received ()

Handles reception of a message from a registered connection. This normally includes informing a group's NetObject and forwarding the message to other group members.

 

enqueued ()

Handles when a message has been enqueued to be sent on a registered connection.

 

sent ()

Handles when a message has been sent to a registered connection.

 

Signal Details

The “add-member†signal

void
user_function (InfCommunicationMethod *method,
               InfXmlConnection       *connection,
               gpointer                user_data)

This signal is emitted whenever a new connection has been added to the group on the network this method handles.

Parameters

method

The InfCommunicationMethod emitting the signal.

 

connection

The InfXmlConnection that was added.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last


The “remove-member†signal

void
user_function (InfCommunicationMethod *method,
               InfXmlConnection       *connection,
               gpointer                user_data)

This signal is emitted whenever a connection has been removed from the group on the network this method handles.

Parameters

method

The InfCommunicationMethod emitting the signal.

 

connection

The InfXmlConnection that was removed.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfCertificateChain.html0000644000000000000000000000013213055210752026465 xustar0030 mtime=1488261610.884090709 30 atime=1488261610.884090709 30 ctime=1488261610.884090709 libinfinity-0.7.1/docs/reference/libinfinity/html/InfCertificateChain.html0000644000175000017500000005201313055210752027220 0ustar00arminarmin00000000000000 InfCertificateChain: libinfinity-0.7 Reference Manual

InfCertificateChain

InfCertificateChain — X.509 certificate chains

Stability Level

Unstable, unless otherwise indicated

Types and Values

Object Hierarchy

    GBoxed
    ╰── InfCertificateChain

Includes

#include <libinfinity/common/inf-certificate-chain.h>

Description

InfCertificateChain is a reference-counted wrapper around an array of gnutls_x509_crt_t structures, representing a certificate chain.

Functions

inf_certificate_chain_new ()

InfCertificateChain *
inf_certificate_chain_new (gnutls_x509_crt_t *certs,
                           guint n_certs);

Creates a new InfCertificateChain with the given certificates. The certs array needs to be allocated with g_malloc. This function takes ownership of certs .

Parameters

certs

Array of certificates.

[array length=n_certs]

n_certs

Number of elements in certs .

 

Returns

A new InfCertificateChain.

[transfer full]


inf_certificate_chain_ref ()

InfCertificateChain *
inf_certificate_chain_ref (InfCertificateChain *chain);

Increases the reference count of chain by one.

Parameters

chain

A InfCertificateChain:

 

Returns

The same chain .


inf_certificate_chain_unref ()

void
inf_certificate_chain_unref (InfCertificateChain *chain);

Decreases the reference count of chain by one. If the reference count reaches zero, then chain is freed.

Parameters

chain

A InfCertificateChain.

 

inf_certificate_chain_get_raw ()

gnutls_x509_crt_t *
inf_certificate_chain_get_raw (const InfCertificateChain *chain);

Returns the raw array of certificates in the chain.

Parameters

chain

A InfCertificateChain.

 

Returns

An array of certificates owned by the chain.


inf_certificate_chain_get_root_certificate ()

gnutls_x509_crt_t
inf_certificate_chain_get_root_certificate
                               (const InfCertificateChain *chain);

Returns the last certificate in the chain.

Parameters

chain

A InfCertificateChain.

 

Returns

The last certificate in the chain.


inf_certificate_chain_get_own_certificate ()

gnutls_x509_crt_t
inf_certificate_chain_get_own_certificate
                               (const InfCertificateChain *chain);

TODO: Rename this function into something more appropriate.

Returns the first certificate in the chain.

Parameters

chain

A InfCertificateChain.

 

Returns

The first certificate in the chain.


inf_certificate_chain_get_nth_certificate ()

gnutls_x509_crt_t
inf_certificate_chain_get_nth_certificate
                               (const InfCertificateChain *chain,
                                guint n);

Returns the n th certificate in the chain.

Parameters

chain

A InfCertificateChain.

 

n

Index of the certificate to retrieve.

 

Returns

The nth certificate in the chain.


inf_certificate_chain_get_n_certificates ()

guint
inf_certificate_chain_get_n_certificates
                               (const InfCertificateChain *chain);

Returns the number of certificates in chain .

Parameters

chain

A InfCertificateChain.

 

Returns

The number of certificates in chain .

Types and Values

InfCertificateChain

typedef struct _InfCertificateChain InfCertificateChain;

InfCertificateChain is an opaque data type. You should only access it via the public API functions.

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfdRequest.html0000644000000000000000000000013213055210752025074 xustar0030 mtime=1488261610.884090709 30 atime=1488261610.884090709 30 ctime=1488261610.884090709 libinfinity-0.7.1/docs/reference/libinfinity/html/InfdRequest.html0000644000175000017500000002060413055210752025630 0ustar00arminarmin00000000000000 InfdRequest: libinfinity-0.7 Reference Manual

InfdRequest

InfdRequest — Asynchronous request on the server side

Stability Level

Unstable, unless otherwise indicated

Properties

guint node-id Read / Write / Construct Only
InfXmlConnection * requestor Read / Write / Construct Only

Types and Values

Object Hierarchy

    GObject
    ╰── InfdRequest
        ╰── InfdProgressRequest

Implemented Interfaces

InfdRequest implements InfRequest.

Includes

#include <libinfinity/server/infd-request.h>

Description

InfdRequest represents an asynchronous operation carried out on the server side. It has the “requestor†property which specifies which connection triggered the request, if any.

Functions

Types and Values

struct InfdRequest

struct InfdRequest;

InfdRequest is an opaque data type. You should only access it via the public API functions.


struct InfdRequestClass

struct InfdRequestClass {
};

This structure does not contain any public fields.

Property Details

The “node-id†property

  “node-id†                 guint

The ID of the node affected by the request.

Flags: Read / Write / Construct Only

Default value: 4294967295


The “requestor†property

  “requestor†               InfXmlConnection *

The connection making the request.

Flags: Read / Write / Construct Only

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfUserTable.html0000644000000000000000000000013213055210752025166 xustar0030 mtime=1488261610.884090709 30 atime=1488261610.884090709 30 ctime=1488261610.884090709 libinfinity-0.7.1/docs/reference/libinfinity/html/InfUserTable.html0000644000175000017500000013330213055210752025722 0ustar00arminarmin00000000000000 InfUserTable: libinfinity-0.7 Reference Manual

InfUserTable

InfUserTable — User information storage

Stability Level

Unstable, unless otherwise indicated

Types and Values

Object Hierarchy

    GObject
    ╰── InfUserTable

Includes

#include <libinfinity/common/inf-user-table.h>

Description

InfUserTable manages multiple InfUser objects and provides an easy way to look up users by their ID and name. All users within a user table must have a unique ID and name. The user table is used by InfSession to store the users within the session.

Functions

InfUserTableForeachUserFunc ()

void
(*InfUserTableForeachUserFunc) (InfUser *user,
                                gpointer user_data);

This callback is called for every user iterated by inf_user_table_foreach_user() or inf_user_table_foreach_local_user().

Parameters

user

The InfUser for the current iteration.

 

user_data

The user_data passed to inf_user_table_foreach_user() or inf_user_table_foreach_local_user().

 

inf_user_table_new ()

InfUserTable *
inf_user_table_new (void);

Creates a new, empty user table.

[constructor]

Returns

A InfUserTable.

[transfer full]


inf_user_table_add_user ()

void
inf_user_table_add_user (InfUserTable *user_table,
                         InfUser *user);

Inserts user into user_table .

Parameters

user_table

A InfUserTable.

 

user

A InfUser not already contained in user_table .

 

inf_user_table_remove_user ()

void
inf_user_table_remove_user (InfUserTable *user_table,
                            InfUser *user);

Removes user from uesr_table .

Parameters

user_table

A InfUserTable.

 

user

A InfUser contained in table .

 

inf_user_table_lookup_user_by_id ()

InfUser *
inf_user_table_lookup_user_by_id (InfUserTable *user_table,
                                  guint id);

Returns the InfUser with the given User ID in user_table .

Parameters

user_table

A InfUserTable.

 

id

User ID to lookup.

 

Returns

A InfUser, or NULL.

[transfer none][allow-none]


inf_user_table_lookup_user_by_name ()

InfUser *
inf_user_table_lookup_user_by_name (InfUserTable *user_table,
                                    const gchar *name);

Returns an InfUser with the given name if there is one.

Parameters

user_table

A InfUserTable.

 

name

User name to lookup.

 

Returns

A InfUser, or NULL.

[transfer none][allow-none]


inf_user_table_foreach_user ()

void
inf_user_table_foreach_user (InfUserTable *user_table,
                             InfUserTableForeachUserFunc func,
                             gpointer user_data);

Calls the given function for each user in the user_table. You should not add or remove users while this function is being executed.

Parameters

user_table

A InfUserTable.

 

func

The function to call for each user.

[scope call]

user_data

User data to pass to the function.

 

inf_user_table_foreach_local_user ()

void
inf_user_table_foreach_local_user (InfUserTable *user_table,
                                   InfUserTableForeachUserFunc func,
                                   gpointer user_data);

Calls the given function for each local user in the user_table. A local user is a user that has the INF_USER_LOCAL flag set and that has not status INF_USER_UNAVAILABLE. You should not add or remove users while this function is being executed.

Parameters

user_table

A InfUserTable.

 

func

The function to call for each user.

[scope call]

user_data

User data to pass to the function.

 

Types and Values

struct InfUserTable

struct InfUserTable;

InfUserTable is an opaque data type. You should only access it via the public API functions.


struct InfUserTableClass

struct InfUserTableClass {
  void(*add_user)(InfUserTable* user_table,
                  InfUser* user);

  void(*remove_user)(InfUserTable* user_table,
                     InfUser* user);

  void(*add_available_user)(InfUserTable* user_table,
                            InfUser* user);

  void(*remove_available_user)(InfUserTable* user_table,
                               InfUser* user);

  void(*add_local_user)(InfUserTable* user_table,
                        InfUser* user);

  void(*remove_local_user)(InfUserTable* user_table,
                           InfUser* user);
};

Signals for the InfUserTable class.

Members

add_user ()

Default signal handler for the “add_user†signal.

 

remove_user ()

Default signal handler for the “remove_user†signal.

 

add_available_user ()

Default signal handler for the “add-available-user†signal.

 

remove_available_user ()

Default signal handler for the “remove-available-user†signal.

 

add_local_user ()

Default signal handler for the “add_local_user†signal.

 

remove_local_user ()

Default signal handler for the “remove_local_user†signal.

 

Signal Details

The “add-available-user†signal

void
user_function (InfUserTable *user_table,
               InfUser      *user,
               gpointer      user_data)

This signal is emitted when a user in the user table becomes available, i.e. its status is not INF_USER_UNAVAILABLE. The signal is also emitted when a new user is added to the user table who is available, in addition to “add-user†and possibly “add-local-userâ€.

Parameters

user_table

The InfUserTable in which user became available.

 

user

The InfUser that became available.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last


The “add-local-user†signal

void
user_function (InfUserTable *user_table,
               InfUser      *user,
               gpointer      user_data)

This signal is emitted when a user is added to the user table and has the INF_USER_LOCAL flag set. In this case, “add-user†is emitted as well.

This signal is also emitted when an existing user receives the INF_USER_LOCAL flag. This occurs when a user rejoins locally after leaving the session (possibly having the INF_USER_LOCAL flag removed during their absence). “add-user†is not emitted in this case.

Parameters

user_table

The InfUserTable in which user has been set as local

 

user

The InfUser that has set as local

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last


The “add-user†signal

void
user_function (InfUserTable *user_table,
               InfUser      *user,
               gpointer      user_data)

This signal is emitted when inf_user_table_add_user() is called. Note that this does not happen if user rejoins the session and has already been added to user_table previously.

“add-local-user†may also be emitted at this point if user has the INF_USER_LOCAL flag set.

Parameters

user_table

The InfUserTable into which user has been added

 

user

The InfUser that has been added into user_table

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last


The “remove-available-user†signal

void
user_function (InfUserTable *user_table,
               InfUser      *user,
               gpointer      user_data)

This signal is emitted when a user in the user table became unavailable, i.e. its status has changed to INF_USER_UNAVAILABLE. The signal is also emitted when a user who was available has been removed from the user table, in addition to “remove-user†and possibly “remove-local-userâ€.

Parameters

user_table

The InfUserTable in which user became unavailable.

 

user

The InfUser that became unavailable.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last


The “remove-local-user†signal

void
user_function (InfUserTable *user_table,
               InfUser      *user,
               gpointer      user_data)

This signal is emitted when a user is removed from the user table and had the INF_USER_LOCAL flag set. In this case, “remove-user†is emitted as well.

This signal is also emitted when user loses the INF_USER_LOCAL flag. This occurs when the local user leaves the session. “remove-user†is not emitted and the status of user is set to INF_USER_UNAVAILABLE.

Parameters

user_table

The InfUserTable in which user is no longer local

 

user

The InfUser that is no longer local

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last


The “remove-user†signal

void
user_function (InfUserTable *user_table,
               InfUser      *user,
               gpointer      user_data)

This signal is emitted when inf_user_table_remove_user() is called. This does not usually happen, as users leaving a session do not get removed from the table.

“remove-local-user†may also be emitted at this point if user has the INF_USER_LOCAL flag set.

Parameters

user_table

The InfUserTable from which user has been remove

 

user

The InfUser that has been removed from user_table

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last

See Also

InfUser, InfSession

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfdServerPool.html0000644000000000000000000000013213055210752025544 xustar0030 mtime=1488261610.884090709 30 atime=1488261610.884090709 30 ctime=1488261610.884090709 libinfinity-0.7.1/docs/reference/libinfinity/html/InfdServerPool.html0000644000175000017500000004606613055210752026312 0ustar00arminarmin00000000000000 InfdServerPool: libinfinity-0.7 Reference Manual

InfdServerPool

InfdServerPool

Properties

InfdDirectory * directory Read / Write / Construct Only

Types and Values

Object Hierarchy

    GObject
    ╰── InfdServerPool

Description

Functions

InfdServerPoolForeachServerFunc ()

void
(*InfdServerPoolForeachServerFunc) (InfdXmlServer *server,
                                    gpointer user_data);

This is the callback signature of the callback passed to infd_server_pool_foreach_server().

Parameters

server

The currently iterated server.

 

user_data

Additional data passed to infd_server_pool_foreach_server().

 

infd_server_pool_new ()

InfdServerPool *
infd_server_pool_new (InfdDirectory *directory);

Creates a new InfdServerPool.

[constructor]

Parameters

directory

A InfdDirectory to which to add incoming connections.

 

Returns

A new InfdServerPool.

[transfer full]


infd_server_pool_add_server ()

void
infd_server_pool_add_server (InfdServerPool *server_pool,
                             InfdXmlServer *server);

Adds server to server_pool . The server pool accepts incoming connections and gives them to its directory which processes incoming requests.

Parameters

server_pool

A InfdServerPool.

 

server

A InfdXmlServer.

 

infd_server_pool_add_local_publisher ()

void
infd_server_pool_add_local_publisher (InfdServerPool *server_pool,
                                      InfdXmppServer *server,
                                      InfLocalPublisher *publisher);

Publishes a service offered by server on the local network via publisher . This can safely be called when server is not yet open. The service will be published as soon as the server opens.

Parameters

server_pool

A InfdServerPool.

 

server

A InfdXmppServer added to server_pool .

 

publisher

A InfLocalPublisher.

 

infd_server_pool_remove_server ()

void
infd_server_pool_remove_server (InfdServerPool *server_pool,
                                InfdXmlServer *server);

Removed server from servor_pool . If server was published via some publishers then it will be unpublished automatically.

Parameters

server_pool

A InfdServerPool.

 

server

A InfdXmlServer which was previously added to server_pool .

 

infd_server_pool_foreach_server ()

void
infd_server_pool_foreach_server (InfdServerPool *server_pool,
                                 InfdServerPoolForeachServerFunc func,
                                 gpointer user_data);

Calls func for each server in pool registered with infd_server_pool_add_server().

Parameters

server_pool

A InfdServerPool.

 

func

The function to be called for each server.

[scope call]

user_data

Additional data to pass to func .

 

Types and Values

struct InfdServerPool

struct InfdServerPool;

InfdServerPool is an opaque data type. You should only access it via the public API functions.


struct InfdServerPoolClass

struct InfdServerPoolClass {
};

This structure does not contain any public fields.

Property Details

The “directory†property

  “directory†               InfdDirectory *

The directory to which to register incoming connections to.

Flags: Read / Write / Construct Only

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfDiscoveryAvahi.html0000644000000000000000000000013213055210752026220 xustar0030 mtime=1488261610.884090709 30 atime=1488261610.884090709 30 ctime=1488261610.884090709 libinfinity-0.7.1/docs/reference/libinfinity/html/InfDiscoveryAvahi.html0000644000175000017500000006361513055210752026765 0ustar00arminarmin00000000000000 InfDiscoveryAvahi: libinfinity-0.7 Reference Manual

InfDiscoveryAvahi

InfDiscoveryAvahi — Service Discovery via Avahi

Properties

InfCertificateCredentials * credentials Read / Write
InfIo * io Read / Write / Construct Only
InfKeepalive * keepalive Read / Write
InfSaslContext * sasl-context Read / Write
gchar * sasl-mechanisms Read / Write
InfXmppConnectionSecurityPolicy security-policy Read / Write
InfXmppManager * xmpp-manager Read / Write / Construct Only

Types and Values

Object Hierarchy

    GObject
    ╰── InfDiscoveryAvahi

Implemented Interfaces

InfDiscoveryAvahi implements InfDiscovery and InfLocalPublisher.

Includes

#include <libinfinity/common/inf-discovery-avahi.h>

Description

InfDiscoveryAvahi implements the InfDiscovery and InfLocalPublisher interfaces on top of avahi. It resolves services to client-side InfXmppConnections.

This class is only available if the macro LIBINFINITY_HAVE_AVAHI is defined.

Functions

inf_discovery_avahi_new ()

InfDiscoveryAvahi *
inf_discovery_avahi_new (InfIo *io,
                         InfXmppManager *manager,
                         InfCertificateCredentials *creds,
                         InfSaslContext *sasl_context,
                         const gchar *sasl_mechanisms);

Created a new InfDiscoveryAvahi object which can be used to publish and discovery Infinote services on the local network. When resolving a InfDiscoveryInfo (which means obtaining a InfXmlConnection for the discovered service) a new InfXmppConnection needs to be created if there is not already one for the destination host in manager . Such connections are created with the creds and sasl_context parameters. These may be NULL in which case InfXmppConnection uses builtin credentials or a builtin context, respectively.

If this InfDiscoveryAvahi is not used to discover services but only to publish any, then creds , sasl_context and sasl_mechanisms are ignored and can safely set to be NULL.

sasl_mechanisms specifies allowed mechanisms used for authentication with the server. It can be NULL, in which case all available mechanisms are accepted.

[constructor]

Parameters

io

A InfIo object used for watching sockets and timeouts.

 

manager

A InfXmppManager.

 

creds

The certificate credentials used for GnuTLS encryption.

 

sasl_context

A SASL context used for authentication.

 

sasl_mechanisms

A whitespace-separated list of accepted SASL mechanisms, or NULL.

 

Returns

A new InfDiscoveryAvahi.

[transfer full]


inf_discovery_avahi_set_security_policy ()

void
inf_discovery_avahi_set_security_policy
                               (InfDiscoveryAvahi *discovery,
                                InfXmppConnectionSecurityPolicy plcy);

Sets the InfXmppConnectionSecurityPolicy for newly created InfXmppConnections. It does not affect already existing connections.

Parameters

discovery

A InfDiscoveryAvahi.

 

plcy

The new security policy.

 

inf_discovery_avahi_get_security_policy ()

InfXmppConnectionSecurityPolicy
inf_discovery_avahi_get_security_policy
                               (InfDiscoveryAvahi *discovery);

Returns the current security policy used for new InfXmppConnections.

Parameters

discovery

A InfDiscoveryAvahi.

 

Returns

The current security policy.


inf_discovery_avahi_set_keepalive ()

void
inf_discovery_avahi_set_keepalive (InfDiscoveryAvahi *discovery,
                                   const InfKeepalive *keepalive);

Sets the keepalive settings for newly created connections. It does not affect already existing connections.

Parameters

discovery

A InfDiscoveryAvahi.

 

keepalive

The new keepalive configuration.

 

inf_discovery_avahi_get_keepalive ()

const InfKeepalive *
inf_discovery_avahi_get_keepalive (InfDiscoveryAvahi *discovery);

Returns the keepalive settings that will be used for new connections.

Parameters

discovery

A InfDiscoveryAvahi.

 

Returns

A InfKeepalive set for new connections, owned by discovery .

Types and Values

struct InfDiscoveryAvahi

struct InfDiscoveryAvahi;

InfDiscoveryAvahi is an opaque data type. You should only access it via the public API functions.


struct InfDiscoveryAvahiClass

struct InfDiscoveryAvahiClass {
};

This structure does not contain any public fields.

Property Details

The “credentials†property

  “credentials†             InfCertificateCredentials *

The GnuTLS certificate credentials used for encrypting XMPP streams.

Flags: Read / Write


The “io†property

  “io†                      InfIo *

The IO object used for watching sockets and timeouts.

Flags: Read / Write / Construct Only


The “keepalive†property

  “keepalive†               InfKeepalive *

The keepalive settings for new connections.

Flags: Read / Write


The “sasl-context†property

  “sasl-context†            InfSaslContext *

The SASL context used for authentication.

Flags: Read / Write


The “sasl-mechanisms†property

  “sasl-mechanisms†         gchar *

The accepted SASL mechanisms for authentication.

Flags: Read / Write

Default value: NULL


The “security-policy†property

  “security-policy†         InfXmppConnectionSecurityPolicy

How to decide whether to use TLS.

Flags: Read / Write

Default value: INF_XMPP_CONNECTION_SECURITY_BOTH_PREFER_TLS


The “xmpp-manager†property

  “xmpp-manager†            InfXmppManager *

The XMPP manager to register resolved XMPP connections.

Flags: Read / Write / Construct Only

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfRequest.html0000644000000000000000000000013213055210752024730 xustar0030 mtime=1488261610.884090709 30 atime=1488261610.884090709 30 ctime=1488261610.884090709 libinfinity-0.7.1/docs/reference/libinfinity/html/InfRequest.html0000644000175000017500000005441313055210752025471 0ustar00arminarmin00000000000000 InfRequest: libinfinity-0.7 Reference Manual

InfRequest

InfRequest — Asynchronous request

Stability Level

Unstable, unless otherwise indicated

Functions

Properties

gdouble progress Read
gchar * type Read / Write / Construct Only

Signals

Types and Values

Object Hierarchy

    GInterface
    ╰── InfRequest

Prerequisites

InfRequest requires GObject.

Known Implementations

InfRequest is implemented by InfcProgressRequest, InfcRequest, InfdProgressRequest and InfdRequest.

Includes

#include <libinfinity/common/inf-request.h>

Description

InfRequest represents a potentially asynchronous operation. This is a basic interface which allows to query the type of the operation and to be notified when the request finishes.

Functions

InfRequestFunc ()

void
(*InfRequestFunc) (InfRequest *request,
                   const InfRequestResult *result,
                   const GError *error,
                   gpointer user_data);

Signature of a signal handler for the “finished†signal.

Parameters

request

The InfRequest that emits the signal.

 

result

A InfRequestResult which contains the result of the request.

 

error

Error information in case the request failed, or NULL otherwise.

 

user_data

Additional data set when the signal handler was connected.

 

inf_request_fail ()

void
inf_request_fail (InfRequest *request,
                  const GError *error);

Declares the request as failed by emitting the “finished†signal with the given error.

Parameters

request

A InfRequest.

 

error

A GError describing the reason for why the request failed.

 

inf_request_finish ()

void
inf_request_finish (InfRequest *request,
                    InfRequestResult *result);

Declares the request as succeeded by emitting the “finished†signal with the given result. The function takes ownership of result .

Parameters

request

A InfRequest.

 

result

A InfRequestResult containing the result of the request.

[transfer full]

inf_request_is_local ()

gboolean
inf_request_is_local (InfRequest *request);

Returns whether request is local or remote. A local request was triggered by a local API call, whereas a remote request was caused by a remote participant from the network.

Parameters

request

A InfRequest.

 

Returns

TRUE if the request is local and FALSE if it is remote.

Types and Values

InfRequest

typedef struct _InfRequest InfRequest;

InfRequest is an opaque data type. You should only access it via the public API functions.


struct InfRequestInterface

struct InfRequestInterface {
  void (*finished)(InfRequest* request,
                   const InfRequestResult* result,
                   const GError* error);

  gboolean (*is_local)(InfRequest* request);
};

Virtual functions of the InfRequest interface.

Members

finished ()

Default signal handler of the “finished†signal.

 

is_local ()

Virtual function to check whether the request is local or remote.

 

Property Details

The “progress†property

  “progress†                gdouble

Percentage of completion of the request.

Flags: Read

Allowed values: [0,1]

Default value: 0


The “type†property

  “type†                    gchar *

A string identifier for the type of the request.

Flags: Read / Write / Construct Only

Default value: NULL

Signal Details

The “finished†signal

void
user_function (InfRequest       *request,
               InfRequestResult *result,
               GError           *error,
               gpointer          user_data)

This signal is emitted when the request finishes. If error is non-NULL the request failed, otherwise it finished successfully.

Parameters

request

The InfRequest which finished.

 

result

A InfRequestResult which contains the result of the request.

 

error

Error information in case the request failed, or NULL otherwise.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfCommunicationHostedGroup.html0000644000000000000000000000013213055210752030271 xustar0030 mtime=1488261610.884090709 30 atime=1488261610.884090709 30 ctime=1488261610.884090709 libinfinity-0.7.1/docs/reference/libinfinity/html/InfCommunicationHostedGroup.html0000644000175000017500000003600013055210752031022 0ustar00arminarmin00000000000000 InfCommunicationHostedGroup: libinfinity-0.7 Reference Manual

InfCommunicationHostedGroup

InfCommunicationHostedGroup — Communication group opened by the local host

Stability Level

Unstable, unless otherwise indicated

Object Hierarchy

    GObject
    ╰── InfCommunicationGroup
        ╰── InfCommunicationHostedGroup

Includes

#include <libinfinity/communication/inf-communication-hosted-group.h>

Description

InfCommunicationHostedGroup is a InfCommunicationHostedGroup opened on the local host. It allows adding other hosts to the group via inf_communication_hosted_group_add_member(), and to remove hosts via inf_communication_hosted_group_remove_member().

Functions

inf_communication_hosted_group_add_method ()

void
inf_communication_hosted_group_add_method
                               (InfCommunicationHostedGroup *group,
                                const gchar *method);

Adds a method to the hosted group. When a connection from a given network is added to the group the first time, a InfCommunicationMethod is instantiated to handle messaging for the group within this network. The first method added will be tried first. If the communication manager does support it (meaning inf_communication_manager_get_factory_for() for the connection's network and the chosen method returns non-NULL), then it will be used, otherwise the next method will be tried, etc. If no method is supported, or no methods are added to the group, then the "central" method will be used as a fallback.

Parameters

group

A InfCommunicationHostedGroup.

 

method

The method name to add.

 

inf_communication_hosted_group_add_member ()

void
inf_communication_hosted_group_add_member
                               (InfCommunicationHostedGroup *group,
                                InfXmlConnection *connection);

Adds connection as a member to group . On the remote site, a InfCommunicationJoinedGroup with the same name and method used for connection (see inf_communication_group_get_method_for_connection()) needs to be created for successful communication.

Parameters

group

A InfCommunicationGroup.

 

connection

A InfXmlConnection to add to group.

 

inf_communication_hosted_group_remove_member ()

void
inf_communication_hosted_group_remove_member
                               (InfCommunicationHostedGroup *grp,
                                InfXmlConnection *connection);

Removes connection 's membership from group . On the remote site, the corresponding InfCommunicationJoinedGroup needs to be freed.

Parameters

grp

A InfCommunicationGroup.

 

connection

The InfXmlConnection to remove from the group.

 

Types and Values

struct InfCommunicationHostedGroup

struct InfCommunicationHostedGroup;

InfCommunicationHostedGroup is an opaque data type. You should only access it via the public API functions.


struct InfCommunicationHostedGroupClass

struct InfCommunicationHostedGroupClass {
};

This structure does not contain any public fields.

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/libinfinity-0.7-InfCertUtil.html0000644000000000000000000000012613055210752027656 xustar0028 mtime=1488261610.8880907 30 atime=1488261610.884090709 28 ctime=1488261610.8880907 libinfinity-0.7.1/docs/reference/libinfinity/html/libinfinity-0.7-InfCertUtil.html0000644000175000017500000025746413055210752030427 0ustar00arminarmin00000000000000 Certificate utility functions: libinfinity-0.7 Reference Manual

Certificate utility functions

Certificate utility functions — Helper functions to read and write information from X.509 certificates.

Stability Level

Unstable, unless otherwise indicated

Types and Values

Includes

#include <libinfinity/common/inf-cert-util.h>

Description

These functions are utility functions that can be used when dealing with certificates, private key and Diffie-Hellman parameters for key exchange. The functionality these functions provide include creating, reading and writing these data structures to disk in PEM format, or to read values from certificates.

Functions

inf_cert_util_create_dh_params ()

gnutls_dh_params_t
inf_cert_util_create_dh_params (GError **error);

Creates new, random Diffie-Hellman parameters.

Parameters

error

Location to store error information, if any.

 

Returns

New dhparams to be freed with gnutls_dh_params_deinit(), or NULL in case of error.

[transfer full]


inf_cert_util_read_dh_params ()

gnutls_dh_params_t
inf_cert_util_read_dh_params (const gchar *filename,
                              GError **error);

Reads the Diffie-Hellman parameters located at filename into a gnutls_dh_params_t structure.

Parameters

filename

A path to a DH parameters file.

[type filename]

error

Location to store error information, if any.

 

Returns

New dhparams to be freed with gnutls_dh_params_deinit(), or NULL in case of error.

[transfer full]


inf_cert_util_write_dh_params ()

gboolean
inf_cert_util_write_dh_params (gnutls_dh_params_t params,
                               const gchar *filename,
                               GError **error);

Writes the given Diffie-Hellman parameters to the given path on the filesystem. If an error occurs, error is set and FALSE is returned.

Parameters

params

An initialized gnutls_dh_params_t structure.

[transfer none]

filename

The path at which so store params .

[type filename]

error

Location to store error information, if any.

 

Returns

TRUE on success or FALSE otherwise.


inf_cert_util_create_private_key ()

gnutls_x509_privkey_t
inf_cert_util_create_private_key (gnutls_pk_algorithm_t algo,
                                  unsigned int bits,
                                  GError **error);

Generates a new, random X.509 private key. This function is a thin wrapper around gnutls_x509_privkey_generate() which provides GError-style error reporting.

Parameters

algo

The key algorithm to use (RSA or DSA).

 

bits

The length of the key to generate.

 

error

Location to store error information, if any.

 

Returns

A new key to be freed with gnutls_x509_privkey_deinit(), or NULL if an error occured.

[transfer full]


inf_cert_util_read_private_key ()

gnutls_x509_privkey_t
inf_cert_util_read_private_key (const gchar *filename,
                                GError **error);

Reads the key located at filename into a gnutls_x509_privkey_t structure.

Parameters

filename

A path to a X.509 private key file.

[type filename]

error

Location for error information, if any.

 

Returns

A private key. Free with gnutls_x509_privkey_deinit().

[transfer full]


inf_cert_util_write_private_key ()

gboolean
inf_cert_util_write_private_key (gnutls_x509_privkey_t key,
                                 const gchar *filename,
                                 GError **error);

Writes key to the location specified by filename on the filesystem. If an error occurs, the function returns FALSE and error is set.

Parameters

key

An initialized gnutls_x509_privkey_t structure.

[transfer none]

filename

The path at which so store the key.

[type filename]

error

Location to store error information, if any.

 

Returns

TRUE on success, FALSE otherwise.


inf_cert_util_create_certificate ()

gnutls_x509_crt_t
inf_cert_util_create_certificate (gnutls_x509_privkey_t key,
                                  const InfCertUtilDescription *desc,
                                  GError **error);

Creates a new X.509 certificate with the given key and properties. If an error occurs the function returns NULL and error is set. The returned certificate will not be signed.

Parameters

key

The private key to be used for the new certificate.

[transfer none]

desc

The certificate properties.

 

error

Location to store error information, if any, or NULL.

 

Returns

A new gnutls_x509_crt_t, or NULL. Free with gnutls_x509_crt_deinit() when no longer needed.

[transfer full]


inf_cert_util_create_signed_certificate ()

gnutls_x509_crt_t
inf_cert_util_create_signed_certificate
                               (gnutls_x509_privkey_t key,
                                const InfCertUtilDescription *desc,
                                gnutls_x509_crt_t sign_cert,
                                gnutls_x509_privkey_t sign_key,
                                GError **error);

Creates a new X.509 certificate with the given key and properties. If an error occurs the function returns NULL and error is set. The returned certificate will be signed by sign_cert .

Parameters

key

The private key to be used for the new certificate.

[transfer none]

desc

The certificate properties.

 

sign_cert

A certificate used to sign the newly created certificate.

[transfer none]

sign_key

The private key for sign_cert .

[transfer none]

error

Location to store error information, if any, or NULL.

 

Returns

A new gnutls_x509_crt_t, or NULL. Free with gnutls_x509_crt_deinit() when no longer needed.

[transfer full]


inf_cert_util_create_self_signed_certificate ()

gnutls_x509_crt_t
inf_cert_util_create_self_signed_certificate
                               (gnutls_x509_privkey_t key,
                                const InfCertUtilDescription *desc,
                                GError **error);

Creates a new X.509 certificate with the given key and properties. If an error occurs the function returns NULL and error is set. The returned certificate will be signed by itself.

Parameters

key

The private key to be used for the new certificate.

[transfer none]

desc

The certificate properties.

 

error

Location to store error information, if any, or NULL.

 

Returns

A new gnutls_x509_crt_t, or NULL. Free with gnutls_x509_crt_deinit() when no longer needed.

[transfer full]


inf_cert_util_read_certificate ()

GPtrArray *
inf_cert_util_read_certificate (const gchar *filename,
                                GPtrArray *current,
                                GError **error);

Loads X.509 certificates in PEM format from the file at filename . There can be any number of certificates in the file. If current is not NULL, the new certificates are appended to the array. Otherwise, a new array with the read certificates is returned.

If an error occurs, the function returns NULL and error is set. If current is non-NULL and the function succeeds, the return value is the same as current .

Parameters

filename

A path to a X.509 certificate file.

[type filename]

current

An array of gnutls_x509_crt_t objects, or NULL.

[element-type gnutls_x509_crt_t][allow-none][transfer full]

error

Location to store error information, if any.

 

Returns

An array of the read certificates, or NULL on error.

[transfer full][element-type gnutls_x509_crt_t]


inf_cert_util_write_certificate ()

gboolean
inf_cert_util_write_certificate (gnutls_x509_crt_t *certs,
                                 guint n_certs,
                                 const gchar *filename,
                                 GError **error);

This function writes the certificates in the array certs to disk, in PEM format. If an error occurs the function returns FALSE and error is set.

Parameters

certs

An array of gnutls_x509_crt_t objects.

[array length=n_certs][transfer none]

n_certs

Number of certificates in the error.

 

filename

The path at which to store the certificates.

[type filename]

error

Location to store error information, if any.

 

Returns

TRUE on success or FALSE otherwise.


inf_cert_util_write_certificate_mem ()

gchar *
inf_cert_util_write_certificate_mem (gnutls_x509_crt_t *certs,
                                     guint n_certs,
                                     GError **error);

This function writes the certificates in the array certs into memory, in PEM format. If an error occurs the function returns NULL and error is set.

Parameters

certs

An array of gnutls_x509_crt_t objects.

[transfer none]

n_certs

Number of certificates in the error.

 

error

Location to store error information, if any.

 

Returns

A string with PEM-encoded certificate data, or NULL on error. Free with g_free().

[transfer full]


inf_cert_util_write_certificate_with_key ()

gboolean
inf_cert_util_write_certificate_with_key
                               (gnutls_x509_privkey_t key,
                                gnutls_x509_crt_t *certs,
                                guint n_certs,
                                const gchar *filename,
                                GError **error);

This function writes both the private key key as well as the certificates in the array certs to disk, in PEM format. If an error occurs the function returns FALSE and error is set.

Parameters

key

An initialized gnutls_x509_privkey_t structure.

[transfer none]

certs

An array of gnutls_x509_crt_t objects.

[transfer none][array length=n_certs]

n_certs

Number of certificates in the error.

 

filename

The path at which to store the certificates.

[type filename]

error

Location to store error information, if any.

 

Returns

TRUE on success or FALSE otherwise.


inf_cert_util_copy_certificate ()

gnutls_x509_crt_t
inf_cert_util_copy_certificate (gnutls_x509_crt_t src,
                                GError **error);

Creates a copy of the certificate src and returns the copy. If the function fails FALSE is returned and error is set.

Parameters

src

The certificate to copy.

[transfer none]

error

Location to store error information, if any.

 

Returns

A copy of src , or NULL on error. Free with gnutls_x509_crt_deinit() when no longer in use.

[transfer full]


inf_cert_util_read_certificate_map ()

GHashTable *
inf_cert_util_read_certificate_map (const gchar *filename,
                                    GError **error);

Reads a certificate map, i.e. a mapping from hostname to certificate, from the given file. The format of the file is expected to be one entry per line, where each entry consists of the hostname, then a colon character (':'), and then the base64-encoded certificate in DER format.

If the file with the given filename does not exist, an empty hash table is returned and the function succeeds.

Parameters

filename

The filename to read the certificate map from.

 

error

Location to store error information, if any.

 

Returns

A hash table with the read mapping, or NULL on error. Use g_hash_table_unref() to free the hash table when no longer needed.

[transfer container][element-type string gnutls_x509_crt_t]


inf_cert_util_write_certificate_map ()

gboolean
inf_cert_util_write_certificate_map (GHashTable *cert_map,
                                     const gchar *filename,
                                     GError **error);

Writes the given certificate mapping to a file with the given filename. See inf_cert_util_read_certificate_map() for the format of the written file. If an error occurs, error is set and the function returns FALSE.

This function can be useful to implement trust-on-first-use (TOFU) semantics.

Parameters

cert_map

A certificate mapping, i.e. a hash table mapping hostname strings to gnutls_x509_crt_t instances.

[transfer none][element-type string gnutls_x509_crt_t]

filename

The name of the file to write the mapping to.

 

error

Location to store error information, if any.

 

Returns

TRUE on success or FALSE on error.


inf_cert_util_check_certificate_key ()

gboolean
inf_cert_util_check_certificate_key (gnutls_x509_crt_t cert,
                                     gnutls_x509_privkey_t key);

This function returns TRUE if key is the private key belonging to cert , or FALSE otherwise.

Parameters

cert

The certificate to be checked.

[transfer none]

key

The private key to be checked.

[transfer none]

Returns

TRUE if cert was signed with key , or FALSE otherwise.


inf_cert_util_compare_fingerprint ()

gboolean
inf_cert_util_compare_fingerprint (gnutls_x509_crt_t cert1,
                                   gnutls_x509_crt_t cert2,
                                   GError **error);

Checks whether the SHA-256 fingerprints of the two given certificates are identical or not. If a fingerprint cannot be obtained, the function returns FALSE and error is set.

Parameters

cert1

The first certificate to compare.

 

cert2

The second certificate to compare.

 

error

Location to store error information, if any.

 

Returns

Whether the two certificates have identical fingerprints. Returns FALSE on error.


inf_cert_util_get_dn ()

gchar *
inf_cert_util_get_dn (gnutls_x509_crt_t cert);

Retrieves the full distinguished name (DN) from the certificate, allocating memory for the return value.

Parameters

cert

An initialized gnutls_x509_crt_t.

[transfer none]

Returns

The DN of the certificate. Free with g_free() after use.

[transfer full]


inf_cert_util_get_dn_by_oid ()

gchar *
inf_cert_util_get_dn_by_oid (gnutls_x509_crt_t cert,
                             const char *oid,
                             unsigned int index);

Retrieves the given item from the certificate. This function is a thin wrapper around gnutls_x509_crt_get_dn_by_oid(), allocating memory for the return value. The function returns NULL if there is no such entry in the certificate.

Parameters

cert

An initialized gnutls_x509_crt_t.

[transfer none]

oid

The name of the requested entry.

 

index

Index of the entry to retrieve.

 

Returns

The certificate entry, or NULL if it is not present. Free with g_free() after use.

[transfer full]


inf_cert_util_get_issuer_dn_by_oid ()

gchar *
inf_cert_util_get_issuer_dn_by_oid (gnutls_x509_crt_t cert,
                                    const char *oid,
                                    unsigned int index);

Retrieves the given item from the issuer of the certificate. This function is a thin wrapper around gnutls_x509_crt_get_issuer_dn_by_oid(), allocating memory for the return value. The functions returns NULL if there is no such entry in the certificate.

Parameters

cert

An initialized gnutls_x509_crt_t.

[transfer none]

oid

The name of the requested entry.

 

index

Index of the entry to retrieve.

 

Returns

The certificate entry, or NULL if it is not present. Free with g_free() after use.

[transfer full]


inf_cert_util_get_hostname ()

gchar *
inf_cert_util_get_hostname (gnutls_x509_crt_t cert);

Attempts to read the hostname of a certificate. This is done by looking at the DNS name and IP address SANs. If both are not available, the common name of the certificate is returned.

Parameters

cert

An initialized gnutls_x509_crt_t.

[transfer none]

Returns

The best guess for the certificate's hostname, or NULL when it cannot be retrieved. Free with g_free() after use.

[transfer full][allow-none]


inf_cert_util_get_serial_number ()

gchar *
inf_cert_util_get_serial_number (gnutls_x509_crt_t cert);

Read the serial number of a certificate and return it in hexadecimal format. If the serial number cannot be read NULL is returned.

Parameters

cert

An initialized gnutls_x509_crt_t.

[transfer none]

Returns

The serial number of the certificate, or NULL. Free with g_free() after use.

[transfer full]


inf_cert_util_get_fingerprint ()

gchar *
inf_cert_util_get_fingerprint (gnutls_x509_crt_t cert,
                               gnutls_digest_algorithm_t algo);

Returns the fingerprint of the certificate hashed with the specified algorithm, in hexadecimal format. If the fingerprint cannot be read NULL is returned.

Parameters

cert

An initialized gnutls_x509_crt_t.

[transfer none]

algo

The hashing algorithm to use.

 

Returns

The fingerprint of the certificate, or NULL. Free with g_free() after use.

[transfer full]


inf_cert_util_get_activation_time ()

gchar *
inf_cert_util_get_activation_time (gnutls_x509_crt_t cert);

Returns the activation time of the certificate as a string in human-readable format. If the activation time cannot be read NULL is returned.

Parameters

cert

An initialized gnutls_x509_crt_t.

[transfer none]

Returns

The activation time of the certificate, or NULL. Free with g_free() after use.

[transfer full]


inf_cert_util_get_expiration_time ()

gchar *
inf_cert_util_get_expiration_time (gnutls_x509_crt_t cert);

Returns the expiration time of the certificate as a string in human-readable format. If the expiration time cannot be read NULL is returned.

Parameters

cert

An initialized gnutls_x509_crt_t.

[transfer none]

Returns

The expiration time of the certificate, or NULL. Free with g_free() after use.

[transfer full]

Types and Values

struct InfCertUtilDescription

struct InfCertUtilDescription {
  guint64 validity;

  const gchar* dn_common_name;

  const gchar* san_dnsname;
};

This structure contains information that is used to generate a certificate with the inf_cert_util_create_certificate(), inf_cert_util_create_self_signed_certificate() and inf_cert_util_create_signed_certificate() functions.

Members

guint64 validity;

The number of seconds the certificate is valid, beginning from the current time.

 

const gchar *dn_common_name;

The common name of the certificate, or NULL.

 

const gchar *san_dnsname;

The DNS name of the certificate, or NULL.

 
libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfCommunicationObject.html0000644000000000000000000000012413055210752027235 xustar0028 mtime=1488261610.8880907 28 atime=1488261610.8880907 28 ctime=1488261610.8880907 libinfinity-0.7.1/docs/reference/libinfinity/html/InfCommunicationObject.html0000644000175000017500000005455013055210752027777 0ustar00arminarmin00000000000000 InfCommunicationObject: libinfinity-0.7 Reference Manual

InfCommunicationObject

InfCommunicationObject — Network message destinations

Stability Level

Unstable, unless otherwise indicated

Object Hierarchy

    GEnum
    ╰── InfCommunicationScope
    GInterface
    ╰── InfCommunicationObject

Prerequisites

InfCommunicationObject requires GObject.

Known Implementations

InfCommunicationObject is implemented by InfAdoptedSession, InfChatSession, InfSession, InfcBrowser, InfcSessionProxy, InfdDirectory and InfdSessionProxy.

Includes

#include <libinfinity/communication/inf-communication-object.h>

Description

A InfCommunicationObject is the destination of network messages sent through the InfCommunicationManager. Each InfCommunicationGroup is associated with InfCommunicationObject. Requests received by that group are reported to the InfCommunicationObject by calling inf_communication_object_received() on it. Messages sent to a member of that group (via inf_communication_group_send_message()) are also reported by calling inf_communication_object_sent().

Functions

inf_communication_object_received ()

InfCommunicationScope
inf_communication_object_received (InfCommunicationObject *object,
                                   InfXmlConnection *conn,
                                   xmlNodePtr node);

This function is called when a InfCommunicationManager received data from connection belonging to a group whose communication object is object . This function should process the incoming data. If it could not process it, then it should set error .

It should return INF_COMMUNICATION_SCOPE_GROUP if the message is allowed to be forwarded to other group members. Since recipients of forwarded messages don't see the original sender (but just the forwarding host), forwarding arbitrary messages could lead to a security problem in the worst case.

For example, if, in central mode, a client sends an (invalid) <add-node> request to the whole (InfDirectory) group, and the server forwarded this to all clients, those clients would try to create a new node although the server rejected the request. In decentral mode, this is not a problem since all clients see where the message comes from, and can themselves reject all messages not coming from the server.

Parameters

object

A InfCommunicationObject.

 

conn

The InfXmlConnection data was received from.

 

node

The received data.

 

Returns

INF_COMMUNICATION_SCOPE_GROUP if the message is allowed to be forwarded, INF_COMMUNICATION_SCOPE_PTP if not.


inf_communication_object_enqueued ()

void
inf_communication_object_enqueued (InfCommunicationObject *object,
                                   InfXmlConnection *conn,
                                   xmlNodePtr node);

This function is called, when an XML message scheduled to be sent via inf_communication_group_send_message() or inf_communication_group_send_group_message() cannot be cancelled anymore, because it was already passed to conn .

Parameters

object

A InfCommunicationObject.

 

conn

A InfXmlConnection.

 

node

The XML data.

 

inf_communication_object_sent ()

void
inf_communication_object_sent (InfCommunicationObject *object,
                               InfXmlConnection *conn,
                               xmlNodePtr node);

This function is called when a XML message sent via inf_communication_group_send_message() or inf_communication_group_send_group_message() has actually been sent out.

Parameters

object

A InfCommunicationObject.

 

conn

A InfXmlConnection.

 

node

The sent data.

 

Types and Values

enum InfCommunicationScope

InfCommunicationScope specifies to which hosts a message belongs.

Members

INF_COMMUNICATION_SCOPE_PTP

The message is sent from one group member to another.

 

INF_COMMUNICATION_SCOPE_GROUP

The message is sent to all group members.

 

InfCommunicationObject

typedef struct _InfCommunicationObject InfCommunicationObject;

InfCommunicationObject is an opaque data type. You should only access it via the public API functions.


struct InfCommunicationObjectInterface

struct InfCommunicationObjectInterface {
  InfCommunicationScope (*received)(InfCommunicationObject* object,
                                    InfXmlConnection* conn,
                                    xmlNodePtr node);

  void (*enqueued)(InfCommunicationObject* object,
                   InfXmlConnection* conn,
                   xmlNodePtr node);

  void (*sent)(InfCommunicationObject* object,
               InfXmlConnection* conn,
               xmlNodePtr node);
};

The virtual methods of InfCommunicationObject. These are called by the InfCommunicationMethod when appropriate.

Members

received ()

Called when a message for the group related to this InfCommunicationObject was received.

 

enqueued ()

Called when a message to be sent to another group member has been enqueued, which means sending it can no longer be cancelled via inf_communication_group_cancel_messages().

 

sent ()

Called when a message has been sent to another group member of the group related no this InfCommunicationObject.

 
libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/ch06.html0000644000000000000000000000012413055210752023404 xustar0028 mtime=1488261610.8880907 28 atime=1488261610.8880907 28 ctime=1488261610.8880907 libinfinity-0.7.1/docs/reference/libinfinity/html/ch06.html0000644000175000017500000000710713055210752024142 0ustar00arminarmin00000000000000 Network abstraction: libinfinity-0.7 Reference Manual

Network abstraction

InfCommunicationManager — Handling multiple communication sessions
InfCommunicationObject — Network message destinations
InfCommunicationGroup — Communication channel for mulitple connections
InfCommunicationHostedGroup — Communication group opened by the local host
InfCommunicationJoinedGroup — Communication group opened by a remote host
InfCommunicationFactory — Creation of communication methods
InfCommunicationMethod — Network communication method
InfCommunicationRegistry — Sharing connections between multiple groups
InfCommunicationCentralFactory — Factory for InfCommunicationCentralMethod methods
InfCommunicationCentralMethod — Relying group messages via the publisher
libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfdFilesystemAccountStorage.html0000644000000000000000000000012413055210752030433 xustar0028 mtime=1488261610.8880907 28 atime=1488261610.8880907 28 ctime=1488261610.8880907 libinfinity-0.7.1/docs/reference/libinfinity/html/InfdFilesystemAccountStorage.html0000644000175000017500000004244013055210752031170 0ustar00arminarmin00000000000000 InfdFilesystemAccountStorage: libinfinity-0.7 Reference Manual

InfdFilesystemAccountStorage

InfdFilesystemAccountStorage — Standalone account storage backend

Stability Level

Unstable, unless otherwise indicated

Properties

Object Hierarchy

    GObject
    ╰── InfdFilesystemAccountStorage

Implemented Interfaces

InfdFilesystemAccountStorage implements InfdAccountStorage.

Includes

#include <libinfinity/server/infd-filesystem-account-storage.h>

Description

This class implements the InfdAccountStorage interface via an underlying InfdFilesystemStorage. It uses the "root-directory" of that underlying storage to store an XML file there which contains the account information.

This is a simple implementation of an account storage which keeps all accounts read from the file in memory. When you have more than a thousand accounts or so you should start thinking of using a more sophisticated account storage, for example a database backend.

Functions

infd_filesystem_account_storage_new ()

InfdFilesystemAccountStorage *
infd_filesystem_account_storage_new (void);

Creates a new InfdFilesystemAccountStorage that stores its account list as a file in the filesystem. Use infd_filesystem_account_storage_set_filesystem() to set the underlying InfdFilesystemStorage object.

[constructor]

Returns

A new InfdFilesystemAccountStorage.

[transfer full]


infd_filesystem_account_storage_set_filesystem ()

gboolean
infd_filesystem_account_storage_set_filesystem
                               (InfdFilesystemAccountStorage *s,
                                InfdFilesystemStorage *fs,
                                GError **error);

Uses fs as the underlying InfdFilesystemStorage for s . The “root-directory†property specifies where the account list is stored.

If an error occurs while loading the account list, the function returns FALSE and error is set.

Parameters

s

A InfdFilesystemAccountStorage.

 

fs

The underlying InfdFilesystemStorage to use.

 

error

Location for error information, if any, or NULL.

 

Returns

TRUE on success or FALSE on error.

Types and Values

struct InfdFilesystemAccountStorage

struct InfdFilesystemAccountStorage;

InfdFilesystemAccountStorage is an opaque data type. You should only access it via the public API functions.


struct InfdFilesystemAccountStorageClass

struct InfdFilesystemAccountStorageClass {
};

This structure does not contain any public fields.


enum InfdFilesystemAccountStorageError

Specifies the possible error codes in the INFD_FILESYSTEM_ACCOUNT_STORAGE_ERROR error domain. Such errors can occur when reading the accounts file from disk.

Members

INFD_FILESYSTEM_ACCOUNT_STORAGE_ERROR_INVALID_FORMAT

An on-disk XML file is not formatted correctly.

 

INFD_FILESYSTEM_ACCOUNT_STORAGE_ERROR_DUPLICATE_NAME

An account name is already in use.

 

INFD_FILESYSTEM_ACCOUNT_STORAGE_ERROR_DUPLICATE_CERTIFICATE

An account which uses the same certificate to login exists already.

 

INFD_FILESYSTEM_ACCOUNT_STORAGE_ERROR_IDS_EXHAUSTED

Could not obtain a unique account ID.

 

INFD_FILESYSTEM_ACCOUNT_STORAGE_ERROR_NO_SUCH_ACCOUNT

The account with the given ID does not exist.

 

Property Details

The “filesystem-storage†property

  “filesystem-storage†      InfdFilesystemStorage *

The filesystem storage which to use the store the accounts file.

Flags: Read / Write

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfdAccountStorage.html0000644000000000000000000000012413055210752026366 xustar0028 mtime=1488261610.8880907 28 atime=1488261610.8880907 28 ctime=1488261610.8880907 libinfinity-0.7.1/docs/reference/libinfinity/html/InfdAccountStorage.html0000644000175000017500000022620613055210752027127 0ustar00arminarmin00000000000000 InfdAccountStorage: libinfinity-0.7 Reference Manual

InfdAccountStorage

InfdAccountStorage — Interface to user account database

Stability Level

Unstable, unless otherwise indicated

Object Hierarchy

    GFlags
    ╰── InfdAccountStorageSupport
    GInterface
    ╰── InfdAccountStorage

Prerequisites

InfdAccountStorage requires GObject.

Known Implementations

InfdAccountStorage is implemented by InfdFilesystemAccountStorage.

Includes

#include <libinfinity/server/infd-account-storage.h>

Description

InfdAccountStorage provides an interface for InfdDirectory to access a database of user accounts. It provides methods to list and lookup available accounts, and to add and remove accounts.

Each account is uniquely identified by an account ID, InfAclAccount.id, and is assigned a human-readable name, InfAclAccount.name. Typically, most operations can be performed with the ID, and for example permissions for users are stored by refering to the account ID in InfdDirectory. The authentication storage can be used to look up a name for the ID, and it is responsible for storing the account information permanantly.

Interface implementations do not need to support every operation provided by the API of this interface, however if they support a certain operation, InfdDirectory takes advantage of it. The only required operation is to be able to look up an account name by its ID, and the reverse lookup, i.e. find all accounts with a given name. The InfdAccountStorageInterface.get_support() function returns a bitmask of the supported operations.

Implementations of this interface can couple the available accounts to various external sources, such as SQL databases, LDAP or PAM. Libinfinity also provides a standalone implementation of this interface, which stores the account list as a file in the file system, see InfdFilesystemAccountStorage.

Functions

infd_account_storage_get_support ()

InfdAccountStorageSupport
infd_account_storage_get_support (InfdAccountStorage *storage);

Returns a bitmask of operations supported by the account storage backend. If unsupported operations are attempted on storage , an error with code INF_DIRECTORY_ERROR_OPERATION_UNSUPPORTED will be generated.

Parameters

storage

A InfdAccountStorage.

 

Returns

A bitmask of supported operations.


infd_account_storage_supports ()

gboolean
infd_account_storage_supports (InfdAccountStorage *storage,
                               InfdAccountStorageSupport support);

Checks whether support for all operations specified in support is available for storage . This is equivalent to calling infd_account_storage_get_support() and testing the returned value for containing the bits in support .

Parameters

storage

A InfdAccountStorage.

 

support

A bitmask of operations to test.

 

Returns

TRUE if all operations in support are supported or FALSE otherwise.


infd_account_storage_lookup_accounts ()

InfAclAccount *
infd_account_storage_lookup_accounts (InfdAccountStorage *storage,
                                      const InfAclAccountId *accounts,
                                      guint n_accounts,
                                      GError **error);

Looks up the InfAclAccount structure for all IDs present in accounts . The return value is an array of InfAclAccount structures which is in the same order as the accounts array. If an element in the output array has the InfAclAccount.id field set to 0, it means that the account with the corresponding ID in the accounts array does not exist in storage .

Parameters

storage

A InfdAccountStorage.

 

accounts

An array of InfAclAccountIds to look up.

[array length=n_accounts]

n_accounts

The number of elements in accounts .

 

error

Location to store error information, if any, or NULL.

 

Returns

An array of InfAclAccount structures with n_accounts entries. Free with inf_acl_account_array_free().

[array length=n_accounts][transfer full]


infd_account_storage_lookup_accounts_by_name ()

InfAclAccount *
infd_account_storage_lookup_accounts_by_name
                               (InfdAccountStorage *storage,
                                const gchar *name,
                                guint *n_accounts,
                                GError **error);

This function performs the "reverse" lookup: Given an account name, the function returns an array with all accounts that have this name. Many backends make sure that there cannot be duplicated names, in which case this can at most return one account, however in principle accounts with the same name are supported.

If there is no account with the given name, the function returns NULL and sets n_accounts to 0. If an error occurs, NULL is returned, n_accounts is undefined, and error is set. Therefore, to reliably find out whether a lookup error occured or this is no account with the given name, a non-NULL error pointer should be passed and checked after the function call.

Parameters

storage

A InfdAccountStorage.

 

name

The name to look up.

 

n_accounts

An output parameter holding the number of returned accounts.

[out]

error

Location to store error information, if any, or NULL.

 

Returns

An array of InfAclAccount structures with length n_accounts , or NULL on error or when n_accounts is 0 or error is set. Free with inf_acl_account_array_free().

[array length=n_accounts][transfer full]


infd_account_storage_list_accounts ()

InfAclAccount *
infd_account_storage_list_accounts (InfdAccountStorage *storage,
                                    guint *n_accounts,
                                    GError **error);

Returns an array of all accounts in storage . The length of the array is stored in the output parameter n_accounts . The functions returns NULL and sets n_accounts to 0 if there are no accounts in storage . If there is an error, the function returns NULL, n_accounts is undefined, and error is set. Therefore, to reliably find out whether an error occurred or whether there are really no accounts present, a non-NULL error pointer should be passed and checked after the function call.

Note that this function might not be supported by the backend. See infd_account_storage_get_support().

Parameters

storage

A InfdAccountStorage.

 

n_accounts

An output parameter holding the number of accounts in storage .

[out]

error

Location to store error information, if any, or NULL.

 

Returns

An array of InfAclAccount structures with length n_accounts , or NULL if n_accounts is 0 or error is set. Free with inf_acl_account_array_free().

[array length=n_accounts][allow-none][transfer full]


infd_account_storage_add_account ()

InfAclAccountId
infd_account_storage_add_account (InfdAccountStorage *storage,
                                  const gchar *name,
                                  gnutls_x509_crt_t *certs,
                                  guint n_certs,
                                  const gchar *password,
                                  GError **error);

Adds a new account to storage . The account will have the given name. The account ID is determined by the storage backend and if the operation is successful it is returned.

If the operation does not support storing certificates and/or passwords, the function will fail if certs or password are not set to NULL, respectively. Note also that this function might not be supported at all by the backend. See infd_account_storage_get_support().

Parameters

storage

A InfdAccountStorage.

 

name

The name of the new account.

 

certs

An array of certificates that can be used to login to the new account, or NULL.

[array length=n_certs][allow-none]

n_certs

The length of the certificate array.

 

password

A password that can be used to login to the new account, or NULL.

[allow-none]

error

Location to store error information, if any, or NULL.

 

Returns

The InfAclAccountId of the added account, or 0 on error.

[transfer full]


infd_account_storage_remove_account ()

gboolean
infd_account_storage_remove_account (InfdAccountStorage *storage,
                                     InfAclAccountId account,
                                     GError **error);

Removes the account with the given ID from storage .

Note that this function might not be supported by the backend. See infd_account_storage_get_support().

Parameters

storage

A InfdAccountStorage.

 

account

The ID of the account to remove.

 

error

Location to store error information, if any, or NULL.

 

Returns

TRUE on success or FALSE on error.


infd_account_storage_login_by_certificate ()

InfAclAccountId
infd_account_storage_login_by_certificate
                               (InfdAccountStorage *storage,
                                gnutls_x509_crt_t cert,
                                GError **error);

This function returns the ID of the account which belongs to the given client certificate. If there is no such account on an error occurs, the function returns 0, and, in the case of an error, error is set as well.

Note that this function might not be supported by the backend. See infd_account_storage_get_support().

Parameters

storage

A InfdAccountStorage.

 

cert

The certificate presented by the client.

 

error

Location to store error information, if any, or NULL.

 

Returns

The account ID of the account associated to cert , or 0 on error or if there is no such account.

[transfer full]


infd_account_storage_login_by_password ()

InfAclAccountId
infd_account_storage_login_by_password
                               (InfdAccountStorage *storage,
                                const gchar *username,
                                const gchar *password,
                                GError **error);

This function returns the account ID which matches to the given username and password. If there is no such account or if the password is incorrect, the function returns 0. If an error occurs, the function returns 0 and error is set.

Note that when the password is incorrect, error is not set. It is only set if there was an internal error and the login procedure could not be carried out due to technical reasons, such as a database outage.

Note that this function might not be supported by the backend. See infd_account_storage_get_support().

Parameters

storage

A InfdAccountStorage.

 

username

The username of the account to log into.

 

password

The password of the corresponding account.

 

error

Location to store error information, if any.

 

Returns

The account ID of the account associated to username if password is correct, or 0 otherwise.

[transfer full]


infd_account_storage_set_certificate ()

gboolean
infd_account_storage_set_certificate (InfdAccountStorage *storage,
                                      InfAclAccountId account,
                                      gnutls_x509_crt_t *certs,
                                      guint n_certs,
                                      GError **error);

Changes the certificate(s) associated to the account with ID account . All certificates that are currently associated to it are removed, and the given certificates are associated instead. If n_certs is 0, there will be no associated certificates and login by certificate will be disabled for account .

Note that this function might not be supported by the backend. See infd_account_storage_get_support().

Parameters

storage

A InfdAccountStorage.

 

account

The ID of the account whose certificate to set.

 

certs

An array of certificates, or NULL if n_certs is 0.

[array length=n_certs][allow-none]

n_certs

The number of certificates in the certificate array.

 

error

Location to store error information, if any.

 

Returns

TRUE if the operation was successful or FALSE if an error occured.


infd_account_storage_set_password ()

gboolean
infd_account_storage_set_password (InfdAccountStorage *storage,
                                   InfAclAccountId account,
                                   const gchar *password,
                                   GError **error);

Changes the password for the account with the given ID. If this call succeeds, the new password will have to be provided to infd_account_storage_login_by_password() for the login to succeed. If password is NULL, the password will be unset and login by password will no longer be possible.

Note that this function might not be supported by the backend. See infd_account_storage_get_support().

Parameters

storage

A InfdAccountStorage.

 

account

The ID of the account whose password to change.

 

password

The new password for the account, or NULL.

 

error

Location to store error information, if any, or NULL.

 

Returns

TRUE on success or FALSE on error.


infd_account_storage_account_added ()

void
infd_account_storage_account_added (InfdAccountStorage *storage,
                                    const InfAclAccount *account);

Emits the “account-added†signal on storage . This should only be used by interface implementations.

Parameters

storage

A InfdAccountStorage.

 

account

The InfAclAccount that was added to the storage.

 

infd_account_storage_account_removed ()

void
infd_account_storage_account_removed (InfdAccountStorage *storage,
                                      const InfAclAccount *account);

Emits the “account-removed†signal on storage . This should only be used by interface implementations.

Parameters

storage

A InfdAccountStorage.

 

account

The InfAclAccount with the account information for the removed account.

 

Types and Values

InfdAccountStorage

typedef struct _InfdAccountStorage InfdAccountStorage;

InfdAccountStorage is an opaque data type. You should only access it via the public API functions.


struct InfdAccountStorageInterface

struct InfdAccountStorageInterface {
  InfdAccountStorageSupport (*get_support)(InfdAccountStorage* storage);

  InfAclAccount* (*lookup_accounts)(InfdAccountStorage* storage,
                                    const InfAclAccountId* accounts,
                                    guint n_accounts,
                                    GError** error);

  InfAclAccount* (*lookup_accounts_by_name)(InfdAccountStorage* storage,
                                            const gchar* name,
                                            guint* n_accounts,
                                            GError** error);

  InfAclAccount* (*list_accounts)(InfdAccountStorage* storage,
                                  guint* n_accounts,
                                  GError** error);

  InfAclAccountId (*add_account)(InfdAccountStorage* storage,
                                 const gchar* name,
                                 gnutls_x509_crt_t* certs,
                                 guint n_certs,
                                 const gchar* password,
                                 GError** error);

  gboolean (*remove_account)(InfdAccountStorage* storage,
                             InfAclAccountId account,
                             GError** error);

  InfAclAccountId (*login_by_certificate)(InfdAccountStorage* storage,
                                          gnutls_x509_crt_t cert,
                                          GError** error);

  InfAclAccountId (*login_by_password)(InfdAccountStorage* storage,
                                       const gchar* username,
                                       const gchar* password,
                                       GError** error);

  gboolean (*set_certificate)(InfdAccountStorage* storage,
                              InfAclAccountId account,
                              gnutls_x509_crt_t* certs,
                              guint n_certs,
                              GError** error);

  gboolean (*set_password)(InfdAccountStorage* storage,
                           InfAclAccountId account,
                           const gchar* password,
                           GError** error);

  /* Signals */
  void (*account_added)(InfdAccountStorage* storage,
                        const InfAclAccount* account);

  void (*account_removed)(InfdAccountStorage* storage,
                          const InfAclAccount* account);
};

The virtual methods and default signal handlers of InfdAccountStorage. Implementing these allows an infinote server to set a specific source of user accounts.

Members

get_support ()

Virtual function to get the list of supported operations on the backend.

 

lookup_accounts ()

Virtual function to look up account by their identifier.

 

lookup_accounts_by_name ()

Virtual function to reverse-lookup an account identifier when given the account name.

 

list_accounts ()

Virtual function to obtain a list of all available accounts. Can be NULL if not supported by the backend.

 

add_account ()

Virtual function to add a new account. Can be NULL if not supported by the backend.

 

remove_account ()

Virtual function to remove an existing account. Can be NULL if not supported by the backend.

 

login_by_certificate ()

Virtual function to look up the account associated with a given certificate. Can be NULL if not supported by the backend.

 

login_by_password ()

Virtual function to check a username and password, and return the associated account. Can be NULL if not supported by the backend.

 

set_certificate ()

Set the certificate to be associated to a given account, or NULL if not supported.

 

set_password ()

Set the password for a given account, or NULL if not supported.

 

account_added ()

Default signal handler for the “account-added†signal.

 

account_removed ()

Default signal handler for the “account-removed†signal.

 

enum InfdAccountStorageSupport

This enumeration specifies operations that might or might not be supported by a particular InfdAccountStorage implementation. Looking up an account by ID or name must always be supported.

Members

INFD_ACCOUNT_STORAGE_SUPPORT_NOTIFICATION

Whether the “account-added†and “account-removed†signals are emitted when accounts are added or removed externally.

 

INFD_ACCOUNT_STORAGE_SUPPORT_LIST_ACCOUNTS

Whether obtaining a full list of available accounts is supported.

 

INFD_ACCOUNT_STORAGE_SUPPORT_ADD_ACCOUNT

Whether adding a new account to the storage is supported.

 

INFD_ACCOUNT_STORAGE_SUPPORT_REMOVE_ACCOUNT

Whether removing an existing account from the storage is supported.

 

INFD_ACCOUNT_STORAGE_SUPPORT_CERTIFICATE_LOGIN

Whether the account storage supports authenticating users via client certificates.

 

INFD_ACCOUNT_STORAGE_SUPPORT_PASSWORD_LOGIN

Whether the account storage supports authenticating users via username and password.

 

INFD_ACCOUNT_STORAGE_SUPPORT_CERTIFICATE_CHANGE

Whether the account storage supports changing the certificate associated to a user.

 

INFD_ACCOUNT_STORAGE_SUPPORT_PASSWORD_CHANGE

Whether the account storage supports changing a user's password.

 

Signal Details

The “account-added†signal

void
user_function (InfdAccountStorage *storage,
               InfAclAccount      *info,
               gpointer            user_data)

This signal is emitted whenever an account has been added to the account storage. However, the signal is only emitted if the storage implementations supports the INFD_ACCOUNT_STORAGE_SUPPORT_NOTIFICATION support flag.

Parameters

storage

The InfdAccountStorage emitting the signal.

 

info

The InfAclAccount containing the account ID and account name of the added account.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last


The “account-removed†signal

void
user_function (InfdAccountStorage *storage,
               InfAclAccount      *info,
               gpointer            user_data)

This signal is emitted whenever an account has been permanently removed from the storage. However, the signal is only emitted if the storage implementations supports the INFD_ACCOUNT_STORAGE_SUPPORT_NOTIFICATION support flag.

Parameters

storage

The InfdAccountStorage emitting the signal.

 

info

The InfAclAccount containing the account ID and account name of the removed account.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfdXmlServer.html0000644000000000000000000000012413055210752025374 xustar0028 mtime=1488261610.8880907 28 atime=1488261610.8880907 28 ctime=1488261610.8880907 libinfinity-0.7.1/docs/reference/libinfinity/html/InfdXmlServer.html0000644000175000017500000003303213055210752026126 0ustar00arminarmin00000000000000 InfdXmlServer: libinfinity-0.7 Reference Manual

InfdXmlServer

InfdXmlServer

Functions

Properties

Signals

Types and Values

Object Hierarchy

    GEnum
    ╰── InfdXmlServerStatus
    GInterface
    ╰── InfdXmlServer

Prerequisites

InfdXmlServer requires GObject.

Known Implementations

InfdXmlServer is implemented by InfdXmppServer.

Description

Functions

infd_xml_server_close ()

void
infd_xml_server_close (InfdXmlServer *server);

Closes server .

Parameters

server

A InfdXmlServer.

 

infd_xml_server_new_connection ()

void
infd_xml_server_new_connection (InfdXmlServer *server,
                                InfXmlConnection *connection);

Emits the "new-connection" signal on server .

Parameters

server

A InfdXmlServer.

 

connection

A InfXmlConnection.

 

Types and Values

InfdXmlServer

typedef struct _InfdXmlServer InfdXmlServer;


struct InfdXmlServerInterface

struct InfdXmlServerInterface {
  GTypeInterface parent;

  /* Virtual Table */
  void (*close)(InfdXmlServer* server);

  /* Signals */
  void (*new_connection)(InfdXmlServer* server,
                         InfXmlConnection* connection);
};


enum InfdXmlServerStatus

Members

INFD_XML_SERVER_CLOSED

   

INFD_XML_SERVER_CLOSING

   

INFD_XML_SERVER_OPEN

   

INFD_XML_SERVER_OPENING

   

Property Details

The “status†property

  “status†                  InfdXmlServerStatus

The status of the server.

Flags: Read

Default value: INFD_XML_SERVER_CLOSED

Signal Details

The “new-connection†signal

void
user_function (InfdXmlServer    *infdxmlserver,
               InfXmlConnection *arg1,
               gpointer          user_data)

Parameters

infdxmlserver

the object which received the signal.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfBrowser.html0000644000000000000000000000013213055210752024723 xustar0030 mtime=1488261610.892090691 30 atime=1488261610.892090691 30 ctime=1488261610.892090691 libinfinity-0.7.1/docs/reference/libinfinity/html/InfBrowser.html0000644000175000017500000064631013055210752025467 0ustar00arminarmin00000000000000 InfBrowser: libinfinity-0.7 Reference Manual

InfBrowser

InfBrowser — Browsing of infinote directories

Stability Level

Unstable, unless otherwise indicated

Functions

gboolean inf_browser_get_root ()
gboolean inf_browser_get_next ()
gboolean inf_browser_get_prev ()
gboolean inf_browser_get_parent ()
gboolean inf_browser_get_child ()
gboolean inf_browser_is_ancestor ()
InfRequest * inf_browser_explore ()
gboolean inf_browser_get_explored ()
gboolean inf_browser_is_subdirectory ()
InfRequest * inf_browser_add_note ()
InfRequest * inf_browser_add_subdirectory ()
InfRequest * inf_browser_remove_node ()
const gchar * inf_browser_get_node_name ()
const gchar * inf_browser_get_node_type ()
gchar * inf_browser_get_path ()
InfRequest * inf_browser_subscribe ()
InfSessionProxy * inf_browser_get_session ()
GSList * inf_browser_list_pending_requests ()
gboolean inf_browser_iter_from_request ()
InfRequest * inf_browser_get_pending_request ()
const InfAclAccount * inf_browser_get_acl_default_account ()
const InfAclAccount * inf_browser_get_acl_local_account ()
InfRequest * inf_browser_query_acl_account_list ()
InfRequest * inf_browser_lookup_acl_accounts ()
InfRequest * inf_browser_lookup_acl_account_by_name ()
InfRequest * inf_browser_create_acl_account ()
InfRequest * inf_browser_remove_acl_account ()
InfRequest * inf_browser_query_acl ()
gboolean inf_browser_has_acl ()
const InfAclSheetSet * inf_browser_get_acl ()
InfRequest * inf_browser_set_acl ()
gboolean inf_browser_check_acl ()
void inf_browser_error ()
void inf_browser_node_added ()
void inf_browser_node_removed ()
void inf_browser_subscribe_session ()
void inf_browser_unsubscribe_session ()
void inf_browser_begin_request ()
void inf_browser_acl_account_added ()
void inf_browser_acl_account_removed ()
void inf_browser_acl_local_account_changed ()
void inf_browser_acl_changed ()

Properties

Types and Values

Object Hierarchy

    GEnum
    ╰── InfBrowserStatus
    GInterface
    ╰── InfBrowser

Prerequisites

InfBrowser requires GObject.

Known Implementations

InfBrowser is implemented by InfcBrowser and InfdDirectory.

Includes

#include <libinfinity/common/inf-browser.h>

Description

InfBrowser provides an interface for browsing an infinote directory. It can be used to navigate through the tree, add or remove nodes and subscribe to sessions.

Nodes in a directory can either contain more nodes in which case this is called a subdirectory. Leaf nodes are also called notes. There is only one root node which must be a subdirectory node.

Functions

inf_browser_get_root ()

gboolean
inf_browser_get_root (InfBrowser *browser,
                      InfBrowserIter *iter);

Sets iter to point to the root node of browser .

Parameters

browser

A InfBrowser.

 

iter

An uninitialized InfBrowserIter.

[out]

Returns

TRUE if iter was set or FALSE if there is no root node, i.e. the browser is not open.


inf_browser_get_next ()

gboolean
inf_browser_get_next (InfBrowser *browser,
                      InfBrowserIter *iter);

Sets iter to point to its next sibling node. If iter points already to the last node then iter is left untouched and the function returns FALSE.

Parameters

browser

A InfBrowser.

 

iter

A InfBrowserIter pointing to a node inside browser .

[inout]

Returns

TRUE if iter was moved or FALSE otherwise.


inf_browser_get_prev ()

gboolean
inf_browser_get_prev (InfBrowser *browser,
                      InfBrowserIter *iter);

Sets iter to point to its previous sibling node. If iter points to the first node already then iter is left untouched and the function returns FALSE.

Parameters

browser

A InfBrowser.

 

iter

A InfBrowserIter pointing to a node inside browser .

[inout]

Returns

TRUE if iter was moved or FALSE otherwise.


inf_browser_get_parent ()

gboolean
inf_browser_get_parent (InfBrowser *browser,
                        InfBrowserIter *iter);

Sets iter to point to its parent node. If iter is already the root node then iter is left untouched and the function returns FALSE.

Parameters

browser

A InfBrowser.

 

iter

A InfBrowserIter pointing to a node inside browser .

[inout]

Returns

TRUE if iter was moved or FALSE otherwise.


inf_browser_get_child ()

gboolean
inf_browser_get_child (InfBrowser *browser,
                       InfBrowserIter *iter);

Sets iter to point to the first child of the subdirectory node it currently points to. If the subdirectory does not contain any children or if iter does not point to a subdirectory the function returns FALSE. This does not necessarily mean that there do not exist any children but it can also be that they have not yet been explored. Nodes can be explored with inf_browser_explore() and it can be checked whether a given node has been explored with inf_browser_get_explored().

Parameters

browser

A InfBrowser.

 

iter

A InfBrowserIter pointing to a subdirectory node inside browser .

[inout]

Returns

TRUE if iter was moved or FALSE otherwise.


inf_browser_is_ancestor ()

gboolean
inf_browser_is_ancestor (InfBrowser *browser,
                         const InfBrowserIter *ancestor,
                         const InfBrowserIter *iter);

Returns whether ancestor is an ancestor of iter , i.e. either the two iterators point to the same node or ancestor is a parent, grand-parent, grand-grand-parent, etc. of the node iter points to.

Parameters

browser

A InfBrowser.

 

ancestor

An iterator pointing to the ancestor node.

 

iter

An iterator pointing to the node to be checked.

 

Returns

Whether ancestor is an ancestor of iter .


inf_browser_explore ()

InfRequest *
inf_browser_explore (InfBrowser *browser,
                     const InfBrowserIter *iter,
                     InfRequestFunc func,
                     gpointer user_data);

Requests the node iter points to to be explored. Initally, subdirectory nodes are not explored, that is not known what content there is. Nodes can be explored to learn about the children nodes they contain. Since exploring is a potentially lengthy process involing networking or I/O with slow devices this function returns a InfExploreRequest which can be used to monitor the progress of the operation and get notified when the exploration finishes. During exploration “node-added†signals are already emitted appropriately for every child explored inside iter .

The request might either finish during the call to this function, in which case func will be called and NULL being returned. If the request does not finish within the function call, a InfRequest object is returned, where func has been installed for the “finished†signal, so that it is called as soon as the request finishes.

Parameters

browser

A InfBrowser.

 

iter

A InfBrowserIter pointing to a subdirectory node inside browser .

 

func

The function to be called when the request finishes, or NULL.

[scope async]

user_data

Additional data to pass to func .

 

Returns

A InfRequest, or NULL if iter points to a non-subdirectory node.

[transfer none][allow-none]


inf_browser_get_explored ()

gboolean
inf_browser_get_explored (InfBrowser *browser,
                          const InfBrowserIter *iter);

Returns whether the node iter points to has already been explored or not.

Parameters

browser

A InfBrowser.

 

iter

A InfBrowserIter pointing to a subdirectory node inside browser .

 

Returns

TRUE if the node iter points to has been explored or FALSE otherwise.


inf_browser_is_subdirectory ()

gboolean
inf_browser_is_subdirectory (InfBrowser *browser,
                             const InfBrowserIter *iter);

Returns whether the node iter points to is a subdirectory node.

Parameters

browser

A InfBrowser.

 

iter

A InfBrowserIter pointing to a node inside browser .

 

Returns

TRUE if the node iter points to is a subdirectory node or FALSE otherwise.


inf_browser_add_note ()

InfRequest *
inf_browser_add_note (InfBrowser *browser,
                      const InfBrowserIter *iter,
                      const char *name,
                      const char *type,
                      const InfAclSheetSet *acl,
                      InfSession *session,
                      gboolean initial_subscribe,
                      InfRequestFunc func,
                      gpointer user_data);

Adds a new leaf node to the browser. The new node is of type type . If session is non-NULL it will be used as the initial content of the new node, otherwise the new node will start empty. In the case of non-NULL session the session must be in status INF_SESSION_RUNNING.

The returned request finishes as soon as the creation of the node is acknowledged. It is however not guaranteed that the content of the note has been synchronized yet. In the case of a client connected to an infinote server the content is usually not transmitted when the request finishes. If an error in the process of transmission happens then the node will be removed again.

On the client side, the progress of synchronization to the server after the request has finished can be monitored with the InfSession::synchronization-failed, InfSession::synchronization-complete and InfSession::synchronization-progress signals. Note that a single session might be synchronized to multiple servers at the same time, you will have to check the connection parameter in the signal hander to find out to which server the session is synchronized.

You can safely unref session after having called this function. If the request or the synchronization fails, the session will be discarded in that case. When the returned request finishes, you can use infc_browser_iter_get_sync_in() to get the session again.

If initial_subscribe is set, then, when the returned request finishes, you might call inf_browser_get_session() on the resulting InfBrowserIter. However, that function is not guaranteed to return non-NULL in this case since the node might have been created, but the subscription could have failed.

The initial ACL for the new node is given by acl . If this parameter is NULL, then the default ACL is used, which inherits all permissions from the parent node. In order to apply non-NULL ACL to the new node, the INF_ACL_CAN_SET_ACL permission must be granted to the local entity for the node iter points to.

The request might either finish during the call to this function, in which case func will be called and NULL being returned. If the request does not finish within the function call, a InfRequest object is returned, where func has been installed for the “finished†signal, so that it is called as soon as the request finishes.

Parameters

browser

A InfBrowser.

 

iter

A InfBrowserIter pointing to a subdirectory node inside browser .

 

name

The name of the node to add.

 

type

The type of the node to add.

 

acl

A InfAclSheetSet representing the initial ACL for this node, or NULL.

[allow-none]

session

A InfSession with a session of type type , or NULL.

[allow-none]

initial_subscribe

Whether to subscribe to the newly created session.

 

func

The function to be called when the request finishes, or NULL.

[scope async]

user_data

Additional data to pass to func .

 

Returns

A InfRequest which can be used to get notified when the request finishes.

[transfer none][allow-none]


inf_browser_add_subdirectory ()

InfRequest *
inf_browser_add_subdirectory (InfBrowser *browser,
                              const InfBrowserIter *iter,
                              const char *name,
                              const InfAclSheetSet *acl,
                              InfRequestFunc func,
                              gpointer user_data);

Adds a new subdirectory node to the browser.

The initial ACL for the new node is given by acl . If this parameter is NULL, then the default ACL is used, which inherits all permissions from the parent node. In order to apply non-NULL ACL to the new node, the INF_ACL_CAN_SET_ACL permission must be granted to the local entity for the node iter points to.

The request might either finish during the call to this function, in which case func will be called and NULL being returned. If the request does not finish within the function call, a InfRequest object is returned, where func has been installed for the “finished†signal, so that it is called as soon as the request finishes.

Parameters

browser

A InfBrowser.

 

iter

A InfBrowserIter pointing to a subdirectory node inside browser .

 

name

The name of the node to add.

 

acl

A InfAclSheetSet representing the initial ACL for this node, or NULL.

[allow-none]

func

The function to be called when the request finishes, or NULL.

[scope async]

user_data

Additional data to pass to func .

 

Returns

A InfRequest which can be used to get notified when the request finishes.

[transfer none][allow-none]


inf_browser_remove_node ()

InfRequest *
inf_browser_remove_node (InfBrowser *browser,
                         const InfBrowserIter *iter,
                         InfRequestFunc func,
                         gpointer user_data);

Requests to remove the node iter points to. It may point to a subdirectory node in which case all its children are removed recursively as well.

The request might either finish during the call to this function, in which case func will be called and NULL being returned. If the request does not finish within the function call, a InfRequest object is returned, where func has been installed for the “finished†signal, so that it is called as soon as the request finishes.

Parameters

browser

A InfBrowser.

 

iter

A InfBrowserIter pointing to a node inside browser .

 

func

The function to be called when the request finishes, or NULL.

[scope async]

user_data

Additional data to pass to func .

 

Returns

A InfRequest which can be used to get notified when the request finishes.

[transfer none][allow-none]


inf_browser_get_node_name ()

const gchar *
inf_browser_get_node_name (InfBrowser *browser,
                           const InfBrowserIter *iter);

Returns the name of the node iter points to.

Parameters

browser

A InfBrowser.

 

iter

A InfBrowserIter pointing to a node inside browser .

 

Returns

A string containing the node's name.


inf_browser_get_node_type ()

const gchar *
inf_browser_get_node_type (InfBrowser *browser,
                           const InfBrowserIter *iter);

Returns the type of the node iter points to.

Parameters

browser

A InfBrowser.

 

iter

A InfBrowserIter pointing to a leaf node inside browser .

 

Returns

The node type as a string.


inf_browser_get_path ()

gchar *
inf_browser_get_path (InfBrowser *browser,
                      const InfBrowserIter *iter);

Returns the full path to the node iter points to. A path always starts with a '/' and then has the name of the node and all its parents separated by '/', much like a filesystem path on Unix.

Parameters

browser

A InfBrowser.

 

iter

A InfBrowserIter pointing to a node inside browser .

 

Returns

The path as a string. Free with g_free() when no longer needed.

[transfer full]


inf_browser_subscribe ()

InfRequest *
inf_browser_subscribe (InfBrowser *browser,
                       const InfBrowserIter *iter,
                       InfRequestFunc func,
                       gpointer user_data);

Attempts to subscribe to the node iter points to, i.e. obtain a InfSession representing its content. This also allows to change the content of the node.

The request might either finish during the call to this function, in which case func will be called and NULL being returned. If the request does not finish within the function call, a InfRequest object is returned, where func has been installed for the “finished†signal, so that it is called as soon as the request finishes.

Parameters

browser

A InfBrowser.

 

iter

A InfBrowserIter pointing to a leaf node inside browser .

 

func

The function to be called when the request finishes, or NULL.

[scope async]

user_data

Additional data to pass to func .

 

Returns

A InfRequest which can be used to get notified when the request finishes.

[transfer none][allow-none]


inf_browser_get_session ()

InfSessionProxy *
inf_browser_get_session (InfBrowser *browser,
                         const InfBrowserIter *iter);

Returns the session which has the content of the node iter points to. The session needs to be subscribed to, see inf_browser_subscribe(). If the session is not subscribed or the subscription request has not yet finished the function returns NULL.

Parameters

browser

A InfBrowser.

 

iter

A InfBrowserIter pointing to a leaf node inside browser .

 

Returns

A InfSessionProxy which contains the session. The proxy object can be used to join a user into the session.

[transfer none][allow-none]


inf_browser_list_pending_requests ()

GSList *
inf_browser_list_pending_requests (InfBrowser *browser,
                                   const InfBrowserIter *iter,
                                   const gchar *request_type);

Returns a list of all pending requests for the node iter points to which match type request_type . A pending request is a request which has been created but has not yet finished. request_type can be NULL in which case all requests for the given node are returned. If it is non-NULL only requests which match the given type are included in the list of returned requests.

If iter is NULL then the function returns all pending global requests.

Parameters

browser

A InfBrowser.

 

iter

A InfBrowserIter pointing to a node inside browser , or NULL.

[allow-none]

request_type

The type of request to return pending requests for, or NULL.

[allow-none]

Returns

A list of InfRequests. Free with g_slist_free() when no longer needed.

[transfer container][element-type InfRequest]


inf_browser_iter_from_request ()

gboolean
inf_browser_iter_from_request (InfBrowser *browser,
                               InfRequest *request,
                               InfBrowserIter *iter);

Sets iter to the node for which request was made. If that node does not exist anymore or if request has already finished the function returns FALSE and iter is left untouched.

Parameters

browser

A InfBrowser.

 

request

A InfRequest which has not yet finished and which was issued by browser .

 

iter

An uninitialized InfBrowserIter.

[out]

Returns

TRUE if iter was moved or FALSE otherwise.


inf_browser_get_pending_request ()

InfRequest *
inf_browser_get_pending_request (InfBrowser *browser,
                                 const InfBrowserIter *iter,
                                 const gchar *request_type);

Returns a pending request for the node iter points to which matches type request_type . If there is no such request the function returns NULL. This function is a shortcut for calling inf_browser_list_pending_requests() and retrieving the first item from the list.

If iter is NULL the function returns a global request.

For many request types, such as "subscribe-session", "subscribe-chat", "explore-node", "query-user-list" or "query-acl" there can only be one request at a time, and therefore this function is more convenient to use than inf_browser_list_pending_requests().

Parameters

browser

A InfBrowser.

 

iter

A InfBrowserIter pointing to a node inside browser , or NULL.

[allow-none]

request_type

The type of request.

[allow-none]

Returns

A InfRequest, or NULL.

[allow-none][transfer none]


inf_browser_get_acl_default_account ()

const InfAclAccount *
inf_browser_get_acl_default_account (InfBrowser *browser);

Returns the default InfAclAccount representing unauthenticated users, and which is used to look up permissions if no permissions are explicitly specified in the ACL of a particular node for a particular account.

Parameters

browser

A InfBrowser.

 

Returns

A InfAclAccount. The returned value is owned by the browser and must not be freed.

[transfer none]


inf_browser_get_acl_local_account ()

const InfAclAccount *
inf_browser_get_acl_local_account (InfBrowser *browser);

Returns the InfAclAccount representing the local host. This can be used to check whether the local account is allowed to perform certain operations in the browser. The function can also return NULL, in which case all operations are allowed, because the browser represents a local infinote directory.

Parameters

browser

A InfBrowser.

 

Returns

A InfAclAccount, or NULL. The returned value is owned by the browser and must not be freed.

[transfer none][allow-none]


inf_browser_query_acl_account_list ()

InfRequest *
inf_browser_query_acl_account_list (InfBrowser *browser,
                                    InfRequestFunc func,
                                    gpointer user_data);

Queries the list of accounts in browser . When this call has finished, a list of accounts is available, and also a flag whether the browser supports notification of accounts. If it does, then the “acl-account-added†and “acl-account-removed†signals are emitted when the account list changes, and the next time this function is called, it might be available to serve the account list from the cache without blocking.

It can also be that the browser does not support listing of accounts at all. In this case, the request will fail with an error code of INF_DIRECTORY_ERROR_OPERATION_UNSUPPORTED.

The request might either finish during the call to this function, in which case func will be called and NULL being returned. If the request does not finish within the function call, a InfRequest object is returned, where func has been installed for the “finished†signal, so that it is called as soon as the request finishes.

Parameters

browser

A InfBrowser.

 

func

The function to be called when the request finishes, or NULL.

[scope async]

user_data

Additional data to pass to func .

 

Returns

A InfRequest that can be used to be notified when the request finishes, or NULL.

[transfer none][allow-none]


inf_browser_lookup_acl_accounts ()

InfRequest *
inf_browser_lookup_acl_accounts (InfBrowser *browser,
                                 const InfAclAccountId *ids,
                                 guint n_ids,
                                 InfRequestFunc func,
                                 gpointer user_data);

Looks up the accounts with the given IDs. If the account list has been queried with inf_browser_query_acl_account_list() before, then it is likely that this function returns instantly, otherwise an asynchronous operation might be started.

The request result contains an array of InfAclAccount objects for the given account IDs, which contain the account names as well. If one account ID does not belong to an actual account, the InfAclAccount.name field will be NULL.

The request might either finish during the call to this function, in which case func will be called and NULL being returned. If the request does not finish within the function call, a InfRequest object is returned, where func has been installed for the “finished†signal, so that it is called as soon as the request finishes.

Parameters

browser

A InfBrowser.

 

ids

An array of account IDs to look up.

[array length=n_ids]

n_ids

The number of elements in the array.

 

func

The function to be called when the request finishes, or NULL.

[scope async]

user_data

Additional data to pass to func .

 

Returns

A InfRequest that can be used to be notified when the request finishes, or NULL.

[transfer none][allow-none]


inf_browser_lookup_acl_account_by_name ()

InfRequest *
inf_browser_lookup_acl_account_by_name
                               (InfBrowser *browser,
                                const gchar *name,
                                InfRequestFunc func,
                                gpointer user_data);

Looks up the account(s) with the given name. While in principal, there can be many accounts with the same name, in practise user names are often unique.

The request result contains an array of InfAclAccount objects, all with the same name. If there is only one entry with ID set to 0, there are no accounts with the given name.

The request might either finish during the call to this function, in which case func will be called and NULL being returned. If the request does not finish within the function call, a InfRequest object is returned, where func has been installed for the “finished†signal, so that it is called as soon as the request finishes.

Parameters

browser

A InfBrowser.

 

name

The name of the user account to look up.

 

func

The function to be called when the request finishes, or NULL.

[scope async]

user_data

Additional data to pass to func .

 

Returns

A InfRequest that can be used to be notified when the request finishes, or NULL.

[allow-none][transfer none]


inf_browser_create_acl_account ()

InfRequest *
inf_browser_create_acl_account (InfBrowser *browser,
                                gnutls_x509_crq_t crq,
                                InfRequestFunc func,
                                gpointer user_data);

Requests creation of a new account. If the request succeeds, crq will be used by the server to create a certificate which is sent back to the client and is associated to the newly created account.

The request might either finish during the call to this function, in which case func will be called and NULL being returned. If the request does not finish within the function call, a InfRequest object is returned, where func has been installed for the “finished†signal, so that it is called as soon as the request finishes.

Parameters

browser

A InfBrowser.

 

crq

A certificate request.

 

func

The function to be called when the request finishes, or NULL.

[scope async]

user_data

Additional data to pass to func .

 

Returns

A InfRequest that can be used to get notified when the request finishes or fails.

[transfer none][allow-none]


inf_browser_remove_acl_account ()

InfRequest *
inf_browser_remove_acl_account (InfBrowser *browser,
                                InfAclAccountId account,
                                InfRequestFunc func,
                                gpointer user_data);

Requests deletion of the given account.

The request might either finish during the call to this function, in which case func will be called and NULL being returned. If the request does not finish within the function call, a InfRequest object is returned, where func has been installed for the “finished†signal, so that it is called as soon as the request finishes.

Parameters

browser

A InfBrowser.

 

account

The ID of the account to remove.

 

func

The function to be called when the request finishes, or NULL.

[scope async]

user_data

Additional data to pass to func .

 

Returns

A InfRequest that can be used to get notified when the request finishes or fails.

[transfer none][allow-none]


inf_browser_query_acl ()

InfRequest *
inf_browser_query_acl (InfBrowser *browser,
                       const InfBrowserIter *iter,
                       InfRequestFunc func,
                       gpointer user_data);

Queries the ACLs for all users of the node iter points to. When the request has finished, inf_browser_get_acl() can be used to retrieve the ACLs.

The request might either finish during the call to this function, in which case func will be called and NULL being returned. If the request does not finish within the function call, a InfRequest object is returned, where func has been installed for the “finished†signal, so that it is called as soon as the request finishes.

Parameters

browser

A InfBrowser.

 

iter

An iterator pointing to a node for which to query the ACLs.

 

func

The function to be called when the request finishes, or NULL.

[scope async]

user_data

Additional data to pass to func .

 

Returns

A InfRequest which can be used to be notified when the request finishes.

[transfer none][allow-none]


inf_browser_has_acl ()

gboolean
inf_browser_has_acl (InfBrowser *browser,
                     const InfBrowserIter *iter,
                     InfAclAccountId account);

This function returns whether the ACL sheet for the given account is available or not. If the function returns FALSE then inf_browser_query_acl() can be called in order to retrieve the full ACL. If account is 0, the function checks whether the full ACL is available, i.e. the ACL sheets for all accounts. Usually the ACL sheets for the default account and the local account are always available.

Parameters

browser

A InfBrowser.

 

iter

An iterator pointing to a node for which to check full ACL availability.

 

account

The account to check ACL availability for, or 0.

 

Returns

TRUE when the ACL sheet for account is available or FALSE otherwise.


inf_browser_get_acl ()

const InfAclSheetSet *
inf_browser_get_acl (InfBrowser *browser,
                     const InfBrowserIter *iter);

Retrieves the ACL for the node iter points to. This function can also be called if the ACL has not been queried before using inf_browser_query_acl(). In that case, the returned sheet set will only contain sheets for the default user and the local user. The function can return NULL which is equivalent to an empty sheet set, i.e. no ACL.

When the full ACL has been successfully queried with inf_browser_query_acl(), the full ACL is returned by this function. The function inf_browser_has_acl() can be used to check whether this function will return the full ACL or only the sheets for the default and local users.

Parameters

browser

A InfBrowser.

 

iter

An iterator pointing to a node for which to retrieve ACLs.

 

Returns

A InfAclSheetSet containing the requested ACL, or NULL. The returned value is owned by the InfBrowser and should not be freed.


inf_browser_set_acl ()

InfRequest *
inf_browser_set_acl (InfBrowser *browser,
                     const InfBrowserIter *iter,
                     const InfAclSheetSet *sheet_set,
                     InfRequestFunc func,
                     gpointer user_data);

Changes the ACLs for the node iter points to. Existing sheets that are not in sheet_set are left untouched. This operation is only allowed when the ACL for the node iter points to has been retrieved already with inf_browser_query_acl(). Use inf_browser_has_acl() to check whether this function can be called or whether the ACL needs to be queried first.

The request might either finish during the call to this function, in which case func will be called and NULL being returned. If the request does not finish within the function call, a InfRequest object is returned, where func has been installed for the “finished†signal, so that it is called as soon as the request finishes.

Parameters

browser

A InfBrowser.

 

iter

An iterator pointing to the node for which to change ACLs.

 

sheet_set

An InfAclSheetSet with the sheets to update.

 

func

The function to be called when the request finishes, or NULL.

[scope async]

user_data

Additional data to pass to func .

 

Returns

A InfRequest which can be used to be notified when the request finishes.

[transfer none][allow-none]


inf_browser_check_acl ()

gboolean
inf_browser_check_acl (InfBrowser *browser,
                       const InfBrowserIter *iter,
                       InfAclAccountId account,
                       const InfAclMask *check_mask,
                       InfAclMask *out_mask);

Checks whether the given account has permissions to perform the operations specified by mask on the node iter points to. The mask parameter should have all permissions enabled that are to be checked. The function will then write those permissions that are actually granted to the mask specified by the out_mask parameter.

The function returns TRUE if all permissions asked for are granted, i.e. when *out_mask equals *mask after the function call. The out_mask parameter is allowed to be NULL which is useful if only the return value is of interest.

In order for this function to work, the ACL sheet for account has to be available for the node iter points to and all of its parent nodes. If account is not the default or the local account, these need to be queried before using inf_browser_query_acl().

If account is 0, it is assumed that local access to the directory is available and the function always returns TRUE.

Parameters

browser

A InfBrowser.

 

iter

A InfBrowserIter pointing to a node in a browser.

 

account

The ID of the account whose permission to check, or NULL.

 

check_mask

A bitmask of InfAclSettings with permissions to check.

 

out_mask

Output parameter with the granted permissions, or NULL.

[out]

Returns

TRUE if all checked permissions are granted, or FALSE otherwise.


inf_browser_error ()

void
inf_browser_error (InfBrowser *browser,
                   const GError *error);

This function emits the “error†signal on browser . It is meant to be used by interface implementations only.

Parameters

browser

A InfBrowser.

 

error

A GError explaining what went wronig.

 

inf_browser_node_added ()

void
inf_browser_node_added (InfBrowser *browser,
                        const InfBrowserIter *iter,
                        InfRequest *request);

This function emits the “node-added†signal on browser . It is meant to be used by interface implementations only.

Parameters

browser

A InfBrowser.

 

iter

A InfBrowserIter pointing to the newly added node.

 

request

The InfRequest that was used to add or explore the node, or NULL.

 

inf_browser_node_removed ()

void
inf_browser_node_removed (InfBrowser *browser,
                          const InfBrowserIter *iter,
                          InfRequest *request);

This function emits the “node-removed†signal on browser . It is meant to be used by interface implementations only.

Parameters

browser

A InfBrowser.

 

iter

A InfBrowserIter pointing to the node to be removed.

 

request

The InfRequest that was used to delete the node, or NULL.

 

inf_browser_subscribe_session ()

void
inf_browser_subscribe_session (InfBrowser *browser,
                               const InfBrowserIter *iter,
                               InfSessionProxy *proxy,
                               InfRequest *request);

This function emits the “subscribe-session†signal on browser . It is meant to be used by interface implementations only.

Parameters

browser

A InfBrowser.

 

iter

A InfBrowserIter pointing to the node to whose session a subscription was made, or NULL.

 

proxy

A session proxy for the newly subscribed session.

 

request

The InfRequest that was used to initiate the subscription, or NULL.

 

inf_browser_unsubscribe_session ()

void
inf_browser_unsubscribe_session (InfBrowser *browser,
                                 const InfBrowserIter *iter,
                                 InfSessionProxy *proxy,
                                 InfRequest *request);

This function emits the “unsubscribe-session†signal on browser . It is meant to be used by interface implementations only.

Parameters

browser

A InfBrowser.

 

iter

A InfBrowserIter pointing to the node to whose session the subscription was removed, or NULL.

 

proxy

A session proxy for the unsubscribed session.

 

request

The InfRequest due to which the session was unsubscribed, or NULL.

 

inf_browser_begin_request ()

void
inf_browser_begin_request (InfBrowser *browser,
                           const InfBrowserIter *iter,
                           InfRequest *request);

This function emits the “begin_request†signal on browser . It is meant to be used by interface implementations only.

Parameters

browser

A InfBrowser.

 

iter

A infBrowserIter pointing to the node for which a request was made, or NULL.

 

request

The request which was made.

 

inf_browser_acl_account_added ()

void
inf_browser_acl_account_added (InfBrowser *browser,
                               const InfAclAccount *account,
                               InfRequest *request);

This function emits the “acl-account-added†signal on browser . It is meant to be used by interface implementations only.

Parameters

browser

A InfBrowser.

 

account

The new InfAclAccount.

 

request

The InfRequest that was used to add the account, or NULL.

 

inf_browser_acl_account_removed ()

void
inf_browser_acl_account_removed (InfBrowser *browser,
                                 const InfAclAccount *account,
                                 InfRequest *request);

This function emits the “acl-account-removed†signal on browser . It is meant to be used by interface implementations only.

Parameters

browser

A InfBrowser.

 

account

The removed InfAclAccount.

 

request

The InfRequest that was used to remove the account, or NULL.

 

inf_browser_acl_local_account_changed ()

void
inf_browser_acl_local_account_changed (InfBrowser *browser,
                                       const InfAclAccount *account,
                                       InfRequest *request);

This function emits the “acl-local-account-changed†signal on browser . It is meant to be used by interface implementations only.

Parameters

browser

A InfBrowser.

 

account

The new local InfAclAccount.

 

request

The InfRequest that triggered the account change, or NULL.

 

inf_browser_acl_changed ()

void
inf_browser_acl_changed (InfBrowser *browser,
                         const InfBrowserIter *iter,
                         const InfAclSheetSet *sheet_set,
                         InfRequest *request);

This function emits the “acl-changed†signal on browser . It is meant to be used by interface implementations only.

Parameters

browser

A InfBrowser.

 

iter

An iterator pointing to the node for which the ACL has changed.

 

sheet_set

A InfAclSheetSet containing the changed ACL sheets.

 

request

The InfRequest that was used to change the ACL, or NULL.

 

Types and Values

InfBrowser

typedef struct _InfBrowser InfBrowser;

InfBrowser is an opaque data type. You should only access it via the public API functions.


struct InfBrowserInterface

struct InfBrowserInterface {
  void (*error)(InfBrowser* browser,
                const GError* error);

  void (*node_added)(InfBrowser* browser,
                     const InfBrowserIter* iter,
                     InfRequest* request);

  void (*node_removed)(InfBrowser* browser,
                       const InfBrowserIter* iter,
                       InfRequest* request);

  void (*subscribe_session)(InfBrowser* browser,
                            const InfBrowserIter* iter,
                            InfSessionProxy* proxy,
                            InfRequest* request);

  void (*unsubscribe_session)(InfBrowser* browser,
                              const InfBrowserIter* iter,
                              InfSessionProxy* proxy,
                              InfRequest* request);

  void (*begin_request)(InfBrowser* browser,
                        const InfBrowserIter* iter,
                        InfRequest* request);

  void (*acl_account_added)(InfBrowser* browser,
                            const InfAclAccount* account,
                            InfRequest* request);

  void (*acl_account_removed)(InfBrowser* browser,
                              const InfAclAccount* account,
                              InfRequest* request);

  void (*acl_local_account_changed)(InfBrowser* browser,
                                    const InfAclAccount* account,
                                    InfRequest* request);

  void (*acl_changed)(InfBrowser* browser,
                      const InfBrowserIter* iter,
                      const InfAclSheetSet* sheet_set,
                      InfRequest* request);

  /* Virtual functions */

  gboolean (*get_root)(InfBrowser* browser,
                       InfBrowserIter* iter);
  gboolean (*get_next)(InfBrowser* browser,
                       InfBrowserIter* iter);
  gboolean (*get_prev)(InfBrowser* browser,
                       InfBrowserIter* iter);
  gboolean (*get_parent)(InfBrowser* browser,
                         InfBrowserIter* iter);
  gboolean (*get_child)(InfBrowser* browser,
                        InfBrowserIter* iter);
  InfRequest* (*explore)(InfBrowser* browser,
                         const InfBrowserIter* iter,
                         InfRequestFunc func,
                         gpointer user_data);
  gboolean (*get_explored)(InfBrowser* browser,
                           const InfBrowserIter* iter);
  gboolean (*is_subdirectory)(InfBrowser* browser,
                              const InfBrowserIter* iter);

  InfRequest* (*add_note)(InfBrowser* browser,
                          const InfBrowserIter* iter,
                          const char* name,
                          const char* type,
                          const InfAclSheetSet* acl,
                          InfSession* session,
                          gboolean initial_subscribe,
                          InfRequestFunc func,
                          gpointer user_data);
  InfRequest* (*add_subdirectory)(InfBrowser* browser,
                                  const InfBrowserIter* iter,
                                  const char* name,
                                  const InfAclSheetSet* acl,
                                  InfRequestFunc func,
                                  gpointer user_data);
  InfRequest* (*remove_node)(InfBrowser* browser,
                             const InfBrowserIter* iter,
                             InfRequestFunc func,
                             gpointer user_data);
  const gchar* (*get_node_name)(InfBrowser* browser,
                                const InfBrowserIter* iter);
  const gchar* (*get_node_type)(InfBrowser* browser,
                                const InfBrowserIter* iter);

  InfRequest* (*subscribe)(InfBrowser* browser,
                           const InfBrowserIter* iter,
                           InfRequestFunc func,
                           gpointer user_data);
  InfSessionProxy* (*get_session)(InfBrowser* browser,
                                  const InfBrowserIter* iter);

  GSList* (*list_pending_requests)(InfBrowser* browser,
                                   const InfBrowserIter* iter,
                                   const gchar* request_type);
  gboolean (*iter_from_request)(InfBrowser* browser,
                                InfRequest* request,
                                InfBrowserIter* iter);

  const InfAclAccount* (*get_acl_default_account)(InfBrowser* browser);

  const InfAclAccount* (*get_acl_local_account)(InfBrowser* browser);

  InfRequest* (*query_acl_account_list)(InfBrowser* browser,
                                        InfRequestFunc func,
                                        gpointer user_data);

  InfRequest* (*lookup_acl_accounts)(InfBrowser* browser,
                                     const InfAclAccountId* ids,
                                     guint n_ids,
                                     InfRequestFunc func,
                                     gpointer user_data);

  InfRequest* (*lookup_acl_account_by_name)(InfBrowser* browser,
                                            const gchar* name,
                                            InfRequestFunc func,
                                            gpointer user_data);

  InfRequest* (*create_acl_account)(InfBrowser* browser,
                                    gnutls_x509_crq_t crq,
                                    InfRequestFunc func,
                                    gpointer user_data);

  InfRequest* (*remove_acl_account)(InfBrowser* browser,
                                    InfAclAccountId account,
                                    InfRequestFunc func,
                                    gpointer user_data);

  InfRequest* (*query_acl)(InfBrowser* browser,
                           const InfBrowserIter* iter,
                           InfRequestFunc func,
                           gpointer user_data);

  gboolean (*has_acl)(InfBrowser* browser,
                      const InfBrowserIter* iter,
                      InfAclAccountId account);

  const InfAclSheetSet* (*get_acl)(InfBrowser* browser,
                                   const InfBrowserIter* iter);

  InfRequest* (*set_acl)(InfBrowser* browser,
                         const InfBrowserIter* iter,
                         const InfAclSheetSet* sheet_set,
                         InfRequestFunc func,
                         gpointer user_data);
};

Signals and virtual functions for the InfBrowser interface.

Members

error ()

Default signal handler for the “error†signal.

 

node_added ()

Default signal handler for the “node-added†signal.

 

node_removed ()

Default signal handler for the “node-removed†signal.

 

subscribe_session ()

Default signal handler for the “subscribe-session†signal.

 

unsubscribe_session ()

Default signal handler for the “unsubscribe-session†signal.

 

begin_request ()

Default signal handler for the “begin-request†signal.

 

acl_account_added ()

Default signal handler for the “acl-account-added†signal.

 

acl_account_removed ()

Default signal handler for the “acl-account-removed†signal.

 

acl_local_account_changed ()

Default signal handler for the “acl-local-account-changed†signal.

 

acl_changed ()

Default signal handler for the “acl-changed†signal.

 

get_root ()

Virtual function to return the root node of the browser.

 

get_next ()

Virtual function to return the next sibling in a browser.

 

get_prev ()

Virtual function to return the previous sibling in a browser.

 

get_parent ()

Virtual function to return the parent node in a browser.

 

get_child ()

Virtual function to return the first child node in a browser.

 

explore ()

Virtual function to start exploring a node.

 

get_explored ()

Virtual function to query whether a node is explored already.

 

is_subdirectory ()

Virtual function to find out whether a node is a subdirectory node.

 

add_note ()

Virtual function to add a new leaf node to the directory.

 

add_subdirectory ()

Virtual function to a new subdirectory node to the directory.

 

remove_node ()

Virtual function to remove a node from the directory.

 

get_node_name ()

Virtual function to return the name of a node in a browser.

 

get_node_type ()

Virtual function to return the type of a node in a browser.

 

subscribe ()

Virtual function to subscribe to a session of a node in a browser.

 

get_session ()

Virtual function to return a session for a node in a browser.

 

list_pending_requests ()

Virtual function to return a list of all pending requests for a node in a browser.

 

iter_from_request ()

Virtual function to return an iterator pointing to the node a given request was made for.

 

get_acl_default_account ()

Virtual function to return the "default" ACL account.

 

get_acl_local_account ()

Virtual function to return the ACL account of the local host.

 

query_acl_account_list ()

Virtual function for querying the list of accounts.

 

lookup_acl_accounts ()

Virtual function to find accounts by their ID.

 

lookup_acl_account_by_name ()

Virtual function to find an account by its name.

 

create_acl_account ()

Virtual function to create a new account.

 

remove_acl_account ()

Virtual function to remove an account.

 

query_acl ()

Virtual function for querying the ACL for a node for all other users.

 

has_acl ()

Virtual function for checking whether the ACL has been queried or is otherwise available.

 

get_acl ()

Virtual function for obtaining the full ACL for a node.

 

set_acl ()

Virtual function for changing the ACL for one node.

 

enum InfBrowserStatus

This enumeration contains possible status values for InfBrowser. Several operations, such as exploring a node or subscribing to a session can only be performed when the browser is open (for example, connected to a remote infinote server).

Members

INF_BROWSER_CLOSED

The browser is closed and cannot be used currently.

 

INF_BROWSER_OPENING

The browser is currently being opened but cannot be used yet.

 

INF_BROWSER_OPEN

The browser is open and can be used to browse the directory.

 

Property Details

The “status†property

  “status†                  InfBrowserStatus

The connectivity status of the browser.

Flags: Read

Default value: INF_BROWSER_CLOSED

Signal Details

The “acl-account-added†signal

void
user_function (InfBrowser    *browser,
               InfAclAccount *account,
               InfRequest    *request,
               gpointer       user_data)

This signal is emitted whenever a new account is added to the browser, and the browser supports account list notification.

Parameters

browser

The InfBrowser object emitting the signal.

 

account

The new InfAclAccount.

 

request

The request which lead to the newly added account, or NULL.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last


The “acl-account-removed†signal

void
user_function (InfBrowser    *browser,
               InfAclAccount *account,
               InfRequest    *request,
               gpointer       user_data)

This signal is emitted whenever an account is removed from the browser, and the browser supports account list notification.

Parameters

browser

The InfBrowser object emitting the signal.

 

account

The removed InfAclAccount.

 

request

The request which lead to the removal of the account, or NULL.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last


The “acl-changed†signal

void
user_function (InfBrowser     *browser,
               InfBrowserIter *iter,
               InfAclSheetSet *sheet_set,
               InfRequest     *request,
               gpointer        user_data)

This signal is emitted whenever an ACL for the node iter points to are changed. This signal is emitted whenever the ACL change for the local user, the default user, or for a node that all ACLs have been queried with inf_browser_query_acl().

The sheet_set parameter contains only the ACL sheets that have changed. In order to get the new full sheet set, call inf_browser_get_acl().

Parameters

browser

The InfBrowser object emitting the signal.

 

iter

An iterator pointing to the node for which the ACL has changed.

 

sheet_set

A InfAclSheetSet containing the changed ACL sheets.

 

request

The request which lead to the ACL being changed, or NULL.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last


The “acl-local-account-changed†signal

void
user_function (InfBrowser    *browser,
               InfAclAccount *account,
               InfRequest    *request,
               gpointer       user_data)

This signal is emitted whenever the account into which the local host is logged into changes. This can happen for example on a delayed login, or when the current account is deleted from the server in which case the host is demoted to the default account.

Parameters

browser

The InfBrowser object emitting the signal.

 

account

The new local InfAclAccount.

 

request

The request which triggered the account change, or NULL.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last


The “begin-request†signal

void
user_function (InfBrowser     *browser,
               InfBrowserIter *iter,
               InfRequest     *request,
               gpointer        user_data)

This signal is emitted whenever a request is made with the browser. The signal is detailed with the request type, so that it is possible to connect to e.g. "begin-request::add-subdirectory" to only get notified about subdirectory creation requests.

If iter is NULL the request is a global request and not attached to a particular node.

Parameters

browser

The InfBrowser object emitting the signal.

 

iter

An iterator pointing to the node for which a request is made, or NULL.

 

request

The request being made.

 

user_data

user data set when the signal handler was connected.

 

Flags: Has Details


The “error†signal

void
user_function (InfBrowser *browser,
               GError     *error,
               gpointer    user_data)

This signal is emitted whenever there was an asynchronous error with the browser itself which was not the result of a particular user request. The error may or may not be fatal. If it is fatal the browser will also be closed which can be checked with the status property.

Parameters

browser

The InfBrowser object emitting the signal.

 

error

A GError describing what went wrong.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last


The “node-added†signal

void
user_function (InfBrowser     *browser,
               InfBrowserIter *iter,
               InfRequest     *request,
               gpointer        user_data)

This signal is emitted when a node is added to the browser.

Parameters

browser

The InfBrowser object emitting the signal.

 

iter

An iterator pointing to the newly added node.

 

request

The request that lead to the node being added, or NULL.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last


The “node-removed†signal

void
user_function (InfBrowser     *browser,
               InfBrowserIter *iter,
               InfRequest     *request,
               gpointer        user_data)

This signal is emitted just before a node is being removed from the browser. The iterator is still valid and can be used to access the node which will be removed.

Parameters

browser

The InfBrowser object emitting the signal.

 

iter

An iterator pointing to the node being removed.

 

request

The request that lead to the node being removed, or NULL.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last


The “subscribe-session†signal

void
user_function (InfBrowser      *browser,
               InfBrowserIter  *iter,
               InfSessionProxy *session,
               InfRequest      *request,
               gpointer         user_data)

This signal is emitted whenever the browser is subscribed to a session. This can happen as a result of a inf_browser_subscribe() or inf_browser_add_note() call, but it is also possible that a subscription is initiated without user interaction.

If iter is NULL the session was a global session and not attached to a particular node.

Parameters

browser

The InfBrowser object emitting the signal.

 

iter

An iterator pointing to the node to which a subscription. was made, or NULL.

 

session

The subscribed session.

 

request

The request that lead to the subscription, or NULL.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last


The “unsubscribe-session†signal

void
user_function (InfBrowser      *browser,
               InfBrowserIter  *iter,
               InfSessionProxy *session,
               InfRequest      *request,
               gpointer         user_data)

This signal is emitted whenever a session is detached from a browser node. This can happen when a subscribed session is closed, or, in the case of a server, if the session is idle for a long time it is stored on disk and removed from memory.

Note that this signal does not mean that the corresponding session can no longer be used. It only means that it is no longer associated to a browser node, for example also when the browser node is deleted. The session might still be intact, though, and can continue even when it is detached from the browser.

In order to find out whether the local host was unsubscribed from a session and the connection to the other session participants has been lost, the “subscription-group†property should be monitored, and if that property changes and inf_session_get_subscription_group() returns NULL afterwards, it means the session is no longer connected.

If iter is NULL the session was a global session and not attached to a particular node.

Parameters

browser

The InfBrowser object emitting the signal.

 

iter

An iterator pointing to the node from which a subscription. was removed, or NULL.

 

session

The session to which the subscription was removed.

 

request

The request that lead to the unsubscription, or NULL.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last

See Also

InfBrowserIter

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfCertificateCredentials.html0000644000000000000000000000013213055210752027700 xustar0030 mtime=1488261610.892090691 30 atime=1488261610.892090691 30 ctime=1488261610.892090691 libinfinity-0.7.1/docs/reference/libinfinity/html/InfCertificateCredentials.html0000644000175000017500000003144213055210752030436 0ustar00arminarmin00000000000000 InfCertificateCredentials: libinfinity-0.7 Reference Manual

InfCertificateCredentials

InfCertificateCredentials — Reference-counted wrapper for gnutls_certificate_credentials_t

Stability Level

Unstable, unless otherwise indicated

Types and Values

Object Hierarchy

    GBoxed
    ╰── InfCertificateCredentials

Includes

#include <libinfinity/common/inf-certificate-credentials.h>

Description

This is a thin wrapper class for gnutls_certificate_credentials_t. It provides reference counting and a boxed GType for it.

Functions

inf_certificate_credentials_new ()

InfCertificateCredentials *
inf_certificate_credentials_new (void);

Creates a new InfCertificateCredentials with an initial reference count of 1. Use inf_certificate_credentials_get() to access the underlying gnutls_certificate_credentials_t.

Returns

A new InfCertificateCredentials. Free with inf_certificate_credentials_unref() when no longer needed.


inf_certificate_credentials_ref ()

InfCertificateCredentials *
inf_certificate_credentials_ref (InfCertificateCredentials *creds);

Increases the reference count of creds by 1.

Parameters

Returns

The passed InfCertificateCredentials, creds .


inf_certificate_credentials_unref ()

void
inf_certificate_credentials_unref (InfCertificateCredentials *creds);

Decreases the reference count of creds by 1. If its reference count reaches 0, then the InfCertificateCredentials will be freed.

Parameters


inf_certificate_credentials_get ()

gnutls_certificate_credentials_t
inf_certificate_credentials_get (InfCertificateCredentials *creds);

Provides access to the creds ' underlying gnutls_certificate_credentials_t.

Parameters

Returns

creds ' gnutls_certificate_credentials_t.

Types and Values

InfCertificateCredentials

typedef struct _InfCertificateCredentials InfCertificateCredentials;

InfCertificateCredentials is an opaque data type. You should only access it via the public API functions.

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfdDirectory.html0000644000000000000000000000013213055210752025410 xustar0030 mtime=1488261610.892090691 30 atime=1488261610.892090691 30 ctime=1488261610.892090691 libinfinity-0.7.1/docs/reference/libinfinity/html/InfdDirectory.html0000644000175000017500000021425613055210752026154 0ustar00arminarmin00000000000000 InfdDirectory: libinfinity-0.7 Reference Manual

InfdDirectory

InfdDirectory — Directory of published documents

Stability Level

Unstable, unless otherwise indicated

Properties

InfdAccountStorage * account-storage Read / Write / Construct
InfCertificateChain * certificate Read / Write
InfdSessionProxy * chat-session Read
InfCommunicationManager * communication-manager Read / Write / Construct Only
InfIo * io Read / Write / Construct Only
gpointer private-key Read / Write
InfdStorage * storage Read / Write / Construct

Types and Values

Object Hierarchy

    GObject
    ╰── InfdDirectory

Implemented Interfaces

InfdDirectory implements InfCommunicationObject and InfBrowser.

Includes

#include <libinfinity/server/infd-directory.h>

Description

The InfdDirectory manages a directory of documents. An item in the directory is also called "node". A node may either be a subdirectory or a document (also called "note"). Notes may be of different type - there may be plain text notes, rich text notes, graphics notes, etc.

InfdStorage defines where the directory structure and the notes are read from and how they are permanently stored.

Functions

InfdDirectoryForeachConnectionFunc ()

void
(*InfdDirectoryForeachConnectionFunc) (InfXmlConnection *conn,
                                       gpointer user_data);

This is the signature of the callback function passed to infd_directory_foreach_connection().

Parameters

conn

The connection corresponding to the current iteration.

 

user_data

Additional data passed to the call to infd_directory_foreach_connection().

 

infd_directory_new ()

InfdDirectory *
infd_directory_new (InfIo *io,
                    InfdStorage *storage,
                    InfCommunicationManager *comm_manager);

Creates a new InfdDirectory. If storage is NULL then the directory keeps all content in memory. This can make sense for ad-hoc sessions where no central document storage is required.

[constructor]

Parameters

io

IO object to watch connections and schedule timeouts.

 

storage

Storage backend that is used to read/write notes from permanent memory into InfBuffer objects, or NULL.

 

comm_manager

A InfCommunicationManager to register added connections to and which forwards incoming data to the directory or running sessions.

 

Returns

A new InfdDirectory.

[transfer full]


infd_directory_get_io ()

InfIo *
infd_directory_get_io (InfdDirectory *directory);

Returns the IO object in use by the directory.

Parameters

directory

A InfdDirectory.

 

Returns

A InfIo.

[transfer none]


infd_directory_get_storage ()

InfdStorage *
infd_directory_get_storage (InfdDirectory *directory);

Returns the storage backend in use by the directory.

Parameters

directory

A InfdDirectory:

 

Returns

An InfdStorage.

[transfer none][allow-none]


infd_directory_get_communication_manager ()

InfCommunicationManager *
infd_directory_get_communication_manager
                               (InfdDirectory *directory);

Returns the connection manager of the directory.

Parameters

directory

A InfdDirectory.

 

Returns

An InfCommunicationManager.

[transfer none]


infd_directory_set_certificate ()

void
infd_directory_set_certificate (InfdDirectory *directory,
                                gnutls_x509_privkey_t key,
                                InfCertificateChain *cert);

Sets the private key and certificate chain of the directory. The directory does not use these for certificate authentication with added connections. Connections should already be authenticated, for example with the means of InfXmppConnection.

At the moment, the directory certificate is used to sign incoming certificate requests. Selected clients can request a certificate signed with the server's certificates, see inf_browser_create_acl_account(). If the server certificate is set with this function, the request is handled properly. If no certificate is set with this function, such a request is rejected.

Parameters

directory

A InfdDirectory.

 

key

The private key of the directory.

 

cert

The certificate chain of the directory.

[transfer none]

infd_directory_add_plugin ()

gboolean
infd_directory_add_plugin (InfdDirectory *directory,
                           const InfdNotePlugin *plugin);

Adds plugin to directory . This allows the directory to create sessions of the plugin's type. Only one plugin of each type can be added to the directory. The plugin's storage_type must match the storage of directory . If the directory's storage is NULL, then the plugin's storage type does not matter, and the plugin's session_read and session_write functions will not be used (and can therefore be NULL).

Parameters

directory

A InfdDirectory.

 

plugin

A InfdNotePlugin.

 

Returns

Whether the plugin was added successfully.


infd_directory_remove_plugin ()

void
infd_directory_remove_plugin (InfdDirectory *directory,
                              const InfdNotePlugin *plugin);

Removes a note plugin from the directory. If there are any sessions running using this plugin, they are unsubscribed from the directory.

Parameters

directory

A InfdDirectory.

 

plugin

The plugin to remove.

 

infd_directory_lookup_plugin ()

const InfdNotePlugin *
infd_directory_lookup_plugin (InfdDirectory *directory,
                              const gchar *note_type);

Returns the InfdNotePlugin that handles the given note type, or NULL in case no corresponding plugin was added.

Parameters

directory

A InfdDirectory.

 

note_type

A note type for which to lookup the plugin.

 

Returns

A InfdNotePlugin, or NULL.

[transfer none][allow-none]


infd_directory_add_connection ()

gboolean
infd_directory_add_connection (InfdDirectory *directory,
                               InfXmlConnection *connection);

Adds connection to the connections of directory . The directory will then receive requests from connection . If the directory's method manager does not contain a "central" method for connection's network, then the connection will not be added and the function returns FALSE.

The connection is removed again automatically if it is closed.

Parameters

directory

A InfdDirectory.

 

connection

A InfXmlConnection.

 

Returns

Whether the connection was added to the directory.


infd_directory_get_support_mask ()

void
infd_directory_get_support_mask (InfdDirectory *directory,
                                 InfAclMask *mask);

This function writes all operations supported by directory to mask . If an operation is unsupported by the server, the corresponding field in the mask will not be set.

Parameters

directory

A InfdDirectory.

 

mask

A pointer to a InfAclMask that will be filled.

[out]

infd_directory_get_acl_account_for_connection ()

InfAclAccountId
infd_directory_get_acl_account_for_connection
                               (InfdDirectory *directory,
                                InfXmlConnection *connection);

This function returns the InfAclAccountId that the given connection is logged into. The connection must have been added to the directory before with infd_directory_add_connection(). If no special login was performed, the default account is returned.

Parameters

directory

A InfdDirectory.

 

connection

A connection added to directory .

 

Returns

A InfAclAccountId.

[transfer full]


infd_directory_set_acl_account_for_connection ()

gboolean
infd_directory_set_acl_account_for_connection
                               (InfdDirectory *directory,
                                InfXmlConnection *connection,
                                InfAclAccountId account_id,
                                GError **error);

This function changes the account that the given connection is logged into. The connection must have been added to the directory before with infd_directory_add_connection(). In order to remove a login, account_id should be set to the default account.

The function might fail if there is no account that corresponds to account , or if the account storage reports an error when looking up the account.

Parameters

directory

A InfdDirectory.

 

connection

A connection added to directory .

 

account_id

A InfAclAccountId representing a valid account in directory .

 

error

Location to store error information, if any, or NULL.

 

Returns

TRUE on success or FALSE on error.


infd_directory_foreach_connection ()

void
infd_directory_foreach_connection (InfdDirectory *directory,
                                   InfdDirectoryForeachConnectionFunc func,
                                   gpointer user_data);

Calls func for each connection in directory that has previously been added to the directory. It is allowed to add and remove connections while this function is being called.

Parameters

directory

A InfdDirectory.

 

func

The function to call for each connection in directory .

[scope call]

user_data

Additional data to pass to the callback function.

 

infd_directory_iter_save_session ()

gboolean
infd_directory_iter_save_session (InfdDirectory *directory,
                                  const InfBrowserIter *iter,
                                  GError **error);

Attempts to store the session the node iter points to represents into the background storage.

Parameters

directory

A InfdDirectory.

 

iter

A InfBrowserIter pointing to a note in directory .

 

error

Location to store error information.

 

Returns

TRUE if the operation succeeded, FALSE otherwise.


infd_directory_enable_chat ()

void
infd_directory_enable_chat (InfdDirectory *directory,
                            gboolean enable);

If enable is TRUE, this enables the chat on the server. This allows clients subscribing to the chat via infc_browser_subscribe_chat(). If enable is FALSE the chat is disabled which means closing an existing chat session if any and no longer allowing subscription to the chat. The chat is initially disabled.

Parameters

directory

A InfdDirectory.

 

enable

Whether to enable or disable the chat.

 

infd_directory_get_chat_session ()

InfdSessionProxy *
infd_directory_get_chat_session (InfdDirectory *directory);

Returns a InfdSessionProxy for the chat session, if any. If the chat is enabled (see infd_directory_enable_chat()) this returns a InfdSessionProxy that can be used to join local users to the chat, or to get chat contents (by getting the InfChatBuffer from the proxy's InfChatSession). If the chat is disabled the function returns NULL.

Parameters

directory

A InfdDirectory.

 

Returns

A InfdSessionProxy, or NULL if the chat is disabled.

[transfer none][allow-none]


infd_directory_create_acl_account ()

InfAclAccountId
infd_directory_create_acl_account (InfdDirectory *directory,
                                   const gchar *account_name,
                                   gboolean transient,
                                   gnutls_x509_crt_t *certificates,
                                   guint n_certificates,
                                   GError **error);

Creates a new account on the directory with the given account_name . If the certificates array is not empty and a clients connects with one of the certificates, the client will automatically be logged into the account.

If the transient parameter is TRUE then the account is made transient, i.e. it will not be stored to permanent storage. When the server is re-started, the account will no longer exist. If the parameter is FALSE, then the account is persistent.

This function is similar to inf_browser_create_acl_account(), but it allows more options.

Parameters

directory

A InfdDirectory.

 

account_name

The name of the new account.

 

transient

Whether the account should be transient or not.

 

certificates

An array of certificates to be associated to the account, or NULL.

[array length=n_certificates][allow-none]

n_certificates

The number of certificates.

 

error

Location to store error information, if any, or NULL.

 

Returns

The account ID of the created account, or 0 in case of error.

[transfer full]

Types and Values

struct InfdDirectory

struct InfdDirectory;

InfdDirectory is an opaque data type. You should only access it via the public API functions.


struct InfdDirectoryClass

struct InfdDirectoryClass {
  void (*connection_added)(InfdDirectory* directory,
                           InfXmlConnection* connection);
  void (*connection_removed)(InfdDirectory* directory,
                             InfXmlConnection* connection);
};

Default signal handlers for InfdDirectory.

Members

connection_added ()

Default signal handler for the “connection-added†signal.

 

connection_removed ()

Default signal handler for the “connection-removed†signal.

 

Property Details

The “account-storage†property

  “account-storage†         InfdAccountStorage *

The account storage backend, to read available user accounts from.

Flags: Read / Write / Construct


The “certificate†property

  “certificate†             InfCertificateChain *

The certificate chain of the server.

Flags: Read / Write


The “chat-session†property

  “chat-session†            InfdSessionProxy *

The server's chat session.

Flags: Read


The “communication-manager†property

  “communication-manager†   InfCommunicationManager *

The communication manager for the directory.

Flags: Read / Write / Construct Only


The “io†property

  “io†                      InfIo *

IO object to watch sockets and schedule timeouts.

Flags: Read / Write / Construct Only


The “private-key†property

  “private-key†             gpointer

The private key of the server with which belongs to its certificate.

Flags: Read / Write


The “storage†property

  “storage†                 InfdStorage *

The storage backend to use.

Flags: Read / Write / Construct

Signal Details

The “connection-added†signal

void
user_function (InfdDirectory    *directory,
               InfXmlConnection *connection,
               gpointer          user_data)

This signal is emitted when a connection that is served by the InfdDirectory was added. The only way this can happen is by a call to infd_directory_add_connection(). This can be done automatically by an InfdServerPool instance, however.

Parameters

directory

The InfdDirectory emitting the signal.

 

connection

The InfXmlConnection that was added.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last


The “connection-removed†signal

void
user_function (InfdDirectory    *directory,
               InfXmlConnection *connection,
               gpointer          user_data)

This signal is emitted when a connection stopes being served by directory . Usually this happens only when the connection is closed.

Parameters

directory

The InfdDirectory emitting the signal.

 

connection

The InfXmlConnection that was removed.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfUser.html0000644000000000000000000000013213055210752024216 xustar0030 mtime=1488261610.892090691 30 atime=1488261610.892090691 30 ctime=1488261610.892090691 libinfinity-0.7.1/docs/reference/libinfinity/html/InfUser.html0000644000175000017500000010061013055210752024746 0ustar00arminarmin00000000000000 InfUser: libinfinity-0.7 Reference Manual

InfUser

InfUser — User in a InfSession.

Stability Level

Unstable, unless otherwise indicated

Properties

InfXmlConnection * connection Read / Write
InfUserFlags flags Read / Write
guint id Read / Write / Construct Only
gchar * name Read / Write
InfUserStatus status Read / Write

Signals

Types and Values

Object Hierarchy

    GEnum
    ╰── InfUserStatus
    GFlags
    ╰── InfUserFlags
    GObject
    ╰── InfUser
        ╰── InfAdoptedUser

Includes

#include <libinfinity/common/inf-user.h>

Description

InfUser represents a user in an InfSession. The InfUser object stores basic user information required in all kinds of sessions, that is the user ID, user name, its status and auxiliary flags.

Functions

inf_user_get_id ()

guint
inf_user_get_id (InfUser *user);

Returns the ID of the given InfUser.

Parameters

user

A InfUser.

 

Returns

A numerical User ID.


inf_user_get_name ()

const gchar *
inf_user_get_name (InfUser *user);

Returns the name of the given InfUser.

Parameters

user

A InfUser.

 

Returns

The user's name.

[transfer none]


inf_user_get_status ()

InfUserStatus
inf_user_get_status (InfUser *user);

Returns the status of the given InfUser.

Parameters

user

A InfUser.

 

Returns

The user's status.


inf_user_get_flags ()

InfUserFlags
inf_user_get_flags (InfUser *user);

Returns the flags for the given InfUser.

Parameters

user

A InfUser.

 

Returns

The user's flags.


inf_user_get_connection ()

InfXmlConnection *
inf_user_get_connection (InfUser *user);

Returns a connection to the given InfUser, or NULL. If a non-NULL connection is returned, then this is the connection through which records from that user come from. This means that, when this connection is closed, then the user is no longer available. However, you cannot send something to this connection expecting the user will receive it. For example, in central messaging mode, this connection is always the publisher, because all records from the user are relayed via the publisher.

If this functions returns NULL, this either means user is a local user (INF_USER_LOCAL flag set) or it is not available (status is INF_USER_UNAVAILABLE).

Parameters

user

A InfUser.

 

Returns

A InfXmlConnection, or NULL.

[transfer none][allow-none]


inf_user_status_to_string ()

const gchar *
inf_user_status_to_string (InfUserStatus status);

Returns a non-localized string identifying the given status. This is not meant to be shown to a user, but rather to serialize a user status, for example to store it in XML.

Parameters

status

A value from the InfUserStatus enumeration.

 

Returns

A static string representation of status .

[transfer none]


inf_user_status_from_string ()

gboolean
inf_user_status_from_string (const gchar *string,
                             InfUserStatus *status,
                             GError **error);

This function does the opposite of inf_user_status_to_string(). It turns the given string back to a InfUserStatus, storing the result in status if status is non-NULL. If string is invalid, then status is left untouched, error is set and FALSE is returned. Otherwise, the function returns TRUE.

Parameters

string

A string representation of a InfUserStatus.

 

status

A pointer to a InfUserStatus value, or NULL.

[out][allow-none]

error

Location to store error information, if any.

 

Returns

When an error occured during the conversion, FALSE is returned, and TRUE otherwise.

Types and Values

enum InfUserStatus

Different possible types of status an InfUser can have.

Members

INF_USER_ACTIVE

The user is available and currently looking at this session.

 

INF_USER_INACTIVE

The user is available but currently not paying attention to this session.

 

INF_USER_UNAVAILABLE

The user is not available, i.e. not joined into the session.

 

enum InfUserFlags

Additional flags for InfUser.

Members

INF_USER_LOCAL

The user is local, i.e. joined by the local instance.

 

struct InfUser

struct InfUser;

InfUser is an opaque data type. You should only access it via the public API functions.


struct InfUserClass

struct InfUserClass {
  void (*set_status)(InfUser* user,
                     InfUserStatus status);
};

This structure contains virtual functions for the InfUser class.

Members

set_status ()

Virtual function to change the status of a user. This is a hook for user subclasses to react on status change.

 

Property Details

The “connection†property

  “connection†              InfXmlConnection *

Connection to the user.

Flags: Read / Write


The “flags†property

  “flags†                   InfUserFlags

Flags the user currently has.

Flags: Read / Write


The “id†property

  “id†                      guint

A Unique User ID.

Flags: Read / Write / Construct Only

Default value: 0


The “name†property

  “name†                    gchar *

The Name with which a user joined a session. Most servers ensure that it is unique.

Flags: Read / Write

Default value: ""


The “status†property

  “status†                  InfUserStatus

Whether the user is currently available or not.

Flags: Read / Write

Default value: INF_USER_UNAVAILABLE

Signal Details

The “set-status†signal

void
user_function (InfUser      *user,
               InfUserStatus status,
               gpointer      user_data)

This signal is emitted whenever the user's status changes. This is basically the same as a notification for the “status†property, but it allows to access the previous user status when connecting before the default signal handler.

Parameters

user

The InfUser that changes status.

 

status

The new user status.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last

See Also

InfSession

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfdXmppServer.html0000644000000000000000000000013213055210752025557 xustar0030 mtime=1488261610.892090691 30 atime=1488261610.892090691 30 ctime=1488261610.892090691 libinfinity-0.7.1/docs/reference/libinfinity/html/InfdXmppServer.html0000644000175000017500000005453213055210752026322 0ustar00arminarmin00000000000000 InfdXmppServer: libinfinity-0.7 Reference Manual

InfdXmppServer

InfdXmppServer

Properties

InfCertificateCredentials * credentials Read / Write / Construct
gchar * local-hostname Read / Write / Construct Only
InfSaslContext * sasl-context Read / Write / Construct
gchar * sasl-mechanisms Read / Write / Construct
InfXmppConnectionSecurityPolicy security-policy Read / Write / Construct
InfdTcpServer * tcp-server Read / Write / Construct Only

Signals

Types and Values

Object Hierarchy

    GObject
    ╰── InfdXmppServer

Implemented Interfaces

InfdXmppServer implements InfdXmlServer.

Description

Functions

infd_xmpp_server_new ()

InfdXmppServer *
infd_xmpp_server_new (InfdTcpServer *tcp,
                      InfXmppConnectionSecurityPolicy policy,
                      InfCertificateCredentials *creds,
                      InfSaslContext *sasl_context,
                      const gchar *sasl_mechanisms);

Creates a new InfdXmppServer with tcp as underlaying TCP server object. No attempt is being made to open tcp , if it is not already open. When a new connection comes in, the XMPP server creates a XMPP connection that may be used to communicate with the client. Note however that the resulting connection will be in status OPENING until authentication has completed.

If policy is INF_XMPP_CONNECTION_SECURITY_ONLY_UNSECURED, then creds may be NULL. If creds is non-NULL nevertheless, then it is possible to change the security policy later using infd_xmpp_server_set_security_policy(). creds can also be changed later while the server is running. So just set valid credentials before changing policy to allow TLS.

If sasl_context is NULL, the server uses a built-in context that only supports ANONYMOUS authentication. If sasl_context is not NULL, then sasl_mechanisms specifies the mechanisms offered to clients. If sasl_mechanisms is NULL, then all available mechanims will be offered. If sasl_context is NULL, then this parameter is ignored.

[constructor]

Parameters

tcp

A InfdTcpServer.

 

policy

The initial security policy.

 

creds

Certificate credentials used to secure any communication.

 

sasl_context

A SASL context used for authentication.

 

sasl_mechanisms

A whitespace-sparated list of SASL mechanisms.

 

Returns

A new InfdXmppServer.

[transfer full]


infd_xmpp_server_set_security_policy ()

void
infd_xmpp_server_set_security_policy (InfdXmppServer *server,
                                      InfXmppConnectionSecurityPolicy policy);

Sets the security policy for newly accepted InfXmppConnections. Does not already established connections.

Parameters

server

A InfdXmppServer.

 

policy

The new security policy.

 

infd_xmpp_server_get_security_policy ()

InfXmppConnectionSecurityPolicy
infd_xmpp_server_get_security_policy (InfdXmppServer *server);

Returns the current security policy for newly accepted InfXmppConnections.

Parameters

server

A InfdXmppServer.

 

Returns

The current security policy.

Types and Values

struct InfdXmppServer

struct InfdXmppServer;


struct InfdXmppServerClass

struct InfdXmppServerClass {
  GObjectClass parent_class;

  /* Signals */
  void (*error)(InfdXmppServer* server,
                GError* error);
};

Property Details

The “credentials†property

  “credentials†             InfCertificateCredentials *

The certificate credentials for GnuTLS.

Flags: Read / Write / Construct


The “local-hostname†property

  “local-hostname†          gchar *

Hostname of the server.

Flags: Read / Write / Construct Only

Default value: NULL


The “sasl-context†property

  “sasl-context†            InfSaslContext *

The SASL context used for authentaction.

Flags: Read / Write / Construct


The “sasl-mechanisms†property

  “sasl-mechanisms†         gchar *

The SASL mechanisms offered to the client for authentication.

Flags: Read / Write / Construct

Default value: NULL


The “security-policy†property

  “security-policy†         InfXmppConnectionSecurityPolicy

Whether to offer or require TLS.

Flags: Read / Write / Construct

Default value: INF_XMPP_CONNECTION_SECURITY_ONLY_UNSECURED


The “tcp-server†property

  “tcp-server†              InfdTcpServer *

Underlaying TCP server.

Flags: Read / Write / Construct Only

Signal Details

The “error†signal

void
user_function (InfdXmppServer *infdxmppserver,
               GError         *arg1,
               gpointer        user_data)

Parameters

infdxmppserver

the object which received the signal.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfXmlConnection.html0000644000000000000000000000013213055210752026060 xustar0030 mtime=1488261610.892090691 30 atime=1488261610.892090691 30 ctime=1488261610.892090691 libinfinity-0.7.1/docs/reference/libinfinity/html/InfXmlConnection.html0000644000175000017500000011552513055210752026623 0ustar00arminarmin00000000000000 InfXmlConnection: libinfinity-0.7 Reference Manual

InfXmlConnection

InfXmlConnection — Exchange of XML messages

Stability Level

Unstable, unless otherwise indicated

Signals

Object Hierarchy

    GEnum
    ╰── InfXmlConnectionStatus
    GInterface
    ╰── InfXmlConnection

Prerequisites

InfXmlConnection requires GObject.

Known Implementations

InfXmlConnection is implemented by InfSimulatedConnection and InfXmppConnection.

Includes

#include <libinfinity/common/inf-xml-connection.h>

Description

InfXmlConnection provides a generic interface for sending an receiving messages in the form of XML nodes. The rest of the libinfinity library works with InfXmlConnections to transfer data between nodes. Therefore, simply implementing this interface allows to use the core functionality of the library with any kind of network or transport.

Apart from the virtual functions, implementations also need to provide the “remote-id†and “local-id†properties. These properties represent string identifiers that are unique to the particular hosts in the network, such as IP addresses for IP connections. If the connection is supposed to be used with other communication methods (see InfCommunicationMethod) than the "central" one, these IDs must be unique and every host must see the same ID for the other hosts in the network. This is no longer fulfilled by simple IP addresses, but for example for JIDs when sending XML messages over a jabber server.

Functions

inf_xml_connection_open ()

gboolean
inf_xml_connection_open (InfXmlConnection *connection,
                         GError **error);

Attempts to open the given XML connection. If the process fails, error will be set. The connection needs to be in status INF_XML_CONNECTION_CLOSED for this function to be called. Even if this function succeeds, the connection process can fail later. In that case the status of connection will be reset to INF_XML_CONNECTION_CLOSED and the “error†signal will be emitted.

Parameters

connection

A infXmlConnection.

 

error

Location to store error information, if any.

 

Returns

TRUE on succes, or FALSE on error.


inf_xml_connection_close ()

void
inf_xml_connection_close (InfXmlConnection *connection);

Closes the given connection.

Parameters

connection

A InfXmlConnection.

 

inf_xml_connection_send ()

void
inf_xml_connection_send (InfXmlConnection *connection,
                         xmlNodePtr xml);

Sends the given XML message to the remote host.

Parameters

connection

A InfXmlConnection.

 

xml

A XML message to send. The function takes ownership of the XML node.

[transfer full]

inf_xml_connection_sent ()

void
inf_xml_connection_sent (InfXmlConnection *connection,
                         const xmlNodePtr xml);

Emits the "sent" signal on connection . This will most likely only be useful to implementors.

Parameters

connection

A InfXmlConnection.

 

xml

The XML message that has been sent.

[transfer none]

inf_xml_connection_received ()

void
inf_xml_connection_received (InfXmlConnection *connection,
                             const xmlNodePtr xml);

Emits the "received" signal on connection . This will most likely only be useful to implementors.

Parameters

connection

A InfXmlConnection.

 

xml

The XML message that has been received.

[transfer none]

inf_xml_connection_error ()

void
inf_xml_connection_error (InfXmlConnection *connection,
                          const GError *error);

Emits the "error" signal on connection . This will most likely only be useful to implementors.

Note that the error may or may not be fatal for the connection. If it is fatal, then a status notify to INF_XML_CONNECTION_CLOSING or INF_XML_CONNECTION_CLOSED will follow. If you are implementing a custom class implementing InfXmlConnection, make sure to always emit the "error" signal before doing the status notify because many users of the connection will release their reference when the connection is no longer connected.

Parameters

connection

A InfXmlConnection.

 

error

The error that occured.

 

Types and Values

InfXmlConnection

typedef struct _InfXmlConnection InfXmlConnection;

InfXmlConnection is an opaque data type. You should only access it via the public API functions.


struct InfXmlConnectionInterface

struct InfXmlConnectionInterface {
  /* Virtual table */
  gboolean (*open)(InfXmlConnection* connection,
                   GError** error);
  void (*close)(InfXmlConnection* connection);
  void (*send)(InfXmlConnection* connection,
               xmlNodePtr xml);

  /* Signals */
  void (*sent)(InfXmlConnection* connection,
               const xmlNodePtr xml);
  void (*received)(InfXmlConnection* connection,
                   const xmlNodePtr xml);
  void (*error)(InfXmlConnection* connection,
                const GError* error);
};

Virtual functions and default signal handlers for the InfXmlConnection interface.

Members

open ()

Virtual function to start the connection.

 

close ()

Virtual function to stop the connection.

 

send ()

Virtual function to transmit data over the connection.

 

sent ()

Default signal handler of the “sent†signal.

 

received ()

Default signal handler of the “received†signal.

 

error ()

Default signal handler of the “error†signal.

 

enum InfXmlConnectionStatus

The possible connection status of an InfXmlConnection.

Members

INF_XML_CONNECTION_CLOSED

The connection is currently not established.

 

INF_XML_CONNECTION_CLOSING

The connection is in the process of being closed, no more data can be sent.

 

INF_XML_CONNECTION_OPEN

The connection is up and data can be transmitted.

 

INF_XML_CONNECTION_OPENING

The connection is being established.

 

Property Details

The “local-certificate†property

  “local-certificate†       gpointer

The X.509 certificate (gnutls_x509_crt_t) of the local site.

Flags: Read


The “local-id†property

  “local-id†                gchar *

A unique identification on the network for the local site.

Flags: Read

Default value: NULL


The “network†property

  “network†                 gchar *

An identifier for the type of network this connection is on.

Flags: Read

Default value: NULL


The “remote-certificate†property

  “remote-certificate†      InfCertificateChain *

The X.509 certificate of the remote site.

Flags: Read


The “remote-id†property

  “remote-id†               gchar *

A unique identification on the network for the remote site.

Flags: Read

Default value: NULL


The “status†property

  “status†                  InfXmlConnectionStatus

The status of the connection.

Flags: Read

Default value: INF_XML_CONNECTION_CLOSED

Signal Details

The “error†signal

void
user_function (InfXmlConnection *connection,
               GError           *error,
               gpointer          user_data)

This signal is emitted when an error occurs for this connection. For example, if the connection cannot be established and the status changes from INF_XML_CONNECTION_OPENING to INF_XML_CONNECTION_CLOSED, then this signal is usually emitted with more details on the error.

Note however that the error may or may not be fatal for the connection. If it is fatal, then a status notify to INF_XML_CONNECTION_CLOSING or INF_XML_CONNECTION_CLOSED will follow.

Parameters

connection

The erroneous InfXmlConnection

 

error

A pointer to a GError object with details on the error

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last


The “received†signal

void
user_function (InfXmlConnection *connection,
               gpointer          node,
               gpointer          user_data)

Signal which is emitted when an XML node has been received by this connection.

Parameters

connection

The InfXmlConnection through which node has been received

 

node

An xmlNodePtr refering to the XML node that has been received

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last


The “sent†signal

void
user_function (InfXmlConnection *connection,
               gpointer          node,
               gpointer          user_data)

Signal which is emitted when an XML node has been successfully transmitted with this connection.

Parameters

connection

The InfXmlConnection through which node has been sent

 

node

An xmlNodePtr refering to the XML node that has been sent

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfXmppConnection.html0000644000000000000000000000013213055210752026244 xustar0030 mtime=1488261610.896090682 30 atime=1488261610.896090682 30 ctime=1488261610.896090682 libinfinity-0.7.1/docs/reference/libinfinity/html/InfXmppConnection.html0000644000175000017500000026732213055210752027012 0ustar00arminarmin00000000000000 InfXmppConnection: libinfinity-0.7 Reference Manual

InfXmppConnection

InfXmppConnection — Implementation of the XMPP core protocol

Stability Level

Unstable, unless otherwise indicated

Properties

InfCertificateCredentials * credentials Read / Write / Construct
gchar * local-hostname Read / Write / Construct Only
gchar * remote-hostname Read / Write / Construct Only
InfSaslContext * sasl-context Read / Write / Construct
gchar * sasl-mechanisms Read / Write / Construct
InfXmppConnectionSecurityPolicy security-policy Read / Write / Construct Only
InfXmppConnectionSite site Read / Write / Construct Only
InfTcpConnection * tcp-connection Read / Write / Construct Only
gboolean tls-enabled Read

Object Hierarchy

    GEnum
    ├── InfXmppConnectionSecurityPolicy
    ╰── InfXmppConnectionSite
    GObject
    ╰── InfXmppConnection

Implemented Interfaces

InfXmppConnection implements InfXmlConnection.

Includes

#include <libinfinity/common/inf-xmpp-connection.h>

Description

This class implements the XMPP protocol as defined by RFC 3920. It handles the authentication and authorization. Once the connection is established, XML messages can be sent and received with the API of the InfXmlConnection interface.

Note that any sort of XML messages can be exchanged, and that the XML does not need to adhere to the XMPP standard. It is in the responsibility of the user of this class to send only XML message that the remote counterpart can understand.

Functions

InfXmppConnectionCrtCallback ()

void
(*InfXmppConnectionCrtCallback) (InfXmppConnection *xmpp,
                                 gnutls_session_t session,
                                 InfCertificateChain *chain,
                                 gpointer user_data);

Specifies the callback signature for the certificate callback set with inf_xmpp_connection_set_certificate_callback(). The callback should decide whether to trust the certificate in chain or not.

Parameters

xmpp

The InfXmppConnection validating a certificate.

 

session

The underlying GnuTLS session.

 

chain

The certificate chain presented by the remote host.

 

user_data

Additional data supplied when inf_xmpp_connection_set_certificate_callback() was called.

 

inf_xmpp_connection_error_quark ()

GQuark
inf_xmpp_connection_error_quark (void);

Error domain for generic connection errors. Errors in this domain will be from the InfXmppConnectionError enumeration. See GError for information on error domains.


inf_xmpp_connection_new ()

InfXmppConnection *
inf_xmpp_connection_new (InfTcpConnection *tcp,
                         InfXmppConnectionSite site,
                         const gchar *local_hostname,
                         const gchar *remote_hostname,
                         InfXmppConnectionSecurityPolicy security_policy,
                         InfCertificateCredentials *creds,
                         InfSaslContext *sasl_context,
                         const gchar *sasl_mechanisms);

Creates a new InfXmppConnection with tcp as communication channel. No attempt is being made to open tcp , if it is not already open. However, communication is initiated as soon as tcp gets into INF_TCP_CONNECTION_CONNECTED state, so you might still open it lateron yourself.

local_hostname specifies the hostname of the local host, and remote_hostname specifies the hostname of the remote host, as known to the caller. These can be a string representation of the IP address of tcp , or a DNS name such as "example.com". local_hostname can be NULL in which case the host name as reported by g_get_host_name() is used.

creds may be NULL in which case the connection creates the credentials as soon as they are required. However, this only works if site is INF_XMPP_CONNECTION_CLIENT or security_policy is INF_XMPP_CONNECTION_SECURITY_ONLY_UNSECURED (or both, of course). For server connections creds must contain a valid server certificate in case security_policy is not INF_XMPP_CONNECTION_SECURITY_ONLY_UNSECURED. creds can contain a certificate for the client site and, if so, is used for client authentication.

If sasl_context is NULL, InfXmppConnection uses a built-in context that only supports ANONYMOUS authentication. In sasl_context 's callback function, the InfXmppConnection for which the authentication shall be performed can be accessed via the session_data parameter of InfSaslContextCallbackFunc.

If sasl_context is not NULL, then the sasl_mechanisms parameter defines what SASL mechanisms are used. On the server side, these are the mechanisms offered to the client, and on the client side, these are the accepted mechanisms (meaning that if a server does not offer any of these, the connection will be closed). If sasl_context is NULL, then this parameter is ignored. sasl_mechanisms can be NULL in which case all available mechanisms are accepted or offered, respectively.

[constructor]

Parameters

tcp

The underlaying TCP connection to use.

 

site

Whether this is a XMPP client or server.

 

local_hostname

The hostname of the local host, or NULL.

[allow-none]

remote_hostname

The hostname of the remote host.

 

security_policy

Whether to use (or offer, as a server) TLS. See InfXmppConnectionSecurityPolicy for the meaning of this parameter.

 

creds

Certificate credentials used to secure the communication.

[allow-none]

sasl_context

A SASL context used for authentication.

[allow-none]

sasl_mechanisms

A whitespace-separated list of SASL mechanisms to accept/offer, or NULL.

[allow-none]

Returns

A new InfXmppConnection.

[transfer full]


inf_xmpp_connection_get_tls_enabled ()

gboolean
inf_xmpp_connection_get_tls_enabled (InfXmppConnection *xmpp);

Returns whether TLS encryption is enabled for xmpp . This returns TRUE as soon as the TLS handshake is completed but before the server certificate was verified (see inf_xmpp_connection_set_certificate_callback()).

Parameters

xmpp

A InfXmppConnection.

 

Returns

TRUE if TLS is enabled and FALSE otherwise.


inf_xmpp_connection_get_own_certificate ()

gnutls_x509_crt_t
inf_xmpp_connection_get_own_certificate
                               (InfXmppConnection *xmpp);

Returns the local host's certificate that was used to authenticate with the remote host, or NULL if no certificate was used. This function can only be used after the TLS handshake has completed, see inf_xmpp_connection_get_tls_enabled().

Parameters

xmpp

A InfXmppConnection.

 

Returns

The certificate of the local host. The returned value should not be freed, it is owned by the InfXmppConnection.

[transfer none]


inf_xmpp_connection_get_peer_certificate ()

InfCertificateChain *
inf_xmpp_connection_get_peer_certificate
                               (InfXmppConnection *xmpp);

Returns the certificate chain that the remote host authenticated itself with. This function can only be used after the TLS handshake has completed, see inf_xmpp_connection_get_tls_enabled().

Parameters

xmpp

A InfXmppConnection.

 

Returns

The certificate chain of the remote host. The returned value should not be freed, it is owned by the InfXmppConnection.

[transfer none]


inf_xmpp_connection_get_kx_algorithm ()

gnutls_kx_algorithm_t
inf_xmpp_connection_get_kx_algorithm (InfXmppConnection *xmpp);

Returns the key exchange algorithm used for this connection. This function can only be used if inf_xmpp_connection_get_tls_enabled() returns true.

Parameters

xmpp

A InfXmppConnection.

 

Returns

The key exchange algorithm used.


inf_xmpp_connection_get_cipher_algorithm ()

gnutls_cipher_algorithm_t
inf_xmpp_connection_get_cipher_algorithm
                               (InfXmppConnection *xmpp);

Returns the cipher algorithm used for this connection. This function can only be used if inf_xmpp_connection_get_tls_enabled() returns true.

Parameters

xmpp

A InfXmppConnection.

 

Returns

The cipher algorithm used.


inf_xmpp_connection_get_mac_algorithm ()

gnutls_mac_algorithm_t
inf_xmpp_connection_get_mac_algorithm (InfXmppConnection *xmpp);

Returns the MAC algorithm used for this connection. This function can only be used if inf_xmpp_connection_get_tls_enabled() returns true.

Parameters

xmpp

A InfXmppConnection.

 

Returns

The MAC algorithm used.


inf_xmpp_connection_get_tls_protocol ()

gnutls_protocol_t
inf_xmpp_connection_get_tls_protocol (InfXmppConnection *xmpp);

Returns the TLS protocol version used for this connection. This function can only be used if inf_xmpp_connection_get_tls_enabled() returns true.

Parameters

xmpp

A InfXmppConnection.

 

Returns

The TLS protocol version used.


inf_xmpp_connection_get_dh_prime_bits ()

guint
inf_xmpp_connection_get_dh_prime_bits (InfXmppConnection *xmpp);

Returns the number of prime bits used for the Diffie-Hellman group if a key exchange algorithm based on Diffie-Hellman is used. Otherwise, 0 is returned. This function can only be used if inf_xmpp_connection_get_tls_enabled() returns true.

Parameters

xmpp

A InfXmppConnection.

 

Returns

The number of Diffie-Hellman prime bits.


inf_xmpp_connection_set_certificate_callback ()

void
inf_xmpp_connection_set_certificate_callback
                               (InfXmppConnection *xmpp,
                                gnutls_certificate_request_t req,
                                InfXmppConnectionCrtCallback cb,
                                gpointer user_data,
                                GDestroyNotify notify);

This function sets a callback that is called when the connection needs to verify the peer's certificate. It does not need to respond immediately, but can, for example, show a dialog to a user and continue when the user finished with it.

When the certificate is trusted, then call inf_xmpp_connection_certificate_verify_continue(), otherwise inf_xmpp_connection_certificate_verify_cancel(). This can happen in the callback or some time later. The connection process is stopped until either of these functions is called.

Note that the function is also called if the peer did not send a certificate, in which case the certificate chain parameter in the callback will be NULL.

If cb is NULL, or this function has not been called before a certificate needs to be verified, then the certificate is always trusted.

Parameters

xmpp

A InfXmppConnection.

 

req

Whether to request a client certificate from the peer.

[type int]

cb

Function to be called to verify the peer's certificate, or NULL.

[allow-none]

user_data

Additional data to pass to the callback function.

 

notify

Function to call to free the user data, or NULL.

[allow-none]

inf_xmpp_connection_certificate_verify_continue ()

void
inf_xmpp_connection_certificate_verify_continue
                               (InfXmppConnection *xmpp);

Call this function when your callback set in inf_xmpp_connection_set_certificate_callback() was called and you do trust the peer's certificate. The connection process will then continue.

Parameters

xmpp

A InfXmppConnection.

 

inf_xmpp_connection_certificate_verify_cancel ()

void
inf_xmpp_connection_certificate_verify_cancel
                               (InfXmppConnection *xmpp,
                                const GError *error);

Call this function when your callback set in inf_xmpp_connection_set_certificate_callback() was called and you do not trust the peer's certificate. The connection will then be closed with a corresponding error.

If error is non-NULL, then it should contain a reason why the certificate was not trusted. If you verified the peer's certificate with gnutls_certificate_verify_peers2(), or gnutls_x509_crt_list_verify(), then a corresponding error can be generated with the verification result with inf_gnutls_certificate_verification_set_error(). The reason is then shown to the local user.

Parameters

xmpp

A InfXmppConnection.

 

error

Reason why the certificate is not trusted, or NULL.

 

inf_xmpp_connection_reset_sasl_authentication ()

void
inf_xmpp_connection_reset_sasl_authentication
                               (InfXmppConnection *xmpp,
                                InfSaslContext *new_context,
                                const gchar *new_mechanisms);

Sets a new SASL context and mechanisms to use for authentication. This does not have any effect if authentication has already been performed. This can be useful if a server decides to use a stricter authentication policy and gets away with its previous SASL context. If new_context is NULL, then a built-in SASL context is used which only accepts anonymous authentication.

If the authentication is currently in progress then it is aborted. The server sends an INF_XMPP_CONNECTION_AUTH_ERROR_TEMPORARY_AUTH_FAILURE error to the client with INF_AUTHENTICATION_DETAIL_ERROR_TRY_AGAIN detail (see inf_xmpp_connection_get_sasl_error()).

On the client side, if authentication is in progress, a request to abort the authentication is sent to the server. The server will then reply with an INF_XMPP_CONNECTION_AUTH_ERROR_ABORTED error. In the signal handler of the “error†signal you should reinitiate the authentication with inf_xmpp_connection_retry_sasl_authentication() or the connection will be closed. It is also possible that the final authentication request has already been sent, and the server replies with successful authentication instead. In that case calling this function will have no effect apart from closing and reopening the connection will use the new context and mechanisms.

Parameters

xmpp

A InfXmppConnection.

 

new_context

The new sasl context to set, or NULL.

[allow-none]

new_mechanisms

Allowed SASL mechanisms to use. Ignored if new_context is NULL.

[allow-none]

inf_xmpp_connection_retry_sasl_authentication ()

gboolean
inf_xmpp_connection_retry_sasl_authentication
                               (InfXmppConnection *xmpp,
                                GError **error);

When SASL authentication failed then the “error†signal is emitted with an error from the INF_XMPP_CONNECTION_AUTH_ERROR domain. If the signal handler wants to retry authentication then it should call this function, possibly modifying the “sasl-mechanisms†property before. If this function is not called then the connection will terminate.

The function can fail if the server does not support any of the available mechanisms given in “sasl-mechanismsâ€. If so, the function returns FALSE and error is set.

Parameters

xmpp

A InfXmppConnection.

 

error

Location to store error information, if any.

 

Returns

TRUE if auth retry is being performed, FALSE otherwise.


inf_xmpp_connection_set_sasl_error ()

void
inf_xmpp_connection_set_sasl_error (InfXmppConnection *xmpp,
                                    const GError *error);

Sets the SASL error of xmpp . The SASL error is an additional hint of what went wrong during authentication. It should be set on the server side in the gsasl callback checking the user authentication. If on the client side “error†is emitted with an error from the INF_XMPP_CONNECTION_AUTH_ERROR domain then inf_xmpp_connection_get_sasl_error() can be used to obtain more detailed error information.

Parameters

xmpp

A InfXmppConnection.

 

error

The SASL error to set.

 

inf_xmpp_connection_get_sasl_error ()

const GError *
inf_xmpp_connection_get_sasl_error (InfXmppConnection *xmpp);

Gets the SASL error of xmpp . See inf_xmpp_connection_set_sasl_error().

Parameters

xmpp

A InfXmppConnection.

 

Returns

A pointer to a GError object owned by xmpp .

Types and Values

enum InfXmppConnectionSite

Specifies whether the local site of the connection is a client or a server.

Members

INF_XMPP_CONNECTION_SERVER

The local site of this connection is an XMPP server and the remote counterpart is a client.

 

INF_XMPP_CONNECTION_CLIENT

The local site of this connection is a XMPP client and the remote counterpart is a server.

 

enum InfXmppConnectionSecurityPolicy

The InfXmppConnectionSecurityPolicy enumeration specifies various options of how to deal with the other site allowing or requiring TLS-secured connections. Note that if the local site is a server, then INF_XMPP_CONNECTION_SECURITY_BOTH_PREFER_UNSECURED and INF_XMPP_CONNECTION_SECURITY_BOTH_PREFER_TLS are equivalent.

Members

INF_XMPP_CONNECTION_SECURITY_ONLY_UNSECURED

In the case of a server, do not offer TLS to the client. As a client, only connect if the server does not require TLS.

 

INF_XMPP_CONNECTION_SECURITY_ONLY_TLS

In the case of a server, require all connections to be TLS-secured. As a client, only connect if the server supports TLS.

 

INF_XMPP_CONNECTION_SECURITY_BOTH_PREFER_UNSECURED

In the case of a server, offer both unsecured and secured messaging to the client. As a client, use unsecured communication unless TLS is required by the server.

 

INF_XMPP_CONNECTION_SECURITY_BOTH_PREFER_TLS

In the case of a server, offer both unsecured and secured messaging to the client. As a client, use TLS unless not supported by the server.

 

enum InfXmppConnectionError

Specifies the error codes in the INF_XMPP_CONNECTION_ERROR error domain.

Members

INF_XMPP_CONNECTION_ERROR_TLS_UNSUPPORTED

Server does not support TLS, but the security policy is set to INF_XMPP_CONNECTION_SECURITY_ONLY_TLS.

 

INF_XMPP_CONNECTION_ERROR_TLS_REQUIRED

The server requires TLS, but the security policy is set to INF_XMPP_CONNECTION_SECURITY_ONLY_UNSECURED.

 

INF_XMPP_CONNECTION_ERROR_TLS_FAILURE

Server cannot proceed with the TLS handshake.

 

INF_XMPP_CONNECTION_ERROR_NO_CERTIFICATE_PROVIDED

The server did not provide a certificate.

 

INF_XMPP_CONNECTION_ERROR_CERTIFICATE_NOT_TRUSTED

The server certificate is not trusted. Whether the server certificate is trusted or not is defined by the API user, by providing a certificate callback with inf_xmpp_connection_set_certificate_callback().

 

INF_XMPP_CONNECTION_ERROR_AUTHENTICATION_UNSUPPORTED

The server does not provide any authentication mechanisms.

 

INF_XMPP_CONNECTION_ERROR_NO_SUITABLE_MECHANISM

The server does not offer a suitable authentication mechanism that is accepted by the client.

 

INF_XMPP_CONNECTION_ERROR_FAILED

General error code for otherwise unknown errors.

 

enum InfXmppConnectionStreamError

Specifies the error codes in the INF_XMPP_CONNECTION_STREAM_ERROR error domain. These errors correspond to the ones defined in RFC 3920, section 4.7.3.

Members

INF_XMPP_CONNECTION_STREAM_ERROR_BAD_FORMAT

The entity has sent XML that cannot be processed.

 

INF_XMPP_CONNECTION_STREAM_ERROR_BAD_NAMESPACE_PREFIX

The entity has sent a namespace prefix that is unsupported, or has sent no namespace prefix on an element that requires such a prefix.

 

INF_XMPP_CONNECTION_STREAM_ERROR_CONFLICT

The server is closing the active stream for this entity because a new stream has been initiated that conflicts with the existing stream.

 

INF_XMPP_CONNECTION_STREAM_ERROR_CONNECTION_TIMEOUT

The entity has not generated any traffic over the stream for some period of time.

 

INF_XMPP_CONNECTION_STREAM_ERROR_HOST_GONE

The value of the 'to' attribute provided by the initiating entity in the stream header corresponds to a hostname that is no longer hosted by the server.

 

INF_XMPP_CONNECTION_STREAM_ERROR_HOST_UNKNOWN

The value of the 'to' attribute provided by the initiating entity in the stream header does not correspond to a hostname that is hosted by the server.

 

INF_XMPP_CONNECTION_STREAM_ERROR_IMPROPER_ADDRESSING

A stanza sent between two servers lacks a 'to' or 'from' attribute.

 

INF_XMPP_CONNECTION_STREAM_ERROR_INTERNAL_SERVER_ERROR

The server has experienced a misconfiguration or an otherwise-undefined internal error that prevents it from servicing the stream.

 

INF_XMPP_CONNECTION_STREAM_ERROR_INVALID_FROM

The JID or hostname provided in a 'from' address does not match an authorized JID or validated domain negotiated between servers via SASL or dialback, or between a client and a server via authentication and resource binding.

 

INF_XMPP_CONNECTION_STREAM_ERROR_INVALID_ID

The stream ID or dialback ID is invalid or does not match an ID previously provided.

 

INF_XMPP_CONNECTION_STREAM_ERROR_INVALID_NAMESPACE

The streams namespace is something other than http://etherx.jabber.org/streams or the dialback namespace name is something other than jabber:server:dialback.

 

INF_XMPP_CONNECTION_STREAM_ERROR_INVALID_XML

The entity has sent invalid XML over the stream to a server that performs validation.

 

INF_XMPP_CONNECTION_STREAM_ERROR_NOT_AUTHORIZED

The entity has attempted to send data before the stream has been authenticated, or otherwise is not authorized to perform an action related to stream negotiation.

 

INF_XMPP_CONNECTION_STREAM_ERROR_POLICY_VIOLATION

The entity has violated some local service policy.

 

INF_XMPP_CONNECTION_STREAM_ERROR_REMOTE_CONNECTION_FAILED

The server is unable to properly connect to a remote entity that is required for authentication or authorization.

 

INF_XMPP_CONNECTION_STREAM_ERROR_RESOURCE_CONSTRAINT

The server lacks the system resources necessary to service the stream.

 

INF_XMPP_CONNECTION_STREAM_ERROR_RESTRICTED_XML

The entity has attempted to send restricted XML features.

 

INF_XMPP_CONNECTION_STREAM_ERROR_SEE_OTHER_HOST

The server will not provide service to the initiating entity but is redirecting traffic to another host.

 

INF_XMPP_CONNECTION_STREAM_ERROR_SYSTEM_SHUTDOWN

The server is being shut down and all active streams are being closed.

 

INF_XMPP_CONNECTION_STREAM_ERROR_UNDEFINED_CONDITION

The error condition is not one of those defined by the other conditions.

 

INF_XMPP_CONNECTION_STREAM_ERROR_UNSUPPORTED_ENCODING

The initiating entity has encoded the stream in an encoding that is not supported by the server.

 

INF_XMPP_CONNECTION_STREAM_ERROR_UNSUPPORTED_STANZA_TYPE

The initiating entity has sent a first-level child of the stream that is not supported by the server.

 

INF_XMPP_CONNECTION_STREAM_ERROR_UNSUPPORTED_VERSION

The value of the 'version' attribute provided by the initiating entity in the stream header specifies a version of XMPP that is not supported by the server.

 

INF_XMPP_CONNECTION_STREAM_ERROR_XML_NOT_WELL_FORMED

The initiating entity has sent XML that is not well-formed.

 

INF_XMPP_CONNECTION_STREAM_ERROR_FAILED

General error code for otherwise unknown errors.

 

enum InfXmppConnectionAuthError

Specifies the error codes in the INF_XMPP_CONNECTION_AUTH_ERROR error domain. These errors correspond to the ones defined in RFC 3920, section 6.4.

Members

INF_XMPP_CONNECTION_AUTH_ERROR_ABORTED

The receiving entity acknowledged an <abort/> element sent by the initiating entity.

 

INF_XMPP_CONNECTION_AUTH_ERROR_INCORRECT_ENCODING

The data provided by the initiating entity could not be processed because the Base64 encoding is incorrect.

 

INF_XMPP_CONNECTION_AUTH_ERROR_INVALID_AUTHZID

The authzid provided by the initiating entity is invalid, either because it is incorrectly formatted or because the initiating entity does not have permissions to authorize that ID.

 

INF_XMPP_CONNECTION_AUTH_ERROR_INVALID_MECHANISM

The initiating entity did not provide a mechanism or requested a mechanism that is not supported by the receiving entity.

 

INF_XMPP_CONNECTION_AUTH_ERROR_MECHANISM_TOO_WEAK

The mechanism requsted by the initiating entity is weaker than server policy permits for that initiating entity.

 

INF_XMPP_CONNECTION_AUTH_ERROR_NOT_AUTHORIZED

The authentication failed because the initiating entity did not provide valid credentials.

 

INF_XMPP_CONNECTION_AUTH_ERROR_TEMPORARY_AUTH_FAILURE

The authentication failed because of a temporary error condition within the receiving entity.

 

INF_XMPP_CONNECTION_AUTH_ERROR_FAILED

General error code for otherwise unknown errors.

 

struct InfXmppConnection

struct InfXmppConnection;

InfXmppConnection is an opaque data type. You should only access it via the public API functions.


struct InfXmppConnectionClass

struct InfXmppConnectionClass {
};

This structure does not contain any public fields.

Property Details

The “credentials†property

  “credentials†             InfCertificateCredentials *

The certificate credentials for GnuTLS.

Flags: Read / Write / Construct


The “local-hostname†property

  “local-hostname†          gchar *

The hostname of the local host.

Flags: Read / Write / Construct Only

Default value: NULL


The “remote-hostname†property

  “remote-hostname†         gchar *

The hostname of the remote host.

Flags: Read / Write / Construct Only

Default value: NULL


The “sasl-context†property

  “sasl-context†            InfSaslContext *

The SASL context used for authentication.

Flags: Read / Write / Construct


The “sasl-mechanisms†property

  “sasl-mechanisms†         gchar *

Whitespace separated list of SASL mechanisms to accept/offer.

Flags: Read / Write / Construct

Default value: NULL


The “security-policy†property

  “security-policy†         InfXmppConnectionSecurityPolicy

How to choose whether to use (or offer, as a server) TLS.

Flags: Read / Write / Construct Only

Default value: INF_XMPP_CONNECTION_SECURITY_BOTH_PREFER_TLS


The “site†property

  “site†                    InfXmppConnectionSite

Site of the connection (client or server).

Flags: Read / Write / Construct Only

Default value: INF_XMPP_CONNECTION_CLIENT


The “tcp-connection†property

  “tcp-connection†          InfTcpConnection *

Underlaying TCP connection.

Flags: Read / Write / Construct Only


The “tls-enabled†property

  “tls-enabled†             gboolean

Whether TLS is enabled for the connection or not.

Flags: Read

Default value: FALSE

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfAdoptedUser.html0000644000000000000000000000013213055210752025517 xustar0030 mtime=1488261610.896090682 30 atime=1488261610.896090682 30 ctime=1488261610.896090682 libinfinity-0.7.1/docs/reference/libinfinity/html/InfAdoptedUser.html0000644000175000017500000004165113055210752026260 0ustar00arminarmin00000000000000 InfAdoptedUser: libinfinity-0.7 Reference Manual

InfAdoptedUser

InfAdoptedUser — User in a InfAdoptedUser.

Stability Level

Unstable, unless otherwise indicated

Properties

InfAdoptedRequestLog * request-log Read / Write / Construct Only
InfAdoptedStateVector * vector Read / Write

Types and Values

Object Hierarchy

    GObject
    ╰── InfUser
        ╰── InfAdoptedUser

Includes

#include <libinfinity/adopted/inf-adopted-user.h>

Description

InfAdoptedUser is a InfUser-derived class that is used in InfAdoptedSession. It holds all user-specific information that is needed by InfAdoptedAlgorithm to handle the concurrency control. This includes the user's request log which stores all the requests made by the user and a state vector which specifies the document state that the user has, as known to the local host. This information is extracted from the most recent request received from the user.

Functions

inf_adopted_user_get_component ()

guint
inf_adopted_user_get_component (InfAdoptedUser *user,
                                guint id);

Returns the amount of requests user is guaranteed to have processed from the user with ID id .

Parameters

user

A InfAdoptedUser.

 

id

The component to retrieve.

 

Returns

The number of requests user has processed from id .


inf_adopted_user_get_vector ()

InfAdoptedStateVector *
inf_adopted_user_get_vector (InfAdoptedUser *user);

Returns the current vector time of user .

Parameters

user

A InfAdoptedUser.

 

Returns

The current vector time of user .

[transfer none]


inf_adopted_user_set_vector ()

void
inf_adopted_user_set_vector (InfAdoptedUser *user,
                             InfAdoptedStateVector *vec);

Updates the state vector of user . This function takes ownership of vec .

Parameters

user

A InfAdoptedUser.

 

vec

A InfAdoptedStateVector.

 

inf_adopted_user_get_request_log ()

InfAdoptedRequestLog *
inf_adopted_user_get_request_log (InfAdoptedUser *user);

Returns the request log of user .

Parameters

user

A InfAdoptedUser.

 

Returns

User's InfAdoptedRequestLog.

[transfer none]

Types and Values

InfAdoptedUser

typedef struct _InfAdoptedUser InfAdoptedUser;

InfAdoptedUser is an opaque data type. You should only access it via the public API functions.


struct InfAdoptedUserClass

struct InfAdoptedUserClass {
};

This structure does not contain any public fields.

Property Details

The “request-log†property

  “request-log†             InfAdoptedRequestLog *

Request log of this user.

Flags: Read / Write / Construct Only


The “vector†property

  “vector†                  InfAdoptedStateVector *

The state this user is currently at.

Flags: Read / Write

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/libinfinity-0.7-InfdNotePlugin.ht0000644000000000000000000000013213055210752030017 xustar0030 mtime=1488261610.896090682 30 atime=1488261610.896090682 30 ctime=1488261610.896090682 libinfinity-0.7.1/docs/reference/libinfinity/html/libinfinity-0.7-InfdNotePlugin.html0000644000175000017500000002253113055210752031105 0ustar00arminarmin00000000000000 InfdNotePlugin: libinfinity-0.7 Reference Manual

InfdNotePlugin

InfdNotePlugin

Types and Values

Description

Functions

InfdNotePluginSessionNew ()

InfSession *
(*InfdNotePluginSessionNew) (InfIo *Param1,
                             InfCommunicationManager *Param2,
                             InfSessionStatus Param3,
                             InfCommunicationGroup *Param4,
                             InfXmlConnection *Param5,
                             const char *Param6,
                             gpointer Param7);


InfdNotePluginSessionRead ()

InfSession *
(*InfdNotePluginSessionRead) (InfdStorage *Param1,
                              InfIo *Param2,
                              InfCommunicationManager *Param3,
                              const gchar *Param4,
                              gpointer Param5,
                              GError **Param6);


InfdNotePluginSessionWrite ()

gboolean
(*InfdNotePluginSessionWrite) (InfdStorage *Param1,
                               InfSession *Param2,
                               const gchar *Param3,
                               gpointer Param4,
                               GError **Param5);

Types and Values

struct InfdNotePlugin

struct InfdNotePlugin {
  gpointer user_data;

  /* The typename of the storage backend this plugin can be used with, such
   * as InfdFilesystemStorage. */
  const gchar* storage_type;

  /* The note type this plugin handles, such as InfText */
  const gchar* note_type;

  InfdNotePluginSessionNew session_new;
  InfdNotePluginSessionRead session_read;
  InfdNotePluginSessionWrite session_write;
};

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfBuffer.html0000644000000000000000000000013213055210752024511 xustar0030 mtime=1488261610.896090682 30 atime=1488261610.896090682 30 ctime=1488261610.896090682 libinfinity-0.7.1/docs/reference/libinfinity/html/InfBuffer.html0000644000175000017500000003075013055210752025250 0ustar00arminarmin00000000000000 InfBuffer: libinfinity-0.7 Reference Manual

InfBuffer

InfBuffer — Abstract document interface

Properties

gboolean modified Read / Write

Types and Values

Object Hierarchy

    GInterface
    ╰── InfBuffer

Prerequisites

InfBuffer requires GObject.

Known Implementations

InfBuffer is implemented by InfChatBuffer.

Includes

#include <libinfinity/common/inf-buffer.h>

Description

InfBuffer represents a document containing a session's content. It does not cope with keeping its content in-sync with other participants but just offers an interface to modify the document.

The InfBuffer interface itself is probably not too useful, but actual documents implementing functionality (such as text editing or graphics editing) need to implement this interface to be passed to InfSession.

Functions

inf_buffer_get_modified ()

gboolean
inf_buffer_get_modified (InfBuffer *buffer);

Indicates whether the buffer has been modified since the last call to inf_buffer_set_modified() set the modification flag to FALSE.

Parameters

buffer

A InfBuffer.

 

Returns

Whether the buffer has been modified.


inf_buffer_set_modified ()

void
inf_buffer_set_modified (InfBuffer *buffer,
                         gboolean modified);

Sets the modification flag of buffer to modified . You should normally set the flag to FALSE every time the document is saved onto disk. The buffer itself will set it to TRUE when it has been changed.

To get notified when the modification flag changes, connect to GObject::notify for the InfBuffer:modified property.

Parameters

buffer

A InfBuffer.

 

modified

Whether the buffer is considered modified or not.

 

Types and Values

InfBuffer

typedef struct _InfBuffer InfBuffer;

InfBuffer is an opaque data type. You should only access it via the public API functions.


struct InfBufferInterface

struct InfBufferInterface {
  gboolean (*get_modified)(InfBuffer* buffer);

  void (*set_modified)(InfBuffer* buffer,
                       gboolean modified);
};

The virtual methods of InfBuffer.

Members

get_modified ()

Returns whether the buffer has been modified since the last call to set_modified set modified flag to FALSE.

 

set_modified ()

Set the current modified state of the buffer.

 

Property Details

The “modified†property

  “modified†                gboolean

Whether the buffer was modified since it has been saved.

Flags: Read / Write

Default value: FALSE

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfdSessionProxy.html0000644000000000000000000000013213055210752026131 xustar0030 mtime=1488261610.896090682 30 atime=1488261610.896090682 30 ctime=1488261610.896090682 libinfinity-0.7.1/docs/reference/libinfinity/html/InfdSessionProxy.html0000644000175000017500000011302213055210752026662 0ustar00arminarmin00000000000000 InfdSessionProxy: libinfinity-0.7 Reference Manual

InfdSessionProxy

InfdSessionProxy — Server-side session management

Stability Level

Unstable, unless otherwise indicated

Properties

gboolean idle Read
InfIo * io Read / Write / Construct Only
InfCommunicationHostedGroup * subscription-group Read / Write / Construct Only

Types and Values

Object Hierarchy

    GObject
    ╰── InfdSessionProxy

Implemented Interfaces

InfdSessionProxy implements InfCommunicationObject and InfSessionProxy.

Includes

#include <libinfinity/server/infd-session-proxy.h>

Description

InfdSessionProxy is a manager for InfSession that is specific for the server side. The InfdSessionProxy manages exactly one InfSession. It is usually created by InfdDirectory when the content of a node is requested.

InfdSessionProxy allows to perform server-specific operations for the session it manages, such as joining a local user, or removing a connection from the list of subscribed connections. In addition it handles requests made by its counterpart, InfcSessionProxy, for the client side, such as remote user joins.

InfdSessionProxy implements the InfSessionProxy interface, which can be used to access the underlying InfSession or to join a local user.

Functions

infd_session_proxy_subscribe_to ()

void
infd_session_proxy_subscribe_to (InfdSessionProxy *proxy,
                                 InfXmlConnection *connection,
                                 guint seq_id,
                                 gboolean synchronize);

Subscribes connection to proxy 's session. The first thing that will be done is a synchronization (see inf_session_synchronize_to()). Then, all changes to the session are propagated to connection .

seq_id should be a unique number for connection , and the same number must be passed on the client side to the InfcSessionProxy object. Normally InfdDirectory and InfcBrowser take care of choosing an appropriate sequence identifier.

Normally, you want to set synchronize to TRUE in which case the whole session state will be synchronized to connection (within the subscription group). However, if for whatever reason the remote site already has a copy of the session, then you may set synchronize to FALSE to skip synchronization. This happens for example for newly created documents, or when the remote site synchronized the local site and wants to be initially subscribed.

If proxy 's session is not in INF_SESSION_RUNNING status, but in INF_SESSION_SYNCHRONIZING, then connection must be the connection that synchronizes the session and synchronize needs to be set to FALSE. This causes the synchronizing connection to initially be subscribed. This needs to be called directly after having created the session proxy (i.e. without returning to the main loop before) so that the synchronization connection is added to the subscription group for synchronization.

Otherwise a subscription can only be initiated if proxy 's session is in state INF_SESSION_RUNNING.

Parameters

proxy

A InfdSessionProxy.

 

connection

A InfXmlConnection that is not yet subscribed.

 

seq_id

The sequence identifier for connection .

 

synchronize

If TRUE, then synchronize the session to connection first.

 

infd_session_proxy_unsubscribe ()

void
infd_session_proxy_unsubscribe (InfdSessionProxy *proxy,
                                InfXmlConnection *connection);

Unsubscribes a subscribed connection from proxy 's session. This will prevent all users joined via connection to continue modifying the session's buffer, and it will cancel ongoing synchronization to connection , if not yet finished.

Parameters

proxy

A InfdSessionProxy.

 

connection

The InfXmlConnection to unsubscribe.

 

infd_session_proxy_has_subscriptions ()

gboolean
infd_session_proxy_has_subscriptions (InfdSessionProxy *proxy);

Returns whether there are subscribed connections to the session.

Parameters

proxy

A InfdSessionProxy.

 

Returns

Whether there are subscribed connections.


infd_session_proxy_is_subscribed ()

gboolean
infd_session_proxy_is_subscribed (InfdSessionProxy *proxy,
                                  InfXmlConnection *connection);

Returns TRUE when connection is subscribed to the session and FALSE otherwise.

Parameters

proxy

A InfdSessionProxy.

 

connection

The connection to check for being subscribed.

 

Returns

Whether connection is subscribed.


infd_session_proxy_is_idle ()

gboolean
infd_session_proxy_is_idle (InfdSessionProxy *proxy);

Returns whether the session is idle. The session is considered idle when there are no subscriptions and no synchronizations (in either direction).

Parameters

proxy

A InfdSessionProxy.

 

Returns

Whether the session is idle.

Types and Values

struct InfdSessionProxy

struct InfdSessionProxy;

InfdSessionProxy is an opaque data type. You should only access it via the public API functions.


struct InfdSessionProxyClass

struct InfdSessionProxyClass {
  /* Signals */
  void (*add_subscription)(InfdSessionProxy* proxy,
                           InfXmlConnection* connection,
                           guint seq_id);

  void (*remove_subscription)(InfdSessionProxy* proxy,
                              InfXmlConnection* connection);

  gboolean (*reject_user_join)(InfdSessionProxy* proxy,
                               InfXmlConnection* connection,
                               const GArray* user_properties,
                               InfUser* rejoin_user);
};

This structure contains the default signal handlers of the InfdSessionProxy class.

Members

add_subscription ()

Default signal handler for the “add-subscription†signal.

 

remove_subscription ()

Default signal handler for the “remove-subscription†signal.

 

reject_user_join ()

Default signal handler for the “reject-user-join†signal.

 

Property Details

The “idle†property

  “idle†                    gboolean

The session is considered idle when are no subscriptions and no synchronizations.

Flags: Read

Default value: TRUE


The “io†property

  “io†                      InfIo *

The InfIo object for scheduling events.

Flags: Read / Write / Construct Only


The “subscription-group†property

  “subscription-group†      InfCommunicationHostedGroup *

The communication manager group of subscribed connections.

Flags: Read / Write / Construct Only

Signal Details

The “add-subscription†signal

void
user_function (InfdSessionProxy *proxy,
               InfXmlConnection *connection,
               guint             seq_id,
               gpointer          user_data)

Emitted every time a connection is subscribed to the session.

Parameters

proxy

The InfdSessionProxy emitting the signal.

 

connection

The subscribed InfXmlConnection.

 

seq_id

The sequence identifier for connection as passed to infd_session_proxy_subscribe_to().

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last


The “reject-user-join†signal

gboolean
user_function (InfdSessionProxy *proxy,
               InfXmlConnection *connection,
               GArray           *user_properties,
               InfUser          *rejoin_user,
               gpointer          user_data)

This signal is emitted before every remote user join. The signal handler can return TRUE in which case the InfdSessionProxy does not allow the user join with INF_REQUEST_ERROR_NOT_AUTHORIZED error. If there is more than one signal handler, then if one of them returns TRUE the user join is rejected.

The user_properties parameter is a GArray of GParameter values. It contains the construct properties for the InfUser object that would be created if the user join is not rejected. It must not be modified, but it can be used to make the decision whether to reject the user join or not dependent on the parameters, such as allowing the user join only if the user has a predefined name. The function inf_session_lookup_user_property() can be used to look up a named parameter in the array.

Parameters

proxy

The InfdSessionProxy emitting the signal.

 

connection

A subscribed InfXmlConnection requesting the user join.

 

user_properties

An array with the properties for the new user.

 

rejoin_user

The existing unavailable user that is being rejoined, or NULL.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last


The “remove-subscription†signal

void
user_function (InfdSessionProxy *proxy,
               InfXmlConnection *connection,
               gpointer          user_data)

Emitted every time a connection is unsubscribed to the session, or a subscription is removed because the session is closed.

Parameters

proxy

The InfdSessionProxy emitting the signal.

 

connection

The unsubscribed InfXmlConnection.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last

See Also

InfSession

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfAdoptedRequest.html0000644000000000000000000000013213055210752026231 xustar0030 mtime=1488261610.896090682 30 atime=1488261610.896090682 30 ctime=1488261610.896090682 libinfinity-0.7.1/docs/reference/libinfinity/html/InfAdoptedRequest.html0000644000175000017500000016123313055210752026771 0ustar00arminarmin00000000000000 InfAdoptedRequest: libinfinity-0.7 Reference Manual

InfAdoptedRequest

InfAdoptedRequest — Request processed by InfAdoptedAlgorithm.

Stability Level

Unstable, unless otherwise indicated

Properties

gint64 executed Read / Write
InfAdoptedOperation * operation Read / Write / Construct Only
gint64 received Read / Write / Construct Only
InfAdoptedRequestType type Read / Write / Construct Only
guint user-id Read / Write / Construct Only
InfAdoptedStateVector * vector Read / Write / Construct Only

Types and Values

Object Hierarchy

    GEnum
    ╰── InfAdoptedRequestType
    GObject
    ╰── InfAdoptedRequest

Includes

#include <libinfinity/adopted/inf-adopted-request.h>

Description

An InfAdoptedRequest is basically an InfAdoptedOperation with some metadata used by InfAdoptedAlgorithm to determine which operations to transform against each other. If the type of the request is INF_ADOPTED_REQUEST_DO, then it contains the operation to perform, otherwise it does not because the request does not know the operation, it is computed by InfAdoptedAlgorithm when required. A InfAdoptedRequest also contains the state in which the operation can be applied to the buffer and the user ID of the InfAdoptedUser having generated the request.

Functions

inf_adopted_request_new_do ()

InfAdoptedRequest *
inf_adopted_request_new_do (InfAdoptedStateVector *vector,
                            guint user_id,
                            InfAdoptedOperation *operation,
                            gint64 received);

Creates a new InfAdoptedRequest with type INF_ADOPTED_REQUEST_DO.

[constructor]

Parameters

vector

The vector time at which the request was made.

 

user_id

The ID of the user that made the request.

 

operation

The operation the user performed.

 

received

Time the request was received, in microseconds since the epoch.

 

Returns

A new DO request.

[transfer full]


inf_adopted_request_new_undo ()

InfAdoptedRequest *
inf_adopted_request_new_undo (InfAdoptedStateVector *vector,
                              guint user_id,
                              gint64 received);

Creates a new InfAdoptedRequest with type INF_ADOPTED_REQUEST_UNDO. The operation performed is implicitely defined by reverting the operation of the associated DO or REDO request, but must still be computed by InfAdoptedAlgorithm.

[constructor]

Parameters

vector

The vector time at which the request was made.

 

user_id

The ID of the user that made the request.

 

received

Time the request was received, in microseconds since the epoch.

 

Returns

A new UNDO request.

[transfer full]


inf_adopted_request_new_redo ()

InfAdoptedRequest *
inf_adopted_request_new_redo (InfAdoptedStateVector *vector,
                              guint user_id,
                              gint64 received);

Creates a new InfAdoptedRequest with type INF_ADOPTED_REQUEST_REDO. The operation performed is implicitely defined by reverting the operation of the associated UNDO request, but must still be computed by InfAdoptedAlgorithm.

[constructor]

Parameters

vector

The vector time at which the request was made.

 

user_id

The ID of the user that made the request.

 

received

Time the request was received, in microseconds since the epoch.

 

Returns

A new REDO request.

[transfer full]


inf_adopted_request_copy ()

InfAdoptedRequest *
inf_adopted_request_copy (InfAdoptedRequest *request);

Creates a copy of request with an initial reference count of 1.

Parameters

request

The InfAdoptedRequest to copy.

 

Returns

A new InfAdoptedRequest.

[transfer full]


inf_adopted_request_get_request_type ()

InfAdoptedRequestType
inf_adopted_request_get_request_type (InfAdoptedRequest *request);

Returns the request type of request .

Parameters

request

A InfAdoptedRequest.

 

Returns

The type of request .


inf_adopted_request_get_vector ()

InfAdoptedStateVector *
inf_adopted_request_get_vector (InfAdoptedRequest *request);

Returns the vector time the request was made i.e. its operation can be applied to the buffer.

Parameters

request

A InfAdoptedRequest.

 

Returns

The state vector of request . The returned value should not be freed, it is owned by the InfAdoptedRequest.

[transfer none]


inf_adopted_request_get_user_id ()

guint
inf_adopted_request_get_user_id (InfAdoptedRequest *request);

Returns the user ID of the user that issued request .

Parameters

request

A InfAdoptedRequest.

 

Returns

The request's user ID.


inf_adopted_request_get_operation ()

InfAdoptedOperation *
inf_adopted_request_get_operation (InfAdoptedRequest *request);

Returns the operation carried by the request. This can only be called if the request's type is INF_ADOPTED_REQUEST_DO.

Parameters

request

A InfAdoptedRequest.

 

Returns

The request's operation.

[transfer none]


inf_adopted_request_get_index ()

guint
inf_adopted_request_get_index (InfAdoptedRequest *request);

Returns the vector time component of the request's own users. This corresponds to the request index by that user.

Parameters

request

A InfAdoptedRequest.

 

Returns

The vector time component of the request's own user.


inf_adopted_request_get_receive_time ()

gint64
inf_adopted_request_get_receive_time (InfAdoptedRequest *request);

Returns the time when the request was received, or, if it's a local request, generated. The time is given in microseconds since January 1, 1970.

Parameters

request

A InfAdoptedRequest.

 

Returns

Time when the request was received.


inf_adopted_request_get_execute_time ()

gint64
inf_adopted_request_get_execute_time (InfAdoptedRequest *request);

Returns the time when the request was executed by an InfAdoptedAlgorithm, see inf_adopted_algorithm_execute_request(). The time is given in microseconds since January 1, 1970. If the request was not yet executed, the function returns 0.

Parameters

request

A InfAdoptedRequest.

 

Returns

The time when the function was executed, or 0.


inf_adopted_request_set_execute_time ()

void
inf_adopted_request_set_execute_time (InfAdoptedRequest *request,
                                      gint64 time);

Sets the time when request was executed. Usually this is called by InfAdoptedAlgorithm when it executes a request, i.e. translates it to the current state of the document.

Parameters

request

A InfAdoptedRequest.

 

time

A time in microseconds since January 1, 1970.

 

inf_adopted_request_need_concurrency_id ()

gboolean
inf_adopted_request_need_concurrency_id
                               (InfAdoptedRequest *request,
                                InfAdoptedRequest *against);

Returns whether transforming request against against requires a concurrency ID. If this function returns TRUE, you must provide the request_lcs and against_lcs parameters when calling inf_adopted_request_transform().

Both request need to be of type INF_ADOPTED_REQUEST_DO, and their state vectors must be the same.

Parameters

request

The request to transform.

 

against

The request to transform against.

 

Returns

Whether transformation of request against against requires a concurrency ID.


inf_adopted_request_transform ()

InfAdoptedRequest *
inf_adopted_request_transform (InfAdoptedRequest *request,
                               InfAdoptedRequest *against,
                               InfAdoptedRequest *request_lcs,
                               InfAdoptedRequest *against_lcs);

Transforms the operation of request against the operation of against . Both requests must be of type INF_ADOPTED_REQUEST_DO, and their state vectors must be the same.

If the function inf_adopted_request_need_concurrency_id() returns TRUE, request_lcs and against_lcs must not be NULL.

Parameters

request

The request to transform.

 

against

The request to transform against.

 

request_lcs

The request to transform in a previous state, or NULL.

 

against_lcs

The request to transform against in a previous state, or NULL.

 

Returns

A new InfAdoptedRequest, the result of the transformation.

[transfer full]


inf_adopted_request_mirror ()

InfAdoptedRequest *
inf_adopted_request_mirror (InfAdoptedRequest *request,
                            guint by);

Mirrors request as described in "Reducing the Problems of Group Undo" by Matthias Ressel and Rul Gunzenhäuser (http://portal.acm.org/citation.cfm?doid=320297.320312).

Note that by is the total amount of requests between the original and mirrored request, and thus equivalent to 2j-1 in the paper's definition.

request must be of type INF_ADOPTED_REQUEST_DO and its operation must be reversible.

Parameters

request

A InfAdoptedRequest.

 

by

The number of requests between the original and the mirrored operation.

 

Returns

The mirrored request as a new InfAdoptedRequest.

[transfer full]


inf_adopted_request_fold ()

InfAdoptedRequest *
inf_adopted_request_fold (InfAdoptedRequest *request,
                          guint into,
                          guint by);

Folds request as described in "Reducing the Problems of Group Undo" by Matthias Ressel and Rul Gunzenhäuser (http://portal.acm.org/citation.cfm?doid=320297.320312).

Note that by is the total amount of requests between the original and the fold request, and thus equivalent to 2j in the paper's definition.

into must not be the same user as the one that issued request .

Parameters

request

A InfAdoptedRequest.

 

into

The direction into which to fold.

 

by

The number of operations between the original and the fold request.

 

Returns

The folded request as a new InfAdoptedRequest.

[transfer full]


inf_adopted_request_affects_buffer ()

gboolean
inf_adopted_request_affects_buffer (InfAdoptedRequest *request);

Returns whether this request, when applied, changes the content of the buffer. If this is a INF_ADOPTED_REQUEST_UNDO or INF_ADOPTED_REQUEST_REDO request, than it always affects the buffer, because only requests that affect the buffer can be undone or redone. If it is a INF_ADOPTED_REQUEST_DO request, than it returns whether its operation has the INF_ADOPTED_OPERATION_AFFECTS_BUFFER flag set.

Parameters

request

A InfAdoptedRequest.

 

Returns

Whether request affects the session's buffer.

Types and Values

enum InfAdoptedRequestType

Possible types for an InfAdoptedRequest.

Members

INF_ADOPTED_REQUEST_DO

A request that performs an operation.

 

INF_ADOPTED_REQUEST_UNDO

A request that undoes a previously applied request.

 

INF_ADOPTED_REQUEST_REDO

A request that redoes a previously undone request.

 

struct InfAdoptedRequest

struct InfAdoptedRequest;

InfAdoptedRequest is an opaque data type. You should only access it via the public API functions.


struct InfAdoptedRequestClass

struct InfAdoptedRequestClass {
};

This structure does not contain any public fields.

Property Details

The “executed†property

  “executed†                gint64

Time the request was executed, in microseconds.

Flags: Read / Write

Default value: 0


The “operation†property

  “operation†               InfAdoptedOperation *

The operation of the request.

Flags: Read / Write / Construct Only


The “received†property

  “received†                gint64

Time the request was received, in microseconds.

Flags: Read / Write / Construct Only

Default value: 0


The “type†property

  “type†                    InfAdoptedRequestType

The type of the operation.

Flags: Read / Write / Construct Only

Default value: INF_ADOPTED_REQUEST_DO


The “user-id†property

  “user-id†                 guint

The ID of the user that made the request.

Flags: Read / Write / Construct Only

Default value: 0


The “vector†property

  “vector†                  InfAdoptedStateVector *

The vector time at which the request was made.

Flags: Read / Write / Construct Only

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/libinfinity-0.7-infd-storage.html0000644000000000000000000000013213055210752030045 xustar0030 mtime=1488261610.896090682 30 atime=1488261610.896090682 30 ctime=1488261610.896090682 libinfinity-0.7.1/docs/reference/libinfinity/html/libinfinity-0.7-infd-storage.html0000644000175000017500000012057413055210752030610 0ustar00arminarmin00000000000000 infd-storage: libinfinity-0.7 Reference Manual

infd-storage

infd-storage

Types and Values

Object Hierarchy

    GBoxed
    ├── InfdStorageAcl
    ╰── InfdStorageNode
    GEnum
    ╰── InfdStorageNodeType
    GInterface
    ╰── InfdStorage

Prerequisites

InfdStorage requires GObject.

Known Implementations

InfdStorage is implemented by InfdFilesystemStorage.

Description

Functions

infd_storage_node_new_subdirectory ()

InfdStorageNode *
infd_storage_node_new_subdirectory (const gchar *path);

Creates a new InfdStorageNode with type INFD_STORAGE_NODE_SUBDIRECTORY and the given path. This is most likely only going to be used by InfdStorage implementations.

[constructor]

Parameters

path

Path to the node.

 

Returns

A new InfdStorageNode.

[transfer full]


infd_storage_node_new_note ()

InfdStorageNode *
infd_storage_node_new_note (const gchar *path,
                            const gchar *identifier);

Creates a new InfdStorageNode with type INFD_STORAGE_NODE_NOTE and the given path and identifier. This is most likely only going to be used by InfdStorage implementations.

[constructor]

Parameters

path

Path to the node.

 

identifier

Identifier of the note type, for example 'InfText' for text notes.

 

Returns

A new InfdStorageNode.

[transfer full]


infd_storage_node_copy ()

InfdStorageNode *
infd_storage_node_copy (const InfdStorageNode *node);

Creates a copy of a InfdStorageNode object.

Parameters

node

Node from which to make a copy.

 

Returns

A copy of node .

[transfer full]


infd_storage_node_free ()

void
infd_storage_node_free (InfdStorageNode *node);

Frees a InfdStorageNode allocated with infd_storage_node_new_subdirectory(), infd_storage_node_new_note() or infd_storage_node_copy().

Parameters

node

A InfdStorageNode.

 

infd_storage_node_list_free ()

void
infd_storage_node_list_free (GSList *node_list);

Frees a singly-linked list of InfdStorageNode as returned by infd_storage_read_subdirectory().

Parameters

node_list

A list of InfdStorageNode objects.

[element-type InfdStorageNode]

infd_storage_acl_copy ()

InfdStorageAcl *
infd_storage_acl_copy (const InfdStorageAcl *acl);

Creates a copy of a InfdStorageAcl object.

Parameters

acl

ACL settings from which to make a copy.

 

Returns

A copy of acl .


infd_storage_acl_free ()

void
infd_storage_acl_free (InfdStorageAcl *acl);

Frees a InfdStorageAcl allocated with infd_storage_acl_copy().

Parameters

acl

A InfdStorageAcl.

 

infd_storage_acl_list_free ()

void
infd_storage_acl_list_free (GSList *acl_list);

Frees a singly-linked list of InfdStorageAcl as returned by infd_storage_read_acls().

Parameters

acl_list

A list of InfdStorageAcl objects.

[element-type InfdStorageAcl]

infd_storage_read_subdirectory ()

GSList *
infd_storage_read_subdirectory (InfdStorage *storage,
                                const gchar *path,
                                GError **error);

Reads a subdirectory from the storage. Returns a list of InfdStorageNode objects. Both the list and the objects need to be freed by the caller via infd_storage_node_list_free().

Parameters

storage

A InfdStorage

 

path

A path pointing to a subdirectory node.

 

error

Location to store error information.

 

Returns

A GSList that contains InfdStorageNode objects, or NULL if either the subdirectory is empty or an error occured.

[transfer full][element-type InfdStorageNode][allow-none]


infd_storage_create_subdirectory ()

gboolean
infd_storage_create_subdirectory (InfdStorage *storage,
                                  const gchar *path,
                                  GError **error);

Creates a new subdirectory at the given path that is initially empty.

Parameters

storage

A InfdStorage.

 

path

A path pointing to non-existing node.

 

error

Location to store error information.

 

Returns

TRUE on success.


infd_storage_remove_node ()

gboolean
infd_storage_remove_node (InfdStorage *storage,
                          const gchar *identifier,
                          const gchar *path,
                          GError **error);

Removes the node at path from storage. If it is a subdirectory node, all containing nodes and subdirectory nodes are removed recursively.

Parameters

storage

A InfdStorage

 

identifier

The type of the node to remove, or NULL to remove a subdirectory (TODO: This shouldn't be necessary).

 

path

A path pointing to an existing node.

 

error

Location to store error information.

 

Returns

TRUE on success.


infd_storage_read_acl ()

GSList *
infd_storage_read_acl (InfdStorage *storage,
                       const gchar *path,
                       GError **error);

Reads the ACL for the node at the path path from the storage. It returns a list of InfdStorageAcl objects.

Parameters

storage

A InfdStorage.

 

path

A path pointing to an existing node.

 

error

Location to store error information, if any.

 

Returns

A possibly empty list of InfdStorageAcl objects. Free with infd_storage_acl_list_free() when no longer needed.

[transfer full][element-type InfdStorageAcl][allow-none]


infd_storage_write_acl ()

gboolean
infd_storage_write_acl (InfdStorage *storage,
                        const gchar *path,
                        const InfAclSheetSet *sheet_set,
                        GError **error);

Writes the ACL defined by sheet_set into storage. If sheet_set is NULL this is equivalent to an empty set. Returns TRUE on success or FALSE on error. If the function fails, error is set.

Parameters

storage

A InfdStorage.

 

path

A path to an existing node.

 

sheet_set

Sheets to set for the node at path , or NULL.

 

error

Location to store error information, if any.

 

Returns

TRUE on success or FALSE on error.

Types and Values

InfdStorage

typedef struct _InfdStorage InfdStorage;


struct InfdStorageInterface

struct InfdStorageInterface {
  GTypeInterface parent;

  /* All these calls are supposed to be synchronous, e.g. completly perform
   * the required task. Some day, we could implement asynchronous
   * behaviour in InfdDirectory (e.g. it caches operations and executes
   * them via the storage in the background). */

  /* Virtual Table */
  GSList* (*read_subdirectory)(InfdStorage* storage,
                               const gchar* path,
                               GError** error);

  gboolean (*create_subdirectory)(InfdStorage* storage,
                                  const gchar* path,
                                  GError** error);

  /* TODO: Remove the identifier here */
  gboolean (*remove_node)(InfdStorage* storage,
                          const gchar* identifier,
                          const gchar* path,
                          GError** error);

  /* TODO: Add further methods to copy, move and expunge nodes */

  GSList* (*read_acl)(InfdStorage* storage,
                      const gchar* path,
                      GError** error);

  gboolean (*write_acl)(InfdStorage* storage,
                        const gchar* path,
                        const InfAclSheetSet* sheet_set,
                        GError** error);
};


enum InfdStorageNodeType

Members

INFD_STORAGE_NODE_SUBDIRECTORY

   

INFD_STORAGE_NODE_NOTE

   

struct InfdStorageNode

struct InfdStorageNode {
  InfdStorageNodeType type;
  gchar* name;

  gchar* identifier; /* Only set when type == INFD_STORAGE_NODE_NOTE */
};


struct InfdStorageAcl

struct InfdStorageAcl {
  gchar* account_id;
  InfAclMask mask;
  InfAclMask perms;  
};

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/annotation-glossary.html0000644000000000000000000000013213055210752026656 xustar0030 mtime=1488261610.896090682 30 atime=1488261610.896090682 30 ctime=1488261610.896090682 libinfinity-0.7.1/docs/reference/libinfinity/html/annotation-glossary.html0000644000175000017500000001414113055210752027411 0ustar00arminarmin00000000000000 Annotation Glossary: libinfinity-0.7 Reference Manual

Annotation Glossary

A

allow-none

NULL is OK, both for passing and for returning.

array

Parameter points to an array of items.

C

constructor

This symbol is a constructor, not a static method.

E

element-type

Generics and defining elements of containers and arrays.

I

in

Parameter for input. Default is transfer none.

inout

Parameter for input and for returning results. Default is transfer full.

O

out

Parameter for returning results. Default is transfer full.

S

scope async

The callback is valid until first called.

scope call

The callback is valid only during the call to the method.

T

transfer container

Free data container after the code is done.

transfer full

Free data after the code is done.

transfer none

Don't free data after the code is done.

type

Override the parsed C type with given type.

U

Unstable

Unstable interfaces are experimental or transitional. They are typically used to give outside developers early access to new or rapidly changing technology, or to provide an interim solution to a problem where a more general solution is anticipated. No claims are made about either source or binary compatibility from one minor release to the next. The Unstable interface level is a warning that these interfaces are subject to change without warning and should not be used in unbundled products. Given such caveats, customer impact need not be a factor when considering incompatible changes to an Unstable interface in a major or minor release. Nonetheless, when such changes are introduced, the changes should still be mentioned in the release notes for the affected release.

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfAdoptedRequestLog.html0000644000000000000000000000013213055210752026673 xustar0030 mtime=1488261610.900090673 30 atime=1488261610.900090673 30 ctime=1488261610.900090673 libinfinity-0.7.1/docs/reference/libinfinity/html/InfAdoptedRequestLog.html0000644000175000017500000017445213055210752027442 0ustar00arminarmin00000000000000 InfAdoptedRequestLog: libinfinity-0.7 Reference Manual

InfAdoptedRequestLog

InfAdoptedRequestLog — History of requests

Stability Level

Unstable, unless otherwise indicated

Properties

guint begin Read / Write / Construct Only
guint end Read
InfAdoptedRequest * next-redo Read
InfAdoptedRequest * next-undo Read
guint user-id Read / Write / Construct Only

Signals

Types and Values

Object Hierarchy

    GObject
    ╰── InfAdoptedRequestLog

Includes

#include <libinfinity/adopted/inf-adopted-request-log.h>

Description

InfAdoptedRequestLog stores all requests by a particular user. These need to be looked up by InfAdoptedAlgorithm to perform transformations of older requests to the current state. It also adds relations between the requests so that is easy to find the request that an Undo request undoes, or the Undo request undoing a given request, if available.

When requests are no longer needed, then they can also be removed again from the log, however requests can only be removed so that remaining Undo or Redo requests do not refer to some request that is about to be removed.

Functions

inf_adopted_request_log_new ()

InfAdoptedRequestLog *
inf_adopted_request_log_new (guint user_id);

Creates a new InfAdoptedRequestLog for the user with the given ID.

[constructor]

Parameters

user_id

The ID of the InfAdoptedUser to create a request log for. The request log only contains requests of that particular user.

 

Returns

A new InfAdoptedRequestLog.

[transfer full]


inf_adopted_request_log_get_user_id ()

guint
inf_adopted_request_log_get_user_id (InfAdoptedRequestLog *log);

Returns the ID of the user whose requests log contains.

Parameters

log

A InfAdoptedRequestLog.

 

Returns

The log's user ID.


inf_adopted_request_log_get_begin ()

guint
inf_adopted_request_log_get_begin (InfAdoptedRequestLog *log);

Returns the first index (i.e. the index of the oldest request) in the log.

Parameters

log

A InfAdoptedRequestLog.

 

Returns

The first index in the log.


inf_adopted_request_log_get_end ()

guint
inf_adopted_request_log_get_end (InfAdoptedRequestLog *log);

Returns the index a newly inserted request would have (i.e. one past the index of the newest request in the log). This ensures that inf_adopted_request_log_get_end() - inf_adopted_request_log_get_begin() reveals the number of requests in the log.

Parameters

log

A InfAdoptedRequestLog.

 

Returns

The index of the next request in the log.


inf_adopted_request_log_is_empty ()

gboolean
inf_adopted_request_log_is_empty (InfAdoptedRequestLog *log);

Returns whether log is empty. A log is empty if it does not contain any requsets.

Parameters

log

A InfAdoptedRequestLog.

 

Returns

Whether log is empty.


inf_adopted_request_log_set_begin ()

void
inf_adopted_request_log_set_begin (InfAdoptedRequestLog *log,
                                   guint n);

This function sets the index of the first log that will be added to log . For a new request log, this is set to 0. If you intend to insert a request sequence into log that does not start with 0, then you can call this function with the desired start index, so that inf_adopted_request_log_get_begin() and inf_adopted_request_log_get_end() return the correct value.

If you don't need inf_adopted_request_log_get_begin() or inf_adopted_request_log_get_end() before adding the first request to the log, then you don't need to call this function, since inf_adopted_request_log_add_request() will do it implicitely based on the request's vector time component for the request log's user.

This function can only be called if the request log is empty, see inf_adopted_request_log_is_empty().

Parameters

log

A InfAdoptedRequestLog.

 

n

The index of the first request to be added to the log.

 

inf_adopted_request_log_get_request ()

InfAdoptedRequest *
inf_adopted_request_log_get_request (InfAdoptedRequestLog *log,
                                     guint n);

Returns the request with the given index. Such a request must exist in log .

Parameters

log

A InfAdoptedRequestLog.

 

n

The index of a request contained in log .

 

Returns

A InfAdoptedRequest. The request is owned by the request log, you do not need to free it.

[transfer none]


inf_adopted_request_log_add_request ()

void
inf_adopted_request_log_add_request (InfAdoptedRequestLog *log,
                                     InfAdoptedRequest *request);

Inserts request into log . The component represented by the log's user of the request's state vector must match the end index of log if log is not empty. Also, the user that issued request must be the same user as the one this request log belongs to.

Parameters

log

A InfAdoptedRequestLog.

 

request

A InfAdoptedRequest.

 

inf_adopted_request_log_remove_requests ()

void
inf_adopted_request_log_remove_requests
                               (InfAdoptedRequestLog *log,
                                guint up_to);

Removes all requests with index lower than up_to . This function only works if the request before up_to is an "upper related" request. See inf_adopted_request_log_upper_related(). This condition guarantees that remaining requests do not refer to removed ones.

Parameters

log

A InfAdoptedRequestLog.

 

up_to

The index of the first request not to remove.

 

inf_adopted_request_log_next_associated ()

InfAdoptedRequest *
inf_adopted_request_log_next_associated
                               (InfAdoptedRequestLog *log,
                                InfAdoptedRequest *request);

If request is of type INF_ADOPTED_REQUEST_DO or INF_ADOPTED_REQUEST_REDO, this returns UNDO request that undoes this request, if any. If request is a INF_ADOPTED_REQUEST UNDO request, this returns a request that redoes request , if any.

Parameters

log

A InfAdoptedRequestLog.

 

request

A InfAdoptedRequest contained in log .

 

Returns

The next associated request of request , or NULL.

[transfer none][allow-none]


inf_adopted_request_log_prev_associated ()

InfAdoptedRequest *
inf_adopted_request_log_prev_associated
                               (InfAdoptedRequestLog *log,
                                InfAdoptedRequest *request);

If request is of type INF_ADOPTED_REQUEST_REDO or, this returns the UNDO request that is redone by request , if request is a INF_ADOPTED_REQUEST_UNDO request, this returns the request that is undone by request .

request must either be contained in log or the vector time component of its own user must be equivalent to inf_adopted_request_log_get_end(), in which case request is treated as it if was the newest request in log .

Parameters

log

A InfAdoptedRequestLog.

 

request

A InfAdoptedRequest.

 

Returns

The previous associated request of request , or NULL.

[transfer none][allow-none]


inf_adopted_request_log_original_request ()

InfAdoptedRequest *
inf_adopted_request_log_original_request
                               (InfAdoptedRequestLog *log,
                                InfAdoptedRequest *request);

Returns the most previous associated request for request , that is, the INF_ADOPTED_REQUEST_DO request that request undoes or redoes, respectively. If request itself is a INF_ADOPTED_REQUEST_DO request, request itself is returned.

request must either be contained in log or the vector time component of its own user must be equivalent to inf_adopted_request_log_get_end(), in which case request is treated as it if was the newest request in log .

Parameters

log

A InfAdoptedRequestLog.

 

request

A InfAdoptedRequest.

 

Returns

The original request of request . This function never returns NULL.

[transfer none]


inf_adopted_request_log_next_undo ()

InfAdoptedRequest *
inf_adopted_request_log_next_undo (InfAdoptedRequestLog *log);

Returns the request that would be undone if a undo request was added to the request log.

Parameters

log

A InfAdoptedRequestLog.

 

Returns

The next request to be undone, or NULL.

[transfer none][allow-none]


inf_adopted_request_log_next_redo ()

InfAdoptedRequest *
inf_adopted_request_log_next_redo (InfAdoptedRequestLog *log);

Returns the request that would be redone if a redo request was added to the request log.

Parameters

log

A InfAdoptedRequestLog.

 

Returns

The next request to be redone, or NULL.

[transfer none][allow-none]


inf_adopted_request_log_upper_related ()

InfAdoptedRequest *
inf_adopted_request_log_upper_related (InfAdoptedRequestLog *log,
                                       guint n);

Returns the newest request in log that is related to n th request in log. Requests are considered related when they are enclosed by a do/undo, an undo/redo or a redo/undo pair.

Note that the sets of related requests within a request log are disjoint.

Parameters

log

A InfAdoptedRequestLog.

 

n

Index of a request in log .

 

Returns

The newest request in log being related to the n th request.

[transfer none]


inf_adopted_request_log_lower_related ()

InfAdoptedRequest *
inf_adopted_request_log_lower_related (InfAdoptedRequestLog *log,
                                       guint n);

Returns the oldest request in log that is related to n th request in log. Requests are considered related when they are enclosed by a do/undo, an undo/redo or a redo/undo pair.

Note that the sets of related requests within a request log are disjoint.

Parameters

log

A InfAdoptedRequestLog.

 

n

Index of a request in log .

 

Returns

The oldest request in log being related to the n th request.

[transfer none]


inf_adopted_request_log_add_cached_request ()

void
inf_adopted_request_log_add_cached_request
                               (InfAdoptedRequestLog *log,
                                InfAdoptedRequest *request);

InfAdoptedRequestLog has a cache for translated requests built in. This can be used to store requests that have been translated to another point in the state space, and to efficiently look them up later. The advantage of having this functionality within InfAdoptedRequestLog is that when requests are removed from the log the cache is automatically updated accordingly.

The data structure of the cache is optimized for quick lookup of entries by the state vector and cleaning up entries in an efficient manner also when the cache has grown very big.

The request cache is mainly used by InfAdoptedAlgorithm to efficiently handle big transformations.

This function adds a request to the cache of the request log. request must be a translated version of a request existing in log .

Parameters

log

A InfAdoptedRequestLog.

 

request

The InfAdoptedRequest to add to the cache.

 

inf_adopted_request_log_lookup_cached_request ()

InfAdoptedRequest *
inf_adopted_request_log_lookup_cached_request
                               (InfAdoptedRequestLog *log,
                                InfAdoptedStateVector *vec);

Looks up the request at vec from the cache of the request log. If the queried request does not exist in the cache, the function returns NULL.

See inf_adopted_request_log_add_cached_request() for an explanation of the request cache.

Parameters

log

A InfAdoptedRequestLog.

 

vec

The state vector at which to look up the request.

 

Returns

The cached InfAdoptedRequest according to vec , or NULL.

[transfer none][allow-none]

Types and Values

struct InfAdoptedRequestLog

struct InfAdoptedRequestLog;

InfAdoptedRequestLog is an opaque data type. You should only access it via the public API functions.


struct InfAdoptedRequestLogClass

struct InfAdoptedRequestLogClass {
  void(*add_request)(InfAdoptedRequestLog* log,
                     InfAdoptedRequest* request);
};

This structure contains the default signal handlers for InfAdoptedRequestLog.

Members

add_request ()

Default signal handler for the “add-request†signal.

 

Property Details

The “begin†property

  “begin†                   guint

The first index contained in the log.

Flags: Read / Write / Construct Only

Default value: 0


The “end†property

  “end†                     guint

The index of the next request that is inserted into the log.

Flags: Read

Default value: 0


The “next-redo†property

  “next-redo†               InfAdoptedRequest *

The request that is redone when the user issues a redo request new.

Flags: Read


The “next-undo†property

  “next-undo†               InfAdoptedRequest *

The request that is undone when the user issues an undo request now.

Flags: Read


The “user-id†property

  “user-id†                 guint

The ID of the user whose requests the log contains.

Flags: Read / Write / Construct Only

Default value: 0

Signal Details

The “add-request†signal

void
user_function (InfAdoptedRequestLog *log,
               InfAdoptedRequest    *request,
               gpointer              user_data)

This signal is emitted whenever a new request is added to the request log via inf_adopted_request_log_add_request().

Parameters

log

The InfAdoptedRequestLog to which a new request is added.

 

request

The new request being added.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/libinfinity-0.7-InfcNotePlugin.ht0000644000000000000000000000013213055210752030016 xustar0030 mtime=1488261610.900090673 30 atime=1488261610.900090673 30 ctime=1488261610.900090673 libinfinity-0.7.1/docs/reference/libinfinity/html/libinfinity-0.7-InfcNotePlugin.html0000644000175000017500000001272613055210752031111 0ustar00arminarmin00000000000000 InfcNotePlugin: libinfinity-0.7 Reference Manual

InfcNotePlugin

InfcNotePlugin

Functions

Types and Values

Description

Functions

InfcNotePluginSessionNew ()

InfSession *
(*InfcNotePluginSessionNew) (InfIo *Param1,
                             InfCommunicationManager *Param2,
                             InfSessionStatus Param3,
                             InfCommunicationGroup *Param4,
                             InfXmlConnection *Param5,
                             const char *Param6,
                             gpointer Param7);

Types and Values

struct InfcNotePlugin

struct InfcNotePlugin {
  gpointer user_data;

  const gchar* note_type;

  InfcNotePluginSessionNew session_new;
};

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/up-insensitive.png0000644000000000000000000000013213055210752025445 xustar0030 mtime=1488261610.832090825 30 atime=1488261610.832090825 30 ctime=1488261610.832090825 libinfinity-0.7.1/docs/reference/libinfinity/html/up-insensitive.png0000644000175000017500000000056613055210752026206 0ustar00arminarmin00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEà 4ÓkMIDAT8Ëí’?/QÅÏ™?[êu$¾€V³î›ÑâHTD³ø”ÛˆBM+¡!™ÂÌ<ˆDã+èô[mdÞ\…·bø{º{sÎ/97˜ªSÖÚ£º®»<ìTõ8ŒcÌÉ¿UU­‘¼‡•WÕÍ,Ë®ÿ”e¹EÑ €žªîÉSïmÛ®æy~û+À9·è½¿0`hŒ9u†ªº`Çñr¿ßùpÎÍ{ïÌ8‘m’ ªJkí€-o$—Dä¢  išË¾'¹; ‡ Jr‡äCð\¨*¿HΑ|JÓtCDÆßo#"ã$IÖ<«êBQ½é£êêÉ]•TKúIEND®B`‚libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfcBrowser.html0000644000000000000000000000013213055210752025066 xustar0030 mtime=1488261610.900090673 30 atime=1488261610.900090673 30 ctime=1488261610.900090673 libinfinity-0.7.1/docs/reference/libinfinity/html/InfcBrowser.html0000644000175000017500000013330113055210752025621 0ustar00arminarmin00000000000000 InfcBrowser: libinfinity-0.7 Reference Manual

InfcBrowser

InfcBrowser — Browse remote directories

Stability Level

Unstable, unless otherwise indicated

Properties

InfcSessionProxy * chat-session Read
InfCommunicationManager * communication-manager Read / Write / Construct Only
InfXmlConnection * connection Read / Write / Construct Only
InfIo * io Read / Write / Construct Only

Types and Values

Object Hierarchy

    GObject
    ╰── InfcBrowser

Implemented Interfaces

InfcBrowser implements InfCommunicationObject and InfBrowser.

Includes

#include <libinfinity/client/infc-browser.h>

Description

The InfcBrowser is used to browse a remote directory and can be used to subscribe to sessions. InfcBrowser implements the InfBrowser interface, through which most operations are performed.

Functions

infc_browser_new ()

InfcBrowser *
infc_browser_new (InfIo *io,
                  InfCommunicationManager *comm_manager,
                  InfXmlConnection *connection);

Creates a new InfcBrowser.

[constructor]

Parameters

io

A InfIo object used to schedule timeouts.

 

comm_manager

A InfCommunicationManager to register the server connection and which forwards incoming data to the browser or running sessions.

 

connection

Connection to the server.

 

Returns

A new InfcBrowser.

[transfer full]


infc_browser_get_communication_manager ()

InfCommunicationManager *
infc_browser_get_communication_manager
                               (InfcBrowser *browser);

Returns the communication manager of this browser.

Parameters

browser

A InfcBrowser.

 

Returns

A InfCommunicationManager.

[transfer none]


infc_browser_get_connection ()

InfXmlConnection *
infc_browser_get_connection (InfcBrowser *browser);

Returns the connection to the server.

Parameters

browser

A InfcBrowser.

 

Returns

A InfXmlConnection.

[transfer none]


infc_browser_add_plugin ()

gboolean
infc_browser_add_plugin (InfcBrowser *browser,
                         const InfcNotePlugin *plugin);

Adds plugin to browser . This allows the browser to create sessions of the plugin's type. Only one plugin of each type can be added to the directory.

Parameters

browser

A InfcBrowser.

 

plugin

A InfcNotePlugin.

 

Returns

Whether the plugin was added successfully.

[transfer none]


infc_browser_lookup_plugin ()

const InfcNotePlugin *
infc_browser_lookup_plugin (InfcBrowser *browser,
                            const gchar *note_type);

Returns a previously registered plugin (see infc_browser_add_plugin()) for the given note type, or NULL if there is no such plugin.

Parameters

browser

A InfcBrowser.

 

note_type

A note type, such as "InfText".

 

Returns

A InfcNotePlugin, or NULL.

[transfer none]


infc_browser_iter_save_session ()

InfRequest *
infc_browser_iter_save_session (InfcBrowser *browser,
                                const InfBrowserIter *iter,
                                InfRequestFunc func,
                                gpointer user_data);

Requests that the server saves the note pointed to by iter into its background storage. Normally, the server only does this when it is either shut down or when the there are no more subscriptions to the note. Note that this is merely a request and the server might decide not to save the session for whatever reason.

The request might either finish during the call to this function, in which case func will be called and NULL being returned. If the request does not finish within the function call, a InfRequest object is returned, where func has been installed for the “finished†signal, so that it is called as soon as the request finishes.

Parameters

browser

A InfcBrowser.

 

iter

A InfBrowserIter pointing to a note in browser .

 

func

The function to be called when the request finishes, or NULL.

[scope async]

user_data

Additional data to pass to func .

 

Returns

A InfRequest that may be used to get notified when the request finishes or fails.

[transfer none][allow-none]


infc_browser_iter_get_sync_in ()

InfcSessionProxy *
infc_browser_iter_get_sync_in (InfcBrowser *browser,
                               const InfBrowserIter *iter);

Returns the InfcSessionProxy that is used to synchronize the note iter points to to the server. Such a node is created by inf_browser_add_note() with non-NULL session parameter. If the client is subscribed to this note, then this returns the same session as inf_browser_get_session(). However, it is possible that we synchronize this node to the server without being subscribed to it. In this case, this function returns the session that does the synchronization, while inf_browser_get_session() would return NULL.

Parameters

browser

A InfcBrowser.

 

iter

A InfBrowserIter pointing to a note in browser .

 

Returns

A InfcSessionProxy, or NULL if we are currently not synchronizing this node to the server.

[transfer none][allow-none]


infc_browser_iter_get_sync_in_requests ()

GSList *
infc_browser_iter_get_sync_in_requests
                               (InfcBrowser *browser,
                                const InfBrowserIter *iter);

Returns a list of all InfRequests created with inf_browser_add_note() with the node iter points to as parent. Such requests begin a synchronization to the server when they have finished.

Parameters

browser

A InfcBrowser.

 

iter

A InfBrowserIter pointing to a subdirectory node in browser .

 

Returns

A list of InfRequests. Free with g_slist_free() when done.

[transfer container][element-type InfRequest]


infc_browser_iter_is_valid ()

gboolean
infc_browser_iter_is_valid (InfcBrowser *browser,
                            const InfBrowserIter *iter);

Returns whether iter points to a valid node in browser . This is generally the case for any InfBrowserIter returned by one of the InfcBrowser functions, it gets invalid however as soon as the node it points to is removed.

Parameters

browser

A InfcBrowser.

 

iter

A InfBrowserIter.

 

Returns

Whether iter points to a node in browser .


infc_browser_subscribe_chat ()

InfRequest *
infc_browser_subscribe_chat (InfcBrowser *browser,
                             InfRequestFunc func,
                             gpointer user_data);

Attempts to subscribe to the server's chat. When the operation finishes infc_browser_get_chat_session() will return a InfcSessionProxy representing the chat session. It can be used to read the chat's content. The request can fail in case the server chat is disabled.

The request might either finish during the call to this function, in which case func will be called and NULL being returned. If the request does not finish within the function call, a InfRequest object is returned, where func has been installed for the “finished†signal, so that it is called as soon as the request finishes.

Parameters

browser

A InfcBrowser.

 

func

The function to be called when the request finishes, or NULL.

[scope async]

user_data

Additional data to pass to func .

 

Returns

A InfRequest that may be used to get notified when the request finishes or fails.

[transfer none][allow-none]


infc_browser_get_subscribe_chat_request ()

InfRequest *
infc_browser_get_subscribe_chat_request
                               (InfcBrowser *browser);

Returns the InfRequest that represests the request sent to the server which attempts to subscribe to its chat. If there is no such request running, then the function returns NULL. After such a request finishes, call infc_browser_get_chat_session() to get the InfcSessionProxy for the chat session. To initiate the request, call infc_browser_subscribe_chat().

Parameters

browser

A InfcBrowser.

 

Returns

A InfRequest, or NULL.

[transfer none][allow-none]


infc_browser_get_chat_session ()

InfcSessionProxy *
infc_browser_get_chat_session (InfcBrowser *browser);

Returns the InfcSessionProxy representing the running chat session if the local client is subscribed to it, or NULL otherwise.

Parameters

browser

A InfcBrowser.

 

Returns

A InfcSessionProxy for the chat, or NULL.

[transfer none][allow-none]

Types and Values

struct InfcBrowser

struct InfcBrowser;

InfcBrowser is an opaque data type. You should only access it via the public API functions.


struct InfcBrowserClass

struct InfcBrowserClass {
};

This structure does not contain any public fields.

Property Details

The “chat-session†property

  “chat-session†            InfcSessionProxy *

Active chat session.

Flags: Read


The “communication-manager†property

  “communication-manager†   InfCommunicationManager *

The communication manager for the browser.

Flags: Read / Write / Construct Only


The “connection†property

  “connection†              InfXmlConnection *

Connection to the server exposing the directory to browse.

Flags: Read / Write / Construct Only


The “io†property

  “io†                      InfIo *

The InfIo to schedule timeouts.

Flags: Read / Write / Construct Only

See Also

InfdDirectory

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfAdoptedSession.html0000644000000000000000000000013213055210752026224 xustar0030 mtime=1488261610.900090673 30 atime=1488261610.900090673 30 ctime=1488261610.900090673 libinfinity-0.7.1/docs/reference/libinfinity/html/InfAdoptedSession.html0000644000175000017500000012232613055210752026764 0ustar00arminarmin00000000000000 InfAdoptedSession: libinfinity-0.7 Reference Manual

InfAdoptedSession

InfAdoptedSession — Session handling concurrency control via the adOPTed algorithm.

Stability Level

Unstable, unless otherwise indicated

Properties

InfAdoptedAlgorithm * algorithm Read
InfIo * io Read / Write / Construct Only
guint max-total-log-size Read / Write / Construct Only

Object Hierarchy

    GObject
    ╰── InfSession
        ╰── InfAdoptedSession

Implemented Interfaces

InfAdoptedSession implements InfCommunicationObject.

Includes

#include <libinfinity/adopted/inf-adopted-session.h>

Description

InfAdoptedSession handles concurrency control with an InfAdoptedAlgorithm on top of a InfSession. It takes care of sending all necessary information to joining users, receives requests from the network (passing them to InfAdoptedAlgorithm) and transfers local requests to the other users. It also makes sure to periodically send the state the local host is in to other uses even if the local users are idle (which is required for others to cleanup their request logs and request caches).

Functions

inf_adopted_session_get_io ()

InfIo *
inf_adopted_session_get_io (InfAdoptedSession *session);

Returns the InfIo object of session .

Parameters

session

A InfAdoptedSession.

 

Returns

A InfIo.

[transfer none]


inf_adopted_session_get_algorithm ()

InfAdoptedAlgorithm *
inf_adopted_session_get_algorithm (InfAdoptedSession *session);

Returns the InfAdoptedAlgorithm object of session . Returns NULL if session has status INF_SESSION_PRESYNC or INF_SESSION_SYNCHRONIZING because there the algorithm object is not yet created before successful synchronization.

Parameters

session

A InfAdoptedSession.

 

Returns

A InfAdoptedAlgorithm, or NULL.

[transfer none]


inf_adopted_session_broadcast_request ()

void
inf_adopted_session_broadcast_request (InfAdoptedSession *session,
                                       InfAdoptedRequest *request);

Sends a request to all subscribed connections. The request should originate from a call to inf_adopted_algorithm_generate_request(), with session 's InfAdoptedAlgorithm.

Parameters

session

A InfAdoptedSession.

 

request

A InfAdoptedRequest obtained from session 's algorithm.

 

inf_adopted_session_undo ()

void
inf_adopted_session_undo (InfAdoptedSession *session,
                          InfAdoptedUser *user,
                          guint n);

This is a shortcut for creating n undo requests and broadcasting them. If n > 1 then this is also more efficient.

Parameters

session

A InfAdoptedSession.

 

user

A local InfAdoptedUser.

 

n

The number of undo requests to issue.

 

inf_adopted_session_redo ()

void
inf_adopted_session_redo (InfAdoptedSession *session,
                          InfAdoptedUser *user,
                          guint n);

This is a shortcut for creating n redo requests and broadcasting them. If n > 1 then this is also more efficient.

Parameters

session

A InfAdoptedSession.

 

user

A local InfAdoptedUser.

 

n

The number of redo requests to issue.

 

inf_adopted_session_read_request_info ()

gboolean
inf_adopted_session_read_request_info (InfAdoptedSession *session,
                                       xmlNodePtr xml,
                                       InfAdoptedStateVector *diff_vec,
                                       InfAdoptedUser **user,
                                       InfAdoptedStateVector **time,
                                       xmlNodePtr *operation,
                                       GError **error);

This function reads common information such as the state vector the request was made and the user that made the request from XML. It is most likely to be used by implementations of the xml_to_request virtual function.

Parameters

session

A InfAdoptedSession.

 

xml

The XML to read the data from.

 

diff_vec

The reference vector of the time vector of the request, or NULL.

 

user

Location to store the user of the request, or NULL.

[out][transfer none][allow-none]

time

Location to store the state the request was made, or NULL.

[out][transfer full][allow-none]

operation

Location to store the operation of the request, or NULL.

[out][transfer none][allow-none]

error

Location to place an error, if any.

 

Returns

TRUE if the data could be read successfully, FALSE if the XML request does not contain valid request data, in which case error is set.


inf_adopted_session_write_request_info ()

void
inf_adopted_session_write_request_info
                               (InfAdoptedSession *session,
                                InfAdoptedRequest *request,
                                InfAdoptedStateVector *diff_vec,
                                xmlNodePtr xml,
                                xmlNodePtr operation);

This function writes common data from request , such as the user that issued the request and the state in which the request was made into xml . If diff_vec is given, then the state is written as a diff to this vector, see inf_adopted_state_vector_to_string_diff(). Deserializing this data again (via inf_adopted_session_read_request_info()) requires the same diff_vec then.

This function is most likely to be used by implementations of the request_to_xml virtual function.

Parameters

session

A InfAdoptedSession.

 

request

The InfAdoptedRequest whose info to write.

 

diff_vec

A reference state vector, or NULL.

 

xml

The XML node to write the data into.

 

operation

An XML node representing the operation of the request, or NULL.

 

Types and Values

enum InfAdoptedSessionError

Error codes for InfAdoptedSession. These only occur when invalid requests are received from the network.

Members

INF_ADOPTED_SESSION_ERROR_NO_SUCH_USER

The "user" field in a request message does not contain a valid user ID.

 

INF_ADOPTED_SESSION_ERROR_MISSING_OPERATION

A request message does not contain an operation.

 

INF_ADOPTED_SESSION_ERROR_INVALID_REQUEST

A request in a synchronized request log is invalid. Invalid means that it is not the request that was issued after the previous request in the log, or that it is an Undo or Redo request without a request to Undo or Redo, respectively.

 

INF_ADOPTED_SESSION_ERROR_MISSING_STATE_VECTOR

A synchronized user does not contain that the state that user currently is in.

 

INF_ADOPTED_SESSION_ERROR_FAILED

No further specified error code.

 

struct InfAdoptedSession

struct InfAdoptedSession;

InfAdoptedSession is an opaque data type. You should only access it via the public API functions.


struct InfAdoptedSessionClass

struct InfAdoptedSessionClass {
  InfAdoptedRequest*(*xml_to_request)(InfAdoptedSession* session,
                                      xmlNodePtr xml,
                                      InfAdoptedStateVector* diff_vec,
                                      gboolean for_sync,
                                      GError** error);

  void(*request_to_xml)(InfAdoptedSession* session,
                        xmlNodePtr xml,
                        InfAdoptedRequest* request,
                        InfAdoptedStateVector* diff_vec,
                        gboolean for_sync);

  /* Signals */

  gboolean(*check_request)(InfAdoptedSession* session,
                           InfAdoptedRequest* request,
                           InfAdoptedUser* user);
};

Virtual functions and default signal handlers for InfAdoptedSession.

Members

xml_to_request ()

Virtual function to deserialize an InfAdoptedRequest from XML. The implementation of this function can use inf_adopted_session_read_request_info() to read the common info.

 

request_to_xml ()

Virtual function to serialize an InfAdoptedRequest to XML. This function should add properties and children to the given XML node. At might use inf_adopted_session_write_request_info() to write the common info.

 

check_request ()

Default signal handler of the InfAdoptedSession::check-request signal.

 

Property Details

The “algorithm†property

  “algorithm†               InfAdoptedAlgorithm *

The adOPTed algorithm used for translating incoming requests.

Flags: Read


The “io†property

  “io†                      InfIo *

The IO object used for timeouts.

Flags: Read / Write / Construct Only


The “max-total-log-size†property

  “max-total-log-size†      guint

The maximum number of requests to keep in all user's logs.

Flags: Read / Write / Construct Only

Default value: 2048

Signal Details

The “check-request†signal

gboolean
user_function (InfAdoptedSession *session,
               InfAdoptedRequest *request,
               InfAdoptedUser    *user,
               gpointer           user_data)

This signal is emitted whenever the session received a request from a non-local user. It is used to decide whether the request should be processed or not. Note that generally not processing a request results is loss of synchronization, since other hosts might process the request. Only if the same condition can be applied on all sites a request should be rejected. Another possibility is to reject a request at a central host before it gets distributed to all other clients. If there is one signal handler returning TRUE the request is rejected, i.e. only if all signal handlers return FALSE it is accepted.

Parameters

session

The InfAdoptedSession which is about to process a request.

 

request

The request to be processed.

 

user

The user who issued the request.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfCommunicationManager.html0000644000000000000000000000013213055210752027400 xustar0030 mtime=1488261610.900090673 30 atime=1488261610.900090673 30 ctime=1488261610.900090673 libinfinity-0.7.1/docs/reference/libinfinity/html/InfCommunicationManager.html0000644000175000017500000005710113055210752030136 0ustar00arminarmin00000000000000 InfCommunicationManager: libinfinity-0.7 Reference Manual

InfCommunicationManager

InfCommunicationManager — Handling multiple communication sessions

Stability Level

Unstable, unless otherwise indicated

Types and Values

Object Hierarchy

    GObject
    ╰── InfCommunicationManager

Includes

#include <libinfinity/communication/inf-communication-manager.h>

Description

InfCommunicationManager manages multiple communication sessions represented by InfCommunicationGroup. A InfCommunicationGroup provides an easy way to send messages between group members, possibly sharing connections with other groups handled by the same InfCommunicationManager.

Functions

inf_communication_manager_new ()

InfCommunicationManager *
inf_communication_manager_new (void);

Creates a new InfCommunicationManager.

[constructor]

Returns

A new InfCommunicationManager.

[transfer full]


inf_communication_manager_open_group ()

InfCommunicationHostedGroup *
inf_communication_manager_open_group (InfCommunicationManager *manager,
                                      const gchar *group_name,
                                      const gchar * const*methods);

Opens a new communication group published by the local host. group_name is an identifier for the group via which other hosts can join the group using inf_communication_manager_join_group(). It needs to be unique among all groups opened by the local host.

methods specifies what communication methods the group should use, in order of priority. If a method is not supported for a given network, then the next one in the array is tried. If none is supported, then the "central" method will be used, which is guaranteed to be supported for all networks.

Parameters

manager

A InfCommunicationManager.

 

group_name

A name for the new group.

 

methods

Methods to support, or NULL.

[allow-none][array zero-terminated=1]

Returns

A InfCommunicationHostedGroup. Free with g_object_unref() to leave the group.

[transfer full]


inf_communication_manager_join_group ()

InfCommunicationJoinedGroup *
inf_communication_manager_join_group (InfCommunicationManager *manager,
                                      const gchar *group_name,
                                      InfXmlConnection *publisher_conn,
                                      const gchar *method);

Joins a communication group published by a remote host. publisher_conn needs to be a to the publishing host with status INF_XML_CONNECTION_OPEN or INF_XML_CONNECTION_OPENING. group_name specifies the name of the group to join.

method specifies the communication method to use. It must match the communication method the publisher has chosen for publisher_conn 's network (see inf_communication_group_get_method_for_network()). The function returns NULL if method is not supported (which means inf_communication_manager_get_factory_for() for publisher_conn 's network and method returns NULL).

Parameters

manager

A InfCommunicationManager.

 

group_name

The group to join.

 

publisher_conn

A InfXmlConnection to the publishing host.

 

method

The communication method to use.

 

Returns

A new InfCommunicationJoinedGroup, or NULL. Free with g_object_unref() to leave the group.

[transfer full][allow-none]


inf_communication_manager_add_factory ()

void
inf_communication_manager_add_factory (InfCommunicationManager *manager,
                                       InfCommunicationFactory *factory);

Adds a new InfCommunicationFactory to manager . This makes manager support all method/network combinations that factory supports. If multiple added factories support the same combination, the one which was added first will be used to instantiate the InfCommunicationMethod.

Parameters

manager

A InfCommunicationManager.

 

factory

The InfCommunicationFactory to add.

 

inf_communication_manager_get_factory_for ()

InfCommunicationFactory *
inf_communication_manager_get_factory_for
                               (InfCommunicationManager *manager,
                                const gchar *network,
                                const gchar *method_name);

Returns the InfCommunicationFactory that manager will use to instantiate a InfCommunicationMethod for method_name on network , or NULL if the network/method combination is not supported.

Parameters

manager

A InfCommunicationManager.

 

network

A network identifier.

 

method_name

A method name.

 

Returns

A InfCommunicationFactory, or NULL.

[transfer none][allow-none]

Types and Values

struct InfCommunicationManager

struct InfCommunicationManager;

InfCommunicationManager is an opaque data type. You should only access it via the public API functions.


struct InfCommunicationManagerClass

struct InfCommunicationManagerClass {
};

This structure does not contain any public fields.

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfTcpConnection.html0000644000000000000000000000013213055210752026046 xustar0030 mtime=1488261610.900090673 30 atime=1488261610.900090673 30 ctime=1488261610.900090673 libinfinity-0.7.1/docs/reference/libinfinity/html/InfTcpConnection.html0000644000175000017500000015342213055210752026607 0ustar00arminarmin00000000000000 InfTcpConnection: libinfinity-0.7 Reference Manual

InfTcpConnection

InfTcpConnection — Represents a TCP-based connection to a remote host

Stability Level

Unstable, unless otherwise indicated

Properties

guint device-index Read / Write
gchar * device-name Read / Write
InfIo * io Read / Write / Construct Only
InfKeepalive * keepalive Read / Write
InfIpAddress * local-address Read
guint local-port Read
InfIpAddress * remote-address Read / Write
guint remote-port Read / Write
InfNameResolver * resolver Read / Write / Construct
InfTcpConnectionStatus status Read

Signals

Types and Values

Object Hierarchy

    GEnum
    ╰── InfTcpConnectionStatus
    GObject
    ╰── InfTcpConnection

Includes

#include <libinfinity/common/inf-tcp-connection.h>

Description

InfTcpConnection represents a TCP connection to a remove host. It is a wrapper around a native socket object and integrates into the main loop provided by InfIo. An arbitrary amount of data can be sent with the object, extra data will be buffered and automatically transmitted once kernel space becomes available.

The TCP connection properties should be set and then inf_tcp_connection_open() be called to open a connection. If the “resolver†property is set, then “remote-address†and “remote-port†are ignored, and the hostname as configured in the resolver will be resolved. When the hostname has been resolved and a connection has been made, the “remote-address†and “remote-port†properties are updated to reflect the address actually connected to.

Functions

inf_tcp_connection_new ()

InfTcpConnection *
inf_tcp_connection_new (InfIo *io,
                        const InfIpAddress *remote_addr,
                        guint remote_port);

Creates a new InfTcpConnection. The arguments are stored as properties for an eventual inf_tcp_connection_open() call, this function itself does not establish a connection.

[constructor]

Parameters

io

A InfIo object used to watch for activity.

 

remote_addr

The address to eventually connect to.

 

remote_port

The port to eventually connect to.

 

Returns

A new InfTcpConnection. Free with g_object_unref().

[transfer full]


inf_tcp_connection_new_and_open ()

InfTcpConnection *
inf_tcp_connection_new_and_open (InfIo *io,
                                 const InfIpAddress *remote_addr,
                                 guint remote_port,
                                 GError **error);

Creates a new InfTcpConnection and connects it to the given TCP endpoint. Like inf_tcp_connection_new(), but calls inf_tcp_connection_open().

[constructor]

Parameters

io

A InfIo object used to watch for activity.

 

remote_addr

The address to connect to.

 

remote_port

The port to connect to.

 

error

Location to store error information.

 

Returns

A new InfTcpConnection, or NULL on error. Free with g_object_unref().

[transfer full]


inf_tcp_connection_new_resolve ()

InfTcpConnection *
inf_tcp_connection_new_resolve (InfIo *io,
                                InfNameResolver *resolver);

Creates a new InfTcpConnection and instead of setting the remote IP address and port number directly, a hostname resolver is used to look up the remote hostname before connecting. This has the advantage that all available addresses for that hostname are tried before giving up.

The argument is stored as a property for an eventual inf_tcp_connection_open() call, this function itself does not establish a connection.

[constructor]

Parameters

io

A InfIo object used to watch for activity.

 

resolver

The hostname resolver object used to look up the remote hostname.

 

Returns

A new InfTcpConnection. Free with g_object_unref().

[transfer full]


inf_tcp_connection_open ()

gboolean
inf_tcp_connection_open (InfTcpConnection *connection,
                         GError **error);

Attempts to open connection . Make sure to have set the "remote-address" and "remote-port" property before calling this function. If an error occurs, the function returns FALSE and error is set. Note however that the connection might not be fully open when the function returns (check the "status" property if you need to know). If an asynchronous error occurs while the connection is being opened, the "error" signal is emitted.

Parameters

connection

A InfTcpConnection.

 

error

Location to store error information.

 

Returns

FALSE if an error occured and TRUE otherwise.


inf_tcp_connection_close ()

void
inf_tcp_connection_close (InfTcpConnection *connection);

Closes a TCP connection that is either open or currently connecting.

Parameters

connection

A InfTcpConnection.

 

inf_tcp_connection_send ()

void
inf_tcp_connection_send (InfTcpConnection *connection,
                         gconstpointer data,
                         guint len);

Sends data through the TCP connection. The data is not sent immediately, but enqueued to a buffer and will be sent as soon as kernel space becomes available. The "sent" signal will be emitted when data has really been sent.

Parameters

connection

A InfTcpConnection with status INF_TCP_CONNECTION_CONNECTED.

 

data

The data to send.

[type guint8*][array length=len]

len

Number of bytes to send.

 

inf_tcp_connection_get_remote_address ()

InfIpAddress *
inf_tcp_connection_get_remote_address (InfTcpConnection *connection);

Returns the IP address of the remote site.

Parameters

connection

A InfTcpConnection.

 

Returns

A InfIpAddress owned by connection . You do not need to free it, but need to make your own copy if you want to keep it longer than connection 's lifetime.

[transfer none]


inf_tcp_connection_get_remote_port ()

guint
inf_tcp_connection_get_remote_port (InfTcpConnection *connection);

Returns the port of the remote site to which connection is (or was) connected or connecting.

Parameters

connection

A InfTcpConnection.

 

Returns

The port of the remote site.


inf_tcp_connection_set_keepalive ()

gboolean
inf_tcp_connection_set_keepalive (InfTcpConnection *connection,
                                  const InfKeepalive *keepalive,
                                  GError **error);

Sets the keepalive settings for connection . When this function is not called, the system defaults are used. If the connection is closed, then the function always succeeds and stores the keepalive values internally. The values are actually set on the underlying socket when the connection is opened. If the connection is already open, the function might fail if the system call fails.

Parameters

connection

A InfTcpConnection.

 

keepalive

New keepalive settings for the connection.

 

error

Location to store error information, if any, or NULL.

 

Returns

TRUE if the new keeplalive values were set, or FALSE on error.


inf_tcp_connection_get_keepalive ()

const InfKeepalive *
inf_tcp_connection_get_keepalive (InfTcpConnection *connection);

Returns the current keepalive settings for connection .

Parameters

connection

A InfTcpConnection.

 

Returns

The current keepalive configuration for connection , owned by connection .

Types and Values

enum InfTcpConnectionStatus

InfTcpConnectionStatus specifies the connection status of a InfTcpConnection.

Members

INF_TCP_CONNECTION_CONNECTING

A new connection is currently being established.

 

INF_TCP_CONNECTION_CONNECTED

The connection is ready to send and receive data.

 

INF_TCP_CONNECTION_CLOSED

The connection is closed. Before data can be transmitted, it needs to be opened with inf_tcp_connection_open().

 

struct InfTcpConnection

struct InfTcpConnection;

InfTcpConnection is an opaque data type. You should only access it via the public API functions.


struct InfTcpConnectionClass

struct InfTcpConnectionClass {
  /* Signals */
  void (*sent)(InfTcpConnection* connection,
               gconstpointer data,
               guint len);

  void (*received)(InfTcpConnection* connection,
                   gconstpointer data,
                   guint len);

  void (*error)(InfTcpConnection* connection,
                GError* error);
};

This structure contains the default signal handlers of InfTcpConnection.

Members

sent ()

Default signal handler for the “sent†signal.

 

received ()

Default signal handler for the “received†signal.

 

error ()

Default signal handler for the “error†signal.

 

Property Details

The “device-index†property

  “device-index†            guint

The index of the device to use for the connection.

Flags: Read / Write

Default value: 0


The “device-name†property

  “device-name†             gchar *

The name of the device to use for the connection, such as `eth0'.

Flags: Read / Write

Default value: NULL


The “io†property

  “io†                      InfIo *

I/O handler.

Flags: Read / Write / Construct Only


The “keepalive†property

  “keepalive†               InfKeepalive *

The keepalive settings for the connection.

Flags: Read / Write


The “local-address†property

  “local-address†           InfIpAddress *

The local address of the connection.

Flags: Read


The “local-port†property

  “local-port†              guint

The local port of the connection.

Flags: Read

Allowed values: <= 65535

Default value: 0


The “remote-address†property

  “remote-address†          InfIpAddress *

Address to connect to.

Flags: Read / Write


The “remote-port†property

  “remote-port†             guint

Port to connect to.

Flags: Read / Write

Allowed values: <= 65535

Default value: 0


The “resolver†property

  “resolver†                InfNameResolver *

The hostname resolver.

Flags: Read / Write / Construct


The “status†property

  “status†                  InfTcpConnectionStatus

Status of the TCP connection.

Flags: Read

Default value: INF_TCP_CONNECTION_CLOSED

Signal Details

The “error†signal

void
user_function (InfTcpConnection *connection,
               GError           *error,
               gpointer          user_data)

This signal is emitted when an error occured with the connection. If the error is fatal, the connection will change its status to INF_TCP_CONNECTION_CLOSED.

Parameters

connection

The erroneous InfTcpConnection.

 

error

A pointer to a GError object with details on the error.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last


The “received†signal

void
user_function (InfTcpConnection *connection,
               gpointer          data,
               guint             length,
               gpointer          user_data)

This signal is emitted whenever data has been received from the connection.

Parameters

connection

The InfTcpConnection through which the data has been received.

 

data

A gpointer refering to the data that has been received.

 

length

A guint holding the number of bytes that has been received.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last


The “sent†signal

void
user_function (InfTcpConnection *connection,
               gpointer          data,
               guint             length,
               gpointer          user_data)

This signal is emitted whenever data has been sent over the connection.

Parameters

connection

The InfTcpConnection through which the data has been sent.

 

data

A gpointer refering to the data that has been sent.

 

length

A guint holding the number of bytes that has been sent.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfSaslContext.html0000644000000000000000000000013213055210752025547 xustar0030 mtime=1488261610.900090673 30 atime=1488261610.900090673 30 ctime=1488261610.904090664 libinfinity-0.7.1/docs/reference/libinfinity/html/InfSaslContext.html0000644000175000017500000017150013055210752026305 0ustar00arminarmin00000000000000 InfSaslContext: libinfinity-0.7 Reference Manual

InfSaslContext

InfSaslContext — Asynchronous SASL processing

Stability Level

Unstable, unless otherwise indicated

Types and Values

Object Hierarchy

    GBoxed
    ╰── InfSaslContext

Includes

#include <libinfinity/common/inf-sasl-context.h>

Description

InfSaslContext is a wrapper for the Gsasl library. It basically adds functionality to provide properties asynchronously to Gsasl, so that for example a dialog can be shown to the user before continuing with the authentication process. With Gsasl, it is expected that the callback function sets the requested property before returning, which makes it hard to give control back to a main loop while waiting for user input.

This wrapper makes sure the callback is called in another thread so that it can block without affecting the rest of the program. Use inf_sasl_context_session_feed() as a replacement for gsasl_step64(). Instead of returning the result data directly, the function calls a callback once all properties requested have been provided.

All threading internals are hidden by the wrapper, so all callbacks are issued in the user thread. However, it requires an InfIo object to dispatch messages to it. Also, all InfSaslContext functions are fully thread-safe.

Functions

InfSaslContextCallbackFunc ()

void
(*InfSaslContextCallbackFunc) (InfSaslContextSession *session,
                               Gsasl_property property,
                               gpointer session_data,
                               gpointer user_data);

This callback is called whenever a property is required to proceed with authentication. For example, when a password is required, the callback is called with property set to GSASL_PASSCODE.

The function is then expected to set that property using inf_sasl_context_session_set_property() and, once it is done, call inf_sasl_context_session_continue(). This can happen fully asynchronously, that is it does not need to take place directly within the callback but the callback can, for example, open a dialog for the user to enter a password and then once the user closes the dialog call the two functions mentioned above.

Parameters

session

A InfSaslContextSession.

 

property

The property requested.

 

session_data

The session data for session specified in inf_sasl_context_server_start_session() or inf_sasl_context_client_start_session().

 

user_data

The user data specified in inf_sasl_context_set_callback().

 

InfSaslContextSessionFeedFunc ()

void
(*InfSaslContextSessionFeedFunc) (InfSaslContextSession *session,
                                  const char *data,
                                  gboolean needs_more,
                                  const GError *error,
                                  gpointer user_data);

This function is called in response to inf_sasl_context_session_feed(). When all required properties (if any) have been provided by the callback function then this function is called with the response to send to the remote site.

If an error occurred then error will be set and data will be NULL.

Parameters

session

A InfSaslContextSession.

 

data

The response to the fed data, base64 encoded and null-terminated.

 

needs_more

If TRUE then inf_sasl_context_session_feed() needs to be called again with more data, otherwise the authentication has finished.

 

error

This is nonzero if an error occured while processing the input data.

 

user_data

The user data specified in inf_sasl_context_session_feed().

 

inf_sasl_context_new ()

InfSaslContext *
inf_sasl_context_new (GError **error);

Creates a new InfSaslContext with a reference count of 1. If the function fails it returns NULL and error is set.

[constructor]

Parameters

error

Location to store error information, if any.

 

Returns

A new InfSaslContext, or NULL on error. Free with inf_sasl_context_unref() when no longer needed.

[transfer full]


inf_sasl_context_ref ()

InfSaslContext *
inf_sasl_context_ref (InfSaslContext *context);

Increases the reference count of context by one.

Parameters

context

A InfSaslContext.

 

Returns

The passed in pointer, context .


inf_sasl_context_unref ()

void
inf_sasl_context_unref (InfSaslContext *context);

Decreases the reference count of sasl by one. When the reference count reaches zero then the object is freed and may no longer be used. If that happens then also all sessions created with inf_sasl_context_client_start_session() or inf_sasl_context_server_start_session() are stopped automatically.

Parameters

context

A InfSaslContext.

 

inf_sasl_context_set_callback ()

void
inf_sasl_context_set_callback (InfSaslContext *context,
                               InfSaslContextCallbackFunc callback,
                               gpointer user_data,
                               GDestroyNotify notify);

Sets the callback to call when, during authentication, a certain properties needs to be provided, such as a username or a password. The callback function is expected to set the requested property using inf_sasl_context_session_set_property() and then call inf_sasl_context_session_continue() with retval being GSASL_OK. If it cannot provide the property then it should only call inf_sasl_context_session_continue() with retval indicating the problem.

The callback function does not need to provide the property immediately. It is also allowed return and call inf_sasl_context_session_continue() later.

Parameters

context

A InfSaslContext.

 

callback

A function to call to query properties for authentication.

 

user_data

Additional context to pass to callback .

 

notify

Function called to destroy user_data once it is no longer needed, or NULL.

 

inf_sasl_context_client_start_session ()

InfSaslContextSession *
inf_sasl_context_client_start_session (InfSaslContext *context,
                                       InfIo *io,
                                       const char *mech,
                                       gpointer session_data,
                                       GError **error);

Starts a new client-side SASL session using mech for authentication. When the session finished, that is either when an error occurred or the authentication finished successfully, use inf_sasl_context_stop_session().

The callback function will be called in the thread that io runs in.

Parameters

context

A InfSaslContext.

 

io

The InfIo main loop to which to dispatch callbacks.

 

mech

The mechanism to use for the session.

 

session_data

Session-specific data to provide to the InfSaslContextCallbackFunc.

 

error

Location to store error information, if any.

 

Returns

A InfSaslContextSession.

[transfer none]


inf_sasl_context_client_list_mechanisms ()

char *
inf_sasl_context_client_list_mechanisms
                               (InfSaslContext *context,
                                GError **error);

Returns a newly allocated space-separated string containing SASL mechanisms that context supports for client sessions.

Parameters

context

A InfSaslContext.

 

error

Location to store error information, if any.

 

Returns

A newly allocated string. Free with g_free() when no longer in use.

[transfer full]


inf_sasl_context_client_supports_mechanism ()

gboolean
inf_sasl_context_client_supports_mechanism
                               (InfSaslContext *context,
                                const char *mech);

Checks whether context supports the mechanism with name mech for client sessions.

Parameters

context

A InfSaslContext.

 

mech

The name of the mechanism to be tested.

 

Returns

TRUE if mech is supported or FALSE otherwise.


inf_sasl_context_client_suggest_mechanism ()

const char *
inf_sasl_context_client_suggest_mechanism
                               (InfSaslContext *context,
                                const char *mechanisms);

Given a list of SASL mechanisms this function suggests the which is the "best" one to be used.

Parameters

context

A InfSaslContext.

 

mechanisms

Space-separated list of SASL mechanism names.

 

Returns

The name of the suggested mechanism.

[transfer none]


inf_sasl_context_server_start_session ()

InfSaslContextSession *
inf_sasl_context_server_start_session (InfSaslContext *context,
                                       InfIo *io,
                                       const char *mech,
                                       gpointer session_data,
                                       GError **error);

Starts a new server-side SASL session using mech for authentication. When the session finished, that is either when an error occurred or the authentication finished successfully, use inf_sasl_context_stop_session().

The callback function will be called in the thread that io runs in.

Parameters

context

A InfSaslContext.

 

io

The InfIo main loop to which to dispatch callbacks.

 

mech

The mechanism to use for the session.

 

session_data

Session-specific data to provide to the InfSaslContextCallbackFunc.

 

error

Location to store error information, if any.

 

Returns

A InfSaslContextSession.

[transfer none]


inf_sasl_context_server_list_mechanisms ()

char *
inf_sasl_context_server_list_mechanisms
                               (InfSaslContext *context,
                                GError **error);

Returns a newly allocated space-separated string containing SASL mechanisms that context supports for server sessions.

Parameters

context

A InfSaslContext.

 

error

Location to store error information, if any.

 

Returns

A newly allocated string. Free with g_free() when no longer in use.

[transfer full]


inf_sasl_context_server_supports_mechanism ()

gboolean
inf_sasl_context_server_supports_mechanism
                               (InfSaslContext *context,
                                const char *mech);

Checks whether context supports the mechanism with name mech for server sessions.

Parameters

context

A InfSaslContext.

 

mech

The name of the mechanism to be tested.

 

Returns

TRUE if mech is supported or FALSE otherwise.


inf_sasl_context_stop_session ()

void
inf_sasl_context_stop_session (InfSaslContext *context,
                               InfSaslContextSession *session);

Finishes session and frees all resources allocated to it. This can be used to cancel an authentication session, or to free it after it finished (either successfully or not).

session should no longer be used after this function was called.

Parameters

context

A InfSaslContext.

 

session

A InfSaslContextSession created with context .

 

inf_sasl_context_session_get_property ()

const char *
inf_sasl_context_session_get_property (InfSaslContextSession *session,
                                       Gsasl_property prop);

Returns the value of the property prop in session . If the value does not yet exist then this function returns NULL. It does not invoke the InfSaslContextCallbackFunc to query it.

Parameters

session

A InfSaslContextSession.

 

prop

A SASL property.

 

Returns

The value of the property, or NULL. The value is owned by the session and must not be freed.

[allow-none]


inf_sasl_context_session_set_property ()

void
inf_sasl_context_session_set_property (InfSaslContextSession *session,
                                       Gsasl_property prop,
                                       const char *value);

Sets the property prop in session to value .

Parameters

session

A InfSaslContextSession.

 

prop

A SASL property.

 

value

The value to set the property to.

[allow-none]

inf_sasl_context_session_continue ()

void
inf_sasl_context_session_continue (InfSaslContextSession *session,
                                   int retval);

When the callback function specified in inf_sasl_context_set_callback() is called then session waits for the user to call inf_sasl_context_session_continue(). It should do so once it provided the requested property using inf_sasl_context_session_set_property() with retval being GSASL_OK. If it decides that the property cannot be provided then it should still call this function with retval being a SASL error code specifying the problem.

Parameters

session

A InfSaslContextSession.

 

retval

Error code of the operation requested.

 

inf_sasl_context_session_feed ()

void
inf_sasl_context_session_feed (InfSaslContextSession *session,
                               const char *data,
                               InfSaslContextSessionFeedFunc func,
                               gpointer user_data);

This function feeds data from the session's remote counterpart to session . It should be base64 encoded. This function will, asynchronously, process the data and query for properties it requires to do so. Once it has finished, func is called with output data to send to the remote side to be fed to its session counterpart.

This function must not be called again before func was called.

Parameters

session

A InfSaslContextSession.

 

data

The data to feed to the SASL session.

 

func

The function to call when the data has been processed.

[scope async]

user_data

Additional user data to pass to func .

 

inf_sasl_context_session_is_processing ()

gboolean
inf_sasl_context_session_is_processing
                               (InfSaslContextSession *session);

Returns whether the session is currently asynchronously processing data fed to it with inf_sasl_context_session_feed(). In this case the first call needs to finish before another one is allowed to be made.

Parameters

session

A InfSaslContextSession.

 

Returns

Whether session is currently processing data asynchronously.

Types and Values

InfSaslContext

typedef struct _InfSaslContext InfSaslContext;

InfSaslContext is an opaque data type. You should only access it via the public API functions.


InfSaslContextSession

typedef struct _InfSaslContextSession InfSaslContextSession;

InfSaslContextSession represents an ongoing authentication session. Create with inf_sasl_context_server_start_session() or inf_sasl_context_client_start_session().

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfDiscovery.html0000644000000000000000000000013213055210752025247 xustar0030 mtime=1488261610.904090664 30 atime=1488261610.904090664 30 ctime=1488261610.904090664 libinfinity-0.7.1/docs/reference/libinfinity/html/InfDiscovery.html0000644000175000017500000011247013055210752026006 0ustar00arminarmin00000000000000 InfDiscovery: libinfinity-0.7 Reference Manual

InfDiscovery

InfDiscovery — Discovery of remote services

Stability Level

Unstable, unless otherwise indicated

Types and Values

Object Hierarchy

    GInterface
    ╰── InfDiscovery

Prerequisites

InfDiscovery requires GObject.

Known Implementations

InfDiscovery is implemented by InfDiscoveryAvahi.

Includes

#include <libinfinity/common/inf-discovery.h>

Description

InfDiscovery provides a common interface for the discovery of services. Discovered services are represented by InfDiscoveryInfo objects and can be used to query the name of the discovered service.

To create a connection to the host providing a discovered service, use inf_discovery_resolve().

Functions

InfDiscoveryResolvCompleteFunc ()

void
(*InfDiscoveryResolvCompleteFunc) (InfDiscoveryInfo *info,
                                   InfXmlConnection *connection,
                                   const GError *error,
                                   gpointer user_data);

This callback is called when a call to inf_discovery_resolve() finished.

Parameters

info

The resolved InfDiscoveryInfo.

 

connection

The resulting InfXmlConnection.

 

error

Reason in case of failure.

 

user_data

The user_data passed to inf_discovery_resolve().

 

inf_discovery_discover ()

void
inf_discovery_discover (InfDiscovery *discovery,
                        const gchar *type);

Starts the discovery of the given service type. Whenever a service of this type is discovered, the "discovered" signal is emitted. If the service disappears, the "undiscovered" signal is emitted. This can be called more than once for the same type, but only the first call has an effect.

Note also that implementations of InfDiscovery might restrict the service types that can be discovered.

Parameters

discovery

A InfDiscovery.

 

type

The service type to discover.

 

inf_discovery_get_discovered ()

GSList *
inf_discovery_get_discovered (InfDiscovery *discovery,
                              const gchar *type);

Returns a list of discovered InfDiscoveryInfo for the given type.

Parameters

discovery

A InfDiscovery.

 

type

The service type of which to get discovered infos for.

 

Returns

A newly allocated list that needs to be freed with g_slist_free().

[transfer container][element-type InfDiscoveryInfo]


inf_discovery_resolve ()

void
inf_discovery_resolve (InfDiscovery *discovery,
                       InfDiscoveryInfo *info,
                       InfDiscoveryResolvCompleteFunc complete_func,
                       gpointer user_data);

Attempts to resolve info . Resolving a InfDiscoveryInfo means creating a InfXmlConnection to the publisher. The connection might not be open when complete_func runs.

Parameters

discovery

A InfDiscovery.

 

info

A InfDiscoveryInfo discovered by discovery .

 

complete_func

A callback that will be called when the resolving process has completed.

[scope async]

user_data

Extra data to pass to complete_func and error_func .

 

inf_discovery_info_get_service_name ()

gchar *
inf_discovery_info_get_service_name (InfDiscovery *discovery,
                                     InfDiscoveryInfo *info);

Returns the service name of the discovered info .

Parameters

discovery

A InfDiscovery.

 

info

A InfDiscoveryInfo discovered by discovery .

 

Returns

A newly allocated string. Free with g_free().

[transfer full]


inf_discovery_info_get_service_type ()

const gchar *
inf_discovery_info_get_service_type (InfDiscovery *discovery,
                                     InfDiscoveryInfo *info);

Returns the service type of the discovered info .

Parameters

discovery

A InfDiscovery.

 

info

A InfDiscoveryInfo discovered by discovery .

 

Returns

A string owned by discovery .

[transfer none]


inf_discovery_discovered ()

void
inf_discovery_discovered (InfDiscovery *discovery,
                          InfDiscoveryInfo *info);

Emits the "discovered" signal on discovery .

Parameters

discovery

A InfDiscovery.

 

info

The discovered InfDiscoveryInfo.

 

inf_discovery_undiscovered ()

void
inf_discovery_undiscovered (InfDiscovery *discovery,
                            InfDiscoveryInfo *info);

Emits the "undiscovered" signal on discovery .

Parameters

discovery

A InfDiscovery.

 

info

The undiscovered InfDiscoveryInfo .

 

Types and Values

InfDiscovery

typedef struct _InfDiscovery InfDiscovery;

InfDiscovery is an opaque data type. You should only access it via the public API functions.


struct InfDiscoveryInterface

struct InfDiscoveryInterface {
  void (*discover)(InfDiscovery* discovery,
                   const gchar* type);

  GSList* (*get_discovered)(InfDiscovery* discovery,
                            const gchar* type);

  void (*resolve)(InfDiscovery* discovery,
                  InfDiscoveryInfo* info,
                  InfDiscoveryResolvCompleteFunc complete_func,
                  gpointer user_data);

  gchar*(*info_get_service_name)(InfDiscovery* discovery,
                                 InfDiscoveryInfo* info);

  const gchar*(*info_get_service_type)(InfDiscovery* discovery,
                                       InfDiscoveryInfo* info);

  /* Signals */
  void (*discovered)(InfDiscovery* discovery,
                     InfDiscoveryInfo* info);

  void (*undiscovered)(InfDiscovery* discovery,
                       InfDiscoveryInfo* info);
};

The virtual methods and default signal handlers of InfDiscovery. Implementing these allows discovering infinote servers.

Members

discover ()

Virtual function to start discovery of services of the given type. If the discovery was already started ealier, then this function does nothing.

 

get_discovered ()

Virtual function to retrieve a list of InfDiscoveryInfos that represent discovered services. It needs to be freed by the caller via g_slist_free().

 

resolve ()

Virtual function that attempts to resolve the given discovery info. It guarantees to either call complete_func or error_func when the process has finished.

 

info_get_service_name ()

Returns the service name of the given InfDiscoveryInfo as a new string, to be freed by the caller with g_free().

 

info_get_service_type ()

Returns the type of the discovered service of the given InfDiscoveryInfo as a static string.

 

discovered ()

Default signal handler for the “discovered†signal.

 

undiscovered ()

Default signal handler for the “undiscovered†signal.

 

InfDiscoveryInfo

typedef struct _InfDiscoveryInfo InfDiscoveryInfo;

InfDiscoveryInfo is an opaque data type. You should only access it via the public API functions.

Signal Details

The “discovered†signal

void
user_function (InfDiscovery *discoverer,
               gpointer      info,
               gpointer      user_data)

This signal is detailed. The detail is the name of the service that has been discovered, so you can connect to "discovered::my-service-name" if you are only interested in a particular service.

Parameters

discoverer

The InfDiscovery object discovering something

 

info

The InfDiscoveryInfo describing the discovered service

 

user_data

user data set when the signal handler was connected.

 

Flags: Has Details


The “undiscovered†signal

void
user_function (InfDiscovery *discoverer,
               gpointer      info,
               gpointer      user_data)

This signal is emitted if a previously discovered service is no longer available.

This signal is detailed. The detail is the name of the service that has been undiscovered, so you can connect to "undiscovered::my-service-name" if you are only interested in a particular service.

Parameters

discoverer

The InfDiscovery object undiscovering something

 

info

The InfDiscoveryInfo describing the undiscovered service

 

user_data

user data set when the signal handler was connected.

 

Flags: Has Details

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/libinfinity-0.7-InfFileUtil.html0000644000000000000000000000013213055210752027635 xustar0030 mtime=1488261610.904090664 30 atime=1488261610.904090664 30 ctime=1488261610.904090664 libinfinity-0.7.1/docs/reference/libinfinity/html/libinfinity-0.7-InfFileUtil.html0000644000175000017500000010126013055210752030367 0ustar00arminarmin00000000000000 File and directory utility functions: libinfinity-0.7 Reference Manual

File and directory utility functions

File and directory utility functions — Helper functions to handle directories.

Stability Level

Unstable, unless otherwise indicated

Types and Values

Includes

#include <libinfinity/common/inf-file-util.h>

Description

These functions are utility functions that can be used when dealing with directories. It allows platform-independent creation, deletion and traversal of directories, with proper error reporting.

Functions

InfFileListFunc ()

gboolean
(*InfFileListFunc) (const gchar *name,
                    const gchar *path,
                    InfFileType type,
                    gpointer user_data,
                    GError **error);

This is the prototype of the callback function passed to inf_file_util_list_directory(). If the function returns FALSE then directory traversal is stopped immediately. In addition error can be set and it is propagated to the caller of inf_file_util_list_directory().

Parameters

name

The name of the current file.

 

path

The full path to the current file.

 

type

The type of the current file.

 

user_data

User data specified at the time of the call.

 

error

Location to store error information, if any, or NULL.

 

Returns

TRUE if the iteration should be continued or FALSE otherwise.


inf_file_util_create_single_directory ()

gboolean
inf_file_util_create_single_directory (const gchar *path,
                                       int mode,
                                       GError **error);

Attempts to create a directory at path . The mode parameter is only used on Unix in which case it specifies the permissions to use for all newly created directories in the same way as g_mkdir() would.

Parameters

path

The directory to create.

[type filename]

mode

Permissions to use for the newly created directory.

 

error

Location to store error information, if any, or NULL.

 

Returns

TRUE on success or FALSE on error.


inf_file_util_create_directory ()

gboolean
inf_file_util_create_directory (const gchar *path,
                                int mode,
                                GError **error);

Attempts to create a directory at path , creating intermediate directories as necessary. The mode parameter is only used on Unix in which case it specifies the permissions to use for all newly created directories in the same way as g_mkdir() would.

Parameters

path

The directory to create.

[type filename]

mode

Permissions to use for the newly created directory.

 

error

Location to store error information, if any, or NULL.

 

Returns

TRUE on success or FALSE on error.


inf_file_util_list_directory ()

gboolean
inf_file_util_list_directory (const gchar *path,
                              InfFileListFunc func,
                              gpointer user_data,
                              GError **error);

Calls func for each file within the given directory. It also passes the type of the found file to the callback function. The callback function can return FALSE to stop the iteration. If it does this, then this function still returns TRUE. This can for example be used to find a file in a directory. If, in addition, the callback function sets error , then this function returns FALSE and propagates the error.

Parameters

path

The directory to explore.

[type filename]

func

Callback function to be called for each child of the directory at path .

[scope call]

user_data

Additional data to pass to func .

 

error

Location to store error information, if any, or NULL.

 

Returns

TRUE on success or FALSE on error.


inf_file_util_delete_file ()

gboolean
inf_file_util_delete_file (const gchar *path,
                           GError **error);

Removes the file at path if it is empty. Fails if path points to a directory and not a regular file. If the function fails FALSE is returned and error is set.

Parameters

path

Path to the file to delete.

[type filename]

error

Location to store error information, if any, or NULL.

 

Returns

TRUE on success or FALSE on error.


inf_file_util_delete_single_directory ()

gboolean
inf_file_util_delete_single_directory (const gchar *path,
                                       GError **error);

Removes the directory at path if it is empty, or fails otherwise. Fails if path points to a regular file and not a directory. If the function fails FALSE is returned and error is set.

Parameters

path

Path to the directory to delete.

[type filename]

error

Location to store error information, if any, or NULL.

 

Returns

TRUE on success or FALSE on error.


inf_file_util_delete_directory ()

gboolean
inf_file_util_delete_directory (const gchar *path,
                                GError **error);

Removes the directory at path recursively. Fails if path points to a regular file and not a directory. If the function fails FALSE is returned and error is set.

Parameters

path

Path to the directory to delete.

[type filename]

error

Location to store error information, if any, or NULL.

 

Returns

TRUE on success or FALSE on error.


inf_file_util_delete ()

gboolean
inf_file_util_delete (const gchar *path,
                      GError **error);

Removes the file or directory at path . If it is a directory the directory is deleted recursively. If the function fails FALSE is returned and error is set.

Parameters

path

Path to the object to delete.

[type filename]

error

Location to store error information, if any, or NULL.

 

Returns

TRUE on success or FALSE on error.


inf_file_util_write_private_data ()

gboolean
inf_file_util_write_private_data (const gchar *filename,
                                  const void *data,
                                  size_t length,
                                  GError **error);

Types and Values

enum InfFileType

This type represents the possible file types that inf_file_util_list_directory() can report.

Members

INF_FILE_TYPE_UNKNOWN

Unknown file type.

 

INF_FILE_TYPE_REG

File is a regular file.

 

INF_FILE_TYPE_DIR

File is a directory.

 

INF_FILE_TYPE_LNK

File is a symbolic link.

 
libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/index.html0000644000000000000000000000013213055210752023752 xustar0030 mtime=1488261610.904090664 30 atime=1488261610.904090664 30 ctime=1488261610.904090664 libinfinity-0.7.1/docs/reference/libinfinity/html/index.html0000644000175000017500000003722713055210752024517 0ustar00arminarmin00000000000000 libinfinity-0.7 Reference Manual: libinfinity-0.7 Reference Manual

for libinfinity 0.7.0. The latest version of this documentation can be found on-line at http://infinote.0x539.de/libinfinity/API/libinfinity/.


About libinfinity
Compiling and Using libinfinity
Common libinfinity API
InfInit
InfBrowser — Browsing of infinote directories
InfBrowserIter — Iterating through browsed nodes
InfSessionProxy — Joining users into a session
InfRequest — Asynchronous request
Result of an asynchronous request — Request results for the infinote requests
InfSession — Basic session object and synchronization
InfChatSession — Simple standalone chat
InfChatBuffer — A ring buffer for chat messages
InfUserTable — User information storage
InfUser — User in a InfSession.
Access Control Lists — Common data structures for the infinote ACL Permissions
InfDiscovery — Discovery of remote services
InfLocalPublisher — Publish services on the local network
InfIpAddress — IPv4 and IPv6 addresses
InfNameResolver — Asynchronous DNS name lookup with support for SRV records
InfKeepalive — Platform-independent configuration of TCP keep-alive probes
InfTcpConnection — Represents a TCP-based connection to a remote host
InfXmlConnection — Exchange of XML messages
InfXmppConnection — Implementation of the XMPP core protocol
InfSimulatedConnection — Simulated network connection
InfDiscoveryAvahi — Service Discovery via Avahi
InfXmppManager — Reuse existing connections
InfCertificateVerify — Server certificate verification.
InfIo — Event loop abstraction
InfStandaloneIo — Simple event loop implementation
InfAsyncOperation — Perform long-running operations in a separate thread
InfCertificateChain — X.509 certificate chains
File and directory utility functions — Helper functions to handle directories.
Certificate utility functions — Helper functions to read and write information from X.509 certificates.
XML utility functions — Helper functions to read basic data types from XML
InfCertificateCredentials — Reference-counted wrapper for gnutls_certificate_credentials_t
InfSaslContext — Asynchronous SASL processing
InfError — Common error codes
InfProtocol — Infinote protocol parameters
InfNativeSocket — Uniform access to the BSD socket API
InfBuffer — Abstract document interface
Libinfinity's adOPTed implementation
InfAdoptedSession — Session handling concurrency control via the adOPTed algorithm.
InfAdoptedSessionRecord — Create a record of a session
InfAdoptedSessionReplay — Replay a record of a session
InfAdoptedUndoGrouping — Grouping of requests to be undone simultaneously
InfAdoptedAlgorithm — adOPTed implementation
InfAdoptedRequestLog — History of requests
InfAdoptedRequest — Request processed by InfAdoptedAlgorithm.
InfAdoptedOperation — Operation that can be processed by InfAdoptedAlgorithm.
InfAdoptedNoOperation — An operation not doing anything.
InfAdoptedSplitOperation — Operation wrapping two operations
InfAdoptedUser — User in a InfAdoptedUser.
InfAdoptedStateVector — Represents a state in the interaction model
Libinfinity client side API
InfcBrowser — Browse remote directories
InfcNotePlugin
InfcSessionProxy — Client-side session management
InfcRequest — Asynchronous request
InfcProgressRequest — Asynchronous request with dynamic progress.
InfcRequestManager — Keeps track of pending asynchronous requests
Libinfinity server side API
InfdDirectory — Directory of published documents
InfdNotePlugin
infd-storage
InfdAccountStorage — Interface to user account database
InfdFilesystemStorage
InfdFilesystemAccountStorage — Standalone account storage backend
Storage of chat sessions on the file system — Utility functions to deal with storing InfChatSessions in filesystem storage
InfdSessionProxy — Server-side session management
InfdRequest — Asynchronous request on the server side
InfdProgressRequest — Watch progress of node exploration
InfdTcpServer
InfdXmlServer
InfdXmppServer
InfdServerPool
Network abstraction
InfCommunicationManager — Handling multiple communication sessions
InfCommunicationObject — Network message destinations
InfCommunicationGroup — Communication channel for mulitple connections
InfCommunicationHostedGroup — Communication group opened by the local host
InfCommunicationJoinedGroup — Communication group opened by a remote host
InfCommunicationFactory — Creation of communication methods
InfCommunicationMethod — Network communication method
InfCommunicationRegistry — Sharing connections between multiple groups
InfCommunicationCentralFactory — Factory for InfCommunicationCentralMethod methods
InfCommunicationCentralMethod — Relying group messages via the publisher
Annotation Glossary
libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfAdoptedSessionReplay.html0000644000000000000000000000013213055210752027401 xustar0030 mtime=1488261610.904090664 30 atime=1488261610.904090664 30 ctime=1488261610.904090664 libinfinity-0.7.1/docs/reference/libinfinity/html/InfAdoptedSessionReplay.html0000644000175000017500000006625613055210752030152 0ustar00arminarmin00000000000000 InfAdoptedSessionReplay: libinfinity-0.7 Reference Manual

InfAdoptedSessionReplay

InfAdoptedSessionReplay — Replay a record of a session

Stability Level

Unstable, unless otherwise indicated

Properties

gchar * filename Read
InfAdoptedSession * session Read

Object Hierarchy

    GObject
    ╰── InfAdoptedSessionReplay

Includes

#include <libinfinity/adopted/inf-adopted-session-replay.h>

Description

InfAdoptedSessionReplay can be used to replay a record created with InfAdoptedSessionRecord.

Use inf_adopted_session_replay_set_record() to specify the recording to replay, and then use inf_adopted_session_replay_get_session() to obtain the replayed session.

Functions

inf_adopted_session_replay_new ()

InfAdoptedSessionReplay *
inf_adopted_session_replay_new (void);

Creates a new InfAdoptedSessionReplay. Use inf_adopted_session_replay_set_record() to start the recording, and inf_adopted_session_replay_play_next() or inf_adopted_session_replay_play_to_end() to play it.

[constructor]

Returns

A new InfAdoptedSessionReplay. Free with g_object_unref() when no longer in use.

[transfer full]


inf_adopted_session_replay_set_record ()

gboolean
inf_adopted_session_replay_set_record (InfAdoptedSessionReplay *replay,
                                       const gchar *filename,
                                       const InfcNotePlugin *plugin,
                                       GError **error);

Set the record file for replay to play. It should have been created with InfAdoptedSessionRecord. plugin should match the type of the recorded session. If an error occurs, the function returns FALSE and error is set.

Parameters

replay

A InfAdoptedSessionReplay.

 

filename

Path to the record file to play.

[type filename]

plugin

A InfcNotePlugin for the note type of the recorded session.

 

error

Location to store error information, if any.

 

Returns

TRUE on success, or FALSE if the record file could not be set.


inf_adopted_session_replay_get_session ()

InfAdoptedSession *
inf_adopted_session_replay_get_session
                               (InfAdoptedSessionReplay *replay);

Returns the played back session, or NULL if inf_adopted_session_replay_set_record() was not yet called.

Parameters

replay

A InfAdoptedSessionReplay.

 

Returns

A InfAdoptedSessionReplay, or NULL.

[transfer none]


inf_adopted_session_replay_play_next ()

gboolean
inf_adopted_session_replay_play_next (InfAdoptedSessionReplay *replay,
                                      GError **error);

Reads the next request from the record and passes it to the session. Note that this might do nothing if that request is not yet causally ready, meaning that it depends on another request that has not yet been played. In that case it will be executed as soon as it is ready, that is after some future inf_adopted_session_replay_play_next() call. Therefore, it is also possible that this function executes more than one request.

If an error occurs, then this function returns FALSE and error is set. If the end of the recording is reached, then it also returns FALSE, but error is left untouched. If the next request has been read, then it returns TRUE.

Parameters

replay

A InfAdoptedSessionReplay.

 

error

Location to store error information, if any.

 

Returns

TRUE if a request was read, otherwise FALSE.


inf_adopted_session_replay_play_to_end ()

gboolean
inf_adopted_session_replay_play_to_end
                               (InfAdoptedSessionReplay *replay,
                                GError **error);

Plays all requests that are contained in the recording, so that the replay's session has the same state as the recorded session when the recording was stopped.

Note that, depending on the size of the record, this function may take some time to finish.

If an error occurs during replay, then the function returns FALSE and error is set. Otherwise it returns TRUE.

Parameters

replay

A InfAdoptedSessionReplay.

 

error

Location to store error information, if any.

 

Returns

TRUE on success, or FALSE if an error occurs.

Types and Values

enum InfAdoptedSessionReplayError

Error codes for the INF_ADOPTED_SESSION_REPLAY_ERROR error domain. These can occur while loading or replaying a session with InfAdoptedSessionReplay.

Members

INF_ADOPTED_SESSION_REPLAY_ERROR_BAD_FILE

The record file could not be opened for reading.

 

INF_ADOPTED_SESSION_REPLAY_ERROR_BAD_XML

The record file contains invalid XML.

 

INF_ADOPTED_SESSION_REPLAY_ERROR_BAD_DOCUMENT

The record file is not a session recording.

 

INF_ADOPTED_SESSION_REPLAY_ERROR_BAD_SESSION_TYPE

The record file is a session recording for a different type of session than the one provided.

 

INF_ADOPTED_SESSION_REPLAY_ERROR_BAD_FORMAT

The record file is invalid.

 

INF_ADOPTED_SESSION_REPLAY_ERROR_UNEXPECTED_EOF

More data was expected to be read from the record file, but the end of file was reached.

 

struct InfAdoptedSessionReplay

struct InfAdoptedSessionReplay;

InfAdoptedSessionReplay is an opaque data type. You should only access it via the public API functions.


struct InfAdoptedSessionReplayClass

struct InfAdoptedSessionReplayClass {
};

This structure does not contain any public fields.

Property Details

The “filename†property

  “filename†                gchar *

The filename of the record to play.

Flags: Read

Default value: NULL


The “session†property

  “session†                 InfAdoptedSession *

The replayed session.

Flags: Read

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfcRequest.html0000644000000000000000000000013213055210752025073 xustar0030 mtime=1488261610.904090664 30 atime=1488261610.904090664 30 ctime=1488261610.904090664 libinfinity-0.7.1/docs/reference/libinfinity/html/InfcRequest.html0000644000175000017500000002002113055210752025620 0ustar00arminarmin00000000000000 InfcRequest: libinfinity-0.7 Reference Manual

InfcRequest

InfcRequest — Asynchronous request

Stability Level

Unstable, unless otherwise indicated

Properties

guint node-id Read / Write / Construct Only
guint seq Read / Write / Construct Only

Types and Values

Object Hierarchy

    GObject
    ╰── InfcRequest
        ╰── InfcProgressRequest

Implemented Interfaces

InfcRequest implements InfRequest.

Includes

#include <libinfinity/client/infc-request.h>

Description

InfcRequest represents an asynchronous operation on the client side, waiting for a reply from the server.

Functions

Types and Values

struct InfcRequest

struct InfcRequest;

InfcRequest is an opaque data type. You should only access it via the public API functions.


struct InfcRequestClass

struct InfcRequestClass {
};

This structure does not contain any public fields.

Property Details

The “node-id†property

  “node-id†                 guint

The ID of the node affected by this request.

Flags: Read / Write / Construct Only

Default value: 4294967295


The “seq†property

  “seq†                     guint

The sequence number of the request.

Flags: Read / Write / Construct Only

Default value: 0

See Also

InfcBrowser

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/ch04.html0000644000000000000000000000013213055210752023401 xustar0030 mtime=1488261610.904090664 30 atime=1488261610.904090664 30 ctime=1488261610.904090664 libinfinity-0.7.1/docs/reference/libinfinity/html/ch04.html0000644000175000017500000000516313055210752024140 0ustar00arminarmin00000000000000 Libinfinity client side API: libinfinity-0.7 Reference Manual

Libinfinity client side API

InfcBrowser — Browse remote directories
InfcNotePlugin
InfcSessionProxy — Client-side session management
InfcRequest — Asynchronous request
InfcProgressRequest — Asynchronous request with dynamic progress.
InfcRequestManager — Keeps track of pending asynchronous requests
libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/ch02.html0000644000000000000000000000013213055210752023377 xustar0030 mtime=1488261610.904090664 30 atime=1488261610.904090664 30 ctime=1488261610.904090664 libinfinity-0.7.1/docs/reference/libinfinity/html/ch02.html0000644000175000017500000001762713055210752024146 0ustar00arminarmin00000000000000 Common libinfinity API: libinfinity-0.7 Reference Manual

Common libinfinity API

InfInit
InfBrowser — Browsing of infinote directories
InfBrowserIter — Iterating through browsed nodes
InfSessionProxy — Joining users into a session
InfRequest — Asynchronous request
Result of an asynchronous request — Request results for the infinote requests
InfSession — Basic session object and synchronization
InfChatSession — Simple standalone chat
InfChatBuffer — A ring buffer for chat messages
InfUserTable — User information storage
InfUser — User in a InfSession.
Access Control Lists — Common data structures for the infinote ACL Permissions
InfDiscovery — Discovery of remote services
InfLocalPublisher — Publish services on the local network
InfIpAddress — IPv4 and IPv6 addresses
InfNameResolver — Asynchronous DNS name lookup with support for SRV records
InfKeepalive — Platform-independent configuration of TCP keep-alive probes
InfTcpConnection — Represents a TCP-based connection to a remote host
InfXmlConnection — Exchange of XML messages
InfXmppConnection — Implementation of the XMPP core protocol
InfSimulatedConnection — Simulated network connection
InfDiscoveryAvahi — Service Discovery via Avahi
InfXmppManager — Reuse existing connections
InfCertificateVerify — Server certificate verification.
InfIo — Event loop abstraction
InfStandaloneIo — Simple event loop implementation
InfAsyncOperation — Perform long-running operations in a separate thread
InfCertificateChain — X.509 certificate chains
File and directory utility functions — Helper functions to handle directories.
Certificate utility functions — Helper functions to read and write information from X.509 certificates.
XML utility functions — Helper functions to read basic data types from XML
InfCertificateCredentials — Reference-counted wrapper for gnutls_certificate_credentials_t
InfSaslContext — Asynchronous SASL processing
InfError — Common error codes
InfProtocol — Infinote protocol parameters
InfNativeSocket — Uniform access to the BSD socket API
InfBuffer — Abstract document interface
libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/custom-compiling.html0000644000000000000000000000013213055210752026134 xustar0030 mtime=1488261610.904090664 30 atime=1488261610.904090664 30 ctime=1488261610.904090664 libinfinity-0.7.1/docs/reference/libinfinity/html/custom-compiling.html0000644000175000017500000001314213055210752026667 0ustar00arminarmin00000000000000 Compiling and Using libinfinity: libinfinity-0.7 Reference Manual

Compiling libinfinity

This chapter explains how to compile libinfinity on a UNIX-like operating system such as Linux. On Windows, you can pretty much follow the same instructions once you have set up a MinGW/MSYS build environment and installed the necessary dependencies to the correct locations. This document does not cover how to do this but might in the future. It is also possible to build libinfinity using the Microsoft Compiler and Visual Studio IDE but there are no project files so far.

The first thing to do is to check whether all dependencies of libinfinity are installed. The following list shows what packages are required to be present on your system prior to building libinfinity:

  • libxml2

  • glib-2.0 >= 2.16

  • gnutls >= 1.7.2

  • gsasl >= 0.2.21

  • gtk+ >= 2.12 (optional)

  • avahi-client (optional)

  • libdaemon (optional)

Most if not all of them are most likely available in the package manager of your operating system vendor. It is much more convenient to obtain them from there than building them on your own.

The next step is to obtain the current source code for libinfinity. Point your web browser to http://releases.0x539.de/libinfinity and grab the latest .tar.gz file available, or exactly the version you want if you are looking for a specific one. Then unpack the tarball. On the command line this can be done using the following command:

tar xvfz libinfinity-0.4.tar.gz

After unpacking, descend into the newly created directory and run the configure script there. This performs several checks to adapt the build for your specific operating system and environment. The script can be passed several command-line arguments to alter the build. For example, the --prefix argument specifies the directory libinfinity will be installed into after the build. It defaults to /usr/local but you might want to install it to a different place, such as /opt/libinfinity. In that case run the following:

./configure --prefix=/opt/libinfinity

To get a list of all possible arguments run configure with the --help argument. If you do not want to change the installation path simply omit the --prefix=/opt/libinfinity in the command above.

When all dependencies are installed correctly the configure script will run smoothly and end up with a status summary of what parts of libinfinity will or will not be built. If there are errors you need to fix them (for examply by installing a missing dependency) and run configure again. After it ran it created a Makefile and you can build the package via:

make

This might take some time but it is not supposed to produce an error. If it does something might be wrong with your build setup that configure was unable to detect. When make finished install the package using:

make install

Depending on the installation directory you chose with the --prefix argument to configure you might need superuser privileges for this step.

Compiling applications using libinfinity

Environment variables

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfAdoptedUndoGrouping.html0000644000000000000000000000013213055210752027221 xustar0030 mtime=1488261610.904090664 30 atime=1488261610.904090664 30 ctime=1488261610.904090664 libinfinity-0.7.1/docs/reference/libinfinity/html/InfAdoptedUndoGrouping.html0000644000175000017500000007665613055210752027777 0ustar00arminarmin00000000000000 InfAdoptedUndoGrouping: libinfinity-0.7 Reference Manual

InfAdoptedUndoGrouping

InfAdoptedUndoGrouping — Grouping of requests to be undone simultaneously

Stability Level

Unstable, unless otherwise indicated

Properties

InfAdoptedAlgorithm * algorithm Read / Write
InfAdoptedUser * user Read / Write

Types and Values

Object Hierarchy

    GObject
    ╰── InfAdoptedUndoGrouping

Includes

#include <libinfinity/adopted/inf-adopted-undo-grouping.h>

Description

InfAdoptedUndoGrouping groups related requests together so that they can be undone at the same time. For example, Undo in a text editor is normally expected to operate on written words, not characters. Therefore, multiple requests need to be undone at once.

The undo grouping helps with this. Everytime it needs to decide whether two requests should be grouped it emits “group-requestsâ€. If the signal handler returns TRUE then the two requests will be undone at the same time, otherwise not.

It is also possible to explicitely group a bunch of requests that would not be grouped otherwise, by calling inf_adopted_undo_grouping_start_group() and inf_adopted_undo_grouping_end_group() before and after issuing the requests, respectively.

The default signal handler always returns FALSE. However, this behaviour can be changed in derived classes.

Functions

inf_adopted_undo_grouping_new ()

InfAdoptedUndoGrouping *
inf_adopted_undo_grouping_new (void);

Creates a new InfAdoptedUndoGrouping. To start grouping requests, set a user whose requests to group via inf_adopted_undo_grouping_set_algorithm(). Before doing so you might want to connect to “group-requestsâ€, so the user's initial requests can be grouped correctly.

[constructor]

Returns

A new InfAdoptedUndoGrouping, to be freed via g_object_unref().

[transfer full]


inf_adopted_undo_grouping_get_algorithm ()

InfAdoptedAlgorithm *
inf_adopted_undo_grouping_get_algorithm
                               (InfAdoptedUndoGrouping *grouping);

Returns the InfAdoptedAlgorithm for grouping .

Parameters

grouping

A InfAdoptedUndoGrouping.

 

Returns

grouping 's algorithm.

[transfer none]


inf_adopted_undo_grouping_set_algorithm ()

void
inf_adopted_undo_grouping_set_algorithm
                               (InfAdoptedUndoGrouping *grouping,
                                InfAdoptedAlgorithm *algorithm,
                                InfAdoptedUser *user);

Sets the algorithm and user to group requests for. This function will group all requests in user's request log, and also each new request that is added to it's log. Requests that cannot be undone anymore (because they are too old), will be correctly taken care off.

Parameters

grouping

A InfAdoptedUndoGrouping.

 

algorithm

The InfAdoptedAlgorithm for the document to group requests, or NULL.

 

user

The user for which to group requests, or NULL. Ignored if algorithm is NULL.

 

inf_adopted_undo_grouping_start_group ()

void
inf_adopted_undo_grouping_start_group (InfAdoptedUndoGrouping *grouping,
                                       gboolean allow_group_with_prev);

Makes all requests issued after this call belong into the same group, i.e. they will be undone at once. This can make sense for example when the user copy+pastes something into the document which causes multiple requests to be generated. A call to inf_adopted_undo_grouping_end_group() restores the normal behavior.

Parameters

grouping

A InfAdoptedUndoGrouping.

 

allow_group_with_prev

Whether the new group can be part of the previous group if “group-requests†allows.

 

inf_adopted_undo_grouping_end_group ()

void
inf_adopted_undo_grouping_end_group (InfAdoptedUndoGrouping *grouping,
                                     gboolean allow_group_with_next);

When inf_adopted_undo_grouping_start_group() was called before, then this function restores the normal behaviour of grouping requests.

Parameters

grouping

A InfAdoptedUndoGrouping.

 

allow_group_with_next

Whether subsequent requests are allow to be part of this group if “group-requests†allows.

 

inf_adopted_undo_grouping_get_undo_size ()

guint
inf_adopted_undo_grouping_get_undo_size
                               (InfAdoptedUndoGrouping *grouping);

Returns the number of requests to undo so that a whole group is being undone. This takes into account that possibly not the whole group cannot be undone due to the “max-total-log-size†constraint.

Parameters

grouping

A InfAdoptedUndoGrouping.

 

Returns

The number of requests in the current undo group.


inf_adopted_undo_grouping_get_redo_size ()

guint
inf_adopted_undo_grouping_get_redo_size
                               (InfAdoptedUndoGrouping *grouping);

Returns the number of requests to redo so that a whole group is being redone. This takes into account that possibly not the whole group cannot be undone due to the “max-total-log-size†constraint.

Parameters

grouping

A InfAdoptedUndoGrouping.

 

Returns

The number of requests in the current redo group.

Types and Values

struct InfAdoptedUndoGrouping

struct InfAdoptedUndoGrouping;

InfAdoptedUndoGrouping is an opaque data type. You should only access it via the public API functions.


struct InfAdoptedUndoGroupingClass

struct InfAdoptedUndoGroupingClass {
  gboolean (*group_requests)(InfAdoptedUndoGrouping* grouping,
                             InfAdoptedRequest* first,
                             InfAdoptedRequest* second);
};

This structure contains default signal handlers for InfAdoptedUndoGrouping.

Members

group_requests ()

Default signal handler for the “group-requests†signal.

 

Property Details

The “algorithm†property

  “algorithm†               InfAdoptedAlgorithm *

The algorithm for which to group requests.

Flags: Read / Write


The “user†property

  “user†                    InfAdoptedUser *

The user for which to group requests.

Flags: Read / Write

Signal Details

The “group-requests†signal

gboolean
user_function (InfAdoptedUndoGrouping *grouping,
               InfAdoptedRequest      *first,
               InfAdoptedRequest      *second,
               gpointer                user_data)

This signal is emitted whenever the InfAdoptedUndoGrouping needs to decide whether to put two requests into the same undo group or not. A signal handler should return TRUE if they belong into the same group or FALSE otherwise. Note however that the two requests may not immediately follow each other because other users may have issued requests inbetween. Check the vector times of the requests to find out, using inf_adopted_request_get_vector().

Parameters

grouping

The InfAdoptedUndoGrouping which is about to group a request.

 

first

The previous request.

 

second

The current request.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfXmppManager.html0000644000000000000000000000013213055210752025517 xustar0030 mtime=1488261610.904090664 30 atime=1488261610.904090664 30 ctime=1488261610.904090664 libinfinity-0.7.1/docs/reference/libinfinity/html/InfXmppManager.html0000644000175000017500000007572213055210752026266 0ustar00arminarmin00000000000000 InfXmppManager: libinfinity-0.7 Reference Manual

InfXmppManager

InfXmppManager — Reuse existing connections

Stability Level

Unstable, unless otherwise indicated

Types and Values

Object Hierarchy

    GObject
    ╰── InfXmppManager

Includes

#include <libinfinity/common/inf-xmpp-manager.h>

Description

InfXmppManager stores InfXmppConnection objects and allows to look them up by the IP address and port number of their underlaying InfTcpConnections. This can be used to reuse existing network connections instead of creating new ones.

Each object which needs to make connections should be passed a InfXmppManager. Then, when making a connection to a certain address/port pair, it should first look in the XMPP manager whether there is already an existing connection to the destination host, via inf_xmpp_manager_lookup_connection_by_address(). If there is, it should use it (maybe reopen it if it is closed). Otherwise, it should create a new connection and add it to the XMPP manager via inf_xmpp_manager_add_connection() for others to use.

The XMPP manager can also handle connections whose address is still to be looked up. Such connections are looked up by the hostname given to the name resolver. Once the hostname has been looked up, and if another connection with the same address and port number exists already, the new connection is removed in favor of the already existing one.

Functions

inf_xmpp_manager_new ()

InfXmppManager *
inf_xmpp_manager_new (void);

Creates a new xmpp manager.

[constructor]

Returns

A new InfXmppManager.

[transfer full]


inf_xmpp_manager_lookup_connection_by_address ()

InfXmppConnection *
inf_xmpp_manager_lookup_connection_by_address
                               (InfXmppManager *manager,
                                const InfIpAddress *address,
                                guint port);

Looks for a InfXmppConnection contained in manager whose underlaying InfTcpConnection has the given address and port set. Returns NULL if there is no such connection.

This function may also return a closed connection. You can then attempt to reopen it, or remove it from the manager using inf_xmpp_manager_remove_connection() when that fails.

Parameters

manager

A InfXmppManager.

 

address

The remote InfIpAddress of the connection to look for.

 

port

The remote port number of the connection to look for.

 

Returns

A InfXmppConnection with the given address and port, or NULL if not found.

[transfer none][allow-none]


inf_xmpp_manager_lookup_connection_by_hostname ()

InfXmppConnection *
inf_xmpp_manager_lookup_connection_by_hostname
                               (InfXmppManager *manager,
                                const gchar *hostname,
                                const gchar *service,
                                const gchar *srv);

Looks for a InfXmppConnection contained in manager whose underlaying InfTcpConnection has a InfNameResolver with the given properties.

This function may also return a closed connection. You can then attempt to reopen it, or remove it from the manager using inf_xmpp_manager_remove_connection() when that fails.

Parameters

manager

A InfXmppManager.

 

hostname

The remote hostname to look for.

 

service

The service string of the connection to look for.

[allow-none]

srv

The SRV record corresponding to the connection.

[allow-none]

Returns

A InfXmppConnection with the given hostname, service and srv, or NULL if not found.

[transfer none][allow-none]


inf_xmpp_manager_contains_connection ()

gboolean
inf_xmpp_manager_contains_connection (InfXmppManager *manager,
                                      InfXmppConnection *connection);

Returns whether connection is contained in manager .

Parameters

manager

A InfXmppManager.

 

connection

A InfXmppConnection.

 

Returns

TRUE if connection is contained in manager , FALSE otherwise.


inf_xmpp_manager_add_connection ()

void
inf_xmpp_manager_add_connection (InfXmppManager *manager,
                                 InfXmppConnection *connection);

Adds the given connection to manager so that it is found by inf_xmpp_manager_lookup_connection_by_address(), inf_xmpp_manager_lookup_connection_by_hostname() and inf_xmpp_manager_contains_connection().

Parameters

manager

A InfXmppManager.

 

connection

A InfXmppConnection not yet contained in manager .

 

inf_xmpp_manager_remove_connection ()

void
inf_xmpp_manager_remove_connection (InfXmppManager *manager,
                                    InfXmppConnection *connection);

Removes the given connection from manager .

Parameters

manager

A InfXmppManager.

 

connection

A InfXmppConnection contained in manager .

 

Types and Values

struct InfXmppManager

struct InfXmppManager;

InfXmppManager is an opaque data type. You should only access it via the public API functions.


struct InfXmppManagerClass

struct InfXmppManagerClass {
  void(*connection_added)(InfXmppManager* manager,
                          InfXmppConnection* connection);
  void(*connection_removed)(InfXmppManager* manager,
                            InfXmppConnection* connection,
                            InfXmppConnection* replaced_by);
};

This structure contains the default signal handlers for InfXmppManager.

Members

connection_added ()

Default signal handler for the “connection-added†signal.

 

connection_removed ()

Default signal handler for the “connection-removed†signal.

 

Signal Details

The “connection-added†signal

void
user_function (InfXmppManager    *xmpp_manager,
               InfXmppConnection *connection,
               gpointer           user_data)

This signal is emitted whenever a new connection has been added to the InfXmppManager, via inf_xmpp_manager_add_connection().

Parameters

xmpp_manager

The InfXmppManager emitting the signal.

 

connection

The InfXmppConnection that was added to xmpp_manager .

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last


The “connection-removed†signal

void
user_function (InfXmppManager    *infxmppmanager,
               InfXmppConnection *arg1,
               InfXmppConnection *arg2,
               gpointer           user_data)

Parameters

infxmppmanager

the object which received the signal.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/libinfinity-0.7-InfInit.html0000644000000000000000000000013213055210752027023 xustar0030 mtime=1488261610.904090664 30 atime=1488261610.904090664 30 ctime=1488261610.904090664 libinfinity-0.7.1/docs/reference/libinfinity/html/libinfinity-0.7-InfInit.html0000644000175000017500000001223713055210752027562 0ustar00arminarmin00000000000000 InfInit: libinfinity-0.7 Reference Manual

InfInit

InfInit

Functions

gboolean inf_init ()
void inf_deinit ()

Description

Functions

inf_init ()

gboolean
inf_init (GError **error);

This function initializes the libinfinity library and should be called before any other functions of the library. The function does nothing if it has already been called before.

Parameters

error

Location to store error information, if any.

 

Returns

Whether the initialization was successful or not.


inf_deinit ()

void
inf_deinit (void);

This functions deinitializes the libinfinity library. Make sure that all objects the library provides have been freed before calling this function. If inf_init() has been called multiple times, then inf_deinit() needs to be called the same number of times to actually deinitialize the library.

Types and Values

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfCommunicationGroup.html0000644000000000000000000000013213055210752027122 xustar0030 mtime=1488261610.908090655 30 atime=1488261610.908090655 30 ctime=1488261610.908090655 libinfinity-0.7.1/docs/reference/libinfinity/html/InfCommunicationGroup.html0000644000175000017500000012675313055210752027672 0ustar00arminarmin00000000000000 InfCommunicationGroup: libinfinity-0.7 Reference Manual

InfCommunicationGroup

InfCommunicationGroup — Communication channel for mulitple connections

Stability Level

Unstable, unless otherwise indicated

Properties

InfCommunicationManager * communication-manager Write / Construct Only
InfCommunicationRegistry * communication-registry Write / Construct Only
gchar * name Read / Write / Construct Only
InfCommunicationObject * target Read / Write

Types and Values

Object Hierarchy

    GObject
    ╰── InfCommunicationGroup
        ├── InfCommunicationHostedGroup
        ╰── InfCommunicationJoinedGroup

Includes

#include <libinfinity/communication/inf-communication-group.h>

Description

InfCommunicationGroup represents a group of different hosts. The group supports sending messages between group members and to the whole group.

A communication group supports multiple networks. Each connection belongs to a network, identified by the “network†property. It is assumed that hosts on different networks can't directly communicate with each other. Examples for networks are "tcp/ip" or "jabber".

All communication for a given network is performed by a InfCommunicationMethod. The method defines how data is sent is sent to the group. For example, a method could choose to relay all data via a central server, or to send all data directly between the hosts, or in case of a jabber network, use jabber groupchat functionality.

Functions

inf_communication_group_get_name ()

const gchar *
inf_communication_group_get_name (InfCommunicationGroup *group);

Returns the name of the group.

Parameters

group

A InfCommunicationGroup.

 

Returns

The name of the group. The returned string is owned by the group, you don't need to free it.


inf_communication_group_get_target ()

InfCommunicationObject *
inf_communication_group_get_target (InfCommunicationGroup *group);

Returns the group's target. The target of a group is the InfCommunicationObject to which received and sent messages are reported.

Parameters

group

A InfCommunicationGroup.

 

Returns

A InfCommunicationGroup, or NULL.

[transfer none][allow-none]


inf_communication_group_set_target ()

void
inf_communication_group_set_target (InfCommunicationGroup *group,
                                    InfCommunicationObject *target);

Sets the group's target. The target of a group is the InfCommunicationObject to which received and sent messages are reported. If target is NULL, then the target will be unset.

You can safely call this function with an object that holds a reference on the group since the InfCommunicationGroup only holds a weak reference to its target . This means that you need to keep a reference on target yourself.

Parameters

group

A InfCommunicationGroup.

 

target

A InfCommunicationObject, or NULL.

 

inf_communication_group_is_member ()

gboolean
inf_communication_group_is_member (InfCommunicationGroup *group,
                                   InfXmlConnection *connection);

Returns whether connection is a member of group .

Parameters

group

A InfCommunicationGroup.

 

connection

A InfXmlConnection.

 

Returns

TRUE if connection is a member of group , FALSE otherwise.


inf_communication_group_send_message ()

void
inf_communication_group_send_message (InfCommunicationGroup *group,
                                      InfXmlConnection *connection,
                                      xmlNodePtr xml);

Sends a message connection which must be a member of group . connection needs to be a member of this group. This function takes ownership of xml .

Parameters

group

A InfCommunicationGroup.

 

connection

The InfXmlConnection to which to send the message.

 

xml

The message to send.

[transfer full]

inf_communication_group_send_group_message ()

void
inf_communication_group_send_group_message
                               (InfCommunicationGroup *group,
                                xmlNodePtr xml);

Sends a message to all members of group . This function takes ownership of xml .

Parameters

group

A InfCommunicationGroup.

 

xml

The message to send.

[transfer full]

inf_communication_group_cancel_messages ()

void
inf_communication_group_cancel_messages
                               (InfCommunicationGroup *group,
                                InfXmlConnection *connection);

Stops all messages scheduled to be sent to connection from being sent. Messages for which inf_communication_object_enqueued() has already been called cannot be cancelled anymore.

Parameters

group

A InfCommunicationGroup.

 

connection

The InfXmlConnection for which to cancel messages.

 

inf_communication_group_get_method_for_network ()

const gchar *
inf_communication_group_get_method_for_network
                               (InfCommunicationGroup *group,
                                const gchar *network);

Returns the method name of the method used for communication on network within group .

Parameters

group

A InfCommunicationGroup.

 

network

A network specifier, such as "tcp/ip" or "jabber".

 

Returns

A method name. The string is owned by the group, you don't need to free it.


inf_communication_group_get_method_for_connection ()

const gchar *
inf_communication_group_get_method_for_connection
                               (InfCommunicationGroup *grp,
                                InfXmlConnection *conn);

Returns the method name of the method used for communication on conn 's network within group . conn does not need to be a member of grp for this function to be called.

Parameters

grp

A InfCommunicationGroup.

 

conn

The InfXmlConnection for which to retrieve the method.

 

Returns

A method name. The string is owned by the group, you don't need to free it.


inf_communication_group_get_publisher_id ()

gchar *
inf_communication_group_get_publisher_id
                               (InfCommunicationGroup *group,
                                InfXmlConnection *for_connection);

Returns a host identifier for the group's publisher (see “local-id†and “remote-idâ€). If the local host is the publisher, then this will simply return for_connection 's local ID, otherwise the remote ID of the connection to the publisher on for_connection 's network is returned.

Parameters

group

A InfCommunicationGroup.

 

for_connection

A InfXmlConnection.

 

Returns

The publisher's host ID. Free with g_free().

[transfer full]

Types and Values

struct InfCommunicationGroup

struct InfCommunicationGroup;

InfCommunicationGroup is an opaque data type. You should only access it via the public API functions.


struct InfCommunicationGroupClass

struct InfCommunicationGroupClass {
  /* Signals */
  void (*member_added)(InfCommunicationGroup* group,
                       InfXmlConnection* connection);
  void (*member_removed)(InfCommunicationGroup* group,
                         InfXmlConnection* connection);

  /* Virtual functions */
  /* TODO: Should this be const gchar* const* get_methods? */
  const gchar* (*get_method)(InfCommunicationGroup* group,
                             unsigned int index);
  gchar* (*get_publisher_id)(InfCommunicationGroup* group,
                             InfXmlConnection* for_connection);
};

The virtual methods and default signal handlers of InfCommunicationGroup.

Members

member_added ()

Default signal handler of the “member-added†signal.

 

member_removed ()

Default signal handler of the “member-removed†signal.

 

get_method ()

Virtual function to determine the methods to use for the group, in order of priority.

 

get_publisher_id ()

Virtual function to obtain the ID of the publishing host of this group.

 

Property Details

The “communication-manager†property

  “communication-manager†   InfCommunicationManager *

The communication manager used for sending requests.

Flags: Write / Construct Only


The “communication-registry†property

  “communication-registry†  InfCommunicationRegistry *

The registry to register connections with.

Flags: Write / Construct Only


The “name†property

  “name†                    gchar *

The name of the group.

Flags: Read / Write / Construct Only

Default value: NULL


The “target†property

  “target†                  InfCommunicationObject *

The communication object to call on received and sent data.

Flags: Read / Write

Signal Details

The “member-added†signal

void
user_function (InfCommunicationGroup *group,
               InfXmlConnection      *connection,
               gpointer               user_data)

This signal is emitted when a connection has been added to the group.

Parameters

group

The InfCommunicationGroup emitting the signal.

 

connection

The newly joined connection.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last


The “member-removed†signal

void
user_function (InfCommunicationGroup *group,
               InfXmlConnection      *connection,
               gpointer               user_data)

This signal is emitted when a connection has been removed from the group.

Parameters

group

The InfCommunicationGroup emitting the signal.

 

connection

The connection that was removed

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/libinfinity-0.7-InfAsyncOperation0000644000000000000000000000013213055210752030113 xustar0030 mtime=1488261610.908090655 30 atime=1488261610.908090655 30 ctime=1488261610.908090655 libinfinity-0.7.1/docs/reference/libinfinity/html/libinfinity-0.7-InfAsyncOperation.html0000644000175000017500000005012013055210752031606 0ustar00arminarmin00000000000000 InfAsyncOperation: libinfinity-0.7 Reference Manual

InfAsyncOperation

InfAsyncOperation — Perform long-running operations in a separate thread

Stability Level

Unstable, unless otherwise indicated

Types and Values

Includes

#include <libinfinity/inf-async-operation.h>

Description

InfAsyncOperation is a simple mechanism to run some code in a separate worker thread and then, once the result is computed, notify the main thread about the result.

Functions

InfAsyncOperationRunFunc ()

void
(*InfAsyncOperationRunFunc) (gpointer *run_data,
                             GDestroyNotify *run_notify,
                             gpointer user_data);

This function performs the asynchronous task and is executed in a separate thread. The pointer written into run_data is passed back to the main thread after the function has finished executing.

Parameters

run_data

Location where to write the result of the asynchronous operation.

 

run_notify

Function to be used to free run_data , or NULL.

 

user_data

Data passed in inf_async_operation_new().

 

InfAsyncOperationDoneFunc ()

void
(*InfAsyncOperationDoneFunc) (gpointer run_data,
                              gpointer user_data);

This function is called in the main thread once the asynchronous operation has finished.

Parameters

run_data

The result of the asynchronous operation.

 

user_data

Data passed in inf_async_operation_new().

 

inf_async_operation_new ()

InfAsyncOperation *
inf_async_operation_new (InfIo *io,
                         InfAsyncOperationRunFunc run_func,
                         InfAsyncOperationDoneFunc done_func,
                         gpointer user_data);

This function creates a new InfAsyncOperation. The function given by run_func will be run asynchronously in a worker thread. Once the function finishes, its result is passed back to the main thread defined by io , and done_func is called with the computed result in the main thread.

To actually start the asynchronous operation, call inf_async_operation_start(). This allows to save the returned value into a structure before starting the operation, avoiding a potential race condition if the asynchronous function finishes quickly.

The asynchronous operation can be canceled by calling inf_async_operation_free() on the returned InfAsyncOperation object. If the operation is not cancelled and after done_func has been called, the operation is freed automatically and must not be freed by the caller. The caller must also keep a reference to io while the operation is running. Before dropping your reference to io , make sure to free the asynchronous operation. When the last reference to io is dropped, the operation is freed automatically, since it cannot pass back its result to the main thread anymore.

Parameters

io

The InfIo object used to pass back the result of the operation.

 

run_func

A function to run asynchronously in a worker thread, computing the result of the operation.

[scope async]

done_func

A function to be called in the thread of io once the result is available.

[scope async]

user_data

Additional user data to pass to both functions.

 

Returns

A new InfAsyncOperation. Free with inf_async_operation_free() to cancel the operation.

[transfer full]


inf_async_operation_start ()

gboolean
inf_async_operation_start (InfAsyncOperation *op,
                           GError **error);

Starts the operation given in op . The operation must have been created before with inf_async_operation_new(). If the operation cannot be started, error is set and FALSE is returned. In that case, the operation must not be used anymore since it will be automatically freed.

Parameters

op

A InfAsyncOperation.

[transfer full]

error

Location to store error information, if any.

 

Returns

TRUE on success or FALSE if the operation could not be started.


inf_async_operation_free ()

void
inf_async_operation_free (InfAsyncOperation *op);

Frees the given asynchronous operation and cancels it if it is currently running. This should only be called to cancel a running operation, or to free an operation that has not been started. In all other cases, the operation is freed automatically.

Parameters

op

A InfAsyncOperation.

 

Types and Values

InfAsyncOperation

typedef struct _InfAsyncOperation InfAsyncOperation;

InfAsyncOperation is an opaque data type and should only be accessed via the public API functions.

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/libinfinity-0.7-InfdChatFilesyste0000644000000000000000000000013213055210752030070 xustar0030 mtime=1488261610.908090655 30 atime=1488261610.908090655 30 ctime=1488261610.908090655 libinfinity-0.7.1/docs/reference/libinfinity/html/libinfinity-0.7-InfdChatFilesystemFormat.html0000644000175000017500000003567113055210752033127 0ustar00arminarmin00000000000000 Storage of chat sessions on the file system: libinfinity-0.7 Reference Manual

Storage of chat sessions on the file system

Storage of chat sessions on the file system — Utility functions to deal with storing InfChatSessions in filesystem storage

Stability Level

Unstable, unless otherwise indicated

Types and Values

Includes

#include <libinfinity/server/infd-chat-filesystem-storage.h>

Description

The functions in this section are utility functions that can be used when implementing a InfdNotePlugin to handle InfChatSessions. These functions implement reading and writing the content of an InfChatSession to an XML file in the storage.

Functions

infd_chat_filesystem_format_read ()

gboolean
infd_chat_filesystem_format_read (InfdFilesystemStorage *storage,
                                  const gchar *path,
                                  InfChatBuffer *buffer,
                                  GError **error);

Reads a chat session from path in storage . The file is expected to have been saved with infd_chat_filesystem_format_write() before. The buffer parameter should be an empty InfChatBuffer, and the document will be written into this buffer. If the function succeeds, the buffer can be used to create an InfChatSession with inf_chat_session_new(). If the function fails, FALSE is returned and error is set.

Parameters

storage

A InfdFilesystemStorage.

 

path

Storage path to retrieve the session from.

 

buffer

An empty InfTextBuffer to use as the new session's buffer.

 

error

Location to store error information, if any, or NULL.

 

Returns

TRUE on success or FALSE on error.


infd_chat_filesystem_format_write ()

gboolean
infd_chat_filesystem_format_write (InfdFilesystemStorage *storage,
                                   const gchar *path,
                                   InfChatBuffer *buffer,
                                   GError **error);

Writes the given buffer into the filesystem storage at path . If successful, the session can then be read back with infd_chat_filesystem_format_read(). If the function fails, FALSE is returned and error is set.

Parameters

storage

A InfdFilesystemStorage.

 

path

Storage path where to write the session to.

 

buffer

The InfChatBuffer to write.

 

error

Location to store error information, if any, or NULL.

 

Returns

TRUE on success or FALSE on error.

Types and Values

enum InfdChatFilesystemFormatError

Errors that can occur when reading a InfChatSession from a InfdFilesystemStorage.

Members

INFD_CHAT_FILESYSTEM_FORMAT_ERROR_NOT_A_CHAT_SESSION

The file to be read is not a serialized chat session.

 
libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/libinfinity-0.7-InfXmlUtil.html0000644000000000000000000000013213055210752027516 xustar0030 mtime=1488261610.908090655 30 atime=1488261610.908090655 30 ctime=1488261610.908090655 libinfinity-0.7.1/docs/reference/libinfinity/html/libinfinity-0.7-InfXmlUtil.html0000644000175000017500000020606313055210752030257 0ustar00arminarmin00000000000000 XML utility functions: libinfinity-0.7 Reference Manual

XML utility functions

XML utility functions — Helper functions to read basic data types from XML

Stability Level

Unstable, unless otherwise indicated

Includes

#include <libinfinity/common/inf-xml-util.h>

Description

In the infinote protocol XML attributes are often required to contain numbers. These function provide some convenience to set and retrieve them. They are mostly used in libinfinity itself but can also be useful when implementing new session types so they are public API.

Functions

inf_xml_util_add_child_text ()

void
inf_xml_util_add_child_text (xmlNodePtr xml,
                             const gchar *text,
                             gsize bytes);

Adds the given text as child text to xml in the same way xmlNodeAddContentLen() would do. The difference is that text is allowed to contain characters that are not valid in

XML text, such

as formfeed characters \f. In case one occurs in text , the function adds an <uchar /> element node instead to xml as specified in the infinote protocol.

Parameters

xml

A xmlNodePtr.

 

text

The child text to add.

[array length=bytes]

bytes

The number of bytes of text .

 

inf_xml_util_get_child_text ()

gchar *
inf_xml_util_get_child_text (xmlNodePtr xml,
                             gsize *bytes,
                             guint *chars,
                             GError **error);

Reads a node's child text. If there are <uchar /> child elements, as added by inf_xml_util_add_child_text() this function will convert them back to character codes. There should not be any other child elements in xml .

Parameters

xml

A xmlNodePtr

 

bytes

Location to store number of bytes of child text, or NULL.

[out][allow-none]

chars

Location to store number of characters of child text, or NULL.

[out][allow-none]

error

Locatian to store error information, if any, or NULL.

 

Returns

The node's child text, or NULL on error. Free with g_free() when no longer needed.

[array length=bytes][transfer full]


inf_xml_util_get_attribute ()

xmlChar *
inf_xml_util_get_attribute (xmlNodePtr xml,
                            const gchar *attribute);

Returns the value of the attribute called attribute in the XML element xml . This function is a thin wrapper around xmlGetProp() which exists mostly for consistency, and for not having to cast the attribute argument from char* to xmlChar*. The return value is a xmlChar*, though.

Parameters

xml

A xmlNodePtr.

 

attribute

The name of the attribute to query.

 

Returns

The value of the attribute, or NULL. Free with xmlFree() when no longer needed.

[transfer full]


inf_xml_util_get_attribute_required ()

xmlChar *
inf_xml_util_get_attribute_required (xmlNodePtr xml,
                                     const gchar *attribute,
                                     GError **error);

Returns the value of the attribute called attribute in the XML element xml . If there is no such attribute then the function returns NULL and error is set.

Parameters

xml

A xmlNodePtr.

 

attribute

The name of the attribute to query.

 

error

Location to store error information, if any.

 

Returns

The attribute's value, or NULL on error. Free with xmlFree() when no longer needed.

[transfer full]


inf_xml_util_get_attribute_int ()

gboolean
inf_xml_util_get_attribute_int (xmlNodePtr xml,
                                const gchar *attribute,
                                gint *result,
                                GError **error);

Reads the attribute named attribute from the XML element xml . The attribute value is expected to be a signed integral number. If it is the function converts the text to an integer and stores the result into result . In this case, TRUE is returned and error is left untouched.

If the value is not a signed integral number, then the function returns FALSE, error is set and result is left untouched.

If the attribute does not exist the function returns FALSE but error is not set.

Parameters

xml

A xmlNodePtr.

 

attribute

The name of the attribute to query.

 

result

Location to store the read value.

[out]

error

Location to store error information, if any.

 

Returns

Whether result was set.


inf_xml_util_get_attribute_int_required ()

gboolean
inf_xml_util_get_attribute_int_required
                               (xmlNodePtr xml,
                                const gchar *attribute,
                                gint *result,
                                GError **error);

Reads the attribute named attribute from the XML element xml . The attribute value is expected to be a signed integral number. If it is the function converts the text to an integere and stores the result into result . In this case, TRUE is returned and error is left untouched.

If the value is not a signed integral number or the attribute does not exist, then the function returns FALSE, error is set and result is left untouched.

Parameters

xml

A xmlNodePtr.

 

attribute

The name of the attribute to query.

 

result

Location to store the read value.

[out]

error

Location to store error information, if any.

 

Returns

Whether result was set.


inf_xml_util_get_attribute_long ()

gboolean
inf_xml_util_get_attribute_long (xmlNodePtr xml,
                                 const gchar *attribute,
                                 glong *result,
                                 GError **error);

Behaves exactly like inf_xml_util_get_attribute_int(). The only difference is that the function reads a signed long integral number.

Parameters

xml

A xmlNodePtr.

 

attribute

The name of the attribute to query.

 

result

Location to store the read value.

[out]

error

Location to store error information, if any.

 

Returns

Whether result was set.


inf_xml_util_get_attribute_long_required ()

gboolean
inf_xml_util_get_attribute_long_required
                               (xmlNodePtr xml,
                                const gchar *attribute,
                                glong *result,
                                GError **error);

Behaves exactly like inf_xml_util_get_attribute_int_required(). The only difference is that the function reads a signed long integral number.

Parameters

xml

A xmlNodePtr.

 

attribute

The name of the attribute to query.

 

result

Location to store the read value.

[out]

error

Location to store error information, if any.

 

Returns

Whether result was set.


inf_xml_util_get_attribute_uint ()

gboolean
inf_xml_util_get_attribute_uint (xmlNodePtr xml,
                                 const gchar *attribute,
                                 guint *result,
                                 GError **error);

Behaves exactly like inf_xml_util_get_attribute_int(). The only difference is that the function reads an unsigned integral number.

Parameters

xml

A xmlNodePtr.

 

attribute

The name of the attribute to query.

 

result

Location to store the read value.

[out]

error

Location to store error information, if any.

 

Returns

Whether result was set.


inf_xml_util_get_attribute_uint_required ()

gboolean
inf_xml_util_get_attribute_uint_required
                               (xmlNodePtr xml,
                                const gchar *attribute,
                                guint *result,
                                GError **error);

Behaves exactly like inf_xml_util_get_attribute_int_required(). The only difference is that the function reads an unsigned integral number.

Parameters

xml

A xmlNodePtr.

 

attribute

The name of the attribute to query.

 

result

Location to store the read value.

[out]

error

Location to store error information, if any.

 

Returns

Whether result was set.


inf_xml_util_get_attribute_ulong ()

gboolean
inf_xml_util_get_attribute_ulong (xmlNodePtr xml,
                                  const gchar *attribute,
                                  gulong *result,
                                  GError **error);

Behaves exactly like inf_xml_util_get_attribute_int(). The only difference is that the function reads an unsigned long integral number.

Parameters

xml

A xmlNodePtr.

 

attribute

The name of the attribute to query.

 

result

Location to store the read value.

[out]

error

Location to store error information, if any.

 

Returns

Whether result was set.


inf_xml_util_get_attribute_ulong_required ()

gboolean
inf_xml_util_get_attribute_ulong_required
                               (xmlNodePtr xml,
                                const gchar *attribute,
                                gulong *result,
                                GError **error);

Behaves exactly like inf_xml_util_get_attribute_int_required(). The only difference is that the function reads an unsigned long integral number.

Parameters

xml

A xmlNodePtr.

 

attribute

The name of the attribute to query.

 

result

Location to store the read value.

[out]

error

Location to store error information, if any.

 

Returns

Whether result was set.


inf_xml_util_get_attribute_double ()

gboolean
inf_xml_util_get_attribute_double (xmlNodePtr xml,
                                   const gchar *attribute,
                                   gdouble *result,
                                   GError **error);

Behaves exactly like inf_xml_util_get_attribute_int(). The only difference is that the function reads a double-precision floating point number.

Parameters

xml

A xmlNodePtr.

 

attribute

The name of the attribute to query.

 

result

Location to store the read value.

[out]

error

Location to store error information, if any.

 

Returns

Whether result was set.


inf_xml_util_get_attribute_double_required ()

gboolean
inf_xml_util_get_attribute_double_required
                               (xmlNodePtr xml,
                                const gchar *attribute,
                                gdouble *result,
                                GError **error);

Behaves exactly like inf_xml_util_get_attribute_int_required(). The only difference is that the function reads a double-precision floating point number.

Parameters

xml

A xmlNodePtr.

 

attribute

The name of the attribute to query.

 

result

Location to store the read value.

[out]

error

Location to store error information, if any.

 

Returns

Whether result was set.


inf_xml_util_set_attribute ()

void
inf_xml_util_set_attribute (xmlNodePtr xml,
                            const gchar *attribute,
                            const gchar *value);

Sets the attribute named attribute to the given value of the XML element xml . This is a thin wrapper around xmlSetProp(), mainly provided for consistency and for not having to cast the arguments to xmlChar*.

Parameters

xml

A xmlNodePtr.

 

attribute

The name of the attribute to set.

 

value

The value to set.

 

inf_xml_util_set_attribute_int ()

void
inf_xml_util_set_attribute_int (xmlNodePtr xml,
                                const gchar *attribute,
                                gint value);

Sets the attribute named attribute to the given signed integral value converted to text.

Parameters

xml

A xmlNodePtr.

 

attribute

The name of the attribute to set.

 

value

The value to set.

 

inf_xml_util_set_attribute_long ()

void
inf_xml_util_set_attribute_long (xmlNodePtr xml,
                                 const gchar *attribute,
                                 glong value);

Sets the attribute named attribute to the given signed long integral value converted to text.

Parameters

xml

A xmlNodePtr.

 

attribute

The name of the attribute to set.

 

value

The value to set.

 

inf_xml_util_set_attribute_uint ()

void
inf_xml_util_set_attribute_uint (xmlNodePtr xml,
                                 const gchar *attribute,
                                 guint value);

Sets the attribute named attribute to the given unsigned integral value converted to text.

Parameters

xml

A xmlNodePtr.

 

attribute

The name of the attribute to set.

 

value

The value to set.

 

inf_xml_util_set_attribute_ulong ()

void
inf_xml_util_set_attribute_ulong (xmlNodePtr xml,
                                  const gchar *attribute,
                                  gulong value);

Sets the attribute named attribute to the given unsigned long integral value converted to text.

Parameters

xml

A xmlNodePtr.

 

attribute

The name of the attribute to set.

 

value

The value to set.

 

inf_xml_util_set_attribute_double ()

void
inf_xml_util_set_attribute_double (xmlNodePtr xml,
                                   const gchar *attribute,
                                   gdouble value);

Sets the attribute named attribute to the given double-precision floating point number converted to text.

Parameters

xml

A xmlNodePtr.

 

attribute

The name of the attribute to set.

 

value

The value to set.

 

inf_xml_util_new_error_from_node ()

GError *
inf_xml_util_new_error_from_node (xmlNodePtr xml);

Creates a new GError with the domain and erro code given in xml 's attributes. The message is parsed from the child text as with inf_xml_util_get_child_text(). The element name and namespace are ignored. If xml does not have the attributes as expected, NULL is returned.

Parameters

xml

A xmlNodePtr as returned by inf_xml_util_new_node_from_error().

 

Returns

A pointer to a new GError, or NULL on failure. It is the caller's responsibility to dispose the GError object using g_error_free().

[transfer full]


inf_xml_util_new_node_from_error ()

xmlNodePtr
inf_xml_util_new_node_from_error (GError *error,
                                  xmlNsPtr name_space,
                                  const gchar *name);

Creates a new xmlNode that encodes error . The element's name is optionally specified by name , or "error" by default, error 's domain and code are set as attributes and its message is set as child text using inf_xml_util_add_child_text(). name_space is set as the element's namespace, if not NULL.

Parameters

error

The error object to represent in xml.

 

name_space

The element's namespace, or NULL.

 

name

An element name, or NULL.

 

Returns

A new xmlNodePtr. It is the caller's responsibility to dispose it using xmlFreeNode().

[transfer full]

Types and Values

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfCommunicationCentralMethod.htm0000644000000000000000000000013213055210752030403 xustar0030 mtime=1488261610.908090655 30 atime=1488261610.908090655 30 ctime=1488261610.908090655 libinfinity-0.7.1/docs/reference/libinfinity/html/InfCommunicationCentralMethod.html0000644000175000017500000002172413055210752031317 0ustar00arminarmin00000000000000 InfCommunicationCentralMethod: libinfinity-0.7 Reference Manual

InfCommunicationCentralMethod

InfCommunicationCentralMethod — Relying group messages via the publisher

Stability Level

Unstable, unless otherwise indicated

Properties

InfCommunicationGroup * group Read / Write / Construct Only
InfCommunicationRegistry * registry Read / Write / Construct Only

Object Hierarchy

    GObject
    ╰── InfCommunicationCentralMethod

Implemented Interfaces

InfCommunicationCentralMethod implements InfCommunicationMethod.

Includes

#include <libinfinity/communication/inf-communication-central-method.h>

Description

InfCommunicationCentralMethod implements InfCommunicationMethod by relaying all messages via the group's publisher. If the connection to the publisher is lost, so is the connection to all other group members.

Functions

Types and Values

struct InfCommunicationCentralMethod

struct InfCommunicationCentralMethod;

InfCommunicationCentralMethod is an opaque data type. You should only access it * via the public API functions.


struct InfCommunicationCentralMethodClass

struct InfCommunicationCentralMethodClass {
};

This structure does not contain any public fields.

Property Details

The “group†property

  “group†                   InfCommunicationGroup *

The communication group for which to handle messages.

Flags: Read / Write / Construct Only


The “registry†property

  “registry†                InfCommunicationRegistry *

The communication registry to register connections with.

Flags: Read / Write / Construct Only

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/ch01.html0000644000000000000000000000013213055210752023376 xustar0030 mtime=1488261610.908090655 30 atime=1488261610.908090655 30 ctime=1488261610.908090655 libinfinity-0.7.1/docs/reference/libinfinity/html/ch01.html0000644000175000017500000000345113055210752024133 0ustar00arminarmin00000000000000 About libinfinity: libinfinity-0.7 Reference Manual libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfAdoptedAlgorithm.html0000644000000000000000000000013213055210752026527 xustar0030 mtime=1488261610.908090655 30 atime=1488261610.908090655 30 ctime=1488261610.908090655 libinfinity-0.7.1/docs/reference/libinfinity/html/InfAdoptedAlgorithm.html0000644000175000017500000020755613055210752027300 0ustar00arminarmin00000000000000 InfAdoptedAlgorithm: libinfinity-0.7 Reference Manual

InfAdoptedAlgorithm

InfAdoptedAlgorithm — adOPTed implementation

Stability Level

Unstable, unless otherwise indicated

Properties

InfBuffer * buffer Read / Write / Construct Only
InfAdoptedStateVector * buffer-modified-state Read
InfAdoptedStateVector * current-state Read
guint max-total-log-size Read / Write / Construct Only
InfUserTable * user-table Read / Write / Construct Only

Object Hierarchy

    GObject
    ╰── InfAdoptedAlgorithm

Includes

#include <libinfinity/adopted/inf-adopted-algorithm.h>

Description

InfAdoptedAlgorithm implements the adOPTed algorithm for concurrency control as described in the paper "An integrating, transformation-oriented approach to concurrency control and undo in group editors" by Matthias Ressel, Doris Nitsche-Ruhland and Rul Gunzenhäuser (http://portal.acm.org/citation.cfm?id=240305).

It is based on requests, represented by the InfAdoptedRequest class. If there is at least one local InfUser in the algorithm's user table, then you can create own requests with the inf_adopted_algorithm_generate_request() function. Remote requests can be applied via inf_adopted_algorithm_execute_request(). This class does not take care of transfering the generated requests to other users which is the scope of InfAdoptedSession.

The implementation is not tied to text editing. It can handle any operations implementing InfAdoptedOperation as long as they define sufficient transformation functions. The libinftext library provides operations for text editing, see InfTextInsertOperation and InfTextDeleteOperation.

Functions

inf_adopted_algorithm_new ()

InfAdoptedAlgorithm *
inf_adopted_algorithm_new (InfUserTable *user_table,
                           InfBuffer *buffer);

Creates a InfAdoptedAlgorithm.

[constructor]

Parameters

user_table

The table of participating users.

 

buffer

The buffer to apply operations to.

 

Returns

A new InfAdoptedAlgorithm.

[transfer full]


inf_adopted_algorithm_new_full ()

InfAdoptedAlgorithm *
inf_adopted_algorithm_new_full (InfUserTable *user_table,
                                InfBuffer *buffer,
                                guint max_total_log_size);

Note that it is possible that request logs need to grow a bit larger than max_total_log_size in high-latency situations or when a user does not send status updates frequently. However, when all requests have been processed by all users, the sum of all requests in the logs is guaranteed to be lower or equal to this value.

Set to G_MAXUINT to disable limitation. In theory, this would allow everyone to undo every operation up to the first one ever made. In practise, this issues a huge amount of data that needs to be synchronized on user join and is too expensive to compute anyway.

The default value is 2048.

[constructor]

Parameters

user_table

The table of participating users.

 

buffer

The buffer to apply operations to.

 

max_total_log_size

The maxmimum number of operations to keep in all user's request logs.

 

Returns

A new InfAdoptedAlgorithm.

[transfer full]


inf_adopted_algorithm_get_current ()

InfAdoptedStateVector *
inf_adopted_algorithm_get_current (InfAdoptedAlgorithm *algorithm);

Returns the current vector time of algorithm .

Parameters

algorithm

A InfAdoptedAlgorithm.

 

Returns

A InfAdoptedStateVector owned by algorithm .

[transfer none]


inf_adopted_algorithm_get_execute_request ()

InfAdoptedRequest *
inf_adopted_algorithm_get_execute_request
                               (InfAdoptedAlgorithm *algorithm);

Returns whether the algorithm is currently transforming a request to the current state and appling its state to the buffer. If it is the function is returning the request that was received and is currently being executed, other wise the function returns NULL. Note that the request execution is not re-entrant, i.e. two requests cannot be executed concurrently at the same time, or recursively.

Parameters

algorithm

A InfAdoptedAlgorithm.

 

Returns

The request that algorithm is currently processing, or NULL. The return value must not be freed by the caller.

[transfer none][allow-none]


inf_adopted_algorithm_generate_request ()

InfAdoptedRequest *
inf_adopted_algorithm_generate_request
                               (InfAdoptedAlgorithm *algorithm,
                                InfAdoptedRequestType type,
                                InfAdoptedUser *user,
                                InfAdoptedOperation *operation);

Creates a new request that can be applied to the current document state. The request is made by the given user. If operation is of type INF_ADOPTED_REQUEST_DO, then operation specifies the operation to be performed. Otherwise, operation must be NULL.

To apply the effect of the request to the document, run inf_adopted_algorithm_execute_request(). Note that even if the effect is already applied to the document, the function must still be called with the apply parameter set to FALSE, so that the algorithm knows that the request has been applied.

Parameters

algorithm

A InfAdoptedAlgorithm.

 

type

The type of request to create.

 

user

The user for which to create the request.

 

operation

The operation to perform, or NULL.

 

Returns

A new InfAdoptedRequest. Free with g_object_unref() when no longer needed.

[transfer full]


inf_adopted_algorithm_translate_request ()

InfAdoptedRequest *
inf_adopted_algorithm_translate_request
                               (InfAdoptedAlgorithm *algorithm,
                                InfAdoptedRequest *request,
                                InfAdoptedStateVector *to);

Translates request so that it can be applied to the document at state to . request will not be modified but a new, translated request is returned instead.

There are several preconditions for this function to be called. to must be a reachable point in the state space. Also, requests can only be translated in forward direction, so request 's vector time must be causally before (see inf_adopted_state_vector_causally_before()) to .

Parameters

algorithm

A InfAdoptedAlgorithm.

 

request

A InfAdoptedRequest.

 

to

The state vector to translate request to.

[transfer none]

Returns

A new or cached InfAdoptedRequest. Free with g_object_unref() when no longer needed.

[transfer full]


inf_adopted_algorithm_execute_request ()

gboolean
inf_adopted_algorithm_execute_request (InfAdoptedAlgorithm *algorithm,
                                       InfAdoptedRequest *request,
                                       gboolean apply,
                                       GError **error);

This function transforms the given request such that it can be applied to the current document state and then applies it the buffer and adds it to the request log of the algorithm, so that it is used for future transformations of other requests.

If apply is FALSE then the request is not applied to the buffer. In this case, it is assumed that the buffer is already modified, and that the request is made as a result from the buffer modification. This also means that the request must be applicable to the current document state, without requiring transformation.

In addition, the function emits the “begin-execute-request†and “end-execute-request†signals, and makes inf_adopted_algorithm_get_execute_request() return request during that period.

This allows other code to hook in before and after request processing. This does not cause any loss of generality because this function is not re-entrant anyway: it cannot work when used concurrently by multiple threads nor in a recursive manner, because only when one request has been added to the log the next request can be translated, since it might need the previous request for the translation path and it needs to be translated to a state where the effect of the previous request is included so that it can consistently applied to the buffer.

There are also runtime errors that can occur if request execution fails. In this case the function returns FALSE and error is set. Possible reasons for this include request being an INF_ADOPTED_REQUEST_UNDO or INF_ADOPTED_REQUEST_REDO request without there being an operation to undo or redo, or if the translated operation cannot be applied to the buffer. This usually means that the input request was invalid. However, this is not considered a programmer error because typically requests are received from untrusted input sources such as network connections. Note that there cannot be any runtime errors if apply is set to FALSE. In that case it is safe to call the function with NULL error.

Parameters

algorithm

A InfAdoptedAlgorithm.

 

request

The request to execute.

 

apply

Whether to apply the request to the buffer.

 

error

Location to store error information, if any.

 

Returns

TRUE on success or FALSE on error.


inf_adopted_algorithm_cleanup ()

void
inf_adopted_algorithm_cleanup (InfAdoptedAlgorithm *algorithm);

Removes requests in all users request logs which are no longer needed. This includes requests which cannot be undone or redone anymore due to the constraints of the “max-total-log-size†property, and requests that every participant is guaranteed to have processed already.

This function can be called after every executed request to keep memory use to a minimum, or it can be called in regular intervals, or it can also be omitted if the request history should be preserved.

Parameters

algorithm

A InfAdoptedAlgorithm.

 

inf_adopted_algorithm_can_undo ()

gboolean
inf_adopted_algorithm_can_undo (InfAdoptedAlgorithm *algorithm,
                                InfAdoptedUser *user);

Returns whether user can issue an undo request in the current state. Note that if user is non-local, then the result of this function does not depend on the current state but on the state that we know user is guaranteed to have reached. This is because user might still issue an Undo request even if the max-total-log-size is already exceeded if user does not know yet that it is exceeded.

Parameters

algorithm

A InfAdoptedAlgorithm.

 

user

A local InfAdoptedUser.

 

Returns

TRUE if Undo is possible, FALSE otherwise.


inf_adopted_algorithm_can_redo ()

gboolean
inf_adopted_algorithm_can_redo (InfAdoptedAlgorithm *algorithm,
                                InfAdoptedUser *user);

Returns whether user can issue a redo request in the current state. Note that if user is non-local, then the result of this function does not depend on the current state but on the state that we know user is guaranteed to have reached. This is because user might still issue a Redo request even if the max-total-log-size is already exceeded if user does not know yet that it is exceeded.

Parameters

algorithm

A InfAdoptedAlgorithm.

 

user

A local InfAdoptedUser.

 

Returns

TRUE if Redo is possible, FALSE otherwise.

Types and Values

enum InfAdoptedAlgorithmError

Error codes for InfAdoptedAlgorithm. These can occur when invalid requests are passed to inf_adopted_algorithm_execute_request().

Members

INF_ADOPTED_ALGORITHM_ERROR_NO_UNDO

An undo request was about to be executed but there is no operation to undo.

 

INF_ADOPTED_ALGORITHM_ERROR_NO_REDO

A redo request was about to be executed but there is no operation to redo.

 

INF_ADOPTED_ALGORITHM_ERROR_FAILED

No further specified error code.

 

struct InfAdoptedAlgorithm

struct InfAdoptedAlgorithm;

InfAdoptedAlgorithm is an opaque data type. You should only access it via the public API functions.


struct InfAdoptedAlgorithmClass

struct InfAdoptedAlgorithmClass {
  void(*can_undo_changed)(InfAdoptedAlgorithm* algorithm,
                          InfAdoptedUser* user,
                          gboolean can_undo);

  void(*can_redo_changed)(InfAdoptedAlgorithm* algorithm,
                          InfAdoptedUser* user,
                          gboolean can_redo);

  void(*begin_execute_request)(InfAdoptedAlgorithm* algorithm,
                               InfAdoptedUser* user,
                               InfAdoptedRequest* request);

  void(*end_execute_request)(InfAdoptedAlgorithm* algorithm,
                             InfAdoptedUser* user,
                             InfAdoptedRequest* request,
                             InfAdoptedRequest* translated_request,
                             const GError* error);
};

Signals for the InfAdoptedAlgorithm class.

Members

can_undo_changed ()

Default signal handler for the “can_undo_changed†signal.

 

can_redo_changed ()

Default signal handler for the “can_redo_changed†signal.

 

begin_execute_request ()

Default signal handler for the “begin-execute-request†signal.

 

end_execute_request ()

Default signal handler for the “end-execute-request†signal.

 

Property Details

The “buffer†property

  “buffer†                  InfBuffer *

The buffer to apply operations to.

Flags: Read / Write / Construct Only


The “buffer-modified-state†property

  “buffer-modified-state†   InfAdoptedStateVector *

The state in which the buffer is considered not being modified.

Flags: Read


The “current-state†property

  “current-state†           InfAdoptedStateVector *

The state vector describing the current document state.

Flags: Read


The “max-total-log-size†property

  “max-total-log-size†      guint

The maximum number of requests to keep in all user's logs.

Flags: Read / Write / Construct Only

Default value: 2048


The “user-table†property

  “user-table†              InfUserTable *

The user table.

Flags: Read / Write / Construct Only

Signal Details

The “begin-execute-request†signal

void
user_function (InfAdoptedAlgorithm *algorithm,
               InfAdoptedUser      *user,
               InfAdoptedRequest   *request,
               gpointer             user_data)

This signal is emitted every time the algorithm executes a request, i.e. transforms it such that it can be applied to the current state, resolves undo/redo operations and applies the resulting operation to the buffer.

Parameters

algorithm

The InfAdoptedAlgorithm executing a request.

 

user

The InfAdoptedUser executing the request.

 

request

The InfAdoptedRequest being executed.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last


The “can-redo-changed†signal

void
user_function (InfAdoptedAlgorithm *algorithm,
               InfAdoptedUser      *user,
               gboolean             can_undo,
               gpointer             user_data)

This signal is emitted every time the can-redo state of a local user in algorithm 's user table changed. The can-redo state defines whether user can generate a redo request (via inf_adopted_algorithm_generate_request()) in the current situation, see also inf_adopted_algorithm_can_redo().

Parameters

algorithm

The InfAdoptedAlgorithm for which a user's can-redo state changed.

 

user

The InfAdoptedUser whose can-redo state has changed.

 

can_undo

Whether user can issue a redo request in the current state or not.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last


The “can-undo-changed†signal

void
user_function (InfAdoptedAlgorithm *algorithm,
               InfAdoptedUser      *user,
               gboolean             can_undo,
               gpointer             user_data)

This signal is emitted every time the can-undo state of a local user in algorithm 's user table changed. The can-undo state defines whether user can generate an undo request (via inf_adopted_algorithm_generate_request()) in the current situation, see also inf_adopted_algorithm_can_undo().

Parameters

algorithm

The InfAdoptedAlgorithm for which a user's can-undo state changed.

 

user

The InfAdoptedUser whose can-undo state has changed.

 

can_undo

Whether user can issue an undo request in the current state or not.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last


The “end-execute-request†signal

void
user_function (InfAdoptedAlgorithm *algorithm,
               InfAdoptedUser      *user,
               InfAdoptedRequest   *request,
               InfAdoptedRequest   *translated,
               GError              *error,
               gpointer             user_data)

This signal is emitted after a request has been executed. The request parameter is not necessarily the same as the one in the corresponding emission of “begin-execute-requestâ€, however its effect on the buffer is the same. The difference is that the request in this signal might be reversible while the request in the “begin-execute-request†emission might not be reversible. The algorithm can make some requests reversible during their execution.

The translated request is the result of the transformation, i.e. it is always a INF_ADOPTED_REQUEST_DO type request and its state vector corresponds to the current state. It has already been applied on the buffer by the algorithm. If request is of type INF_ADOPTED_REQUEST_UNDO or INF_ADOPTED_REQUEST_REDO then translated represents the operation that actually was performed on the buffer to undo or redo the effect of a previous request.

It can happen that an error occurs during execution. Usually this is due to invalid input, such as a request that cannot be transformed to the current state, a INF_ADOPTED_REQUEST_UNDO request which has no corresponding INF_ADOPTED_REQUEST_DO or INF_ADOPTED_REQUEST_REDO request, or a request that ends up in an invalid operation (e.g. inserting text behind the end of the document). If such an error occurs then request is the same as the one in the InfAdoptedAlgorithm::begin-execute-request emission, translated may or may not be NULL and error contains information on the error occured.

Parameters

algorithm

The InfAdoptedAlgorithm executing a request.

 

user

The InfAdoptedUser executing the request.

 

request

The InfAdoptedRequest that was executed.

 

translated

The result of the request transformation, or NULL.

 

error

The error that occurred during execution, or NULL.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfdFilesystemStorage.html0000644000000000000000000000013213055210752027115 xustar0030 mtime=1488261610.908090655 30 atime=1488261610.908090655 30 ctime=1488261610.908090655 libinfinity-0.7.1/docs/reference/libinfinity/html/InfdFilesystemStorage.html0000644000175000017500000010731213055210752027653 0ustar00arminarmin00000000000000 InfdFilesystemStorage: libinfinity-0.7 Reference Manual

InfdFilesystemStorage

InfdFilesystemStorage

Properties

gchar * root-directory Read / Write / Construct Only

Object Hierarchy

    GObject
    ╰── InfdFilesystemStorage

Implemented Interfaces

InfdFilesystemStorage implements InfdStorage.

Description

Functions

infd_filesystem_storage_new ()

InfdFilesystemStorage *
infd_filesystem_storage_new (const gchar *root_directory);

Creates a new InfdFilesystemStorage that stores its nodes in the given directory on the file system. The directory is created if it does not exist.

[constructor]

Parameters

root_directory

A directory name in UTF-8.

 

Returns

A new InfdFilesystemStorage.

[transfer full]


infd_filesystem_storage_get_path ()

gchar *
infd_filesystem_storage_get_path (InfdFilesystemStorage *storage,
                                  const gchar *identifier,
                                  const gchar *path,
                                  GError **error);

Returns the full file name to the given path within the storage's root directory. The function might fail if path contains invalid characters. If the function fails, NULL is returned and error is set.

Only if identifier starts with "Inf", the file will show up in the directory listing of infd_storage_read_subdirectory(). Other identifiers can be used to store custom data in the filesystem, linked to this InfdFilesystemStorage object.

Parameters

storage

A InfdFilesystemStorage.

 

identifier

The type of node to open.

 

path

The path to open, in UTF-8.

 

error

Location to store error information, if any, or NULL.

 

Returns

An absolute filename path to be freed with g_free(), or NULL.

[type filename][allow-none][transfer full]


infd_filesystem_storage_open ()

FILE *
infd_filesystem_storage_open (InfdFilesystemStorage *storage,
                              const gchar *identifier,
                              const gchar *path,
                              const gchar *mode,
                              gchar **full_path,
                              GError **error);

Opens a file in the given path within the storage's root directory. If the file exists already, and mode is set to "w", the file is overwritten.

If full_path is not NULL, then it will be set to a newly allocated string which contains the full name of the opened file, in the Glib file name encoding. Note that full_path will also be set if the function fails.

Only if identifier starts with "Inf", the file will show up in the directory listing of infd_storage_read_subdirectory(). Other identifiers can be used to store custom data in the filesystem, linked to this InfdFilesystemStorage object.

Parameters

storage

A InfdFilesystemStorage.

 

identifier

The type of node to open.

 

path

The path to open, in UTF-8.

 

mode

Either "r" for reading or "w" for writing.

 

full_path

Return location of the full filename, or NULL.

[out][type filename][transfer full]

error

Location to store error information, if any.

 

Returns

A stream for the open file. Close with infd_filesystem_storage_stream_close().

[transfer full]


infd_filesystem_storage_read_xml_file ()

xmlDocPtr
infd_filesystem_storage_read_xml_file (InfdFilesystemStorage *storage,
                                       const gchar *identifier,
                                       const gchar *path,
                                       const gchar *toplevel_tag,
                                       GError **error);

Opens a file in the given path, and parses its XML content. See infd_filesystem_storage_open() for how identifier and path should be interpreted.

If toplevel_tag is non-NULL, then this function generates an error if the XML document read has a toplevel tag with a different name.

Parameters

storage

A InfdFilesystemStorage.

 

identifier

The type of node to open.

 

path

The path to open, in UTF-8.

 

toplevel_tag

The expected toplevel XML tag name, or NULL.

 

error

Location to store error information, if any.

 

Returns

A new XML document, or NULL on error. Free with xmlDocFree().

[transfer full][allow-none]


infd_filesystem_storage_write_xml_file ()

gboolean
infd_filesystem_storage_write_xml_file
                               (InfdFilesystemStorage *storage,
                                const gchar *identifier,
                                const gchar *path,
                                xmlDocPtr doc,
                                GError **error);

Writes the XML doument in doc into a file in the filesystem indicated by identifier and path . See infd_filesystem_storage_open() for how identifier and path should be interpreted.

Parameters

storage

A InfdFilesystemStorage.

 

identifier

The type of node to write.

 

path

The path to write to, in UTF-8.

 

doc

The XML document to write.

 

error

Location to store error information, if any.

 

Returns

TRUE on success or FALSE on error.


infd_filesystem_storage_stream_close ()

int
infd_filesystem_storage_stream_close (FILE *file);

This is a thin wrapper around fclose(). Use this function instead of fclose() if you have opened the file with infd_filesystem_storage_open(), to make sure that the same C runtime is closing the file that has opened it.

Parameters

file

A FILE opened with infd_filesystem_storage_open().

 

Returns

The return value of fclose().


infd_filesystem_storage_stream_read ()

gsize
infd_filesystem_storage_stream_read (FILE *file,
                                     gpointer buffer,
                                     gsize len);

This is a thin wrapper around fread(). Use this function instead of fread() if you have opened the file with infd_filesystem_storage_open(), to make sure that the same C runtime is closing the file that has opened it.

Parameters

file

A FILE opened with infd_filesystem_storage_open().

 

buffer

A buffer into which to read data.

[type guint8*][array length=len][out]

len

Maximum number of bytes to read.

 

Returns

The return value of fread().


infd_filesystem_storage_stream_write ()

gsize
infd_filesystem_storage_stream_write (FILE *file,
                                      gconstpointer buffer,
                                      gsize len);

This is a thin wrapper around fwrite(). Use this function instead of fwrite() if you have opened the file with infd_filesystem_storage_open(), to make sure that the same C runtime is closing the file that has opened it.

Parameters

file

A FILE opened with infd_filesystem_storage_open().

 

buffer

The data to write.

 

len

Maximum number of bytes to write.

 

Returns

The return value of fwrite().

Types and Values

enum InfdFilesystemStorageError

Members

INFD_FILESYSTEM_STORAGE_ERROR_INVALID_PATH

   

INFD_FILESYSTEM_STORAGE_ERROR_REMOVE_FILES

   

INFD_FILESYSTEM_STORAGE_ERROR_INVALID_FORMAT

   

INFD_FILESYSTEM_STORAGE_ERROR_FAILED

   

struct InfdFilesystemStorage

struct InfdFilesystemStorage;


struct InfdFilesystemStorageClass

struct InfdFilesystemStorageClass {
  GObjectClass parent_class;
};

Property Details

The “root-directory†property

  “root-directory†          gchar *

The directory in which the storage stores its content.

Flags: Read / Write / Construct Only

Default value: NULL

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfcSessionProxy.html0000644000000000000000000000013213055210752026130 xustar0030 mtime=1488261610.908090655 30 atime=1488261610.908090655 30 ctime=1488261610.908090655 libinfinity-0.7.1/docs/reference/libinfinity/html/InfcSessionProxy.html0000644000175000017500000005105713055210752026672 0ustar00arminarmin00000000000000 InfcSessionProxy: libinfinity-0.7 Reference Manual

InfcSessionProxy

InfcSessionProxy — Client-side session management

Stability Level

Unstable, unless otherwise indicated

Types and Values

Object Hierarchy

    GObject
    ╰── InfcSessionProxy

Implemented Interfaces

InfcSessionProxy implements InfCommunicationObject and InfSessionProxy.

Includes

#include <libinfinity/client/infc-session-proxy.h>

Description

InfcSessionProxy is a manager for InfSession that is specific for the client side. The InfcSessionProxy manages exactly one InfSession. It is usually created by InfcBrowser when a subscription to a node is made.

InfcSessionProxy allows to perform client-specific operations for the session it manages, such as joining a user. In addition it handles requests made by its counterpart, InfdSessionProxy, for the server side, such as remote user joins and forced session closure.

InfcSessionProxy implements the InfSessionProxy interface, which can be used to access the underlying InfSession or to join a user.

Functions

infc_session_proxy_set_connection ()

void
infc_session_proxy_set_connection (InfcSessionProxy *proxy,
                                   InfCommunicationJoinedGroup *group,
                                   InfXmlConnection *connection,
                                   guint seq_id);

Sets the subscription connection for the given session. The subscription connection is the connection through which session requests are transmitted during subscription.

The subscription connection might be set even if the session is in SYNCHRONIZING state in which case the session is immediately subscribed after synchronization. Note that no attempt is made to tell the other end about the subscription.

seq_id should be a sequence identifier obtained from the server side. It must be the same number that is used on the corresponding InfdSessionProxy on the remote side, see infd_session_proxy_subscribe_to(). Normally InfdDirectory or InfcBrowser, respectively, take care of passing the correct sequence identifier.

When the subscription connection is being closed or replaced (by a subsequent call to this function), all pending requests are dropped and all users are set to be unavailable, but the session will not be closed, so it may be reused by setting another subscription connection. However, the session might not be synchronized again, but it is fully okay to close the session by hand (using inf_session_close) and create a new session that is synchronized.

Parameters

proxy

A InfcSessionProxy.

 

group

A InfCommunicationJoinedGroup of subscribed connections. Ignored if connection is NULL.

 

connection

A InfXmlConnection.

 

seq_id

A sequence identifier for connection . Ignored if connection is NULL.

 

infc_session_proxy_get_connection ()

InfXmlConnection *
infc_session_proxy_get_connection (InfcSessionProxy *proxy);

Returns the connection that is used to transmit requests to the publisher of the session, or NULL if the session is not subscribed.

Parameters

proxy

A InfcSessionProxy.

 

Returns

A InfXmlConnection, or NULL.

[transfer none]


infc_session_proxy_get_subscription_group ()

InfCommunicationJoinedGroup *
infc_session_proxy_get_subscription_group
                               (InfcSessionProxy *proxy);

Returns the group with all subscribed connections to the session, or NULL if the session is not subscribed.

Parameters

proxy

A InfcSessionProxy.

 

Returns

A InfCommunicationJoinedGroup, or NULL.

[transfer none]

Types and Values

struct InfcSessionProxy

struct InfcSessionProxy;

InfcSessionProxy is an opaque data type. You should only access it via the public API functions.


struct InfcSessionProxyClass

struct InfcSessionProxyClass {
  GError* (*translate_error)(InfcSessionProxy* session,
                             GQuark domain,
                             guint code);
};

This structure contains virtual functions of the InfcSessionProxy class.

Members

translate_error ()

Virtual function to transform an error domain and code into a GError object. If the domain and code are known, this allows to show a localized error message to the user, independent from the language the server uses in the error message that went over the wire.

 

Property Details

The “connection†property

  “connection†              InfXmlConnection *

The connection with which the session communicates with the server.

Flags: Read


The “subscription-group†property

  “subscription-group†      InfCommunicationJoinedGroup *

The communication group of subscribed connections.

Flags: Read

See Also

InfSession

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfAdoptedSessionRecord.html0000644000000000000000000000013213055210752027363 xustar0030 mtime=1488261610.908090655 30 atime=1488261610.908090655 30 ctime=1488261610.908090655 libinfinity-0.7.1/docs/reference/libinfinity/html/InfAdoptedSessionRecord.html0000644000175000017500000004776213055210752030135 0ustar00arminarmin00000000000000 InfAdoptedSessionRecord: libinfinity-0.7 Reference Manual

InfAdoptedSessionRecord

InfAdoptedSessionRecord — Create a record of a session

Stability Level

Unstable, unless otherwise indicated

Properties

gchar * filename Read
InfAdoptedSession * session Read / Write / Construct Only

Types and Values

Object Hierarchy

    GObject
    ╰── InfAdoptedSessionRecord

Includes

#include <libinfinity/adopted/inf-adopted-session-record.h>

Description

InfAdoptedSessionRecord creates a record of a InfAdoptedSession. It records every modification made to the session from the beginning of its own lifetime to the end of its lifetime.

It does not record user status changes and thus the recorded session cannot reliably be replayed with all user information. It's main purpose is to make it easy to reproduce bugs in libinfinity. However, it might be extended in the future.

To replay a record, use InfAdoptedSessionReplay or the tool inf-test-text-replay in the infinote test suite.

Functions

inf_adopted_session_record_new ()

InfAdoptedSessionRecord *
inf_adopted_session_record_new (InfAdoptedSession *session);

Creates a new InfAdoptedSessionRecord, recording session . To start recording, call inf_adopted_session_record_start_recording().

[constructor]

Parameters

session

A InfAdoptedSession.

 

Returns

A new InfAdoptedSessionRecord.

[transfer full]


inf_adopted_session_record_start_recording ()

gboolean
inf_adopted_session_record_start_recording
                               (InfAdoptedSessionRecord *record,
                                const gchar *filename,
                                GError **error);

Starts to record the session. Make sure the session is not already closed before calling this function. If an error occurs, such as if filename could not be opened, then the function returns FALSE and error is set.

Parameters

record

A InfAdoptedSessionRecord.

 

filename

The file in which to store the record.

[type filename]

error

Location to store error information, if any.

 

Returns

TRUE if the session is started to be recorded, FALSE on error.


inf_adopted_session_record_stop_recording ()

gboolean
inf_adopted_session_record_stop_recording
                               (InfAdoptedSessionRecord *record,
                                GError **error);

Stops the recording of the current session, which must have been started previously via inf_adopted_session_record_start_recording(). If an error occurs, then the function returns FALSE and error is set. Note that even if an error occurs, then the recording is stopped as well. However, the file might not have been completely written to disk, so you should still show any errors during this function to the user.

Parameters

record

A InfAdoptedSessionRecord.

 

error

Location to store error information, if any.

 

Returns

TRUE if the recording has been stored successfully, FALSE otherwise.


inf_adopted_session_record_is_recording ()

gboolean
inf_adopted_session_record_is_recording
                               (InfAdoptedSessionRecord *record);

Returns whether record is currently recording a session.

Parameters

record

A InfAdoptedSessionRecord.

 

Returns

Whether record currently records the session.

Types and Values

struct InfAdoptedSessionRecord

struct InfAdoptedSessionRecord;

InfAdoptedSessionRecord is an opaque data type. You should only access it via the public API functions.


struct InfAdoptedSessionRecordClass

struct InfAdoptedSessionRecordClass {
};

This structure does not contain any public fields.

Property Details

The “filename†property

  “filename†                gchar *

The filename of the record file.

Flags: Read

Default value: NULL


The “session†property

  “session†                 InfAdoptedSession *

The session to record.

Flags: Read / Write / Construct Only

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/libinfinity-0.7.devhelp20000644000000000000000000000013213055210752026232 xustar0030 mtime=1488261610.832090825 30 atime=1488261610.832090825 30 ctime=1488261610.832090825 libinfinity-0.7.1/docs/reference/libinfinity/html/libinfinity-0.7.devhelp20000644000175000017500000060337113055210752026776 0ustar00arminarmin00000000000000 libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfBrowserIter.html0000644000000000000000000000013213055210752025547 xustar0030 mtime=1488261610.908090655 30 atime=1488261610.908090655 30 ctime=1488261610.908090655 libinfinity-0.7.1/docs/reference/libinfinity/html/InfBrowserIter.html0000644000175000017500000002421513055210752026305 0ustar00arminarmin00000000000000 InfBrowserIter: libinfinity-0.7 Reference Manual

InfBrowserIter

InfBrowserIter — Iterating through browsed nodes

Stability Level

Unstable, unless otherwise indicated

Types and Values

Object Hierarchy

    GBoxed
    ╰── InfBrowserIter

Includes

#include <libinfinity/common/inf-browser-iter.h>

Description

InfBrowserIter is used to iterate through the nodes of a InfBrowser. Normally, InfBrowserIter is allocated on the stack and initialized by a InfBrowser API call, such as inf_browser_get_root(). You can also safely copy the struct by value to create a copy. It is not necessary to free it.

Most operations are done via the InfBrowser API. The methods described here could be useful to language bindings, however.

An initialized InfBrowserIter always points to a node within the InfBrowser. It stays valid as long as the node it points to is not removed from the browser (if it is, the “node-removedâ€) signal is emitted.

Functions

inf_browser_iter_copy ()

InfBrowserIter *
inf_browser_iter_copy (const InfBrowserIter *iter);

Makes a dynamically allocated copy of iter . This should not be used by applications because you can copy the structs by value.

Parameters

iter

A InfBrowserIter.

 

Returns

A newly-allocated copy of iter .

[transfer full]


inf_browser_iter_free ()

void
inf_browser_iter_free (InfBrowserIter *iter);

Frees a InfBrowserIter allocated by inf_browser_iter_copy().

Parameters

iter

A InfBrowserIter.

 

Types and Values

struct InfBrowserIter

struct InfBrowserIter {
};

The InfBrowserIter structure is opaque, however it is guaranteed that it can be copied by value and does not hold any dynamic data that would need to be freed explicitly.

See Also

InfBrowser

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfCertificateVerify.html0000644000000000000000000000013213055210752026707 xustar0030 mtime=1488261610.912090646 30 atime=1488261610.912090646 30 ctime=1488261610.912090646 libinfinity-0.7.1/docs/reference/libinfinity/html/InfCertificateVerify.html0000644000175000017500000007053113055210752027447 0ustar00arminarmin00000000000000 InfCertificateVerify: libinfinity-0.7 Reference Manual

InfCertificateVerify

InfCertificateVerify — Server certificate verification.

Stability Level

Unstable, unless otherwise indicated

Properties

gchar * known-hosts-file Read / Write
InfXmppManager * xmpp-manager Read / Write / Construct Only

Object Hierarchy

    GFlags
    ╰── InfCertificateVerifyFlags
    GObject
    ╰── InfCertificateVerify

Includes

#include <libinfinity/common/inf-certificate-verify.h>

Description

InfCertificateVerify attempts to verify server certificates. It is associated to a InfXmppManager, and all client-side connections managed by that manager will be checked.

The policy enforced by InfCertificateVerify is such that if the certificate is not valid, signed with a weak algorithm, expired, or not yet activated, to reject the certificate. On the other hand, if the certificate itself is valid and the hostname that it is issued to matches the hostname of the connection, and its CA is trusted, then the certificate is accepted.

However, if the certificate as such is valid but either the hostname does not match or the CA is not trusted (for example if a self-signed certificate is used), then certificate pinning takes effect. If the certificate is not pinned, the “check-certificate†is emitted, which should cause the certificate to be checked manually, e.g. by presenting it to the user. Once the check is complete, call inf_certificate_verify_checked(). If the check is positive, the certificate is pinned, so that next time a connection to the same hostname presents the same certificate, it is accepted automatically. If a different certificate than the pinned one is being presented, then the “check-certificate†signal is emitted again.

Functions

inf_certificate_verify_new ()

InfCertificateVerify *
inf_certificate_verify_new (InfXmppManager *xmpp_manager,
                            const gchar *known_hosts_file);

Creates a new InfCertificateVerify. For each new client-side InfXmppConnection in xmpp_manager , the certificate manager will verify the server's certificate.

If the certificate is contained in known_hosts_file , or is issued by a trusted CA, then the certificate is accepted automatically. Otherwise, the “check-certificate†signal is emitted for a manual check of the certificate to be performed.

[constructor]

Parameters

xmpp_manager

The InfXmppManager whose InfXmppConnections to manage the certificates for.

 

known_hosts_file

Path pointing to a file that contains certificates of known hosts, or NULL.

[type filename][allow-none]

Returns

A new InfCertificateVerify.

[transfer full]


inf_certificate_verify_checked ()

void
inf_certificate_verify_checked (InfCertificateVerify *verify,
                                InfXmppConnection *connection,
                                gboolean result);

This function should be called as a response to the “check-certificate†signal being emitted.

Parameters

verify

A InfCertificateVerify.

 

connection

The InfXmppConnection whose certificate has been checked.

 

result

TRUE if the certificate of connection should be accepted, or FALSE if it should be rejected.

 

Types and Values

struct InfCertificateVerify

struct InfCertificateVerify;

InfCertificateVerify is an opaque data type. You should only access it via the public API functions.


struct InfCertificateVerifyClass

struct InfCertificateVerifyClass {
  void (*check_certificate)(InfCertificateVerify* verify,
                            InfXmppConnection* connection,
                            InfCertificateChain* certificate_chain,
                            gnutls_x509_crt_t pinned_certificate,
                            InfCertificateVerifyFlags flags);

  void (*check_cancelled)(InfCertificateVerify* verify,
                          InfXmppConnection* connection);
};

This structure contains default signal handlers for InfCertificateVerify.

Members

check_certificate ()

Default signal handler for the “check-certificate†signal.

 

check_cancelled ()

   

enum InfCertificateVerifyFlags

Various flags for why a certificate is not trusted.

Members

INF_CERTIFICATE_VERIFY_HOSTNAME_MISMATCH

The hostname of the machine connected to does not match the one from the certificate.

 

INF_CERTIFICATE_VERIFY_ISSUER_NOT_KNOWN

The issuer of the certificate is not trusted, i.e. is not in the list of trusted CAs.

 

INF_CERTIFICATE_VERIFY_NOT_PINNED

We have pinned a certificate for this host, but the certificate presented is a different one.

 

Property Details

The “known-hosts-file†property

  “known-hosts-file†        gchar *

File containing certificates of known hosts.

Flags: Read / Write

Default value: NULL


The “xmpp-manager†property

  “xmpp-manager†            InfXmppManager *

The XMPP manager of registered connections.

Flags: Read / Write / Construct Only

Signal Details

The “check-cancelled†signal

void
user_function (InfCertificateVerify *verify,
               InfXmppConnection    *connection,
               gpointer              user_data)

This signal is emitted when a manual certificate check as initiated with the “check-certificate†signal should be cancelled. After this signal has been emitted, inf_certificate_verify_checked() should not be called anymore for the specified connection.

This typically happens when the connection to the remote host is lost while the certificate check is in progress.

Parameters

verify

The InfCertificateVerify emitting the signal.

 

connection

The connection to the remote host whose certificate is being verified.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last


The “check-certificate†signal

void
user_function (InfCertificateVerify     *verify,
               InfXmppConnection        *connection,
               InfCertificateChain      *certificate_chain,
               gpointer                  pinned_certificate,
               InfCertificateVerifyFlags flags,
               gpointer                  user_data)

This signal is emitted every time a certificate presented by a remote host needs to be checked manually. This happens when the issuer of the certificate is not in the list of trusted CAs, or the certificate was issued for a different hostname than we expected. In this case, if the certificate is accepted manually, it will be pinned, so that next time a connection is made to the same host under the same hostname, the certificate is accepted automatically.

Consumers of this class should listen to this signal and call inf_certificate_verify_checked() when they finished the manual certificate check.

The pinned_certificate instance is valid until either inf_certificate_verify_checked() is called or the “check-cancelled†signal is emitted.

Parameters

verify

The InfCertificateVerify emitting the signal.

 

connection

The connection to the remote host whose certificate is being verified.

 

certificate_chain

The certificate chain presented by the remote host.

 

pinned_certificate

The certificate that we have pinned for this host, or NULL.

 

flags

Flags explaining why this certificate needs to be checked.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/up.png0000644000000000000000000000013213055210752023107 xustar0030 mtime=1488261610.832090825 30 atime=1488261610.832090825 30 ctime=1488261610.832090825 libinfinity-0.7.1/docs/reference/libinfinity/html/up.png0000644000175000017500000000040413055210752023637 0ustar00arminarmin00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEà 4ÓkM‘IDAT8Ëí’1 ƒ@DŸ•¶{ƒxa™ƒØÄ;$]r =JR´È1,Ë øSd„-©}0°ÌŸÙÏÂÂÎàüo¹L:m-˜¤QÞOäÀ[› Éäåkå T¸zþMÞ Lè¬Ì,š:ךuÀ!tÁK;æ ðP¦õÌôÀp Ot@£l¼ÿò/̵*á§l}IEND®B`‚libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/home.png0000644000000000000000000000013213055210752023413 xustar0030 mtime=1488261610.828090834 30 atime=1488261610.828090834 30 ctime=1488261610.828090834 libinfinity-0.7.1/docs/reference/libinfinity/html/home.png0000644000175000017500000000040013055210752024137 0ustar00arminarmin00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEà 4ÓkMIDAT8ËÝÒ½ AÅñßž¦f`n v`6`/¶`Y€š˜Ü¡`f&k$,Ëá}˜ˆ ÌüßÀ0ü§bŒ+Ô¸aQW~bæ ËOà e˜{‡y N°Á£üö[LáØÌ}.pÇiÀ­÷¨BzüžÆmm Šoæ·.I]7Ì^[úÃô;%:å†ÁVIEND®B`‚libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfCommunicationRegistry.html0000644000000000000000000000013213055210752027636 xustar0030 mtime=1488261610.912090646 30 atime=1488261610.912090646 30 ctime=1488261610.912090646 libinfinity-0.7.1/docs/reference/libinfinity/html/InfCommunicationRegistry.html0000644000175000017500000005722113055210752030377 0ustar00arminarmin00000000000000 InfCommunicationRegistry: libinfinity-0.7 Reference Manual

InfCommunicationRegistry

InfCommunicationRegistry — Sharing connections between multiple groups

Stability Level

Unstable, unless otherwise indicated

Object Hierarchy

    GObject
    ╰── InfCommunicationRegistry

Includes

#include <libinfinity/communication/inf-communication-registry.h>

Description

InfCommunicationRegistry provides a way for InfCommunicationMethod implementations to share connections with other groups. Before using a connection, call inf_communication_registry_register(). Then, messages can be sent to the group via inf_communication_registry_send().

The InfCommunicationRegistry calls inf_communication_method_received() on your method when it received a message for the group, inf_communication_method_enqueued() when sending the message cannot be cancelled anymore via inf_communication_registry_cancel_messages() and inf_communication_method_sent() when the message has been sent.

Functions

inf_communication_registry_register ()

void
inf_communication_registry_register (InfCommunicationRegistry *registry,
                                     InfCommunicationGroup *group,
                                     InfCommunicationMethod *method,
                                     InfXmlConnection *connection);

Registers connection with group . This allows sending messages to connection via inf_communication_registry_send(). For received messages, inf_communication_method_received() is called on method .

connection must have status INF_XML_CONNECTION_OPEN.

Parameters

registry

A InfCommunicationRegistry.

 

group

The group for which to register a connection.

 

method

The InfCommunicationMethod used.

 

connection

The connection to register.

 

inf_communication_registry_unregister ()

void
inf_communication_registry_unregister (InfCommunicationRegistry *registry,
                                       InfCommunicationGroup *group,
                                       InfXmlConnection *connection);

Unregisters connection from group . Incoming messages are no longer reported to group's method, and inf_communication_registry_send() can no longer be called for connection .

Parameters

registry

A InfCommunicationRegistry.

 

group

The group for which to unregister a connection.

 

connection

The connection to unregister.

 

inf_communication_registry_is_registered ()

gboolean
inf_communication_registry_is_registered
                               (InfCommunicationRegistry *registry,
                                InfCommunicationGroup *group,
                                InfXmlConnection *connection);

Returns whether connection has been registered for group with inf_communication_registry_register().

Parameters

registry

A InfCommunicationRegistry.

 

group

The group for which to check whether connection is registered.

 

connection

The connection to check for registration.

 

Returns

TRUE if connection has been registered, or FALSE otherwise.


inf_communication_registry_send ()

void
inf_communication_registry_send (InfCommunicationRegistry *registry,
                                 InfCommunicationGroup *group,
                                 InfXmlConnection *connection,
                                 xmlNodePtr xml);

Sends an XML message to connection . connection must have been registered with inf_communication_registry_register() before. If the message has been sent, inf_communication_method_sent() is called on the method the connection was registered with. inf_communication_method_enqueued() is called when sending the message can no longer be cancelled via inf_communication_registry_cancel_messages().

This function takes ownership of xml .

Parameters

registry

A InfCommunicationRegistry.

 

group

The group for which to send the message InfCommunicationGroup.

 

connection

A registered InfXmlConnection.

 

xml

The message to send.

[transfer full]

inf_communication_registry_cancel_messages ()

void
inf_communication_registry_cancel_messages
                               (InfCommunicationRegistry *registry,
                                InfCommunicationGroup *group,
                                InfXmlConnection *connection);

Stops all messages scheduled to be sent to connection in group from being sent.

Parameters

registry

A InfCommunicationRegistry.

 

group

The group for which to cancel messages.

 

connection

A registered InfXmlConnection.

 

Types and Values

struct InfCommunicationRegistry

struct InfCommunicationRegistry;

InfCommunicationRegistry is an opaque data type. You should only access it via the public API functions.


struct InfCommunicationRegistryClass

struct InfCommunicationRegistryClass {
};

This structure does not contain any public fields.

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/right-insensitive.png0000644000000000000000000000013213055210752026136 xustar0030 mtime=1488261610.832090825 30 atime=1488261610.832090825 30 ctime=1488261610.832090825 libinfinity-0.7.1/docs/reference/libinfinity/html/right-insensitive.png0000644000175000017500000000056513055210752026676 0ustar00arminarmin00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEà 4ÓkMIDAT8ËÍ’±JÃ`…¿ ‚“‹³«/ S’_$ÄÁÁAqrÐÙW(>€“à‚®©“m¥"]\œ„è(‘49.NÚdÒ3¸ß9Ü{á¯eM#MSI‡Î¹·E¯iHz|3{̲l½3 ,K˜k’ž†ÃáV'@EŸEQlwÀŠçyišî·Äqüçù‘™]KÀíh4:mµÄ¦²,;“t˜¤sç\aƒÆR5/¬7'¹W×õp”’Žs×­I’,Kº1³=àËÌÂ0´j0Wg³ÙØ>€Ý ¦­¯PUÕýïð»¤0 §]?qCÒ«™ùιgþ½~œÉkÄAâ…_IEND®B`‚libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/libinfinity-0.7-InfAcl.html0000644000000000000000000000013213055210752026617 xustar0030 mtime=1488261610.912090646 30 atime=1488261610.912090646 30 ctime=1488261610.912090646 libinfinity-0.7.1/docs/reference/libinfinity/html/libinfinity-0.7-InfAcl.html0000644000175000017500000034234613055210752027365 0ustar00arminarmin00000000000000 Access Control Lists: libinfinity-0.7 Reference Manual

Access Control Lists

Access Control Lists — Common data structures for the infinote ACL Permissions

Stability Level

Unstable, unless otherwise indicated

Functions

InfAclAccountId inf_acl_account_id_from_string ()
const gchar * inf_acl_account_id_to_string ()
#define INF_ACL_ACCOUNT_ID_TO_POINTER()
#define INF_ACL_ACCOUNT_POINTER_TO_ID()
InfAclAccount * inf_acl_account_new ()
InfAclAccount * inf_acl_account_copy ()
void inf_acl_account_free ()
void inf_acl_account_array_free ()
InfAclAccount * inf_acl_account_from_xml ()
void inf_acl_account_to_xml ()
InfAclMask * inf_acl_mask_copy ()
void inf_acl_mask_free ()
void inf_acl_mask_clear ()
gboolean inf_acl_mask_empty ()
gboolean inf_acl_mask_equal ()
InfAclMask * inf_acl_mask_set1 ()
InfAclMask * inf_acl_mask_setv ()
InfAclMask * inf_acl_mask_and ()
InfAclMask * inf_acl_mask_and1 ()
InfAclMask * inf_acl_mask_or ()
InfAclMask * inf_acl_mask_or1 ()
InfAclMask * inf_acl_mask_neg ()
gboolean inf_acl_mask_has ()
InfAclSheet * inf_acl_sheet_new ()
InfAclSheet * inf_acl_sheet_copy ()
void inf_acl_sheet_free ()
gboolean inf_acl_sheet_perms_from_xml ()
void inf_acl_sheet_perms_to_xml ()
InfAclSheetSet * inf_acl_sheet_set_new ()
InfAclSheetSet * inf_acl_sheet_set_new_external ()
InfAclSheetSet * inf_acl_sheet_set_copy ()
void inf_acl_sheet_set_free ()
void inf_acl_sheet_set_sink ()
InfAclSheet * inf_acl_sheet_set_add_sheet ()
void inf_acl_sheet_set_remove_sheet ()
InfAclSheetSet * inf_acl_sheet_set_merge_sheets ()
InfAclSheetSet * inf_acl_sheet_set_get_clear_sheets ()
InfAclSheet * inf_acl_sheet_set_find_sheet ()
const InfAclSheet * inf_acl_sheet_set_find_const_sheet ()
InfAclSheetSet * inf_acl_sheet_set_from_xml ()
void inf_acl_sheet_set_to_xml ()

Types and Values

typedef InfAclAccountId
struct InfAclAccount
enum InfAclSetting
struct InfAclMask
struct InfAclSheet
struct InfAclSheetSet
extern const InfAclMask INF_ACL_MASK_ALL
extern const InfAclMask INF_ACL_MASK_DEFAULT
extern const InfAclMask INF_ACL_MASK_LEAF
extern const InfAclMask INF_ACL_MASK_ROOT
extern const InfAclMask INF_ACL_MASK_SUBDIRECTORY

Object Hierarchy

    GBoxed
    ├── InfAclAccount
    ├── InfAclMask
    ├── InfAclSheet
    ╰── InfAclSheetSet
    GEnum
    ╰── InfAclSetting

Includes

#include <libinfinity/common/inf-acl.h>

Description

The basic ACL data structure is InfAclSheet, which represents settings for one user and one node in the infinote directory. One setting can have three states: it can be enabled, it can be disabled or it can be set to default which means to take the setting from the the default account or the parent directory. The default user for the root node must not have any setting set to default.

The various settings are represented by the InfAclSetting enumeration. This specifies different operations for which access can be granted or denied to different users. InfAclMask represents a bitfield of all A InfAclSheetSet represents a set of InfAclSheets, for different users. There is one InfAclSheetSet for each node of a infinote directory.

Usually, for application programming, the functions in this class need not be used. All relevant functionality is exposed by the InfBrowser interface.

Functions

inf_acl_account_id_from_string ()

InfAclAccountId
inf_acl_account_id_from_string (const gchar *id);

Converts the given string into a unique account identifier which can be used with the rest of the ACL API.

Parameters

id

A string representation of an account ID.

 

Returns

The account ID which is equivalent to the given string.

[transfer full]


inf_acl_account_id_to_string ()

const gchar *
inf_acl_account_id_to_string (InfAclAccountId account);

Translates the given account ID to a unique string identifier.

Parameters

account

A InfAclAccountId.

 

Returns

A string representation of the given account ID, or NULL if the account does not exist. The return value must not be freed.


INF_ACL_ACCOUNT_ID_TO_POINTER()

#define             INF_ACL_ACCOUNT_ID_TO_POINTER(id)

Converts a InfAclAccountId to a pointer such that the pointer represents a unique representation of the given ID. The pointer should not be used for anything else except comparisons with other pointer obtained in this way, for example in hash table lookups.

Parameters

id

A InfAclAccountId.

 

INF_ACL_ACCOUNT_POINTER_TO_ID()

#define             INF_ACL_ACCOUNT_POINTER_TO_ID(ptr)

Converts a pointer obtained with INF_ACL_ACCOUNT_ID_TO_POINTER back into the original InfAclAccountId value.

Parameters

ptr

A pointer obtained with INF_ACL_ACCOUNT_ID_TO_POINTER.

 

inf_acl_account_new ()

InfAclAccount *
inf_acl_account_new (InfAclAccountId id,
                     const gchar *name);

Creates a new InfAclAccount.

Parameters

id

The unique ID of the new account.

 

name

The human-readable name of the new account.

[allow-none]

Returns

A new InfAclAccount object.

[transfer full]


inf_acl_account_copy ()

InfAclAccount *
inf_acl_account_copy (const InfAclAccount *account);

Creates a copy of account .

Parameters

account

The InfAclAccount to copy.

 

Returns

A new InfAclAccount. Free with inf_acl_account_free() when no longer needed.

[transfer full]


inf_acl_account_free ()

void
inf_acl_account_free (InfAclAccount *account);

Releases all resources allocated by account .

Parameters

account

A InfAclAccount.

 

inf_acl_account_array_free ()

void
inf_acl_account_array_free (InfAclAccount *accounts,
                            guint n_accounts);

Releases all resources allocated by an array of InfAclAccounts.

Parameters

accounts

An array of InfAclAccount objects.

[array length=n_accounts]

n_accounts

The number of elements in the array.

 

inf_acl_account_from_xml ()

InfAclAccount *
inf_acl_account_from_xml (xmlNodePtr xml,
                          GError **error);

Attempts to deserialize an InfAclAccount that was written to an XML node by the function inf_acl_account_to_xml(). If an error occurs, such as mandatory fields being missing, the function returns NULL and error is set.

Parameters

xml

An XML node.

 

error

Location to store error information, if any.

 

Returns

A new InfAclAccount on success, or NULL on failure. Free with inf_acl_account_free() when no longer needed.

[transfer full]


inf_acl_account_to_xml ()

void
inf_acl_account_to_xml (const InfAclAccount *account,
                        xmlNodePtr xml);

Serializes the properties of account into the XML node xml . The function inf_acl_account_from_xml() does the reverse operation and deserializes the account object from the XML.

Parameters

account

A InfAclAccount.

 

xml

The XML node to write the account attributes to.

 

inf_acl_mask_copy ()

InfAclMask *
inf_acl_mask_copy (const InfAclMask *mask);

Creates a dynamically allocated copy of mask . This function should not usually be used since masks can simply created on the stack and copied by value. This function is mainly meant for the boxed type definition and for language bindings.

Parameters

mask

The InfAclMask to copy.

 

Returns

A new InfAclMask. Free with inf_acl_mask_free() when no longer needed.

[transfer full]


inf_acl_mask_free ()

void
inf_acl_mask_free (InfAclMask *mask);

Releases a InfAclMask that was created with inf_acl_mask_copy().

Parameters

mask

The InfAclMask to free.

 

inf_acl_mask_clear ()

void
inf_acl_mask_clear (InfAclMask *mask);

Resets a mask so that all fields are zero.

Parameters

mask

The InfAclMask to reset.

 

inf_acl_mask_empty ()

gboolean
inf_acl_mask_empty (const InfAclMask *mask);

Checks whether the given mask is empty, i.e. all fields are set to zero.

Parameters

mask

A InfAclMask.

 

Returns

TRUE if mask has all fields zero, or FALSE otherwies.


inf_acl_mask_equal ()

gboolean
inf_acl_mask_equal (const InfAclMask *lhs,
                    const InfAclMask *rhs);

Checks whether the two masks are equal.

Parameters

lhs

The first mask.

 

rhs

The second mask.

 

Returns

TRUE if lhs and rhs are equal or FALSE otherwise.


inf_acl_mask_set1 ()

InfAclMask *
inf_acl_mask_set1 (InfAclMask *mask,
                   const InfAclSetting setting);

Initializes mask such that all permissions are off except the one corresponding to setting .

Parameters

mask

The InfAclMask to initialize.

 

setting

The permission to set.

 

Returns

The mask itself.

[transfer none]


inf_acl_mask_setv ()

InfAclMask *
inf_acl_mask_setv (InfAclMask *mask,
                   const InfAclSetting *settings,
                   guint n_settings);

Initializes mask such that all permissions are off except the ones specified in the settings array.

Parameters

mask

The InfAclMask to initialize.

 

settings

An array of InfAclSettings to set.

[array length=n_settings]

n_settings

The number of settings.

 

Returns

The mask itself.

[transfer none]


inf_acl_mask_and ()

InfAclMask *
inf_acl_mask_and (const InfAclMask *lhs,
                  const InfAclMask *rhs,
                  InfAclMask *out);

Computes the bitwise AND of lhs and rhs and writes the result to out . out is allowed to be equivalent to lhs and/or rhs .

Parameters

lhs

First mask.

 

rhs

Second mask.

 

out

Output mask.

[out]

Returns

The output mask.

[transfer none]


inf_acl_mask_and1 ()

InfAclMask *
inf_acl_mask_and1 (InfAclMask *mask,
                   InfAclSetting setting);

Disables the bit corresponding to setting in mask , leaving all other bits alone.

Parameters

mask

A InfAclMask.

 

setting

The setting to unset.

 

Returns

The mask itself.

[transfer none]


inf_acl_mask_or ()

InfAclMask *
inf_acl_mask_or (const InfAclMask *lhs,
                 const InfAclMask *rhs,
                 InfAclMask *out);

Computes the bitwise OR of lhs and rhs and writes the result to out . out is allowed to be equivalent to lhs and/or rhs .

Parameters

lhs

First mask.

 

rhs

Second mask.

 

out

Output mask.

[out]

Returns

The output mask.

[transfer none]


inf_acl_mask_or1 ()

InfAclMask *
inf_acl_mask_or1 (InfAclMask *mask,
                  InfAclSetting setting);

Enables the bit corresponding to setting in mask , leaving all other bits alone.

Parameters

mask

A InfAclMask.

 

setting

The setting to add.

 

Returns

The mask itself.

[transfer none]


inf_acl_mask_neg ()

InfAclMask *
inf_acl_mask_neg (const InfAclMask *mask,
                  InfAclMask *out);

Negates the given mask bitwise and writes the result to out . The output mask is allowed to be equivalent to mask itself.

Parameters

mask

The mask to negate.

 

out

The output mask.

[out]

Returns

The output mask.

[transfer full]


inf_acl_mask_has ()

gboolean
inf_acl_mask_has (const InfAclMask *mask,
                  InfAclSetting setting);

Returns TRUE if the given mask has the bit which corresponds to setting set, or FALSE otherwise.

Parameters

mask

A InfAclMask.

 

setting

The setting to check.

 

Returns

TRUE if the bit corresponding to setting is set in mask .


inf_acl_sheet_new ()

InfAclSheet *
inf_acl_sheet_new (InfAclAccountId account);

Creates a dynamically allocated InfAclSheet. This is usually not needed because you can copy the structs by value, but it is useful for properties and bindings. The new sheet will hold permissions for the given account. The permissions will initially be all masked out.

Parameters

account

The InfAclAccountId representing a unique account id.

 

Returns

A new InfAclSheet. Free with inf_acl_sheet_free() when no longer in use.

[transfer full]


inf_acl_sheet_copy ()

InfAclSheet *
inf_acl_sheet_copy (const InfAclSheet *sheet);

Makes a dynamically allocated copy of sheet . This should not be used by applications because you can copy the structs by value, but it is useful for properties and bindings.

Parameters

sheet

A InfAclSheet.

 

Returns

A newly-allocated copy of sheet . Free with inf_acl_sheet_free() when no longer in use.

[transfer full]


inf_acl_sheet_free ()

void
inf_acl_sheet_free (InfAclSheet *sheet);

Frees a InfAclSheet allocated by inf_acl_sheet_copy().

Parameters

sheet

A InfAclSheet.

 

inf_acl_sheet_perms_from_xml ()

gboolean
inf_acl_sheet_perms_from_xml (xmlNodePtr xml,
                              InfAclMask *mask,
                              InfAclMask *perms,
                              GError **error);

This function extracts the permission mask and the permission flags from the XML node xml . The counterpart to this function is inf_acl_sheet_perms_to_xml(). If an error occurs the function returns FALSE and error is set.

Parameters

xml

The XML node to read from.

 

mask

Output parameter to write the permission mask to.

[out]

perms

Output parameter to write the permissions to.

[out]

error

Location to store error information, if any.

 

Returns

TRUE if the operation was successful, or FALSE on error.


inf_acl_sheet_perms_to_xml ()

void
inf_acl_sheet_perms_to_xml (const InfAclMask *mask,
                            const InfAclMask *perms,
                            xmlNodePtr xml);

This function writes the given permission mask and permission flags to the XML node xml . They can be converted back using the inf_acl_sheet_perms_from_xml() function.

Parameters

mask

Permission mask to write.

 

perms

Individiual permissions to write.

 

xml

error: Location to store error information, if any.

 

inf_acl_sheet_set_new ()

InfAclSheetSet *
inf_acl_sheet_set_new (void);

Creates a new InfAclSheetSet. Add sheets with inf_acl_sheet_set_add_sheet().

Returns

A new InfAclSheetSet. Free with inf_acl_sheet_set_free().

[transfer full]


inf_acl_sheet_set_new_external ()

InfAclSheetSet *
inf_acl_sheet_set_new_external (const InfAclSheet *sheets,
                                guint n_sheets);

Creates a new InfAclSheetSet refererencing the given ACL sheets. The created sheet set is only holding a reference to the given array, so it must stay alive as long as the sheet set is alive.

No new sheets can be added to the returned sheet set with inf_acl_sheet_set_add_sheet(), or removed with inf_acl_sheet_set_remove_sheet().

Parameters

sheets

An array of InfAclSheets.

[array length=n_sheets]

n_sheets

Number of elements in sheets .

 

Returns

A new InfAclSheetSet. Free with inf_acl_sheet_set_free() when no longer needed.

[transfer full]


inf_acl_sheet_set_copy ()

InfAclSheetSet *
inf_acl_sheet_set_copy (const InfAclSheetSet *sheet_set);

Creates a copy of sheet_set . If sheet_set was created with inf_acl_sheet_set_new_external(), the copied sheet set will also only hold a reference to the external sheets, and the same restrictions apply.

Parameters

sheet_set

A InfAclSheetSet.

 

Returns

A new InfAclSheetSet. Free with inf_acl_sheet_set_free() when no longer needed.

[transfer full]


inf_acl_sheet_set_free ()

void
inf_acl_sheet_set_free (InfAclSheetSet *sheet_set);

Releases all resources allocated for sheet_set .

Parameters

sheet_set

A InfAclSheetSet.

 

inf_acl_sheet_set_sink ()

void
inf_acl_sheet_set_sink (InfAclSheetSet *sheet_set);

If a sheet set was created with inf_acl_sheet_set_new_external(), this function lifts the restrictions that come with it by making an internal copy of the ACL sheets.

Parameters

sheet_set

A InfAclSheetSet.

 

inf_acl_sheet_set_add_sheet ()

InfAclSheet *
inf_acl_sheet_set_add_sheet (InfAclSheetSet *sheet_set,
                             InfAclAccountId account);

Adds a new default sheet for account to sheet_set . The function returns a pointer to the new sheet. The pointer stays valid as long as no other sheet is added to the set. If there is already a sheet for account in the set, then the existing sheet is returned instead.

This function can only be used if the sheet set has not been created with the inf_acl_sheet_set_new_external() function.

Parameters

sheet_set

A InfAclSheetSet.

 

account

The InfAclAccountId representing a unique account ID.

 

Returns

A InfAclSheet for the new account.

[transfer none]


inf_acl_sheet_set_remove_sheet ()

void
inf_acl_sheet_set_remove_sheet (InfAclSheetSet *sheet_set,
                                InfAclSheet *sheet);

Removes a sheet from sheet_set . sheet must be one of the sheets inside sheet_set . The sheet is removed by replacing it with the last sheet in the set, so the order of sheets is not preserved.

This function can only be used if the sheet set has not been created with the inf_acl_sheet_set_new_external() function.

Parameters

sheet_set

A InfAclSheetSet.

 

sheet

The sheet to remove.

 

inf_acl_sheet_set_merge_sheets ()

InfAclSheetSet *
inf_acl_sheet_set_merge_sheets (InfAclSheetSet *sheet_set,
                                const InfAclSheetSet *other);

Replaces all sheets that are present in other in sheet_set with the ones from other . Note that an empty sheet in other (with all permissions masked out) causes the corresponding sheet in sheet_set to be removed.

If sheet_set is NULL it is treated like an empty sheet set, i.e. the merged sheet set is a copy of other . In that case a new sheet set is created and returned, unless other is empty. If the merged sheet set ends up empty, it is freed and the function returns NULL.

Parameters

sheet_set

A InfAclSheetSet, or NULL.

[allow-none][transfer full]

other

The sheet set to merge.

 

Returns

The merged sheet set, or NULL when the merged sheet set would be empty.

[allow-none][transfer full]


inf_acl_sheet_set_get_clear_sheets ()

InfAclSheetSet *
inf_acl_sheet_set_get_clear_sheets (const InfAclSheetSet *sheet_set);

Returns a new sheet set with all sheets that are present in sheet_set , but with all permissions masked. When this set is merged with the original set, all permissions will be reset to default for all accounts. Before the merge, the returned sheet set can be modified. This allows to replace the current permissions with new ones atomically.

Parameters

sheet_set

A InfAclSheetSet.

 

Returns

A new InfAclSheetSet. Free with inf_acl_sheet_set_free() when no longer needed.

[transfer full]


inf_acl_sheet_set_find_sheet ()

InfAclSheet *
inf_acl_sheet_set_find_sheet (InfAclSheetSet *sheet_set,
                              InfAclAccountId account);

Returns the InfAclSheet for account . If there is no such sheet in sheet_set , the function returns NULL.

This function can only be used if the sheet set has not been created with the inf_acl_sheet_set_new_external() function.

Parameters

sheet_set

A InfAclSheetSet.

 

account

The InfAclAccountId representing the unique account ID of the account whose ACL sheet is to be found.

 

Returns

A InfAclSheet for account , or NULL.

[transfer none]


inf_acl_sheet_set_find_const_sheet ()

const InfAclSheet *
inf_acl_sheet_set_find_const_sheet (const InfAclSheetSet *sheet_set,
                                    InfAclAccountId account);

Returns the InfAclSheet for account . If there is no such sheet in sheet_set , the function returns NULL.

The difference between this function and inf_acl_sheet_set_find_sheet() is that this function returns a sheet that cannot be modified, but it can also be used on a sheet set created with the inf_acl_sheet_set_new_external() function.

Parameters

sheet_set

A InfAclSheetSet.

 

account

The InfAclAccountId representing the unique account ID of the account whose ACL sheet is to be found.

 

Returns

A InfAclSheet for account , or NULL.

[transfer none]


inf_acl_sheet_set_from_xml ()

InfAclSheetSet *
inf_acl_sheet_set_from_xml (xmlNodePtr xml,
                            GError **error);

Reads a sheet set from xml that has been written with inf_acl_sheet_set_to_xml(). If an error occurs the function returns NULL and error is set. If there is no ACL stored in xml , the function returns NULL without setting error .

Parameters

xml

The XML node from which to read the sheet set.

 

error

Location to read error information, if any.

 

Returns

A InfAclSheetSet, or NULL. Free with inf_acl_sheet_set_free() when no longer needed.

[transfer full]


inf_acl_sheet_set_to_xml ()

void
inf_acl_sheet_set_to_xml (const InfAclSheetSet *sheet_set,
                          xmlNodePtr xml);

Serializes the sheet set given by sheet_set into an XML node. The sheet set can be deserialized again with inf_acl_sheet_set_from_xml().

Parameters

sheet_set

The InfAclSheetSet to serialize.

 

xml

The XML node to serialize sheet_set into.

 

Types and Values

InfAclAccountId

typedef GQuark InfAclAccountId;

This type represents a unique identifier for a user account.


struct InfAclAccount

struct InfAclAccount {
  InfAclAccountId id;
  gchar* name;
};

This boxed type specifies basic user account information.

Members

InfAclAccountId id;

A unique ID for this account.

 

gchar *name;

A human readable account name.

 

enum InfAclSetting

Defines the actual permissions that can be granted or revoked for different users.

Members

INF_ACL_CAN_ADD_SUBDIRECTORY

The user is allowed to create a new subdirectory node.

 

INF_ACL_CAN_ADD_DOCUMENT

The user is allowed to create a new leaf node.

 

INF_ACL_CAN_SYNC_IN

The user is allowed to create documents with non-empty content.

 

INF_ACL_CAN_REMOVE_NODE

The user is allowed to remove a child node.

 

INF_ACL_CAN_EXPLORE_NODE

The user is allowed to explore a subdirectory node in the directory tree.

 

INF_ACL_CAN_SUBSCRIBE_CHAT

The user can subscribe to the global server-wide chat.

 

INF_ACL_CAN_SUBSCRIBE_SESSION

The user is allowed to subscribe to a session in the directory tree.

 

INF_ACL_CAN_JOIN_USER

The user is allowed to join a user into the session which corresponds to the node.

 

INF_ACL_CAN_QUERY_ACCOUNT_LIST

The user is allowed to query the full list of ACL accounts.

 

INF_ACL_CAN_CREATE_ACCOUNT

The user can create a new account on the server.

 

INF_ACL_CAN_OVERRIDE_ACCOUNT

The user can create an account under a name that exists already, overriding the login credentials.

 

INF_ACL_CAN_REMOVE_ACCOUNT

The user can remove user accounts.

 

INF_ACL_CAN_QUERY_ACL

The user is allowed to query the full ACL for this node.

 

INF_ACL_CAN_SET_ACL

The user is allowed to change the ACL of this node, or create new nodes with a non-default ACL.

 

struct InfAclMask

struct InfAclMask {
  /* leave quite some space for future use */
  guint64 mask[4];
};

This structure represents a mask of InfAclSettings, where each setting can be either turned on or off.

Members

guint64 mask[4];

A 256 bit wide bitfield of InfAclSettings.

 

struct InfAclSheet

struct InfAclSheet {
  InfAclAccountId account;
  InfAclMask mask;
  InfAclMask perms;
};

A set of permissions to be applied for a particular account and a particular node in the infinote directory.

Members

InfAclAccountId account;

The account for which to apply the permissions in this sheet.

 

InfAclMask mask;

Mask which specifies which of the permissions in the perms field take effect. Fields which are masked-out are left at their default value and inherited from the parent node.

 

InfAclMask perms;

Mask which specifies whether or not the user is allowed to perform the various operations defined by InfAclSetting.

 

struct InfAclSheetSet

struct InfAclSheetSet {
  const InfAclSheet* sheets;
  guint n_sheets;
};

A set of InfAclSheets, one for each user.

Members

const InfAclSheet *sheets;

An array of InfAclSheet objects.

 

guint n_sheets;

The number of elements in the sheets array.

 

INF_ACL_MASK_ALL

extern const InfAclMask INF_ACL_MASK_ALL;


INF_ACL_MASK_DEFAULT

extern const InfAclMask INF_ACL_MASK_DEFAULT;


INF_ACL_MASK_LEAF

extern const InfAclMask INF_ACL_MASK_LEAF; /* only applicable for leaf node */


INF_ACL_MASK_ROOT

extern const InfAclMask INF_ACL_MASK_ROOT; /* only applicable for root node */


INF_ACL_MASK_SUBDIRECTORY

extern const InfAclMask INF_ACL_MASK_SUBDIRECTORY; /* only applicable for subdirectory node */

See Also

InfBrowser

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfNameResolver.html0000644000000000000000000000013213055210752025702 xustar0030 mtime=1488261610.912090646 30 atime=1488261610.912090646 30 ctime=1488261610.912090646 libinfinity-0.7.1/docs/reference/libinfinity/html/InfNameResolver.html0000644000175000017500000012022313055210752026434 0ustar00arminarmin00000000000000 InfNameResolver: libinfinity-0.7 Reference Manual

InfNameResolver

InfNameResolver — Asynchronous DNS name lookup with support for SRV records

Stability Level

Unstable, unless otherwise indicated

Properties

gchar * hostname Read / Write / Construct
InfIo * io Read / Write / Construct
gchar * service Read / Write / Construct
gchar * srv Read / Write / Construct

Signals

Types and Values

Object Hierarchy

    GObject
    ╰── InfNameResolver

Includes

#include <libinfinity/common/inf-name-resolver.h>

Description

InfNameResolver provides a portable interface to look up DNS entries. When a resorver object has been created, the name lookup can be started with inf_name_resolver_start(), and once it finishes, the “resolved†signal is emitted. The inf_name_resolver_get_address() and inf_name_resolver_get_port() functions can then be used to obtain the result.

There can at most be one hostname lookup at a time. If you need more than one concurrent hostname lookup, use multiple InfNameResolver objects.

Functions

inf_name_resolver_new ()

InfNameResolver *
inf_name_resolver_new (InfIo *io,
                       const gchar *hostname,
                       const gchar *service,
                       const gchar *srv);

Creates a new InfNameResolver. Use inf_name_resolver_start() to start resolving the hostname.

If service is not NULL, it should be a decimal port number or a well-known service name that is translated into a port number, such as "http&quot. If srv is not NULL, the function will first attempt a SRV lookup, and fall back to a regular A/AAAA lookup in case no SRV record exists. Otherwise the SRV result is taken. If service is provided, it always overwrites the port number obtained from the hostname lookup.

The recommended procedure is to call this function with service equal to the port number entered by the user, or NULL if the user did not provide an explicit port number. If the resulting port number obtained with inf_name_resolver_get_port() is then different from 0, then use that port number, otherwise the default port number for the service.

[constructor]

Parameters

io

A InfIo object used to schedule events in the main thread.

 

hostname

The hostname to look up.

 

service

The name of the service to look up, or NULL.

[allow-none]

srv

The SRV record to look up, or NULL.

[allow-none]

Returns

A new InfNameResolver. Free with g_object_unref().

[transfer full]


inf_name_resolver_get_hostname ()

const gchar *
inf_name_resolver_get_hostname (InfNameResolver *resolver);

Returns the currently configured hostname that resolver will look up.

Parameters

resolver

A InfNameResolver.

 

Returns

The currently configured hostname.

[allow-none]


inf_name_resolver_get_service ()

const gchar *
inf_name_resolver_get_service (InfNameResolver *resolver);

Returns the currently configured service that resolver will look up.

Parameters

resolver

A InfNameResolver.

 

Returns

The currently configured service.

[allow-none]


inf_name_resolver_get_srv ()

const gchar *
inf_name_resolver_get_srv (InfNameResolver *resolver);

Returns the currently configured SRV record that resolver will look up.

Parameters

resolver

A InfNameResolver.

 

Returns

The currently configured SRV record.

[allow-none]


inf_name_resolver_start ()

gboolean
inf_name_resolver_start (InfNameResolver *resolver,
                         GError **error);

Starts the name resolution for the hostname configured with resolver .

When the hostname lookup has finished, the “resolved†signal is emitted. The function can only be called again once this signal has been emitted. When this function is called, the previously looked up result can no longer be obtained with the inf_name_resolver_get_address() and inf_name_resolver_get_port() functions.

Parameters

resolver

A InfNameResolver.

 

error

Location to store error information, if any.

 

Returns

TRUE on success or FALSE if a (synchronous) error occurred.


inf_name_resolver_lookup_backup ()

gboolean
inf_name_resolver_lookup_backup (InfNameResolver *resolver,
                                 GError **error);

Tries to look up backup addresses for the configured hostname. This should be used if connecting to none of the initially reported addresses works. The function returns FALSE if there are no backup addresses available, or TRUE otherwise. If it returns TRUE, it the “resolved†signal will be emitted again, and when it is, more addresses might be available from the resolver object.

Parameters

resolver

A InfNameResolver.

 

error

Location to store error information, if any, or NULL.

 

Returns

TRUE if looking up backup addresses is attempted, or FALSE otherwise.


inf_name_resolver_finished ()

gboolean
inf_name_resolver_finished (InfNameResolver *resolver);

Returns whether the resolver is currently looking up a hostname, or whether it is ready to start a new lookup with inf_name_resolver_start().

Parameters

resolver

A InfNameResolver.

 

Returns

Whether a call to inf_name_resolver_start() can be made.


inf_name_resolver_get_n_addresses ()

guint
inf_name_resolver_get_n_addresses (InfNameResolver *resolver);

Returns the number of resolved addresses that belongs to the hostname that was looked up.

Parameters

resolver

A InfNameResolver.

 

Returns

The number of addresses available.


inf_name_resolver_get_address ()

const InfIpAddress *
inf_name_resolver_get_address (InfNameResolver *resolver,
                               guint index);

Returns the index th address looked up in the last hostname resolution operation.

Parameters

resolver

A InfNameResolver.

 

index

The index for which to return the address, in case multiple IP addresses correspond to the same hostname.

 

Returns

The looked up InfIpAddress.

[transfer none]


inf_name_resolver_get_port ()

guint
inf_name_resolver_get_port (InfNameResolver *resolver,
                            guint index);

Returns the index th port looked up in the last hostname resolution operation. This can be 0 if the service parameter in inf_name_resolver_start() has been set to NULL and no SRV record has been found.

Parameters

resolver

A InfNameResolver.

 

index

The index for which to return the port, in case multiple IP addresses correspond to the same hostname.

 

Returns

The looked up InfIpAddress.

Types and Values

struct InfNameResolver

struct InfNameResolver;

InfNameResolver is an opaque data type. You should only access it via the public API functions.


struct InfNameResolverClass

struct InfNameResolverClass {
  /* Signals */
  void (*resolved)(InfNameResolver* connection,
                   const GError* error);
};

This structure contains the default signal handlers of InfNameResolver.

Members

resolved ()

Default signal handler for the “resolved†signal.

 

Property Details

The “hostname†property

  “hostname†                gchar *

The hostname to be looked up.

Flags: Read / Write / Construct

Default value: NULL


The “io†property

  “io†                      InfIo *

I/O handler.

Flags: Read / Write / Construct


The “service†property

  “service†                 gchar *

The expected service at the remote endpoint.

Flags: Read / Write / Construct

Default value: NULL


The “srv†property

  “srv†                     gchar *

The SRV record to look up for the given hostname, e.g. _jabber._tcp.

Flags: Read / Write / Construct

Default value: NULL

Signal Details

The “resolved†signal

void
user_function (InfNameResolver *resolver,
               GError          *error,
               gpointer         user_data)

This signal is emitted when the hostname has been resolved. The function inf_name_resolver_get_address() and inf_name_resolver_get_port() can be called to obtain the resolved addresses.

Parameters

resolver

The InfNameResolver that has resolved a hostname.

 

error

A description of the error that occurred, or NULL.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfdProgressRequest.html0000644000000000000000000000013213055210752026621 xustar0030 mtime=1488261610.912090646 30 atime=1488261610.912090646 30 ctime=1488261610.912090646 libinfinity-0.7.1/docs/reference/libinfinity/html/InfdProgressRequest.html0000644000175000017500000003005213055210752027353 0ustar00arminarmin00000000000000 InfdProgressRequest: libinfinity-0.7 Reference Manual

InfdProgressRequest

InfdProgressRequest — Watch progress of node exploration

Stability Level

Unstable, unless otherwise indicated

Properties

guint current Read
guint total Read

Types and Values

Object Hierarchy

    GObject
    ╰── InfdRequest
        ╰── InfdProgressRequest

Implemented Interfaces

InfdProgressRequest implements InfRequest.

Includes

#include <libinfinity/server/infd-progress-request.h>

Description

This class represents a request which consists of multiple steps and for which progress on the overall operation is reported.

Functions

infd_progress_request_initiated ()

void
infd_progress_request_initiated (InfdProgressRequest *request,
                                 guint total);

Initiates the request. A progress request is considered initiated as soon as the total number of operations is known.

Parameters

request

A InfdProgressRequest.

 

total

The total number of operations.

 

infd_progress_request_progress ()

void
infd_progress_request_progress (InfdProgressRequest *request);

Indicates that one more operation has been finished and changes the “current†property accordingly.

Parameters

request

A InfdProgressRequest.

 

Types and Values

struct InfdProgressRequest

struct InfdProgressRequest;

InfdProgressRequest is an opaque data type. You should only access it via the public API functions.


struct InfdProgressRequestClass

struct InfdProgressRequestClass {
};

This structure does not contain any public fields.

Property Details

The “current†property

  “current†                 guint

The current number of finished operations.

Flags: Read

Default value: 0


The “total†property

  “total†                   guint

The total number of operations.

Flags: Read

Default value: 0

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/right.png0000644000000000000000000000013213055210752023600 xustar0030 mtime=1488261610.832090825 30 atime=1488261610.832090825 30 ctime=1488261610.832090825 libinfinity-0.7.1/docs/reference/libinfinity/html/right.png0000644000175000017500000000040513055210752024331 0ustar00arminarmin00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEà 4ÓkM’IDAT8ËÕÒ¯aÇñ?›M´½IdErš,¾Ù-¸ÑhîAâIl’Í ¯r’äy§ž}¿ç·s¿X6èæ ö!9¢Ÿ#èD‚ Œr$-¬BrÃ$GÒÀ"$”¹;™á‰æŸÍú—WZêä&–!¸cš·±øŠq \`ðÃÔ軀Oä¾ò=QouføòIEND®B`‚libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfAdoptedSplitOperation.html0000644000000000000000000000013213055210752027555 xustar0030 mtime=1488261610.912090646 30 atime=1488261610.912090646 30 ctime=1488261610.912090646 libinfinity-0.7.1/docs/reference/libinfinity/html/InfAdoptedSplitOperation.html0000644000175000017500000004733513055210752030323 0ustar00arminarmin00000000000000 InfAdoptedSplitOperation: libinfinity-0.7 Reference Manual

InfAdoptedSplitOperation

InfAdoptedSplitOperation — Operation wrapping two operations

Stability Level

Unstable, unless otherwise indicated

Properties

InfAdoptedOperation * first Read / Write / Construct Only
InfAdoptedOperation * second Read / Write / Construct Only

Object Hierarchy

    GObject
    ╰── InfAdoptedSplitOperation

Implemented Interfaces

InfAdoptedSplitOperation implements InfAdoptedOperation.

Includes

#include <libinfinity/adopted/inf-adopted-split-operation.h>

Description

InfAdoptedSplitOperation is a wrapper around that two InfAdoptedOperations. This is normally not required directly but may be a result of some transformation. It can also be used to atomically perform multiple operations at once.

If A denotes the first operation of the split operation and B denotes the second operation, the split operation applies first A and then B to the document. Note that a split operation is not commutative, i.e. the order of the two operations is important and cannot be interchanged at will. When the second operation, B, is applied, it is assumed that the operation A was already applied before.

The reverse of the split operation (A, B) is (R(B), R(A)) where R indicates the reverse operation. When the split operation is transformed against an operation T, the result is (T A, (A T) B). When another operation T is transformed against the split operation, the result is B (A T). The functions inf_adopted_operation_revert(), inf_adopted_operation_transform() and inf_adopted_split_operation_transform_other() perform these three operations, respectively.

Functions

inf_adopted_split_operation_new ()

InfAdoptedSplitOperation *
inf_adopted_split_operation_new (InfAdoptedOperation *first,
                                 InfAdoptedOperation *second);

Creates a new InfAdoptedSplitOperation. A split operation is simply a wrapper around two operations (which may in turn be split operations).

[constructor]

Parameters

first

one of the InfAdoptedOperations to be wrapped

 

second

the other InfAdoptedOperation to be wrapped

 

Returns

A new InfAdoptedSplitOperation.

[transfer full]


inf_adopted_split_operation_unsplit ()

GSList *
inf_adopted_split_operation_unsplit (InfAdoptedSplitOperation *operation);

Returns a list of the operations contained by the split operation. If the splitted operation are in turn split operations, they will also be unsplitted. The returned list is guarenteed to not contain a InfAdoptedSplitOperation.

Parameters

operation

A InfAdoptedSplitOperation.

 

Returns

A list of operations. Free with g_slist_free() when done.

[transfer container][element-type InfAdoptedOperation]


inf_adopted_split_operation_transform_other ()

InfAdoptedOperation *
inf_adopted_split_operation_transform_other
                               (InfAdoptedSplitOperation *op,
                                InfAdoptedOperation *other,
                                InfAdoptedOperation *op_lcs,
                                InfAdoptedOperation *other_lcs,
                                gint concurrency_id);

Transforms other against op .

Parameters

op

A InfAdoptedSplitOperation.

 

other

An arbitrary InfAdoptedOperation.

 

op_lcs

The operation op at a previous state, or NULL.

 

other_lcs

The operation other at a previous state, or NULL.

 

concurrency_id

The concurrency id for the transformation of other against op .

 

Returns

The transformed operation.

[transfer full]

Types and Values

struct InfAdoptedSplitOperation

struct InfAdoptedSplitOperation;

InfAdoptedSplitOperation is an opaque data type. You should only access it via the public API functions.


struct InfAdoptedSplitOperationClass

struct InfAdoptedSplitOperationClass {
};

This structure does not contain any public fields.

Property Details

The “first†property

  “first†                   InfAdoptedOperation *

The first operation of the split operation.

Flags: Read / Write / Construct Only


The “second†property

  “second†                  InfAdoptedOperation *

The second operation of the split operation.

Flags: Read / Write / Construct Only

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfSession.html0000644000000000000000000000013213055210752024723 xustar0030 mtime=1488261610.916090637 30 atime=1488261610.916090637 30 ctime=1488261610.916090637 libinfinity-0.7.1/docs/reference/libinfinity/html/InfSession.html0000644000175000017500000032056413055210752025467 0ustar00arminarmin00000000000000 InfSession: libinfinity-0.7 Reference Manual

InfSession

InfSession — Basic session object and synchronization

Stability Level

Unstable, unless otherwise indicated

Properties

InfBuffer * buffer Read / Write / Construct Only
InfCommunicationManager * communication-manager Read / Write / Construct Only
InfSessionStatus status Read / Write / Construct Only
InfCommunicationGroup * subscription-group Read / Write
InfXmlConnection * sync-connection Read / Write / Construct Only
InfCommunicationGroup * sync-group Read / Write / Construct Only
InfUserTable * user-table Read / Write / Construct Only

Object Hierarchy

    GEnum
    ╰── InfSessionStatus
    GObject
    ╰── InfSession
        ├── InfAdoptedSession
        ╰── InfChatSession

Implemented Interfaces

InfSession implements InfCommunicationObject.

Includes

#include <libinfinity/common/inf-session.h>

Description

InfSession represents an editing session. The actual type of document that is edited is not specified, so instantiating InfSession does not make any sense. You rather want to use a derived class such as InfTextSession. Normally, the InfcBrowser or InfdDirectory, respectively, already take care of instantiating the correct InfSession.

A session basically consists of the document being edited (also called buffer, see InfBuffer) and the users that are working on the document, see InfUserTable.

A session can either start in INF_SESSION_RUNNING state, in which it is created with the initial buffer and user table. It may also start in INF_SESSION_SYNCHRONIZING state. In this case, both buffer and user table are initially empty and are copied from another system over the network. When the copy is complete, the session enters INF_SESSION_RUNNING state.

To be notified about changes other users make to a session, you need to subscribe to the session (on client side), or wait for incoming subscriptions (on server side). This is normally done by inf_browser_subscribe(). The first action that is performed upon subscription is a synchronization as described above. When the synchronization is complete, the “synchronization-complete†signal is emitted.

After subscription, one can observe modifications other users make, but it is not possible to make own modifications. Before doing so, a InfUser needs to be joined. This is done by client/server specific API from InfSessionProxy, in particular inf_session_proxy_join_user(). The required parameters still depend on the actual note type, which is why most note implementations offer their own API to join a user.

Functions

inf_session_lookup_user_property ()

const GParameter *
inf_session_lookup_user_property (const GParameter *params,
                                  guint n_params,
                                  const gchar *name);

Looks up the parameter with the given name in array .

Parameters

params

A pointer to an array of containing GParameter values.

[array length=n_params]

n_params

The number of elements in the aforementioned array

 

name

Name to look up.

 

Returns

A GParameter, or NULL.


inf_session_get_user_property ()

GParameter *
inf_session_get_user_property (GArray *array,
                               const gchar *name);

Looks up the paremeter with the given name in array . If there is no such parameter, a new one will be created.

Parameters

array

A GArray containing GParameter values.

[element-type GParameter]

name

Name to look up.

 

Returns

A GParameter.

[transfer none]


inf_session_user_to_xml ()

void
inf_session_user_to_xml (InfSession *session,
                         InfUser *user,
                         xmlNodePtr xml);

This is a convenience function that queries user 's properties and calls set_xml_user_props with them. This adds the properties of user to xml .

An equivalent user object may be built by calling the get_xml_user_props vfunc on xml and then calling the user_new vfunc with the resulting properties.

Parameters

session

A InfSession.

 

user

A InfUser contained in session .

 

xml

An XML node to which to add user information.

 

inf_session_close ()

void
inf_session_close (InfSession *session);

Closes a running session. When a session is closed, it unrefs all connections and no longer handles requests.

Parameters

session

A InfSession.

 

inf_session_get_communication_manager ()

InfCommunicationManager *
inf_session_get_communication_manager (InfSession *session);

Returns the communication manager for session .

Parameters

session

A InfSession.

 

Returns

A InfCommunicationManager.

[transfer none]


inf_session_get_buffer ()

InfBuffer *
inf_session_get_buffer (InfSession *session);

Returns the buffer used by session .

Parameters

session

A InfSession.

 

Returns

A InfBuffer.

[transfer none]


inf_session_get_user_table ()

InfUserTable *
inf_session_get_user_table (InfSession *session);

Returns the user table used by session .

Parameters

session

A InfSession.

 

Returns

A InfUserTable.

[transfer none]


inf_session_get_status ()

InfSessionStatus
inf_session_get_status (InfSession *session);

Returns the session's status.

Parameters

session

A InfSession.

 

Returns

The status of session .


inf_session_add_user ()

InfUser *
inf_session_add_user (InfSession *session,
                      const GParameter *params,
                      guint n_params);

Adds a user to session . The user object is constructed via the user_new vfunc of InfSessionClass. This will create a new InfUser object by default, but may be overridden by subclasses to create different kinds of users.

Note that this function does not tell the other participants that the user was added. To avoid conflicts, normally only the publisher of the session can add users and notifies others accordingly. This is handled by InfdSessionProxy or InfcSessionProxy, respectively.

You should not call this function unless you know what you are doing. If params comes from an untrusted source, they should be checked first with the validate_user_props virtual function.

Parameters

session

A InfSession.

 

params

Construction parameters for the InfUser (or derived) object.

[array length=n_params]

n_params

Number of parameters.

 

Returns

The new InfUser.

[transfer none]


inf_session_set_user_status ()

void
inf_session_set_user_status (InfSession *session,
                             InfUser *user,
                             InfUserStatus status);

Changes the status of the given user which needs to have the INF_USER_LOCAL flag set for this function to be called. If the status is changed to INF_USER_UNAVAILABLE, then the user leaves the session. To rejoin use inf_session_proxy_join_user() for a proxy proxying session .

Parameters

session

A InfSession.

 

user

A local InfUser from session 's user table.

 

status

New status for user .

 

inf_session_synchronize_from ()

void
inf_session_synchronize_from (InfSession *session);

Switches session 's status to INF_SESSION_SYNCHRONIZING. In INF_SESSION_PRESYNC, all messages from incoming the synchronizing connection are ignored, and no cancellation request is sent to the remote site if the status changes to INF_SESSION_CLOSED. The rationale behind that status is that one can prepare a session for synchronization but start the actual synchronization later, after having made sure that the remote site is ready to perform the synchronization.

Parameters

session

A InfSession in status INF_SESSION_PRESYNC.

 

inf_session_synchronize_to ()

void
inf_session_synchronize_to (InfSession *session,
                            InfCommunicationGroup *group,
                            InfXmlConnection *connection);

Initiates a synchronization to connection . On the other end of connection , a new session with the sync-connection and sync-group construction properties set should have been created. group is used as a group in the communication manager. It is allowed for group to have another InfCommunicationObject than session , however, you should forward the InfCommunicationObject messages your object receives to session then. Also, connection must already be present in group , and should not be removed until synchronization finished.

A synchronization can only be initiated if session is in state INF_SESSION_RUNNING.

Parameters

session

A InfSession in status INF_SESSION_RUNNING.

 

group

A InfCommunicationGroup.

 

connection

A InfXmlConnection.

 

inf_session_cancel_synchronization ()

void
inf_session_cancel_synchronization (InfSession *session,
                                    InfXmlConnection *connection);

Cancells an ongaing synchronization to or from connection . If session is in state INF_SESSION_PRESYNC or INF_SESSION_SYNCHRONIZING, connection must match the connection that session is synchronizing with. If session is in state INF_SESSION_RUNNING, connection can be any connection that the session is currently being synchronized to.

In any case, the “synchronization-failed†signal will be emitted for the cancelled synchronization. If the session is in state INF_SESSION_PRESYNC or INF_SESSION_SYNCHRONIZING, the session will also be closed, with the “close†signal being emited.

Parameters

session

A InfSession.

 

connection

The InfXmlConnection with which to cancel synchronization.

 

inf_session_get_synchronization_status ()

InfSessionSyncStatus
inf_session_get_synchronization_status
                               (InfSession *session,
                                InfXmlConnection *connection);

If session is in status INF_SESSION_SYNCHRONIZING, this always returns INF_SESSION_SYNC_IN_PROGRESS if connection is the connection with which the session is synchronized, and INF_SESSION_SYNC_NONE otherwise.

If session is in status INF_SESSION_RUNNING, this returns the status of the synchronization to connection . INF_SESSION_SYNC_NONE is returned, when there is currently no synchronization ongoing to connection , INF_SESSION_SYNC_IN_PROGRESS is returned, if there is one, and INF_SESSION_SYNC_AWAITING_ACK if the synchronization is finished but we are waiting for the acknowledgement from the remote site that all synchronization data has been progressed successfully. The synchronization can still fail in this state but it can no longer by cancelled.

If session is in status $INF_SESSION_CLOSED, this always returns INF_SESSION_SYNC_NONE.

Parameters

session

A InfSession.

 

connection

A InfXmlConnection.

 

Returns

The synchronization status of connection .


inf_session_get_synchronization_progress ()

gdouble
inf_session_get_synchronization_progress
                               (InfSession *session,
                                InfXmlConnection *connection);

This function requires that the synchronization status of connection is INF_SESSION_SYNC_IN_PROGRESS or INF_SESSION_SYNC_AWAITING_ACK (see inf_session_get_synchronization_status()). Then, it returns a value between 0.0 and 1.0 specifying how much synchronization data has already been transferred to the remote site.

Note that if the session is in status INF_SESSION_RUNNING, it is possible that this function returns 1.0 (i.e. all data has been transmitted) but the synchronization is not yet complete, because the remote site must still acknowledge the synchronization. The synchronization then is in status INF_SESSION_SYNC_AWAITING_ACK.

Parameters

session

A InfSession.

 

connection

A InfXmlConnection.

 

Returns

A value between 0.0 and 1.0.


inf_session_has_synchronizations ()

gboolean
inf_session_has_synchronizations (InfSession *session);

Returns whether there are currently ongoing synchronizations. If the session is in status INF_SESSION_SYNCHRONIZING, then this returns always TRUE, if it is in INF_SESSION_CLOSED, then it returns always FALSE. If the session is in status INF_SESSION_RUNNING, then it returns TRUE when the session is currently at least synchronized to one connection and FALSE otherwise.

Parameters

session

A InfSession.

 

Returns

Whether there are ongoing synchronizations.


inf_session_get_subscription_group ()

InfCommunicationGroup *
inf_session_get_subscription_group (InfSession *session);

Returns the subscription group for session , if any.

Parameters

session

A InfSession.

 

Returns

A InfCommunicationGroup, or NULL.

[transfer none]


inf_session_set_subscription_group ()

void
inf_session_set_subscription_group (InfSession *session,
                                    InfCommunicationGroup *group);

Sets the subscription group for session . The subscription group is the group in which all connections subscribed to the session are a member of.

InfSession itself does not deal with subscriptions, so it is your job to keep group up-to-date (for example if you add non-local users to session ). This is normally done by a so-called session proxy such as InfcSessionProxy or InfdSessionProxy, respectively.

Parameters

session

A InfSession.

 

group

A InfCommunicationGroup.

 

inf_session_send_to_subscriptions ()

void
inf_session_send_to_subscriptions (InfSession *session,
                                   xmlNodePtr xml);

Sends a XML message to the all members of session 's subscription group. This function can only be called if the subscription group is non-NULL. It takes ownership of xml .

Parameters

session

A InfSession.

 

xml

The message to send.

[transfer full]

Types and Values

enum InfSessionStatus

InfSessionStatus defines in what state a session is in.

Members

INF_SESSION_PRESYNC

The session is scheduled to be synchronized from a remote host. This can be useful if the session is needed to be present before the actual synchronization begins. Use inf_session_synchronize_from() to switch to INF_SESSION_SYNCHRONIZING.

 

INF_SESSION_SYNCHRONIZING

The session is currently being synchronized from a remote host. When done synchronizing, it will enter into INF_SESSION_RUNNING state.

 

INF_SESSION_RUNNING

The session is running and ready to synchronize other hosts. If a subscription group is set (see inf_session_set_subscription_group()), then changes to the underlying buffer are transmitted to all subscribed connections.

 

INF_SESSION_CLOSED

The session is closed and can no longer be used. The session enters this state if the synchronization fails in INF_SESSION_SYNCHRONIZING state or inf_session_close() is called.

 

enum InfSessionSyncStatus

InfSessionSyncStatus represents the status of a synchronization. It is used by inf_session_get_synchronization_status().

Members

INF_SESSION_SYNC_NONE

No synchronization is ongoing.

 

INF_SESSION_SYNC_IN_PROGRESS

Synchronization is currently in progress.

 

INF_SESSION_SYNC_AWAITING_ACK

All synchronization data has been sent (progress is 1.0), but we are still waiting for an acknowledgment from the remote site. Synchronization can no longer be cancelled, but it can stiff fail.

 

enum InfSessionSyncError

These are errors that can occur during a synchronization of a session. Additional errors may occur depending on the session type.

Members

INF_SESSION_SYNC_ERROR_GOT_MESSAGE_IN_PRESYNC

Received a message in state INF_SESSION_PRESYNC. It is not processed because inf_session_synchronize_from() was not yet called.

 

INF_SESSION_SYNC_ERROR_UNEXPECTED_NODE

A message has been received that was not understood.

 

INF_SESSION_SYNC_ERROR_ID_NOT_PRESENT

An ID was not provided for a user in the session.

 

INF_SESSION_SYNC_ERROR_ID_IN_USE

The ID of a user is already in use by another user.

 

INF_SESSION_SYNC_ERROR_NAME_NOT_PRESENT

A name was not provided for a user in the session.

 

INF_SESSION_SYNC_ERROR_NAME_IN_USE

The name of a user is already in use by another user.

 

INF_SESSION_SYNC_ERROR_CONNECTION_CLOSED

The synchronization connection has been closed.

 

INF_SESSION_SYNC_ERROR_SENDER_CANCELLED

The sender has cancelled the synchronization.

 

INF_SESSION_SYNC_ERROR_RECEIVER_CANCELLED

The receiver has cancelled the synchronization.

 

INF_SESSION_SYNC_ERROR_UNEXPECTED_BEGIN_OF_SYNC

Received <sync-begin/> not a the beginning of the synchronization.

 

INF_SESSION_SYNC_ERROR_NUM_MESSAGES_MISSING

The <sync-begin/> message does not contain the number of synchronization messages to expect.

 

INF_SESSION_SYNC_ERROR_UNEXPECTED_END_OF_SYNC

The <sync-end/> message was not received at the end of the synchronization.

 

INF_SESSION_SYNC_ERROR_EXPECTED_BEGIN_OF_SYNC

The <sync-begin/> message was not received at the beginning of the synchronization.

 

INF_SESSION_SYNC_ERROR_EXPECTED_END_OF_SYNC

The <sync-end/> message was not received at the end of the synchronization.

 

INF_SESSION_SYNC_ERROR_FAILED

Generic error code when no further reason of failure is known.

 

struct InfSession

struct InfSession;

InfSession is an opaque data type. You should only access it via the public API functions.


struct InfSessionClass

struct InfSessionClass {
  /* Virtual table */
  void(*to_xml_sync)(InfSession* session,
                     xmlNodePtr parent);

  gboolean(*process_xml_sync)(InfSession* session,
                              InfXmlConnection* connection,
                              xmlNodePtr xml,
                              GError** error);

  InfCommunicationScope(*process_xml_run)(InfSession* session,
                                          InfXmlConnection* connection,
                                          xmlNodePtr xml,
                                          GError** error);

  GArray*(*get_xml_user_props)(InfSession* session,
                               InfXmlConnection* conn,
                               xmlNodePtr xml);

  void (*set_xml_user_props)(InfSession* session,
                             const GParameter* params,
                             guint n_params,
                             xmlNodePtr xml);

  gboolean(*validate_user_props)(InfSession* session,
                                 const GParameter* params,
                                 guint n_params,
                                 InfUser* exclude,
                                 GError** error);

  InfUser*(*user_new)(InfSession* session,
                      GParameter* params,
                      guint n_params);

  /* Signals */
  void(*close)(InfSession* session);
  void(*error)(InfSession* session,
               InfXmlConnection* connection,
               xmlNodePtr xml,
               const GError* error);

  void(*synchronization_begin)(InfSession* session,
                               InfCommunicationGroup* group,
                               InfXmlConnection* connection);

  void(*synchronization_progress)(InfSession* session,
                                  InfXmlConnection* connection,
                                  gdouble percentage);

  void(*synchronization_complete)(InfSession* session,
                                  InfXmlConnection* connection);

  void(*synchronization_failed)(InfSession* session,
                                InfXmlConnection* connection,
                                const GError* error);
};

This structure contains the virtual functions and default signal handlers of InfSession.

Members

to_xml_sync ()

Virtual function that saves the session within a XML document. parent is the root node of the document. It should create as much nodes as possible within that root node and not in sub-nodes because these are sent to a client and it is not allowed that other traffic is put in between those nodes. This way, communication through the same connection does not hang just because a large session is synchronized.

 

process_xml_sync ()

Virtual function that is called for every node in the XML document created by to_xml_sync . It is supposed to reconstruct the session content from the XML data.

 

process_xml_run ()

Virtual function that is called for every received message while the session is running. Return INF_COMMUNICATION_SCOPE_GROUP if the message is designated for all group members (see also inf_communication_object_received() on this topic).

 

get_xml_user_props ()

Virtual function that creates a list of GParameters for use with g_object_newv() from a XML node.

 

set_xml_user_props ()

Virtual function that writes the passed user properties into a XML node.

 

validate_user_props ()

Virtual function that checks whether the given user properties are valid for a user join. This prevents a user join if there is already a user with the same name. If exclude is not NULL, then the function does ignore it when validating.

 

user_new ()

Virtual function that creates a new user object with the given properties.

 

close ()

Default signal handler for the “close†signal. This cancels currently running synchronization in InfSession.

 

error ()

Default signal handler for the “error†signal.

 

synchronization_begin ()

Default signal handler for the “synchronization-begin†signal. The default handler queues the synchronization messages.

 

synchronization_progress ()

Default signal handler for the “synchronization-progress†signal.

 

synchronization_complete ()

Default signal handler for the “synchronization-complete†signal. If the session itself got synchronized (and did not synchronize another session), then the default handler changes status to INF_SESSION_RUNNING.

 

synchronization_failed ()

Default signal handler for the “synchronization-failed†signal. If the session itself got synchronized (and did not synchronize another session), then the default handler changes status to INF_SESSION_CLOSED.

 

Property Details

The “buffer†property

  “buffer†                  InfBuffer *

The buffer in which the document content is stored.

Flags: Read / Write / Construct Only


The “communication-manager†property

  “communication-manager†   InfCommunicationManager *

The communication manager used for sending requests.

Flags: Read / Write / Construct Only


The “status†property

  “status†                  InfSessionStatus

Current status of the session.

Flags: Read / Write / Construct Only

Default value: INF_SESSION_RUNNING


The “subscription-group†property

  “subscription-group†      InfCommunicationGroup *

Communication group of subscribed connections.

Flags: Read / Write


The “sync-connection†property

  “sync-connection†         InfXmlConnection *

Connection which synchronizes the initial session state.

Flags: Read / Write / Construct Only


The “sync-group†property

  “sync-group†              InfCommunicationGroup *

Communication group in which to perform synchronization.

Flags: Read / Write / Construct Only


The “user-table†property

  “user-table†              InfUserTable *

User table containing the users of the session.

Flags: Read / Write / Construct Only

Signal Details

The “close†signal

void
user_function (InfSession *session,
               gpointer    user_data)

This signal is emitted if the session is closed. Note that this signal is not called as a client if the connection to the sessions has merely been lost, only the relevant InfXmlConnection has its “status†property changed.

Parameters

session

The InfSession that is being closed

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last


The “error†signal

void
user_function (InfSession       *session,
               InfXmlConnection *connection,
               gpointer          xml,
               GError           *error,
               gpointer          user_data)

This signal is emitted when the session detects an error. The session itself does not know much about the nature of the error. It might mean the session is in an inconsistent state, or it might be recoverable. This signal can be used to handle the error or to write error information into a log file or bring to a user's attention in another manner.

Parameters

session

The InfSession having an error.

 

connection

The InfXmlConnection which sent the erroneous request.

 

xml

The XML request that produced the error.

 

error

A GError providing information about the error.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last


The “synchronization-begin†signal

void
user_function (InfSession            *session,
               InfCommunicationGroup *group,
               InfXmlConnection      *connection,
               gpointer               user_data)

This signal is emitted whenever the session is started to be synchronized to another connection. Note that, in contrast to “synchronization-progressâ€, “synchronization-failed†and “synchronization-complete†it cannot happen that the signal is emitted when session is being synchronized itself, because that can happen at construction time only when no one had a chance to connect signal handlers anyway.

Parameters

session

The InfSession that is synchronizing.

 

group

The InfCommunicationGroup used for synchronization.

 

connection

The InfXmlConnection to which the session is synchronized.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last


The “synchronization-complete†signal

void
user_function (InfSession       *session,
               InfXmlConnection *connection,
               gpointer          user_data)

This signal is emitted when synchronization has completed, in addition to “synchronization-progress†with a progress value of 1.0.

If a callback is connected before the default handler, it can find out whether the remote side is synchronizing the local side by comparing sessions 's status with INF_SESSION_SYNCHRONIZING. The default signal handler sets the status to INF_SESSION_RUNNING, so checking afterwards is not too useful.

Parameters

session

The InfSession that has or was synchronized

 

connection

The InfXmlConnection through which synchronization happened

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last


The “synchronization-failed†signal

void
user_function (InfSession       *session,
               InfXmlConnection *connection,
               GError           *error,
               gpointer          user_data)

This signal is emitted when synchronization has failed before its completion due to malformed data from the other side or network failure.

If this happens during initial synchronization, “close†is emitted as well at this point.

Parameters

session

The InfSession that failed to synchronize or be synchronized

 

connection

The InfXmlConnection through which synchronization happened

 

error

A pointer to a GError object with details on the error

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last


The “synchronization-progress†signal

void
user_function (InfSession       *session,
               InfXmlConnection *connection,
               gdouble           progress,
               gpointer          user_data)

This signal is emitted whenever a new XML node has been sent or received over connection as part of a synchronization. The process is completed when progress reaches the value 1.0. At this point, “synchronization-complete†is also emitted.

If session 's status is INF_SESSION_SYNCHRONIZING, the local side is being synchronized by the remote side. If the status is INF_SESSION_RUNNING, the local side is updating the remote side.

Parameters

session

The InfSession that is synchronizing or being synchronized

 

connection

The InfXmlConnection through which progress is made

 

progress

A gdouble value ranging from 0.0 to 1.0.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/style.css0000644000000000000000000000013213055210752023627 xustar0030 mtime=1488261610.832090825 30 atime=1488261610.832090825 30 ctime=1488261610.832090825 libinfinity-0.7.1/docs/reference/libinfinity/html/style.css0000644000175000017500000002115413055210752024364 0ustar00arminarmin00000000000000body { font-family: cantarell, sans-serif; } .synopsis, .classsynopsis { /* tango:aluminium 1/2 */ background: #eeeeec; background: rgba(238, 238, 236, 0.5); border: solid 1px rgb(238, 238, 236); padding: 0.5em; } .programlisting { /* tango:sky blue 0/1 */ /* fallback for no rgba support */ background: #e6f3ff; border: solid 1px #729fcf; background: rgba(114, 159, 207, 0.1); border: solid 1px rgba(114, 159, 207, 0.2); padding: 0.5em; } .variablelist { padding: 4px; margin-left: 3em; } .variablelist td:first-child { vertical-align: top; } div.gallery-float { float: left; padding: 10px; } div.gallery-float img { border-style: none; } div.gallery-spacer { clear: both; } a, a:visited { text-decoration: none; /* tango:sky blue 2 */ color: #3465a4; } a:hover { text-decoration: underline; /* tango:sky blue 1 */ color: #729fcf; } div.informaltable table { border-collapse: separate; border-spacing: 1em 0.3em; border: none; } div.informaltable table td, div.informaltable table th { vertical-align: top; } .function_type, .variable_type, .property_type, .signal_type, .parameter_name, .struct_member_name, .union_member_name, .define_keyword, .datatype_keyword, .typedef_keyword { text-align: right; } /* dim non-primary columns */ .c_punctuation, .function_type, .variable_type, .property_type, .signal_type, .define_keyword, .datatype_keyword, .typedef_keyword, .property_flags, .signal_flags, .parameter_annotations, .enum_member_annotations, .struct_member_annotations, .union_member_annotations { color: #888a85; } .function_type a, .function_type a:visited, .function_type a:hover, .property_type a, .property_type a:visited, .property_type a:hover, .signal_type a, .signal_type a:visited, .signal_type a:hover, .signal_flags a, .signal_flags a:visited, .signal_flags a:hover { color: #729fcf; } td p { margin: 0.25em; } div.table table { border-collapse: collapse; border-spacing: 0px; /* tango:aluminium 3 */ border: solid 1px #babdb6; } div.table table td, div.table table th { /* tango:aluminium 3 */ border: solid 1px #babdb6; padding: 3px; vertical-align: top; } div.table table th { /* tango:aluminium 2 */ background-color: #d3d7cf; } h4 { color: #555753; margin-top: 1em; margin-bottom: 1em; } hr { /* tango:aluminium 1 */ color: #d3d7cf; background: #d3d7cf; border: none 0px; height: 1px; clear: both; margin: 2.0em 0em 2.0em 0em; } dl.toc dt { padding-bottom: 0.25em; } dl.toc > dt { padding-top: 0.25em; padding-bottom: 0.25em; font-weight: bold; } dl.toc > dl { padding-bottom: 0.5em; } .parameter { font-style: normal; } .footer { padding-top: 3.5em; /* tango:aluminium 3 */ color: #babdb6; text-align: center; font-size: 80%; } .informalfigure, .figure { margin: 1em; } .informalexample, .example { margin-top: 1em; margin-bottom: 1em; } .warning { /* tango:orange 0/1 */ background: #ffeed9; background: rgba(252, 175, 62, 0.1); border-color: #ffb04f; border-color: rgba(252, 175, 62, 0.2); } .note { /* tango:chameleon 0/0.5 */ background: #d8ffb2; background: rgba(138, 226, 52, 0.1); border-color: #abf562; border-color: rgba(138, 226, 52, 0.2); } div.blockquote { border-color: #eeeeec; } .note, .warning, div.blockquote { padding: 0.5em; border-width: 1px; border-style: solid; margin: 2em; } .note p, .warning p { margin: 0; } div.warning h3.title, div.note h3.title { display: none; } p + div.section { margin-top: 1em; } div.refnamediv, div.refsynopsisdiv, div.refsect1, div.refsect2, div.toc, div.section { margin-bottom: 1em; } /* blob links */ h2 .extralinks, h3 .extralinks { float: right; /* tango:aluminium 3 */ color: #babdb6; font-size: 80%; font-weight: normal; } .lineart { color: #d3d7cf; font-weight: normal; } .annotation { /* tango:aluminium 5 */ color: #555753; font-weight: normal; } .structfield { font-style: normal; font-weight: normal; } acronym,abbr { border-bottom: 1px dotted gray; } /* code listings */ .listing_code .programlisting .normal, .listing_code .programlisting .normal a, .listing_code .programlisting .number, .listing_code .programlisting .cbracket, .listing_code .programlisting .symbol { color: #555753; } .listing_code .programlisting .comment, .listing_code .programlisting .linenum { color: #babdb6; } /* tango: aluminium 3 */ .listing_code .programlisting .function, .listing_code .programlisting .function a, .listing_code .programlisting .preproc { color: #204a87; } /* tango: sky blue 3 */ .listing_code .programlisting .string { color: #ad7fa8; } /* tango: plum */ .listing_code .programlisting .keyword, .listing_code .programlisting .usertype, .listing_code .programlisting .type, .listing_code .programlisting .type a { color: #4e9a06; } /* tango: chameleon 3 */ .listing_frame { /* tango:sky blue 1 */ border: solid 1px #729fcf; border: solid 1px rgba(114, 159, 207, 0.2); padding: 0px; } .listing_lines, .listing_code { margin-top: 0px; margin-bottom: 0px; padding: 0.5em; } .listing_lines { /* tango:sky blue 0.5 */ background: #a6c5e3; background: rgba(114, 159, 207, 0.2); /* tango:aluminium 6 */ color: #2e3436; } .listing_code { /* tango:sky blue 0 */ background: #e6f3ff; background: rgba(114, 159, 207, 0.1); } .listing_code .programlisting { /* override from previous */ border: none 0px; padding: 0px; background: none; } .listing_lines pre, .listing_code pre { margin: 0px; } @media screen { /* these have a as a first child, but since there are no parent selectors * we can't use that. */ a.footnote { position: relative; top: 0em ! important; } /* this is needed so that the local anchors are displayed below the naviagtion */ div.footnote a[name], div.refnamediv a[name], div.refsect1 a[name], div.refsect2 a[name], div.index a[name], div.glossary a[name], div.sect1 a[name] { display: inline-block; position: relative; top:-5em; } /* this seems to be a bug in the xsl style sheets when generating indexes */ div.index div.index { top: 0em; } /* make space for the fixed navigation bar and add space at the bottom so that * link targets appear somewhat close to top */ body { padding-top: 2.5em; padding-bottom: 500px; max-width: 60em; } p { max-width: 60em; } /* style and size the navigation bar */ table.navigation#top { position: fixed; background: #e2e2e2; border-bottom: solid 1px #babdb6; border-spacing: 5px; margin-top: 0; margin-bottom: 0; top: 0; left: 0; z-index: 10; } table.navigation#top td { padding-left: 6px; padding-right: 6px; } .navigation a, .navigation a:visited { /* tango:sky blue 3 */ color: #204a87; } .navigation a:hover { /* tango:sky blue 2 */ color: #3465a4; } td.shortcuts { /* tango:sky blue 2 */ color: #3465a4; font-size: 80%; white-space: nowrap; } td.shortcuts .dim { color: #babdb6; } .navigation .title { font-size: 80%; max-width: none; margin: 0px; font-weight: normal; } } @media screen and (min-width: 60em) { /* screen larger than 60em */ body { margin: auto; } } @media screen and (max-width: 60em) { /* screen less than 60em */ #nav_hierarchy { display: none; } #nav_interfaces { display: none; } #nav_prerequisites { display: none; } #nav_derived_interfaces { display: none; } #nav_implementations { display: none; } #nav_child_properties { display: none; } #nav_style_properties { display: none; } #nav_index { display: none; } #nav_glossary { display: none; } .gallery_image { display: none; } .property_flags { display: none; } .signal_flags { display: none; } .parameter_annotations { display: none; } .enum_member_annotations { display: none; } .struct_member_annotations { display: none; } .union_member_annotations { display: none; } /* now that a column is hidden, optimize space */ col.parameters_name { width: auto; } col.parameters_description { width: auto; } col.struct_members_name { width: auto; } col.struct_members_description { width: auto; } col.enum_members_name { width: auto; } col.enum_members_description { width: auto; } col.union_members_name { width: auto; } col.union_members_description { width: auto; } .listing_lines { display: none; } } @media print { table.navigation { visibility: collapse; display: none; } div.titlepage table.navigation { visibility: visible; display: table; background: #e2e2e2; border: solid 1px #babdb6; margin-top: 0; margin-bottom: 0; top: 0; left: 0; height: 3em; } } libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/left.png0000644000000000000000000000013213055210752023415 xustar0030 mtime=1488261610.832090825 30 atime=1488261610.832090825 30 ctime=1488261610.832090825 libinfinity-0.7.1/docs/reference/libinfinity/html/left.png0000644000175000017500000000040613055210752024147 0ustar00arminarmin00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEà 4ÓkM“IDAT8ËÕÒ¯Áa‡ñ?ÁDAPY‘\‚$‹º[p¢+ÐÜIÐIªMlfü('Úì}MpâÙyží{Îá_ª…ž¨¤ÂÞ¥Â}œ^£‘q xZ <Æ=àYjî) <0ù4\~Ó+Púöl#Ü"ÂÕÉ—,QÏ‘ôp ÉÍIÇlswÒÆ>÷•[/]_i0‘3ÃIEND®B`‚libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/libinfinity-0.7-InfNativeSocket.h0000644000000000000000000000013213055210752030002 xustar0030 mtime=1488261610.916090637 30 atime=1488261610.916090637 30 ctime=1488261610.916090637 libinfinity-0.7.1/docs/reference/libinfinity/html/libinfinity-0.7-InfNativeSocket.html0000644000175000017500000002702213055210752031254 0ustar00arminarmin00000000000000 InfNativeSocket: libinfinity-0.7 Reference Manual

InfNativeSocket

InfNativeSocket — Uniform access to the BSD socket API

Stability Level

Unstable, unless otherwise indicated

Includes

#include <libinfinity/common/inf-native-socket.h>

Description

This module provides a common way to access the BSD socket API. While the API is mostly equivalent on Linux and Windows, there are some subtle differences for which uniform identifiers are provided.

Before InfNativeSocket can be used, on Windows WinSock2 must be initialized. You can either do this manually, or call inf_init() which does it for you.

Functions

inf_native_socket_error_quark ()

GQuark
inf_native_socket_error_quark (void);

Returns a GQuark representing the INF_NATIVE_SOCKET_ERROR domain.

Returns

A GQuark representing the INF_NATIVE_SOCKET_ERROR domain.


inf_native_socket_make_error ()

void
inf_native_socket_make_error (int code,
                              GError **error);

Converts the platform-dependent error code code into a GError. The GError will contain the same numerical value and a platform-dependent human-readable error message.

Parameters

code

An error code obtained with INF_NATIVE_SOCKET_LAST_ERROR

 

error

Location to store error information.

 

closesocket()

# define closesocket(s) close(s)

Types and Values

InfNativeSocket

typedef SOCKET InfNativeSocket;

Native socket type on the target platform. This typedef is a simple int on Unix and a SOCKET on Windows.


INF_NATIVE_SOCKET_EAGAIN

# define INF_NATIVE_SOCKET_EAGAIN         WSAEWOULDBLOCK


INF_NATIVE_SOCKET_EINPROGRESS

# define INF_NATIVE_SOCKET_EINPROGRESS    WSAEWOULDBLOCK


INF_NATIVE_SOCKET_EINTR

# define INF_NATIVE_SOCKET_EINTR          WSAEINTR


INF_NATIVE_SOCKET_LAST_ERROR

# define INF_NATIVE_SOCKET_LAST_ERROR     WSAGetLastError()


INF_NATIVE_SOCKET_SENDRECV_FLAGS

# define INF_NATIVE_SOCKET_SENDRECV_FLAGS 0


INVALID_SOCKET

# define INVALID_SOCKET -1

libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/InfCommunicationFactory.html0000644000000000000000000000013213055210752027435 xustar0030 mtime=1488261610.916090637 30 atime=1488261610.916090637 30 ctime=1488261610.916090637 libinfinity-0.7.1/docs/reference/libinfinity/html/InfCommunicationFactory.html0000644000175000017500000004267013055210752030200 0ustar00arminarmin00000000000000 InfCommunicationFactory: libinfinity-0.7 Reference Manual

InfCommunicationFactory

InfCommunicationFactory — Creation of communication methods

Stability Level

Unstable, unless otherwise indicated

Object Hierarchy

    GInterface
    ╰── InfCommunicationFactory

Prerequisites

InfCommunicationFactory requires GObject.

Known Implementations

InfCommunicationFactory is implemented by InfCommunicationCentralFactory.

Includes

#include <libinfinity/communication/inf-communication-factory.h>

Description

A InfCommunicationFactory is used by the communication manager to create InfCommunicationMethods. All a factory has to do is to tell whether it supports a specific network and method name combination, and create a corresponding InfCommunicationMethod if it does.

InfCommunicationFactorys are added to a communication manager via inf_communication_manager_add_factory(). The communication manager will automatically use the factory if it needs to create a method it supports.

Functions

inf_communication_factory_supports_method ()

gboolean
inf_communication_factory_supports_method
                               (InfCommunicationFactory *factory,
                                const gchar *network,
                                const gchar *method_name);

Returns whether factory supports creating methods that implement method_name as communication method for connections on network (see “networkâ€).

Parameters

factory

A InfCommunicationFactory.

 

network

A network specifier, such as "tcp/ip" or "jabber".

 

method_name

A method identifier, such as "central" or "groupchat".

 

Returns

Whether factory supports the given network and method name.


inf_communication_factory_instantiate ()

InfCommunicationMethod *
inf_communication_factory_instantiate (InfCommunicationFactory *factory,
                                       const gchar *network,
                                       const gchar *method_name,
                                       InfCommunicationRegistry *registry,
                                       InfCommunicationGroup *group);

Creates a new InfCommunicationMethod for network and method_name . The factory needs to support that method, see inf_communication_factory_supports_method().

Parameters

factory

A InfCommunicationFactory.

 

network

A network specifier, such as "tcp/ip" or "jabber".

 

method_name

A method identifier, such as "central" or "groupchat".

 

registry

A InfCommunicationRegistry at which the created method can register connections.

 

group

The InfCommunicationGroup for which to create the method.

 

Returns

A new InfCommunicationMethod.

[transfer full]

Types and Values

InfCommunicationFactory

typedef struct _InfCommunicationFactory InfCommunicationFactory;

InfCommunicationFactory is an opaque data type. You should only access it via the public API functions.


struct InfCommunicationFactoryInterface

struct InfCommunicationFactoryInterface {
  gboolean (*supports_method)(InfCommunicationFactory* factory,
                              const gchar* network,
                              const gchar* method_name);

  InfCommunicationMethod* (*instantiate)(InfCommunicationFactory* factory,
                                         const gchar* network,
                                         const gchar* method_name,
                                         InfCommunicationRegistry* registry,
                                         InfCommunicationGroup* group);
};

The virtual methods of InfCommunicationFactory. These handle instantiating a InfCommunicationMethod for a InfCommunicationGroup.

Members

supports_method ()

Returns whether the given method_name is supported for the network in question by the factory.

 

instantiate ()

Instantiates a communication method for the given method name, handling communication for the passed group.

 
libinfinity-0.7.1/docs/reference/libinfinity/html/PaxHeaders.26529/libinfinity-0.7-InfProtocol.html0000644000000000000000000000013213055210752027721 xustar0030 mtime=1488261610.916090637 30 atime=1488261610.916090637 30 ctime=1488261610.916090637 libinfinity-0.7.1/docs/reference/libinfinity/html/libinfinity-0.7-InfProtocol.html0000644000175000017500000002302313055210752030453 0ustar00arminarmin00000000000000 InfProtocol: libinfinity-0.7 Reference Manual

InfProtocol

InfProtocol — Infinote protocol parameters

Stability Level

Unstable, unless otherwise indicated

Includes

#include <libinfinity/common/inf-protocol.h>

Description

This section defines common protocol parameters used by libinfinity.

Functions

inf_protocol_get_version ()

const gchar *
inf_protocol_get_version (void);

Returns the version of the Infinote protocol implemented by this version of libinfinity.

Returns

The supported infinote version.


inf_protocol_parse_version ()

gboolean
inf_protocol_parse_version (const gchar *version,
                            guint *major,
                            guint *minor,
                            GError **error);

Splits the given version string into it's major and minor version number. If the string is badly formatted then the function returns FALSE, error is set and major and minor are left untouched.

It is guaranteed that, if version is inf_protocol_get_version(), the function does not fail.

Parameters

version

A version string, such as "1.0"

 

major

A location to store the major version number to.

 

minor

A location to store the minor version number to

 

error

Location to store error information, if any.

 

Returns

TRUE on success, or FALSE on error.


inf_protocol_get_default_port ()

guint
inf_protocol_get_default_port (void);

Returns the default port on which the infinote daemon listens for new connections.

Returns

The default port.

Types and Values

See Also

InfError
libinfinity-0.7.1/docs/reference/libinfinity/PaxHeaders.26529/Makefile.in0000644000000000000000000000012713051241007023053 xustar0029 mtime=1487225351.68914837 29 atime=1487225351.68914837 29 ctime=1488261590.87213497 libinfinity-0.7.1/docs/reference/libinfinity/Makefile.in0000644000175000017500000007022513051241007023607 0ustar00arminarmin00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 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@ # -*- mode: makefile -*- #################################### # Everything below here is generic # #################################### VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) 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@ subdir = docs/reference/libinfinity ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/gtk-doc.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/libinfinity/inf-config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/gtk-doc.make DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ 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@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIRNAME = @DATADIRNAME@ 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@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ GTKDOC_CHECK = @GTKDOC_CHECK@ GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ GTKDOC_MKPDF = @GTKDOC_MKPDF@ GTKDOC_REBASE = @GTKDOC_REBASE@ HTML_DIR = @HTML_DIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INSTOBJEXT = @INSTOBJEXT@ INTLLIBS = @INTLLIBS@ INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBINFINITY_API_VERSION = @LIBINFINITY_API_VERSION@ LIBINFINITY_LIBTOOL_VERSION = @LIBINFINITY_LIBTOOL_VERSION@ LIBINFINITY_VERSION = @LIBINFINITY_VERSION@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGFMT_OPTS = @MSGFMT_OPTS@ 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@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ 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@ avahi_CFLAGS = @avahi_CFLAGS@ avahi_LIBS = @avahi_LIBS@ 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@ gio_CFLAGS = @gio_CFLAGS@ gio_LIBS = @gio_LIBS@ gtk_requirement = @gtk_requirement@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infgtk_CFLAGS = @infgtk_CFLAGS@ infgtk_LIBS = @infgtk_LIBS@ infinity_CFLAGS = @infinity_CFLAGS@ infinity_LIBS = @infinity_LIBS@ infinoted_CFLAGS = @infinoted_CFLAGS@ infinoted_LIBS = @infinoted_LIBS@ infodir = @infodir@ inftext_CFLAGS = @inftext_CFLAGS@ inftext_LIBS = @inftext_LIBS@ inftextgtk_CFLAGS = @inftextgtk_CFLAGS@ inftextgtk_LIBS = @inftextgtk_LIBS@ install_sh = @install_sh@ libdaemon_CFLAGS = @libdaemon_CFLAGS@ libdaemon_LIBS = @libdaemon_LIBS@ 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@ runstatedir = @runstatedir@ 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@ # We require automake 1.6 at least. AUTOMAKE_OPTIONS = 1.6 # This is a blank Makefile.am for using gtk-doc. # Copy this to your project's API docs directory and modify the variables to # suit your project. See the GTK+ Makefiles in gtk+/docs/reference for examples # of using the various options. # The name of the module, e.g. 'glib'. DOC_MODULE = libinfinity-$(LIBINFINITY_API_VERSION) # The top-level SGML file. You can change this if you want to. DOC_MAIN_SGML_FILE = $(DOC_MODULE)-docs.sgml # The directory containing the source code. Relative to $(srcdir). # gtk-doc will search all .c & .h files beneath here for inline comments # documenting the functions and macros. # e.g. DOC_SOURCE_DIR=../../../gtk DOC_SOURCE_DIR = $(top_srcdir)/libinfinity # Extra options to pass to gtkdoc-scangobj. Not normally needed. SCANGOBJ_OPTIONS = @LIBINFINITY_HAVE_AVAHI_FALSE@IGNORE_HFILES = "inf-marshal.h inf-i18n.h inf-signals.h inf-config.h inf-communication-group-private.h inf-define-enum.h inf-discovery-avahi.h" # Header files to ignore when scanning. # e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h @LIBINFINITY_HAVE_AVAHI_TRUE@IGNORE_HFILES = "inf-marshal.h inf-i18n.h inf-signals.h inf-config.h inf-communication-group-private.h inf-define-enum.h" # Extra options to supply to gtkdoc-mkdb. # Extra options to supply to gtkdoc-scan. # e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED" SCAN_OPTIONS = --rebuild-types --ignore-headers=$(IGNORE_HFILES) # e.g. MKDB_OPTIONS=--sgml-mode --output-format=xml MKDB_OPTIONS = --sgml-mode --output-format=xml # Extra options to supply to gtkdoc-mktmpl # e.g. MKTMPL_OPTIONS=--only-section-tmpl MKTMPL_OPTIONS = # Extra options to supply to gtkdoc-fixref. Not normally needed. # e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html FIXXREF_OPTIONS = # Used for dependencies. The docs will be rebuilt if any of these change. # e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h # e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c HFILE_GLOB = \ $(top_srcdir)/libinfinity/communication/*.h \ $(top_srcdir)/libinfinity/common/*.h \ $(top_srcdir)/libinfinity/adopted/*.h \ $(top_srcdir)/libinfinity/client/*.h \ $(top_srcdir)/libinfinity/server/*.h CFILE_GLOB = \ $(top_srcdir)/libinfinity/communication/*.c \ $(top_srcdir)/libinfinity/common/*.c \ $(top_srcdir)/libinfinity/adopted/*.c \ $(top_srcdir)/libinfinity/client/*.c \ $(top_srcdir)/libinfinity/server/*.c # Images to copy into HTML directory. # e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png HTML_IMAGES = # Extra SGML files that are included by $(DOC_MAIN_SGML_FILE). # e.g. content_files=running.sgml building.sgml changes-2.0.sgml content_files = \ ../version.xml \ ../api_version.xml \ compiling.sgml # SGML files where gtk-doc abbrevations (#GtkWidget) are expanded # These files must be listed here *and* in content_files # e.g. expand_content_files=running.sgml expand_content_files = # CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library. # Only needed if you are using gtkdoc-scangobj to dynamically query widget # signals and properties. # e.g. INCLUDES=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS) # e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib) #INCLUDES=$(infinity_CFLAGS) AM_CPPFLAGS = $(infinity_CFLAGS) GTKDOC_LIBS = \ $(infinity_LIBS) \ $(top_builddir)/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la @GTK_DOC_USE_LIBTOOL_FALSE@GTKDOC_CC = $(CC) $(INCLUDES) $(GTKDOC_DEPS_CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) @GTK_DOC_USE_LIBTOOL_TRUE@GTKDOC_CC = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(INCLUDES) $(GTKDOC_DEPS_CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) @GTK_DOC_USE_LIBTOOL_FALSE@GTKDOC_LD = $(CC) $(GTKDOC_DEPS_LIBS) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) @GTK_DOC_USE_LIBTOOL_TRUE@GTKDOC_LD = $(LIBTOOL) --tag=CC --mode=link $(CC) $(GTKDOC_DEPS_LIBS) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) @GTK_DOC_USE_LIBTOOL_FALSE@GTKDOC_RUN = @GTK_DOC_USE_LIBTOOL_TRUE@GTKDOC_RUN = $(LIBTOOL) --mode=execute # We set GPATH here; this gives us semantics for GNU make # which are more like other make's VPATH, when it comes to # whether a source that is a target of one rule is then # searched for in VPATH/GPATH. # GPATH = $(srcdir) TARGET_DIR = $(HTML_DIR)/$(DOC_MODULE) SETUP_FILES = \ $(content_files) \ $(expand_content_files) \ $(DOC_MAIN_SGML_FILE) \ $(DOC_MODULE)-sections.txt \ $(DOC_MODULE)-overrides.txt # This includes the standard gtk-doc make rules, copied by gtkdocize. # Other files to distribute # e.g. EXTRA_DIST += version.xml.in EXTRA_DIST = $(HTML_IMAGES) $(SETUP_FILES) DOC_STAMPS = setup-build.stamp scan-build.stamp sgml-build.stamp \ html-build.stamp pdf-build.stamp \ sgml.stamp html.stamp pdf.stamp SCANOBJ_FILES = \ $(DOC_MODULE).args \ $(DOC_MODULE).hierarchy \ $(DOC_MODULE).interfaces \ $(DOC_MODULE).prerequisites \ $(DOC_MODULE).signals REPORT_FILES = \ $(DOC_MODULE)-undocumented.txt \ $(DOC_MODULE)-undeclared.txt \ $(DOC_MODULE)-unused.txt CLEANFILES = $(SCANOBJ_FILES) $(REPORT_FILES) $(DOC_STAMPS) gtkdoc-check.test @GTK_DOC_BUILD_HTML_FALSE@HTML_BUILD_STAMP = @GTK_DOC_BUILD_HTML_TRUE@HTML_BUILD_STAMP = html-build.stamp @GTK_DOC_BUILD_PDF_FALSE@PDF_BUILD_STAMP = @GTK_DOC_BUILD_PDF_TRUE@PDF_BUILD_STAMP = pdf-build.stamp #### setup #### GTK_DOC_V_SETUP = $(GTK_DOC_V_SETUP_$(V)) GTK_DOC_V_SETUP_ = $(GTK_DOC_V_SETUP_$(AM_DEFAULT_VERBOSITY)) GTK_DOC_V_SETUP_0 = @echo " DOC Preparing build"; #### scan #### GTK_DOC_V_SCAN = $(GTK_DOC_V_SCAN_$(V)) GTK_DOC_V_SCAN_ = $(GTK_DOC_V_SCAN_$(AM_DEFAULT_VERBOSITY)) GTK_DOC_V_SCAN_0 = @echo " DOC Scanning header files"; GTK_DOC_V_INTROSPECT = $(GTK_DOC_V_INTROSPECT_$(V)) GTK_DOC_V_INTROSPECT_ = $(GTK_DOC_V_INTROSPECT_$(AM_DEFAULT_VERBOSITY)) GTK_DOC_V_INTROSPECT_0 = @echo " DOC Introspecting gobjects"; #### xml #### GTK_DOC_V_XML = $(GTK_DOC_V_XML_$(V)) GTK_DOC_V_XML_ = $(GTK_DOC_V_XML_$(AM_DEFAULT_VERBOSITY)) GTK_DOC_V_XML_0 = @echo " DOC Building XML"; #### html #### GTK_DOC_V_HTML = $(GTK_DOC_V_HTML_$(V)) GTK_DOC_V_HTML_ = $(GTK_DOC_V_HTML_$(AM_DEFAULT_VERBOSITY)) GTK_DOC_V_HTML_0 = @echo " DOC Building HTML"; GTK_DOC_V_XREF = $(GTK_DOC_V_XREF_$(V)) GTK_DOC_V_XREF_ = $(GTK_DOC_V_XREF_$(AM_DEFAULT_VERBOSITY)) GTK_DOC_V_XREF_0 = @echo " DOC Fixing cross-references"; #### pdf #### GTK_DOC_V_PDF = $(GTK_DOC_V_PDF_$(V)) GTK_DOC_V_PDF_ = $(GTK_DOC_V_PDF_$(AM_DEFAULT_VERBOSITY)) GTK_DOC_V_PDF_0 = @echo " DOC Building PDF"; # Files not to distribute # for --rebuild-types in $(SCAN_OPTIONS), e.g. $(DOC_MODULE).types # for --rebuild-sections in $(SCAN_OPTIONS) e.g. $(DOC_MODULE)-sections.txt DISTCLEANFILES = libinfinity-$(LIBINFINITY_API_VERSION).types version.xml api_version.xml all: all-am .SUFFIXES: $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/gtk-doc.make $(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) --foreign docs/reference/libinfinity/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign docs/reference/libinfinity/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_srcdir)/gtk-doc.make $(am__empty): $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs tags TAGS: ctags CTAGS: cscope cscopelist: 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 $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-hook check-am: all-am check: check-am @ENABLE_GTK_DOC_FALSE@all-local: all-am: Makefile all-local installdirs: install: 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) -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic distclean-local dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-data-local install-dvi: install-dvi-am install-dvi-am: install-exec-am: 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 -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic \ maintainer-clean-local mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-local .MAKE: install-am install-strip .PHONY: all all-am all-local check check-am clean clean-generic \ clean-libtool clean-local cscopelist-am ctags-am dist-hook \ distclean distclean-generic distclean-libtool distclean-local \ distdir dvi dvi-am html html-am info info-am install \ install-am install-data install-data-am install-data-local \ 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-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ maintainer-clean-local mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \ uninstall-am uninstall-local .PRECIOUS: Makefile gtkdoc-check.test: Makefile $(AM_V_GEN)echo "#!/bin/sh -e" > $@; \ echo "$(GTKDOC_CHECK_PATH) || exit 1" >> $@; \ chmod +x $@ all-gtk-doc: $(HTML_BUILD_STAMP) $(PDF_BUILD_STAMP) .PHONY: all-gtk-doc @ENABLE_GTK_DOC_TRUE@all-local: all-gtk-doc docs: $(HTML_BUILD_STAMP) $(PDF_BUILD_STAMP) $(REPORT_FILES): sgml-build.stamp setup-build.stamp: -$(GTK_DOC_V_SETUP)if test "$(abs_srcdir)" != "$(abs_builddir)" ; then \ files=`echo $(SETUP_FILES) $(DOC_MODULE).types`; \ if test "x$$files" != "x" ; then \ for file in $$files ; do \ destdir=`dirname $(abs_builddir)/$$file`; \ test -d "$$destdir" || mkdir -p "$$destdir"; \ test -f $(abs_srcdir)/$$file && \ cp -pf $(abs_srcdir)/$$file $(abs_builddir)/$$file || true; \ done; \ fi; \ fi $(AM_V_at)touch setup-build.stamp scan-build.stamp: setup-build.stamp $(HFILE_GLOB) $(CFILE_GLOB) $(GTK_DOC_V_SCAN)_source_dir='' ; \ for i in $(DOC_SOURCE_DIR) ; do \ _source_dir="$${_source_dir} --source-dir=$$i" ; \ done ; \ gtkdoc-scan --module=$(DOC_MODULE) --ignore-headers="$(IGNORE_HFILES)" $${_source_dir} $(SCAN_OPTIONS) $(EXTRA_HFILES) $(GTK_DOC_V_INTROSPECT)if grep -l '^..*$$' $(DOC_MODULE).types > /dev/null 2>&1 ; then \ scanobj_options=""; \ gtkdoc-scangobj 2>&1 --help | grep >/dev/null "\-\-verbose"; \ if test "$$?" = "0"; then \ if test "x$(V)" = "x1"; then \ scanobj_options="--verbose"; \ fi; \ fi; \ CC="$(GTKDOC_CC)" LD="$(GTKDOC_LD)" RUN="$(GTKDOC_RUN)" CFLAGS="$(GTKDOC_CFLAGS) $(CFLAGS)" LDFLAGS="$(GTKDOC_LIBS) $(LDFLAGS)" \ gtkdoc-scangobj $(SCANGOBJ_OPTIONS) $$scanobj_options --module=$(DOC_MODULE); \ else \ for i in $(SCANOBJ_FILES) ; do \ test -f $$i || touch $$i ; \ done \ fi $(AM_V_at)touch scan-build.stamp $(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(DOC_MODULE)-sections.txt $(DOC_MODULE)-overrides.txt: scan-build.stamp @true sgml-build.stamp: setup-build.stamp $(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(HFILE_GLOB) $(CFILE_GLOB) $(DOC_MODULE)-sections.txt $(DOC_MODULE)-overrides.txt $(expand_content_files) xml/gtkdocentities.ent $(GTK_DOC_V_XML)_source_dir='' ; \ for i in $(DOC_SOURCE_DIR) ; do \ _source_dir="$${_source_dir} --source-dir=$$i" ; \ done ; \ gtkdoc-mkdb --module=$(DOC_MODULE) --output-format=xml --expand-content-files="$(expand_content_files)" --main-sgml-file=$(DOC_MAIN_SGML_FILE) $${_source_dir} $(MKDB_OPTIONS) $(AM_V_at)touch sgml-build.stamp sgml.stamp: sgml-build.stamp @true xml/gtkdocentities.ent: Makefile $(GTK_DOC_V_XML)$(MKDIR_P) $(@D) && ( \ echo ""; \ echo ""; \ echo ""; \ echo ""; \ echo ""; \ echo ""; \ echo ""; \ ) > $@ html-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) $(expand_content_files) $(GTK_DOC_V_HTML)rm -rf html && mkdir html && \ mkhtml_options=""; \ gtkdoc-mkhtml 2>&1 --help | grep >/dev/null "\-\-verbose"; \ if test "$$?" = "0"; then \ if test "x$(V)" = "x1"; then \ mkhtml_options="$$mkhtml_options --verbose"; \ fi; \ fi; \ gtkdoc-mkhtml 2>&1 --help | grep >/dev/null "\-\-path"; \ if test "$$?" = "0"; then \ mkhtml_options="$$mkhtml_options --path=\"$(abs_srcdir)\""; \ fi; \ cd html && gtkdoc-mkhtml $$mkhtml_options $(MKHTML_OPTIONS) $(DOC_MODULE) ../$(DOC_MAIN_SGML_FILE) -@test "x$(HTML_IMAGES)" = "x" || \ for file in $(HTML_IMAGES) ; do \ if test -f $(abs_srcdir)/$$file ; then \ cp $(abs_srcdir)/$$file $(abs_builddir)/html; \ fi; \ if test -f $(abs_builddir)/$$file ; then \ cp $(abs_builddir)/$$file $(abs_builddir)/html; \ fi; \ done; $(GTK_DOC_V_XREF)gtkdoc-fixxref --module=$(DOC_MODULE) --module-dir=html --html-dir=$(HTML_DIR) $(FIXXREF_OPTIONS) $(AM_V_at)touch html-build.stamp pdf-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) $(expand_content_files) $(GTK_DOC_V_PDF)rm -f $(DOC_MODULE).pdf && \ mkpdf_options=""; \ gtkdoc-mkpdf 2>&1 --help | grep >/dev/null "\-\-verbose"; \ if test "$$?" = "0"; then \ if test "x$(V)" = "x1"; then \ mkpdf_options="$$mkpdf_options --verbose"; \ fi; \ fi; \ if test "x$(HTML_IMAGES)" != "x"; then \ for img in $(HTML_IMAGES); do \ part=`dirname $$img`; \ echo $$mkpdf_options | grep >/dev/null "\-\-imgdir=$$part "; \ if test $$? != 0; then \ mkpdf_options="$$mkpdf_options --imgdir=$$part"; \ fi; \ done; \ fi; \ gtkdoc-mkpdf --path="$(abs_srcdir)" $$mkpdf_options $(DOC_MODULE) $(DOC_MAIN_SGML_FILE) $(MKPDF_OPTIONS) $(AM_V_at)touch pdf-build.stamp ############## clean-local: @rm -f *~ *.bak @rm -rf .libs @if echo $(SCAN_OPTIONS) | grep -q "\-\-rebuild-types" ; then \ rm -f $(DOC_MODULE).types; \ fi @if echo $(SCAN_OPTIONS) | grep -q "\-\-rebuild-sections" ; then \ rm -f $(DOC_MODULE)-sections.txt; \ fi distclean-local: @rm -rf xml html $(REPORT_FILES) $(DOC_MODULE).pdf \ $(DOC_MODULE)-decl-list.txt $(DOC_MODULE)-decl.txt @if test "$(abs_srcdir)" != "$(abs_builddir)" ; then \ rm -f $(SETUP_FILES) $(DOC_MODULE).types; \ fi maintainer-clean-local: @rm -rf xml html install-data-local: @installfiles=`echo $(builddir)/html/*`; \ if test "$$installfiles" = '$(builddir)/html/*'; \ then echo 1>&2 'Nothing to install' ; \ else \ if test -n "$(DOC_MODULE_VERSION)"; then \ installdir="$(DESTDIR)$(TARGET_DIR)-$(DOC_MODULE_VERSION)"; \ else \ installdir="$(DESTDIR)$(TARGET_DIR)"; \ fi; \ $(mkinstalldirs) $${installdir} ; \ for i in $$installfiles; do \ echo ' $(INSTALL_DATA) '$$i ; \ $(INSTALL_DATA) $$i $${installdir}; \ done; \ if test -n "$(DOC_MODULE_VERSION)"; then \ mv -f $${installdir}/$(DOC_MODULE).devhelp2 \ $${installdir}/$(DOC_MODULE)-$(DOC_MODULE_VERSION).devhelp2; \ fi; \ $(GTKDOC_REBASE) --relative --dest-dir=$(DESTDIR) --html-dir=$${installdir}; \ fi uninstall-local: @if test -n "$(DOC_MODULE_VERSION)"; then \ installdir="$(DESTDIR)$(TARGET_DIR)-$(DOC_MODULE_VERSION)"; \ else \ installdir="$(DESTDIR)$(TARGET_DIR)"; \ fi; \ rm -rf $${installdir} # # Require gtk-doc when making dist # @HAVE_GTK_DOC_TRUE@dist-check-gtkdoc: docs @HAVE_GTK_DOC_FALSE@dist-check-gtkdoc: @HAVE_GTK_DOC_FALSE@ @echo "*** gtk-doc is needed to run 'make dist'. ***" @HAVE_GTK_DOC_FALSE@ @echo "*** gtk-doc was not found when 'configure' ran. ***" @HAVE_GTK_DOC_FALSE@ @echo "*** please install gtk-doc and rerun 'configure'. ***" @HAVE_GTK_DOC_FALSE@ @false dist-hook: dist-check-gtkdoc all-gtk-doc dist-hook-local @mkdir $(distdir)/html @cp ./html/* $(distdir)/html @-cp ./$(DOC_MODULE).pdf $(distdir)/ @-cp ./$(DOC_MODULE).types $(distdir)/ @-cp ./$(DOC_MODULE)-sections.txt $(distdir)/ @cd $(distdir) && rm -f $(DISTCLEANFILES) @$(GTKDOC_REBASE) --online --relative --html-dir=$(distdir)/html .PHONY : dist-hook-local docs # Comment this out if you want your docs-status tested during 'make check' #TESTS = $(GTKDOC_CHECK) # 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: libinfinity-0.7.1/docs/reference/libinfinity/PaxHeaders.26529/Makefile.am0000644000000000000000000000013213034342512023042 xustar0030 mtime=1483851082.013718339 30 atime=1483851082.013718339 30 ctime=1488261590.868134978 libinfinity-0.7.1/docs/reference/libinfinity/Makefile.am0000644000175000017500000000763513034342512023607 0ustar00arminarmin00000000000000## Process this file with automake to produce Makefile.in # We require automake 1.6 at least. AUTOMAKE_OPTIONS = 1.6 # This is a blank Makefile.am for using gtk-doc. # Copy this to your project's API docs directory and modify the variables to # suit your project. See the GTK+ Makefiles in gtk+/docs/reference for examples # of using the various options. # The name of the module, e.g. 'glib'. DOC_MODULE=libinfinity-$(LIBINFINITY_API_VERSION) # The top-level SGML file. You can change this if you want to. DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml # The directory containing the source code. Relative to $(srcdir). # gtk-doc will search all .c & .h files beneath here for inline comments # documenting the functions and macros. # e.g. DOC_SOURCE_DIR=../../../gtk DOC_SOURCE_DIR=$(top_srcdir)/libinfinity # Extra options to pass to gtkdoc-scangobj. Not normally needed. SCANGOBJ_OPTIONS= # Header files to ignore when scanning. # e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h if LIBINFINITY_HAVE_AVAHI IGNORE_HFILES="inf-marshal.h inf-i18n.h inf-signals.h inf-config.h inf-communication-group-private.h inf-define-enum.h" else IGNORE_HFILES="inf-marshal.h inf-i18n.h inf-signals.h inf-config.h inf-communication-group-private.h inf-define-enum.h inf-discovery-avahi.h" endif # Extra options to supply to gtkdoc-mkdb. # Extra options to supply to gtkdoc-scan. # e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED" SCAN_OPTIONS=--rebuild-types --ignore-headers=$(IGNORE_HFILES) # e.g. MKDB_OPTIONS=--sgml-mode --output-format=xml MKDB_OPTIONS=--sgml-mode --output-format=xml # Extra options to supply to gtkdoc-mktmpl # e.g. MKTMPL_OPTIONS=--only-section-tmpl MKTMPL_OPTIONS= # Extra options to supply to gtkdoc-fixref. Not normally needed. # e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html FIXXREF_OPTIONS= # Used for dependencies. The docs will be rebuilt if any of these change. # e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h # e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c HFILE_GLOB = \ $(top_srcdir)/libinfinity/communication/*.h \ $(top_srcdir)/libinfinity/common/*.h \ $(top_srcdir)/libinfinity/adopted/*.h \ $(top_srcdir)/libinfinity/client/*.h \ $(top_srcdir)/libinfinity/server/*.h CFILE_GLOB = \ $(top_srcdir)/libinfinity/communication/*.c \ $(top_srcdir)/libinfinity/common/*.c \ $(top_srcdir)/libinfinity/adopted/*.c \ $(top_srcdir)/libinfinity/client/*.c \ $(top_srcdir)/libinfinity/server/*.c # Images to copy into HTML directory. # e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png HTML_IMAGES= # Extra SGML files that are included by $(DOC_MAIN_SGML_FILE). # e.g. content_files=running.sgml building.sgml changes-2.0.sgml content_files = \ ../version.xml \ ../api_version.xml \ compiling.sgml # SGML files where gtk-doc abbrevations (#GtkWidget) are expanded # These files must be listed here *and* in content_files # e.g. expand_content_files=running.sgml expand_content_files= # CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library. # Only needed if you are using gtkdoc-scangobj to dynamically query widget # signals and properties. # e.g. INCLUDES=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS) # e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib) #INCLUDES=$(infinity_CFLAGS) AM_CPPFLAGS=$(infinity_CFLAGS) GTKDOC_LIBS = \ $(infinity_LIBS) \ $(top_builddir)/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la # This includes the standard gtk-doc make rules, copied by gtkdocize. include $(top_srcdir)/gtk-doc.make # Other files to distribute # e.g. EXTRA_DIST += version.xml.in EXTRA_DIST += # Files not to distribute # for --rebuild-types in $(SCAN_OPTIONS), e.g. $(DOC_MODULE).types # for --rebuild-sections in $(SCAN_OPTIONS) e.g. $(DOC_MODULE)-sections.txt DISTCLEANFILES = libinfinity-$(LIBINFINITY_API_VERSION).types version.xml api_version.xml # Comment this out if you want your docs-status tested during 'make check' #TESTS = $(GTKDOC_CHECK) libinfinity-0.7.1/docs/reference/libinfinity/PaxHeaders.26529/libinfinity-0.7-sections.txt0000644000000000000000000000013213055210752026221 xustar0030 mtime=1488261610.840090807 30 atime=1483851082.013718339 30 ctime=1488261610.840090807 libinfinity-0.7.1/docs/reference/libinfinity/libinfinity-0.7-sections.txt0000644000175000017500000012725213055210752026764 0ustar00arminarmin00000000000000
inf-adopted-session InfAdoptedSession InfAdoptedSessionError InfAdoptedSession InfAdoptedSessionClass inf_adopted_session_get_io inf_adopted_session_get_algorithm inf_adopted_session_broadcast_request inf_adopted_session_undo inf_adopted_session_redo inf_adopted_session_read_request_info inf_adopted_session_write_request_info INF_ADOPTED_SESSION INF_ADOPTED_IS_SESSION INF_ADOPTED_TYPE_SESSION inf_adopted_session_get_type INF_ADOPTED_SESSION_CLASS INF_ADOPTED_IS_SESSION_CLASS INF_ADOPTED_SESSION_GET_CLASS
inf-adopted-undo-grouping InfAdoptedUndoGrouping InfAdoptedUndoGrouping InfAdoptedUndoGroupingClass inf_adopted_undo_grouping_new inf_adopted_undo_grouping_get_algorithm inf_adopted_undo_grouping_set_algorithm inf_adopted_undo_grouping_start_group inf_adopted_undo_grouping_end_group inf_adopted_undo_grouping_get_undo_size inf_adopted_undo_grouping_get_redo_size INF_ADOPTED_UNDO_GROUPING INF_ADOPTED_IS_UNDO_GROUPING INF_ADOPTED_TYPE_UNDO_GROUPING inf_adopted_undo_grouping_get_type INF_ADOPTED_UNDO_GROUPING_CLASS INF_ADOPTED_IS_UNDO_GROUPING_CLASS INF_ADOPTED_UNDO_GROUPING_GET_CLASS
inf-adopted-session-record InfAdoptedSessionRecord InfAdoptedSessionRecord InfAdoptedSessionRecordClass inf_adopted_session_record_new inf_adopted_session_record_start_recording inf_adopted_session_record_stop_recording inf_adopted_session_record_is_recording INF_ADOPTED_SESSION_RECORD INF_ADOPTED_IS_SESSION_RECORD INF_ADOPTED_TYPE_SESSION_RECORD inf_adopted_session_record_get_type INF_ADOPTED_SESSION_RECORD_CLASS INF_ADOPTED_IS_SESSION_RECORD_CLASS INF_ADOPTED_SESSION_RECORD_GET_CLASS
inf-adopted-session-replay InfAdoptedSessionReplay InfAdoptedSessionReplayError InfAdoptedSessionReplay InfAdoptedSessionReplayClass inf_adopted_session_replay_new inf_adopted_session_replay_set_record inf_adopted_session_replay_get_session inf_adopted_session_replay_play_next inf_adopted_session_replay_play_to_end INF_ADOPTED_SESSION_REPLAY INF_ADOPTED_IS_SESSION_REPLAY INF_ADOPTED_TYPE_SESSION_REPLAY inf_adopted_session_replay_get_type INF_ADOPTED_SESSION_REPLAY_CLASS INF_ADOPTED_IS_SESSION_REPLAY_CLASS INF_ADOPTED_SESSION_REPLAY_GET_CLASS
infc-browser InfcBrowser InfcBrowser InfcBrowserClass infc_browser_new infc_browser_get_communication_manager infc_browser_get_connection infc_browser_add_plugin infc_browser_lookup_plugin infc_browser_iter_save_session infc_browser_iter_get_sync_in infc_browser_iter_get_sync_in_requests infc_browser_iter_is_valid infc_browser_subscribe_chat infc_browser_get_subscribe_chat_request infc_browser_get_chat_session INFC_BROWSER INFC_IS_BROWSER INFC_TYPE_BROWSER infc_browser_get_type INFC_BROWSER_CLASS INFC_IS_BROWSER_CLASS INFC_BROWSER_GET_CLASS
infc-progress-request InfcProgressRequest InfcProgressRequest InfcProgressRequestClass infc_progress_request_initiated infc_progress_request_get_initiated infc_progress_request_progress INFC_PROGRESS_REQUEST INFC_IS_PROGRESS_REQUEST INFC_TYPE_PROGRESS_REQUEST infc_progress_request_get_type INFC_PROGRESS_REQUEST_CLASS INFC_IS_PROGRESS_REQUEST_CLASS INFC_PROGRESS_REQUEST_GET_CLASS
infc-request-manager InfcRequestManager InfcRequestManagerForeachFunc InfcRequestManager InfcRequestManagerClass infc_request_manager_new infc_request_manager_add_request infc_request_manager_add_request_valist infc_request_manager_remove_request infc_request_manager_finish_request infc_request_manager_fail_request infc_request_manager_clear infc_request_manager_get_request_by_seq infc_request_manager_get_request_by_xml infc_request_manager_get_request_by_xml_required infc_request_manager_foreach_request infc_request_manager_foreach_named_request INFC_REQUEST_MANAGER INFC_IS_REQUEST_MANAGER INFC_TYPE_REQUEST_MANAGER infc_request_manager_get_type INFC_REQUEST_MANAGER_CLASS INFC_IS_REQUEST_MANAGER_CLASS INFC_REQUEST_MANAGER_GET_CLASS
infc-session-proxy InfcSessionProxy InfcSessionProxy InfcSessionProxyClass infc_session_proxy_set_connection infc_session_proxy_get_connection infc_session_proxy_get_subscription_group INFC_SESSION_PROXY INFC_IS_SESSION_PROXY INFC_TYPE_SESSION_PROXY infc_session_proxy_get_type INFC_SESSION_PROXY_CLASS INFC_IS_SESSION_PROXY_CLASS INFC_SESSION_PROXY_GET_CLASS
infc-request InfcRequest InfcRequest InfcRequestClass INFC_REQUEST INFC_IS_REQUEST INFC_TYPE_REQUEST infc_request_get_type INFC_REQUEST_CLASS INFC_IS_REQUEST_CLASS INFC_REQUEST_GET_CLASS
inf-local-publisher InfLocalPublisher InfLocalPublisher InfLocalPublisherInterface InfLocalPublisherItem inf_local_publisher_publish inf_local_publisher_unpublish INF_LOCAL_PUBLISHER INF_IS_LOCAL_PUBLISHER INF_TYPE_LOCAL_PUBLISHER inf_local_publisher_get_type INF_LOCAL_PUBLISHER_GET_IFACE
inf-name-resolver InfNameResolver InfNameResolver InfNameResolverClass inf_name_resolver_new inf_name_resolver_get_hostname inf_name_resolver_get_service inf_name_resolver_get_srv inf_name_resolver_start inf_name_resolver_lookup_backup inf_name_resolver_finished inf_name_resolver_get_n_addresses inf_name_resolver_get_address inf_name_resolver_get_port INF_NAME_RESOLVER INF_IS_NAME_RESOLVER INF_TYPE_NAME_RESOLVER INF_NAME_RESOLVER_CLASS INF_IS_NAME_RESOLVER_CLASS INF_NAME_RESOLVER_GET_CLASS inf_name_resolver_get_type
inf-tcp-connection InfTcpConnection InfTcpConnectionStatus InfTcpConnection InfTcpConnectionClass inf_tcp_connection_new inf_tcp_connection_new_and_open inf_tcp_connection_new_resolve inf_tcp_connection_open inf_tcp_connection_close inf_tcp_connection_send inf_tcp_connection_get_remote_address inf_tcp_connection_get_remote_port inf_tcp_connection_set_keepalive inf_tcp_connection_get_keepalive INF_TCP_CONNECTION INF_IS_TCP_CONNECTION INF_TYPE_TCP_CONNECTION INF_TCP_CONNECTION_CLASS INF_IS_TCP_CONNECTION_CLASS INF_TCP_CONNECTION_GET_CLASS inf_tcp_connection_get_type inf_tcp_connection_status_get_type INF_TYPE_TCP_CONNECTION_STATUS
inf-native-socket InfNativeSocket InfNativeSocket INF_NATIVE_SOCKET_EAGAIN INF_NATIVE_SOCKET_EINPROGRESS INF_NATIVE_SOCKET_EINTR INF_NATIVE_SOCKET_LAST_ERROR INF_NATIVE_SOCKET_SENDRECV_FLAGS INVALID_SOCKET inf_native_socket_error_quark inf_native_socket_make_error closesocket
inf-browser InfBrowser InfBrowser InfBrowserInterface InfBrowserStatus inf_browser_get_root inf_browser_get_next inf_browser_get_prev inf_browser_get_parent inf_browser_get_child inf_browser_is_ancestor inf_browser_explore inf_browser_get_explored inf_browser_is_subdirectory inf_browser_add_note inf_browser_add_subdirectory inf_browser_remove_node inf_browser_get_node_name inf_browser_get_node_type inf_browser_get_path inf_browser_subscribe inf_browser_get_session inf_browser_list_pending_requests inf_browser_iter_from_request inf_browser_get_pending_request inf_browser_get_acl_default_account inf_browser_get_acl_local_account inf_browser_query_acl_account_list inf_browser_lookup_acl_accounts inf_browser_lookup_acl_account_by_name inf_browser_create_acl_account inf_browser_remove_acl_account inf_browser_query_acl inf_browser_has_acl inf_browser_get_acl inf_browser_set_acl inf_browser_check_acl inf_browser_error inf_browser_node_added inf_browser_node_removed inf_browser_subscribe_session inf_browser_unsubscribe_session inf_browser_begin_request inf_browser_acl_account_added inf_browser_acl_account_removed inf_browser_acl_local_account_changed inf_browser_acl_changed INF_BROWSER INF_IS_BROWSER INF_TYPE_BROWSER inf_browser_get_type INF_BROWSER_GET_IFACE INF_TYPE_BROWSER_STATUS inf_browser_status_get_type
inf-acl InfAcl InfAclAccountId InfAclAccount InfAclSetting InfAclMask InfAclSheet InfAclSheetSet inf_acl_account_id_from_string inf_acl_account_id_to_string INF_ACL_ACCOUNT_ID_TO_POINTER INF_ACL_ACCOUNT_POINTER_TO_ID inf_acl_account_new inf_acl_account_copy inf_acl_account_free inf_acl_account_array_free inf_acl_account_from_xml inf_acl_account_to_xml inf_acl_mask_copy inf_acl_mask_free inf_acl_mask_clear inf_acl_mask_empty inf_acl_mask_equal inf_acl_mask_set1 inf_acl_mask_setv inf_acl_mask_and inf_acl_mask_and1 inf_acl_mask_or inf_acl_mask_or1 inf_acl_mask_neg inf_acl_mask_has INF_ACL_MASK_ALL INF_ACL_MASK_DEFAULT INF_ACL_MASK_LEAF INF_ACL_MASK_ROOT INF_ACL_MASK_SUBDIRECTORY inf_acl_sheet_new inf_acl_sheet_copy inf_acl_sheet_free inf_acl_sheet_perms_from_xml inf_acl_sheet_perms_to_xml inf_acl_sheet_set_new inf_acl_sheet_set_new_external inf_acl_sheet_set_copy inf_acl_sheet_set_free inf_acl_sheet_set_sink inf_acl_sheet_set_add_sheet inf_acl_sheet_set_remove_sheet inf_acl_sheet_set_merge_sheets inf_acl_sheet_set_get_clear_sheets inf_acl_sheet_set_find_sheet inf_acl_sheet_set_find_const_sheet inf_acl_sheet_set_from_xml inf_acl_sheet_set_to_xml inf_acl_account_get_type inf_acl_setting_get_type inf_acl_mask_get_type inf_acl_sheet_get_type inf_acl_sheet_set_get_type INF_TYPE_ACL_ACCOUNT INF_TYPE_ACL_SETTING INF_TYPE_ACL_MASK INF_TYPE_ACL_SHEET INF_TYPE_ACL_SHEET_SET
inf-keepalive InfKeepalive InfKeepaliveMask InfKeepalive inf_keepalive_copy inf_keepalive_free inf_keepalive_apply inf_keepalive_load_default inf_keepalive_mask_get_type inf_keepalive_get_type INF_TYPE_KEEPALIVE_MASK INF_TYPE_KEEPALIVE
inf-browser-iter InfBrowserIter InfBrowserIter inf_browser_iter_copy inf_browser_iter_free inf_browser_iter_get_type INF_TYPE_BROWSER_ITER
inf-request InfRequest InfRequest InfRequestInterface InfRequestFunc inf_request_fail inf_request_finish inf_request_is_local INF_REQUEST INF_IS_REQUEST INF_TYPE_REQUEST inf_request_get_type INF_REQUEST_GET_IFACE
inf-request-result InfRequestResult InfRequestResult inf_request_result_new inf_request_result_copy inf_request_result_free inf_request_result_get inf_request_result_make_add_node inf_request_result_get_add_node inf_request_result_make_remove_node inf_request_result_get_remove_node inf_request_result_make_explore_node inf_request_result_get_explore_node inf_request_result_make_save_session inf_request_result_get_save_session inf_request_result_make_subscribe_session inf_request_result_get_subscribe_session inf_request_result_make_subscribe_chat inf_request_result_get_subscribe_chat inf_request_result_make_query_acl_account_list inf_request_result_get_query_acl_account_list inf_request_result_make_lookup_acl_accounts inf_request_result_get_lookup_acl_accounts inf_request_result_make_create_acl_account inf_request_result_get_create_acl_account inf_request_result_make_remove_acl_account inf_request_result_get_remove_acl_account inf_request_result_make_query_acl inf_request_result_get_query_acl inf_request_result_make_set_acl inf_request_result_get_set_acl inf_request_result_make_join_user inf_request_result_get_join_user INF_TYPE_REQUEST_RESULT inf_request_result_get_type
inf-buffer InfBuffer InfBuffer InfBufferInterface inf_buffer_get_modified inf_buffer_set_modified INF_BUFFER INF_IS_BUFFER INF_TYPE_BUFFER inf_buffer_get_type INF_BUFFER_GET_IFACE
inf-standalone-io InfStandaloneIo InfStandaloneIo InfStandaloneIoClass inf_standalone_io_new inf_standalone_io_iteration inf_standalone_io_iteration_timeout inf_standalone_io_loop inf_standalone_io_loop_quit inf_standalone_io_loop_running INF_STANDALONE_IO INF_IS_STANDALONE_IO INF_TYPE_STANDALONE_IO inf_standalone_io_get_type INF_STANDALONE_IO_CLASS INF_IS_STANDALONE_IO_CLASS INF_STANDALONE_IO_GET_CLASS
inf-discovery-avahi InfDiscoveryAvahi InfDiscoveryAvahi InfDiscoveryAvahiClass inf_discovery_avahi_new inf_discovery_avahi_set_security_policy inf_discovery_avahi_get_security_policy inf_discovery_avahi_set_keepalive inf_discovery_avahi_get_keepalive INF_DISCOVERY_AVAHI INF_IS_DISCOVERY_AVAHI INF_TYPE_DISCOVERY_AVAHI inf_discovery_avahi_get_type INF_DISCOVERY_AVAHI_CLASS INF_IS_DISCOVERY_AVAHI_CLASS INF_DISCOVERY_AVAHI_GET_CLASS
inf-user InfUser InfUserStatus InfUserFlags InfUser InfUserClass inf_user_get_id inf_user_get_name inf_user_get_status inf_user_get_flags inf_user_get_connection inf_user_status_to_string inf_user_status_from_string INF_USER INF_IS_USER INF_TYPE_USER INF_USER_CLASS INF_IS_USER_CLASS INF_USER_GET_CLASS inf_user_status_get_type inf_user_flags_get_type inf_user_get_type INF_TYPE_USER_STATUS INF_TYPE_USER_FLAGS
inf-discovery InfDiscovery InfDiscovery InfDiscoveryInterface InfDiscoveryInfo InfDiscoveryResolvCompleteFunc inf_discovery_discover inf_discovery_get_discovered inf_discovery_resolve inf_discovery_info_get_service_name inf_discovery_info_get_service_type inf_discovery_discovered inf_discovery_undiscovered INF_DISCOVERY INF_IS_DISCOVERY INF_TYPE_DISCOVERY inf_discovery_get_type INF_DISCOVERY_GET_IFACE
inf-user-table InfUserTable InfUserTableForeachUserFunc InfUserTable InfUserTableClass inf_user_table_new inf_user_table_add_user inf_user_table_remove_user inf_user_table_lookup_user_by_id inf_user_table_lookup_user_by_name inf_user_table_foreach_user inf_user_table_foreach_local_user INF_USER_TABLE INF_IS_USER_TABLE INF_TYPE_USER_TABLE inf_user_table_get_type INF_USER_TABLE_CLASS INF_IS_USER_TABLE_CLASS INF_USER_TABLE_GET_CLASS
inf-io InfIo InfIo InfIoInterface InfIoEvent InfIoWatch InfIoTimeout InfIoDispatch InfIoWatchFunc InfIoTimeoutFunc InfIoDispatchFunc inf_io_add_watch inf_io_add_watch_from_fd inf_io_update_watch inf_io_remove_watch inf_io_add_timeout inf_io_remove_timeout inf_io_add_dispatch inf_io_remove_dispatch INF_IO INF_IS_IO INF_TYPE_IO inf_io_event_get_type INF_IO_GET_IFACE inf_io_get_type INF_TYPE_IO_EVENT
inf-session InfSession InfSessionStatus InfSessionSyncStatus InfSessionSyncError InfSession InfSessionClass inf_session_lookup_user_property inf_session_get_user_property inf_session_user_to_xml inf_session_close inf_session_get_communication_manager inf_session_get_buffer inf_session_get_user_table inf_session_get_status inf_session_add_user inf_session_set_user_status inf_session_synchronize_from inf_session_synchronize_to inf_session_cancel_synchronization inf_session_get_synchronization_status inf_session_get_synchronization_progress inf_session_has_synchronizations inf_session_get_subscription_group inf_session_set_subscription_group inf_session_send_to_subscriptions INF_SESSION INF_IS_SESSION INF_TYPE_SESSION inf_session_status_get_type INF_SESSION_CLASS INF_IS_SESSION_CLASS INF_SESSION_GET_CLASS inf_session_get_type INF_TYPE_SESSION_STATUS
inf-session-proxy InfSessionProxy InfSessionProxy InfSessionProxyInterface inf_session_proxy_join_user INF_SESSION_PROXY INF_IS_SESSION_PROXY INF_TYPE_SESSION_PROXY INF_SESSION_PROXY_GET_IFACE inf_session_proxy_get_type INF_TYPE_SESSION_PROXY_STATUS
inf-xmpp-manager InfXmppManager InfXmppManager InfXmppManagerClass inf_xmpp_manager_new inf_xmpp_manager_lookup_connection_by_address inf_xmpp_manager_lookup_connection_by_hostname inf_xmpp_manager_contains_connection inf_xmpp_manager_add_connection inf_xmpp_manager_remove_connection INF_XMPP_MANAGER INF_IS_XMPP_MANAGER INF_TYPE_XMPP_MANAGER inf_xmpp_manager_get_type INF_XMPP_MANAGER_CLASS INF_IS_XMPP_MANAGER_CLASS INF_XMPP_MANAGER_GET_CLASS
inf-xmpp-connection InfXmppConnection InfXmppConnectionCrtCallback InfXmppConnectionSite InfXmppConnectionSecurityPolicy InfXmppConnectionError InfXmppConnectionStreamError InfXmppConnectionAuthError InfXmppConnection InfXmppConnectionClass inf_xmpp_connection_error_quark inf_xmpp_connection_new inf_xmpp_connection_get_tls_enabled inf_xmpp_connection_get_own_certificate inf_xmpp_connection_get_peer_certificate inf_xmpp_connection_get_kx_algorithm inf_xmpp_connection_get_cipher_algorithm inf_xmpp_connection_get_mac_algorithm inf_xmpp_connection_get_tls_protocol inf_xmpp_connection_get_dh_prime_bits inf_xmpp_connection_set_certificate_callback inf_xmpp_connection_certificate_verify_continue inf_xmpp_connection_certificate_verify_cancel inf_xmpp_connection_reset_sasl_authentication inf_xmpp_connection_retry_sasl_authentication inf_xmpp_connection_set_sasl_error inf_xmpp_connection_get_sasl_error INF_XMPP_CONNECTION INF_IS_XMPP_CONNECTION INF_TYPE_XMPP_CONNECTION inf_xmpp_connection_site_get_type inf_xmpp_connection_security_policy_get_type INF_XMPP_CONNECTION_CLASS INF_IS_XMPP_CONNECTION_CLASS INF_XMPP_CONNECTION_GET_CLASS inf_xmpp_connection_get_type INF_TYPE_XMPP_CONNECTION_SITE INF_TYPE_XMPP_CONNECTION_SECURITY_POLICY
inf-xml-connection InfXmlConnection InfXmlConnection InfXmlConnectionInterface InfXmlConnectionStatus inf_xml_connection_open inf_xml_connection_close inf_xml_connection_send inf_xml_connection_sent inf_xml_connection_received inf_xml_connection_error INF_XML_CONNECTION INF_IS_XML_CONNECTION INF_TYPE_XML_CONNECTION inf_xml_connection_status_get_type INF_XML_CONNECTION_GET_IFACE inf_xml_connection_get_type INF_TYPE_XML_CONNECTION_STATUS
inf-simulated-connection InfSimulatedConnection InfSimulatedConnection InfSimulatedConnectionClass InfSimulatedConnectionMode inf_simulated_connection_new inf_simulated_connection_new_with_io inf_simulated_connection_connect inf_simulated_connection_set_mode inf_simulated_connection_flush INF_SIMULATED_CONNECTION INF_IS_SIMULATED_CONNECTION INF_TYPE_SIMULATED_CONNECTION inf_simulated_connection_get_type INF_SIMULATED_CONNECTION_CLASS INF_IS_SIMULATED_CONNECTION_CLASS INF_SIMULATED_CONNECTION_GET_CLASS inf_simulated_connection_mode_get_type INF_TYPE_SIMULATED_CONNECTION_MODE
inf-adopted-operation InfAdoptedOperation InfAdoptedOperation InfAdoptedOperationInterface InfAdoptedOperationFlags InfAdoptedConcurrencyId inf_adopted_operation_need_concurrency_id inf_adopted_operation_transform inf_adopted_operation_copy inf_adopted_operation_get_flags inf_adopted_operation_apply inf_adopted_operation_apply_transformed inf_adopted_operation_is_reversible inf_adopted_operation_revert INF_ADOPTED_OPERATION INF_ADOPTED_IS_OPERATION INF_ADOPTED_TYPE_OPERATION inf_adopted_operation_flags_get_type INF_ADOPTED_OPERATION_GET_IFACE inf_adopted_operation_get_type INF_ADOPTED_TYPE_OPERATION_FLAGS inf_adopted_concurrency_id_get_type
inf-adopted-user InfAdoptedUser InfAdoptedUser InfAdoptedUserClass inf_adopted_user_get_component inf_adopted_user_get_vector inf_adopted_user_set_vector inf_adopted_user_get_request_log INF_ADOPTED_USER INF_ADOPTED_IS_USER INF_ADOPTED_TYPE_USER inf_adopted_user_get_type INF_ADOPTED_USER_CLASS INF_ADOPTED_IS_USER_CLASS INF_ADOPTED_USER_GET_CLASS
inf-adopted-request InfAdoptedRequest InfAdoptedRequestType InfAdoptedRequest InfAdoptedRequestClass inf_adopted_request_new_do inf_adopted_request_new_undo inf_adopted_request_new_redo inf_adopted_request_copy inf_adopted_request_get_request_type inf_adopted_request_get_vector inf_adopted_request_get_user_id inf_adopted_request_get_operation inf_adopted_request_get_index inf_adopted_request_get_receive_time inf_adopted_request_get_execute_time inf_adopted_request_set_execute_time inf_adopted_request_need_concurrency_id inf_adopted_request_transform inf_adopted_request_mirror inf_adopted_request_fold inf_adopted_request_affects_buffer INF_ADOPTED_REQUEST INF_ADOPTED_IS_REQUEST INF_ADOPTED_TYPE_REQUEST inf_adopted_request_type_get_type INF_ADOPTED_REQUEST_CLASS INF_ADOPTED_IS_REQUEST_CLASS INF_ADOPTED_REQUEST_GET_CLASS inf_adopted_request_get_type INF_ADOPTED_TYPE_REQUEST_TYPE
inf-adopted-algorithm InfAdoptedAlgorithm InfAdoptedAlgorithmError InfAdoptedAlgorithm InfAdoptedAlgorithmClass inf_adopted_algorithm_new inf_adopted_algorithm_new_full inf_adopted_algorithm_get_current inf_adopted_algorithm_get_execute_request inf_adopted_algorithm_generate_request inf_adopted_algorithm_translate_request inf_adopted_algorithm_execute_request inf_adopted_algorithm_cleanup inf_adopted_algorithm_can_undo inf_adopted_algorithm_can_redo INF_ADOPTED_ALGORITHM INF_ADOPTED_IS_ALGORITHM INF_ADOPTED_TYPE_ALGORITHM inf_adopted_algorithm_get_type INF_ADOPTED_ALGORITHM_CLASS INF_ADOPTED_IS_ALGORITHM_CLASS INF_ADOPTED_ALGORITHM_GET_CLASS
inf-adopted-split-operation InfAdoptedSplitOperation InfAdoptedSplitOperation InfAdoptedSplitOperationClass inf_adopted_split_operation_new inf_adopted_split_operation_unsplit inf_adopted_split_operation_transform_other INF_ADOPTED_SPLIT_OPERATION INF_ADOPTED_IS_SPLIT_OPERATION INF_ADOPTED_TYPE_SPLIT_OPERATION inf_adopted_split_operation_get_type INF_ADOPTED_SPLIT_OPERATION_CLASS INF_ADOPTED_IS_SPLIT_OPERATION_CLASS INF_ADOPTED_SPLIT_OPERATION_GET_CLASS
inf-adopted-no-operation InfAdoptedNoOperation InfAdoptedNoOperation InfAdoptedNoOperationClass inf_adopted_no_operation_new INF_ADOPTED_NO_OPERATION INF_ADOPTED_IS_NO_OPERATION INF_ADOPTED_TYPE_NO_OPERATION inf_adopted_no_operation_get_type INF_ADOPTED_NO_OPERATION_CLASS INF_ADOPTED_IS_NO_OPERATION_CLASS INF_ADOPTED_NO_OPERATION_GET_CLASS
inf-adopted-request-log InfAdoptedRequestLog InfAdoptedRequestLog InfAdoptedRequestLogClass inf_adopted_request_log_new inf_adopted_request_log_get_user_id inf_adopted_request_log_get_begin inf_adopted_request_log_get_end inf_adopted_request_log_is_empty inf_adopted_request_log_set_begin inf_adopted_request_log_get_request inf_adopted_request_log_add_request inf_adopted_request_log_remove_requests inf_adopted_request_log_next_associated inf_adopted_request_log_prev_associated inf_adopted_request_log_original_request inf_adopted_request_log_next_undo inf_adopted_request_log_next_redo inf_adopted_request_log_upper_related inf_adopted_request_log_lower_related inf_adopted_request_log_add_cached_request inf_adopted_request_log_lookup_cached_request INF_ADOPTED_REQUEST_LOG INF_ADOPTED_IS_REQUEST_LOG INF_ADOPTED_TYPE_REQUEST_LOG inf_adopted_request_log_get_type INF_ADOPTED_REQUEST_LOG_CLASS INF_ADOPTED_IS_REQUEST_LOG_CLASS INF_ADOPTED_REQUEST_LOG_GET_CLASS
infd-xmpp-server InfdXmppServer InfdXmppServer InfdXmppServerClass infd_xmpp_server_new infd_xmpp_server_set_security_policy infd_xmpp_server_get_security_policy INFD_XMPP_SERVER INFD_IS_XMPP_SERVER INFD_TYPE_XMPP_SERVER infd_xmpp_server_get_type INFD_XMPP_SERVER_CLASS INFD_IS_XMPP_SERVER_CLASS INFD_XMPP_SERVER_GET_CLASS
infd-server-pool InfdServerPool InfdServerPoolForeachServerFunc InfdServerPool InfdServerPoolClass infd_server_pool_new infd_server_pool_add_server infd_server_pool_add_local_publisher infd_server_pool_remove_server infd_server_pool_foreach_server INFD_SERVER_POOL INFD_IS_SERVER_POOL INFD_TYPE_SERVER_POOL infd_server_pool_get_type INFD_SERVER_POOL_CLASS INFD_IS_SERVER_POOL_CLASS INFD_SERVER_POOL_GET_CLASS
infd-directory InfdDirectory InfdDirectory InfdDirectoryClass InfdDirectoryForeachConnectionFunc infd_directory_new infd_directory_get_io infd_directory_get_storage infd_directory_get_communication_manager infd_directory_set_certificate infd_directory_add_plugin infd_directory_remove_plugin infd_directory_lookup_plugin infd_directory_add_connection infd_directory_get_support_mask infd_directory_get_acl_account_for_connection infd_directory_set_acl_account_for_connection infd_directory_foreach_connection infd_directory_iter_save_session infd_directory_enable_chat infd_directory_get_chat_session infd_directory_create_acl_account INFD_DIRECTORY INFD_IS_DIRECTORY INFD_TYPE_DIRECTORY INFD_DIRECTORY_CLASS INFD_IS_DIRECTORY_CLASS INFD_DIRECTORY_GET_CLASS infd_directory_get_type
infd-request InfdRequest InfdRequest InfdRequestClass INFD_REQUEST INFD_IS_REQUEST INFD_TYPE_REQUEST infd_request_get_type INFD_REQUEST_CLASS INFD_IS_REQUEST_CLASS INFD_REQUEST_GET_CLASS
infd-progress-request InfdProgressRequest InfdProgressRequest InfdProgressRequestClass infd_progress_request_initiated infd_progress_request_progress INFD_PROGRESS_REQUEST INFD_IS_PROGRESS_REQUEST INFD_TYPE_PROGRESS_REQUEST infd_progress_request_get_type INFD_PROGRESS_REQUEST_CLASS INFD_IS_PROGRESS_REQUEST_CLASS INFD_PROGRESS_REQUEST_GET_CLASS
infd-xml-server InfdXmlServer InfdXmlServer InfdXmlServerInterface InfdXmlServerStatus infd_xml_server_close infd_xml_server_new_connection INFD_XML_SERVER INFD_IS_XML_SERVER INFD_TYPE_XML_SERVER infd_xml_server_status_get_type INFD_XML_SERVER_GET_IFACE infd_xml_server_get_type INFD_TYPE_XML_SERVER_STATUS
infd-tcp-server InfdTcpServer InfdTcpServerStatus InfdTcpServer InfdTcpServerClass infd_tcp_server_bind infd_tcp_server_open infd_tcp_server_close infd_tcp_server_set_keepalive infd_tcp_server_get_keepalive INFD_TCP_SERVER INFD_IS_TCP_SERVER INFD_TYPE_TCP_SERVER infd_tcp_server_status_get_type INFD_TCP_SERVER_CLASS INFD_IS_TCP_SERVER_CLASS INFD_TCP_SERVER_GET_CLASS infd_tcp_server_get_type INFD_TYPE_TCP_SERVER_STATUS
infd-storage InfdStorage InfdStorageInterface InfdStorageNodeType InfdStorageNode InfdStorageAcl infd_storage_node_new_subdirectory infd_storage_node_new_note infd_storage_node_copy infd_storage_node_free infd_storage_node_list_free infd_storage_acl_copy infd_storage_acl_free infd_storage_acl_list_free infd_storage_read_subdirectory infd_storage_create_subdirectory infd_storage_remove_node infd_storage_read_acl infd_storage_write_acl INFD_STORAGE INFD_IS_STORAGE INFD_TYPE_STORAGE infd_storage_node_type_get_type INFD_STORAGE_GET_IFACE infd_storage_node_get_type infd_storage_get_type INFD_TYPE_STORAGE_NODE_TYPE INFD_TYPE_STORAGE_NODE INFD_TYPE_STORAGE_ACL infd_storage_acl_get_type
infd-account-storage InfdAccountStorage InfdAccountStorage InfdAccountStorageInterface InfdAccountStorageSupport infd_account_storage_get_support infd_account_storage_supports infd_account_storage_lookup_accounts infd_account_storage_lookup_accounts_by_name infd_account_storage_list_accounts infd_account_storage_add_account infd_account_storage_remove_account infd_account_storage_login_by_certificate infd_account_storage_login_by_password infd_account_storage_set_certificate infd_account_storage_set_password infd_account_storage_account_added infd_account_storage_account_removed infd_account_storage_get_type infd_account_storage_support_get_type INFD_ACCOUNT_STORAGE INFD_ACCOUNT_STORAGE_GET_IFACE INFD_IS_ACCOUNT_STORAGE INFD_TYPE_ACCOUNT_STORAGE
infd-session-proxy InfdSessionProxy InfdSessionProxy InfdSessionProxyClass infd_session_proxy_subscribe_to infd_session_proxy_unsubscribe infd_session_proxy_has_subscriptions infd_session_proxy_is_subscribed infd_session_proxy_is_idle INFD_SESSION_PROXY INFD_IS_SESSION_PROXY INFD_TYPE_SESSION_PROXY infd_session_proxy_get_type INFD_SESSION_PROXY_CLASS INFD_IS_SESSION_PROXY_CLASS INFD_SESSION_PROXY_GET_CLASS
infd-filesystem-storage InfdFilesystemStorage InfdFilesystemStorageError InfdFilesystemStorage InfdFilesystemStorageClass infd_filesystem_storage_new infd_filesystem_storage_get_path infd_filesystem_storage_open infd_filesystem_storage_read_xml_file infd_filesystem_storage_write_xml_file infd_filesystem_storage_stream_close infd_filesystem_storage_stream_read infd_filesystem_storage_stream_write INFD_FILESYSTEM_STORAGE INFD_IS_FILESYSTEM_STORAGE INFD_TYPE_FILESYSTEM_STORAGE infd_filesystem_storage_get_type INFD_FILESYSTEM_STORAGE_CLASS INFD_IS_FILESYSTEM_STORAGE_CLASS INFD_FILESYSTEM_STORAGE_GET_CLASS
infd-filesystem-account-storage InfdFilesystemAccountStorage InfdFilesystemAccountStorage InfdFilesystemAccountStorageClass InfdFilesystemAccountStorageError infd_filesystem_account_storage_new infd_filesystem_account_storage_set_filesystem INFD_FILESYSTEM_ACCOUNT_STORAGE INFD_FILESYSTEM_ACCOUNT_STORAGE_CLASS INFD_FILESYSTEM_ACCOUNT_STORAGE_GET_CLASS INFD_TYPE_FILESYSTEM_ACCOUNT_STORAGE INFD_IS_FILESYSTEM_ACCOUNT_STORAGE INFD_IS_FILESYSTEM_ACCOUNT_STORAGE_CLASS infd_filesystem_account_storage_get_type
infc-note-plugin InfcNotePlugin InfcNotePluginSessionNew InfcNotePlugin
inf-error InfError InfRequestError InfUserError InfDirectoryError InfAuthenticationDetailError inf_request_error_quark inf_request_strerror inf_user_error_quark inf_user_strerror inf_directory_error_quark inf_directory_strerror inf_authentication_detail_error_quark inf_authentication_detail_strerror inf_gnutls_error_quark inf_gnutls_set_error inf_gnutls_certificate_verification_error_quark inf_gnutls_certificate_verification_set_error inf_gsasl_error_quark inf_gsasl_set_error
inf-protocol InfProtocol inf_protocol_get_version inf_protocol_parse_version inf_protocol_get_default_port
inf-ip-address InfIpAddress InfIpAddress InfIpAddressFamily inf_ip_address_new_raw4 inf_ip_address_new_loopback4 inf_ip_address_new_raw6 inf_ip_address_new_loopback6 inf_ip_address_new_from_string inf_ip_address_copy inf_ip_address_free inf_ip_address_get_family inf_ip_address_get_raw inf_ip_address_to_string inf_ip_address_collate inf_ip_address_family_get_type inf_ip_address_get_type INF_TYPE_IP_ADDRESS INF_TYPE_IP_ADDRESS_FAMILY
inf-certificate-chain InfCertificateChain InfCertificateChain inf_certificate_chain_new inf_certificate_chain_ref inf_certificate_chain_unref inf_certificate_chain_get_raw inf_certificate_chain_get_root_certificate inf_certificate_chain_get_own_certificate inf_certificate_chain_get_nth_certificate inf_certificate_chain_get_n_certificates inf_certificate_chain_get_type INF_TYPE_CERTIFICATE_CHAIN
inf-certificate-credentials InfCertificateCredentials InfCertificateCredentials inf_certificate_credentials_new inf_certificate_credentials_ref inf_certificate_credentials_unref inf_certificate_credentials_get inf_certificate_credentials_get_type INF_TYPE_CERTIFICATE_CREDENTIALS
inf-async-operation InfAsyncOperation InfAsyncOperation InfAsyncOperationRunFunc InfAsyncOperationDoneFunc inf_async_operation_new inf_async_operation_start inf_async_operation_free
inf-sasl-context InfSaslContext InfSaslContext InfSaslContextSession InfSaslContextCallbackFunc InfSaslContextSessionFeedFunc inf_sasl_context_new inf_sasl_context_ref inf_sasl_context_unref inf_sasl_context_set_callback inf_sasl_context_client_start_session inf_sasl_context_client_list_mechanisms inf_sasl_context_client_supports_mechanism inf_sasl_context_client_suggest_mechanism inf_sasl_context_server_start_session inf_sasl_context_server_list_mechanisms inf_sasl_context_server_supports_mechanism inf_sasl_context_stop_session inf_sasl_context_session_get_property inf_sasl_context_session_set_property inf_sasl_context_session_continue inf_sasl_context_session_feed inf_sasl_context_session_is_processing inf_sasl_context_get_type INF_TYPE_SASL_CONTEXT
inf-cert-util InfCertUtil InfCertUtilDescription inf_cert_util_create_dh_params inf_cert_util_read_dh_params inf_cert_util_write_dh_params inf_cert_util_create_private_key inf_cert_util_read_private_key inf_cert_util_write_private_key inf_cert_util_create_certificate inf_cert_util_create_signed_certificate inf_cert_util_create_self_signed_certificate inf_cert_util_read_certificate inf_cert_util_write_certificate inf_cert_util_write_certificate_mem inf_cert_util_write_certificate_with_key inf_cert_util_copy_certificate inf_cert_util_read_certificate_map inf_cert_util_write_certificate_map inf_cert_util_check_certificate_key inf_cert_util_compare_fingerprint inf_cert_util_get_dn inf_cert_util_get_dn_by_oid inf_cert_util_get_issuer_dn_by_oid inf_cert_util_get_hostname inf_cert_util_get_serial_number inf_cert_util_get_fingerprint inf_cert_util_get_activation_time inf_cert_util_get_expiration_time
inf-file-util InfFileUtil InfFileType InfFileListFunc inf_file_util_create_single_directory inf_file_util_create_directory inf_file_util_list_directory inf_file_util_delete_file inf_file_util_delete_single_directory inf_file_util_delete_directory inf_file_util_delete inf_file_util_write_private_data
inf-init InfInit inf_init inf_deinit
inf-xml-util InfXmlUtil inf_xml_util_add_child_text inf_xml_util_get_child_text inf_xml_util_get_attribute inf_xml_util_get_attribute_required inf_xml_util_get_attribute_int inf_xml_util_get_attribute_int_required inf_xml_util_get_attribute_long inf_xml_util_get_attribute_long_required inf_xml_util_get_attribute_uint inf_xml_util_get_attribute_uint_required inf_xml_util_get_attribute_ulong inf_xml_util_get_attribute_ulong_required inf_xml_util_get_attribute_double inf_xml_util_get_attribute_double_required inf_xml_util_set_attribute inf_xml_util_set_attribute_int inf_xml_util_set_attribute_long inf_xml_util_set_attribute_uint inf_xml_util_set_attribute_ulong inf_xml_util_set_attribute_double inf_xml_util_new_error_from_node inf_xml_util_new_node_from_error
inf-adopted-state-vector InfAdoptedStateVector InfAdoptedStateVector InfAdoptedStateVectorError InfAdoptedStateVectorForeachFunc inf_adopted_state_vector_error_quark inf_adopted_state_vector_new inf_adopted_state_vector_copy inf_adopted_state_vector_free inf_adopted_state_vector_get inf_adopted_state_vector_set inf_adopted_state_vector_add inf_adopted_state_vector_foreach inf_adopted_state_vector_compare inf_adopted_state_vector_causally_before inf_adopted_state_vector_causally_before_inc inf_adopted_state_vector_vdiff inf_adopted_state_vector_to_string inf_adopted_state_vector_from_string inf_adopted_state_vector_to_string_diff inf_adopted_state_vector_from_string_diff INF_ADOPTED_TYPE_STATE_VECTOR inf_adopted_state_vector_get_type
infd-note-plugin InfdNotePlugin InfdNotePluginSessionNew InfdNotePluginSessionRead InfdNotePluginSessionWrite InfdNotePlugin
inf-communication-object InfCommunicationObject InfCommunicationScope InfCommunicationObject InfCommunicationObjectInterface inf_communication_object_received inf_communication_object_enqueued inf_communication_object_sent INF_COMMUNICATION_TYPE_SCOPE inf_communication_scope_get_type INF_COMMUNICATION_OBJECT INF_COMMUNICATION_IS_OBJECT INF_COMMUNICATION_TYPE_OBJECT INF_COMMUNICATION_OBJECT_GET_IFACE inf_communication_object_get_type
inf-communication-manager InfCommunicationManager InfCommunicationManager InfCommunicationManagerClass inf_communication_manager_new inf_communication_manager_open_group inf_communication_manager_join_group inf_communication_manager_add_factory inf_communication_manager_get_factory_for INF_COMMUNICATION_MANAGER INF_COMMUNICATION_IS_MANAGER INF_COMMUNICATION_TYPE_MANAGER inf_communication_manager_get_type INF_COMMUNICATION_MANAGER_CLASS INF_COMMUNICATION_IS_MANAGER_CLASS INF_COMMUNICATION_MANAGER_GET_CLASS
inf-communication-group InfCommunicationGroup InfCommunicationGroup InfCommunicationGroupClass inf_communication_group_get_name inf_communication_group_get_target inf_communication_group_set_target inf_communication_group_is_member inf_communication_group_send_message inf_communication_group_send_group_message inf_communication_group_cancel_messages inf_communication_group_get_method_for_network inf_communication_group_get_method_for_connection inf_communication_group_get_publisher_id INF_COMMUNICATION_GROUP INF_COMMUNICATION_IS_GROUP INF_COMMUNICATION_TYPE_GROUP inf_communication_group_get_type INF_COMMUNICATION_GROUP_CLASS INF_COMMUNICATION_IS_GROUP_CLASS INF_COMMUNICATION_GROUP_GET_CLASS
inf-communication-hosted-group InfCommunicationHostedGroup InfCommunicationHostedGroup InfCommunicationHostedGroupClass inf_communication_hosted_group_add_method inf_communication_hosted_group_add_member inf_communication_hosted_group_remove_member INF_COMMUNICATION_HOSTED_GROUP INF_COMMUNICATION_IS_HOSTED_GROUP INF_COMMUNICATION_TYPE_HOSTED_GROUP inf_communication_hosted_group_get_type INF_COMMUNICATION_HOSTED_GROUP_CLASS INF_COMMUNICATION_IS_HOSTED_GROUP_CLASS INF_COMMUNICATION_HOSTED_GROUP_GET_CLASS
inf-communication-joined-group InfCommunicationJoinedGroup InfCommunicationJoinedGroup InfCommunicationJoinedGroupClass inf_communication_joined_group_remove_member inf_communication_joined_group_get_publisher INF_COMMUNICATION_JOINED_GROUP INF_COMMUNICATION_IS_JOINED_GROUP INF_COMMUNICATION_TYPE_JOINED_GROUP inf_communication_joined_group_get_type INF_COMMUNICATION_JOINED_GROUP_CLASS INF_COMMUNICATION_IS_JOINED_GROUP_CLASS INF_COMMUNICATION_JOINED_GROUP_GET_CLASS
inf-communication-registry InfCommunicationRegistry InfCommunicationRegistry InfCommunicationRegistryClass inf_communication_registry_register inf_communication_registry_unregister inf_communication_registry_is_registered inf_communication_registry_send inf_communication_registry_cancel_messages INF_COMMUNICATION_REGISTRY INF_COMMUNICATION_IS_REGISTRY INF_COMMUNICATION_TYPE_REGISTRY inf_communication_registry_get_type INF_COMMUNICATION_REGISTRY_CLASS INF_COMMUNICATION_IS_REGISTRY_CLASS INF_COMMUNICATION_REGISTRY_GET_CLASS
inf-communication-factory InfCommunicationFactory InfCommunicationFactory InfCommunicationFactoryInterface inf_communication_factory_supports_method inf_communication_factory_instantiate INF_COMMUNICATION_FACTORY INF_COMMUNICATION_IS_FACTORY INF_COMMUNICATION_TYPE_FACTORY INF_COMMUNICATION_FACTORY_GET_IFACE inf_communication_factory_get_type
inf-communication-method InfCommunicationMethod InfCommunicationMethod InfCommunicationMethodInterface inf_communication_method_add_member inf_communication_method_remove_member inf_communication_method_is_member inf_communication_method_send_single inf_communication_method_send_all inf_communication_method_cancel_messages inf_communication_method_received inf_communication_method_enqueued inf_communication_method_sent INF_COMMUNICATION_METHOD INF_COMMUNICATION_IS_METHOD INF_COMMUNICATION_TYPE_METHOD INF_COMMUNICATION_METHOD_GET_IFACE inf_communication_method_get_type
inf-communication-central-factory InfCommunicationCentralFactory InfCommunicationCentralFactory InfCommunicationCentralFactoryClass inf_communication_central_factory_get_default INF_COMMUNICATION_CENTRAL_FACTORY INF_COMMUNICATION_CENTRAL_FACTORY_CLASS INF_COMMUNICATION_CENTRAL_FACTORY_GET_CLASS INF_COMMUNICATION_IS_CENTRAL_FACTORY INF_COMMUNICATION_IS_CENTRAL_FACTORY_CLASS INF_COMMUNICATION_TYPE_CENTRAL_FACTORY inf_communication_central_factory_get_type
inf-communication-central-method InfCommunicationCentralMethod InfCommunicationCentralMethod InfCommunicationCentralMethodClass INF_COMMUNICATION_CENTRAL_METHOD INF_COMMUNICATION_CENTRAL_METHOD_CLASS INF_COMMUNICATION_CENTRAL_METHOD_GET_CLASS INF_COMMUNICATION_IS_CENTRAL_METHOD INF_COMMUNICATION_IS_CENTRAL_METHOD_CLASS INF_COMMUNICATION_TYPE_CENTRAL_METHOD inf_communication_central_method_get_type
inf-certificate-verify InfCertificateVerify InfCertificateVerify InfCertificateVerifyClass InfCertificateVerifyFlags inf_certificate_verify_new inf_certificate_verify_checked INF_CERTIFICATE_VERIFY INF_IS_CERTIFICATE_VERIFY INF_CERTIFICATE_VERIFY_CLASS INF_IS_CERTIFICATE_VERIFY_CLASS INF_CERTIFICATE_VERIFY_GET_CLASS inf_certificate_verify_get_type INF_TYPE_CERTIFICATE_VERIFY INF_TYPE_CERTIFICATE_VERIFY_FLAGS inf_certificate_verify_flags_get_type
inf-chat-session InfChatSession InfChatSession InfChatSessionClass InfChatSessionError inf_chat_session_new inf_chat_session_set_log_file INF_CHAT_SESSION INF_IS_CHAT_SESSION INF_CHAT_SESSION_CLASS INF_IS_CHAT_SESSION_CLASS INF_CHAT_SESSION_GET_CLASS inf_chat_session_get_type INF_TYPE_CHAT_SESSION
inf-chat-buffer InfChatBuffer InfChatBufferMessageType InfChatBufferMessageFlags InfChatBufferMessage InfChatBuffer InfChatBufferClass inf_chat_buffer_message_copy inf_chat_buffer_message_free inf_chat_buffer_new inf_chat_buffer_add_message inf_chat_buffer_add_emote_message inf_chat_buffer_add_userjoin_message inf_chat_buffer_add_userpart_message inf_chat_buffer_get_message inf_chat_buffer_get_n_messages inf_chat_buffer_get_size INF_CHAT_BUFFER INF_IS_CHAT_BUFFER inf_chat_buffer_message_type_get_type inf_chat_buffer_message_flags_get_type INF_TYPE_CHAT_BUFFER_MESSAGE_TYPE inf_chat_buffer_message_get_type INF_TYPE_CHAT_BUFFER_MESSAGE INF_CHAT_BUFFER_CLASS INF_IS_CHAT_BUFFER_CLASS INF_CHAT_BUFFER_GET_CLASS inf_chat_buffer_get_type INF_TYPE_CHAT_BUFFER
infd-chat-filesystem-format InfdChatFilesystemFormat InfdChatFilesystemFormatError infd_chat_filesystem_format_read infd_chat_filesystem_format_write
libinfinity-0.7.1/docs/reference/libinfinity/PaxHeaders.26529/libinfinity-0.7-docs.sgml0000644000000000000000000000013213034342512025442 xustar0030 mtime=1483851082.013718339 30 atime=1483851082.013718339 30 ctime=1488261590.876134961 libinfinity-0.7.1/docs/reference/libinfinity/libinfinity-0.7-docs.sgml0000644000175000017500000001300013034342512026166 0ustar00arminarmin00000000000000 ]> libinfinity-&api_version; Reference Manual for libinfinity &version;. The latest version of this documentation can be found on-line at http://infinote.0x539.de/libinfinity/API/libinfinity/. About libinfinity Common libinfinity API Libinfinity's adOPTed implementation Libinfinity client side API Libinfinity server side API Network abstraction libinfinity-0.7.1/docs/reference/libinfinity/PaxHeaders.26529/libinfinity-0.7-overrides.txt0000644000000000000000000000013212401204437026371 xustar0030 mtime=1409616159.478310998 30 atime=1409616159.478310998 30 ctime=1488261590.880134952 libinfinity-0.7.1/docs/reference/libinfinity/libinfinity-0.7-overrides.txt0000644000175000017500000000000012401204437027111 0ustar00arminarmin00000000000000libinfinity-0.7.1/docs/reference/libinfinity/PaxHeaders.26529/compiling.sgml0000644000000000000000000000013212400102201023634 xustar0030 mtime=1409320065.091132986 30 atime=1409320065.091132986 30 ctime=1488261590.876134961 libinfinity-0.7.1/docs/reference/libinfinity/compiling.sgml0000644000175000017500000001045412400102201024372 0ustar00arminarmin00000000000000 Compiling and Using libinfinity Compiling libinfinity This chapter explains how to compile libinfinity on a UNIX-like operating system such as Linux. On Windows, you can pretty much follow the same instructions once you have set up a MinGW/MSYS build environment and installed the necessary dependencies to the correct locations. This document does not cover how to do this but might in the future. It is also possible to build libinfinity using the Microsoft Compiler and Visual Studio IDE but there are no project files so far. The first thing to do is to check whether all dependencies of libinfinity are installed. The following list shows what packages are required to be present on your system prior to building libinfinity: libxml2 glib-2.0 >= 2.16 gnutls >= 1.7.2 gsasl >= 0.2.21 gtk+ >= 2.12 (optional) avahi-client (optional) libdaemon (optional) Most if not all of them are most likely available in the package manager of your operating system vendor. It is much more convenient to obtain them from there than building them on your own. The next step is to obtain the current source code for libinfinity. Point your web browser to http://releases.0x539.de/libinfinity and grab the latest .tar.gz file available, or exactly the version you want if you are looking for a specific one. Then unpack the tarball. On the command line this can be done using the following command: tar xvfz libinfinity-0.4.tar.gz After unpacking, descend into the newly created directory and run the configure script there. This performs several checks to adapt the build for your specific operating system and environment. The script can be passed several command-line arguments to alter the build. For example, the --prefix argument specifies the directory libinfinity will be installed into after the build. It defaults to /usr/local but you might want to install it to a different place, such as /opt/libinfinity. In that case run the following: ./configure --prefix=/opt/libinfinity To get a list of all possible arguments run configure with the --help argument. If you do not want to change the installation path simply omit the --prefix=/opt/libinfinity in the command above. When all dependencies are installed correctly the configure script will run smoothly and end up with a status summary of what parts of libinfinity will or will not be built. If there are errors you need to fix them (for examply by installing a missing dependency) and run configure again. After it ran it created a Makefile and you can build the package via: make This might take some time but it is not supposed to produce an error. If it does something might be wrong with your build setup that configure was unable to detect. When make finished install the package using: make install Depending on the installation directory you chose with the --prefix argument to configure you might need superuser privileges for this step. Compiling applications using libinfinity Environment variables libinfinity-0.7.1/docs/reference/PaxHeaders.26529/version.xml.in.in0000644000000000000000000000013212400102201021670 xustar0030 mtime=1409320065.091132986 30 atime=1409320065.091132986 30 ctime=1488261589.984136914 libinfinity-0.7.1/docs/reference/version.xml.in.in0000644000175000017500000000002612400102201022420 0ustar00arminarmin00000000000000@LIBINFINITY_VERSION@ libinfinity-0.7.1/docs/reference/PaxHeaders.26529/libinftextgtk0000644000000000000000000000013213055210763021274 xustar0030 mtime=1488261619.064072369 30 atime=1488261616.900077235 30 ctime=1488261619.064072369 libinfinity-0.7.1/docs/reference/libinftextgtk/0000755000175000017500000000000013055210763022103 5ustar00arminarmin00000000000000libinfinity-0.7.1/docs/reference/libinftextgtk/PaxHeaders.26529/libinftextgtk-0.7-sections.txt0000644000000000000000000000013213055210763027117 xustar0030 mtime=1488261619.064072369 30 atime=1483851082.013718339 30 ctime=1488261619.064072369 libinfinity-0.7.1/docs/reference/libinftextgtk/libinftextgtk-0.7-sections.txt0000644000175000017500000000527213055210763027657 0ustar00arminarmin00000000000000
inf-text-gtk-buffer InfTextGtkBuffer InfTextGtkBuffer InfTextGtkBufferClass inf_text_gtk_buffer_new inf_text_gtk_buffer_get_text_buffer inf_text_gtk_buffer_set_active_user inf_text_gtk_buffer_get_active_user inf_text_gtk_buffer_get_author inf_text_gtk_buffer_get_user_for_tag inf_text_gtk_buffer_is_author_toggle inf_text_gtk_buffer_forward_to_author_toggle inf_text_gtk_buffer_backward_to_author_toggle inf_text_gtk_buffer_set_wake_on_cursor_movement inf_text_gtk_buffer_get_wake_on_cursor_movement inf_text_gtk_buffer_ensure_author_tags_priority inf_text_gtk_buffer_set_saturation_value inf_text_gtk_buffer_set_fade inf_text_gtk_buffer_get_saturation inf_text_gtk_buffer_get_value inf_text_gtk_buffer_set_show_user_colors inf_text_gtk_buffer_get_show_user_colors inf_text_gtk_buffer_show_user_colors INF_TEXT_GTK_BUFFER INF_TEXT_GTK_IS_BUFFER INF_TEXT_GTK_TYPE_BUFFER inf_text_gtk_buffer_get_type INF_TEXT_GTK_BUFFER_CLASS INF_TEXT_GTK_IS_BUFFER_CLASS INF_TEXT_GTK_BUFFER_GET_CLASS
inf-text-gtk-view InfTextGtkView InfTextGtkView InfTextGtkViewClass inf_text_gtk_view_new inf_text_gtk_view_get_text_view inf_text_gtk_view_get_user_table inf_text_gtk_view_set_active_user inf_text_gtk_view_get_active_user inf_text_gtk_view_set_show_remote_cursors inf_text_gtk_view_set_show_remote_selections inf_text_gtk_view_set_show_remote_current_lines INF_TEXT_GTK_VIEW INF_TEXT_GTK_IS_VIEW INF_TEXT_GTK_TYPE_VIEW inf_text_gtk_view_get_type INF_TEXT_GTK_VIEW_CLASS INF_TEXT_GTK_IS_VIEW_CLASS INF_TEXT_GTK_VIEW_GET_CLASS
inf-text-gtk-viewport InfTextGtkViewport InfTextGtkViewport InfTextGtkViewportClass inf_text_gtk_viewport_new inf_text_gtk_viewport_get_scrolled_window inf_text_gtk_viewport_get_user_table inf_text_gtk_viewport_set_active_user inf_text_gtk_viewport_get_active_user inf_text_gtk_viewport_set_show_user_markers INF_TEXT_GTK_VIEWPORT INF_TEXT_GTK_IS_VIEWPORT INF_TEXT_GTK_TYPE_VIEWPORT inf_text_gtk_viewport_get_type INF_TEXT_GTK_VIEWPORT_CLASS INF_TEXT_GTK_IS_VIEWPORT_CLASS INF_TEXT_GTK_VIEWPORT_GET_CLASS
inf-text-gtk-hue-chooser InfTextGtkHueChooser InfTextGtkHueChooser InfTextGtkHueChooserClass inf_text_gtk_hue_chooser_new inf_text_gtk_hue_chooser_new_with_hue inf_text_gtk_hue_chooser_set_hue inf_text_gtk_hue_chooser_get_hue INF_TEXT_GTK_HUE_CHOOSER INF_TEXT_GTK_IS_HUE_CHOOSER INF_TEXT_GTK_TYPE_HUE_CHOOSER inf_text_gtk_hue_chooser_get_type INF_TEXT_GTK_HUE_CHOOSER_CLASS INF_TEXT_GTK_IS_HUE_CHOOSER_CLASS INF_TEXT_GTK_HUE_CHOOSER_GET_CLASS
libinfinity-0.7.1/docs/reference/libinftextgtk/PaxHeaders.26529/html0000644000000000000000000000013213055210763022240 xustar0030 mtime=1488261619.100072288 30 atime=1488261619.052072396 30 ctime=1488261619.100072288 libinfinity-0.7.1/docs/reference/libinftextgtk/html/0000755000175000017500000000000013055210763023047 5ustar00arminarmin00000000000000libinfinity-0.7.1/docs/reference/libinftextgtk/html/PaxHeaders.26529/left-insensitive.png0000644000000000000000000000013213055210763026313 xustar0030 mtime=1488261619.056072387 30 atime=1488261619.056072387 30 ctime=1488261619.056072387 libinfinity-0.7.1/docs/reference/libinftextgtk/html/left-insensitive.png0000644000175000017500000000061313055210763027045 0ustar00arminarmin00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEà 4ÓkMIDAT8ËÍ’­NQ…¿éö†…@¡p üdsÛÀÖ`*š4Á@ò„W@ A!ÈÔ†@6Ü^ƒ 5hxèIH R`sQpäÌ™339þBÊó|Ês¤ªKEQTÛíöK°@·ÛÎià¦^¯Ï~îWʆ½÷‹ÀÕûðå`0˜åTJ6·Tõ˜‘cYn6›AÞû Æ€½~¿ß±Ö>}Ç­Žœs;ªº ¨ˆlYkwËÞürˆ¼†ºó£ Þû5U= °/"›ÖÚç  ¬µ‡"ÒuU=ɲlü×ArÎÕDä˜zÃáp5I’ûà4^E+ÀP3Æœçàq_«êp Ì¥iñ¯ðUY¥‚p=#IEND®B`‚libinfinity-0.7.1/docs/reference/libinftextgtk/html/PaxHeaders.26529/InfTextGtkView.html0000644000000000000000000000013213055210763026065 xustar0030 mtime=1488261619.096072297 30 atime=1488261619.096072297 30 ctime=1488261619.096072297 libinfinity-0.7.1/docs/reference/libinftextgtk/html/InfTextGtkView.html0000644000175000017500000010303513055210763026621 0ustar00arminarmin00000000000000 InfTextGtkView: libinftextgtk-0.7 Reference Manual

InfTextGtkView

InfTextGtkView — Drawing remote cursors and selections in a GtkTextView

Stability Level

Unstable, unless otherwise indicated

Properties

InfTextUser * active-user Read / Write
InfIo * io Read / Write / Construct Only
gboolean show-remote-current-lines Read / Write
gboolean show-remote-cursors Read / Write
gboolean show-remote-selections Read / Write
InfUserTable * user-table Read / Write / Construct Only
GtkTextView * view Read / Write / Construct Only

Types and Values

Object Hierarchy

    GObject
    ╰── InfTextGtkView

Includes

#include <libinftextgtk/inf-text-gtk-view.h>

Description

InfTextGtkView is a helper object which, as long as it is alive, draws the cursor position, selected text of remote users into a GtkTextView widget. It can also highlight the current line of a remote user in a similar way the GtkSourceView widget can highlight the current line of the local user.

This functionality was not implemented by subclassing GtkTextView such that it can also be used with existing subclasses, such as GtkSourceView.

With the function inf_text_gtk_view_set_active_user() the local InfTextUser who is editing the text can be set, if there is any. The insertion position, seleceted text or current line are not drawn for this user, since the normal GtkTextView takes care of that already. This assumes the local user cursor position and selection is synchronized to the corresponding InfTextUser properties, which is automatically the case when a InfTextGtkBuffer is used for the buffer the GtkTextView is displaying.

See InfTextGtkViewport for drawing a marker at remote users' location into the scrollbar.

Functions

inf_text_gtk_view_new ()

InfTextGtkView *
inf_text_gtk_view_new (InfIo *io,
                       GtkTextView *view,
                       InfUserTable *user_table);

Creates a new InfTextGtkView for view . This draws remote user's cursors and selections into the text view.

[constructor]

Parameters

io

A InfIo.

 

view

A GtkTextView.

 

user_table

The InfUserTable for the text session displayed in view .

 

Returns

A new InfTextGtkView.

[transfer full]


inf_text_gtk_view_get_text_view ()

GtkTextView *
inf_text_gtk_view_get_text_view (InfTextGtkView *view);

Returns the underlying GtkTextView.

Parameters

view

A InfTextGtkView.

 

Returns

The InfTextGtkView's GtkTextView.

[transfer none]


inf_text_gtk_view_get_user_table ()

InfUserTable *
inf_text_gtk_view_get_user_table (InfTextGtkView *view);

Returns the InfUserTable containing the users of the session the InfTextGtkView's GtkTextView is displaying.

Parameters

view

A InfTextGtkView.

 

Returns

The InfTextGtkView's InfUserTable.

[transfer none]


inf_text_gtk_view_set_active_user ()

void
inf_text_gtk_view_set_active_user (InfTextGtkView *view,
                                   InfTextUser *user);

Sets the user for which perspective to draw the view. The selection and cursor position is not drawn for this user since it is assumed that the view's buffer cursor position and selection match the active user ones (which is automatically the case if the buffer is managed by a InfTextGtkBuffer).

Parameters

view

A InfTextGtkView.

 

user

A user from view 's user table, or NULL.

[allow-none]

inf_text_gtk_view_get_active_user ()

InfTextUser *
inf_text_gtk_view_get_active_user (InfTextGtkView *view);

Returns the active user of view . See inf_text_gtk_view_set_active_user().

Parameters

view

A InfTextGtkView.

 

Returns

The active user of view .

[transfer none][allow-none]


inf_text_gtk_view_set_show_remote_cursors ()

void
inf_text_gtk_view_set_show_remote_cursors
                               (InfTextGtkView *view,
                                gboolean show);

If show is TRUE then view draws a cursor for each non-local user in INF_USER_ACTIVE status in that user's color into its underlying GtkTextView. If it is FALSE then remote cursors are not drawn.

Parameters

view

A InfTextGtkView.

 

show

Whether to show cursors of non-local users.

 

inf_text_gtk_view_set_show_remote_selections ()

void
inf_text_gtk_view_set_show_remote_selections
                               (InfTextGtkView *view,
                                gboolean show);

If show is TRUE then view draws the selection ranges for each non-local user in INF_USER_ACTIVE status. The selection range is drawn shaded in that user's color on top of the author color which indicates who wrote the selected text. If more than one user has a given piece of text selected then an alternating stripe pattern with each of the user's colors is drawn. If show is FALSE then selection ranges of remote users are not drawn.

Parameters

view

A InfTextGtkView.

 

show

Whether to show selections of non-local users.

 

inf_text_gtk_view_set_show_remote_current_lines ()

void
inf_text_gtk_view_set_show_remote_current_lines
                               (InfTextGtkView *view,
                                gboolean show);

If show is TRUE then all lines in which the cursor of a non-local user in INF_USER_ACTIVE status is is highlighted with that user's color, similar to GtkSourceView's "highlight current line" functionality. If it is FALSE then the current line of non-local users is not highlighted.

Parameters

view

A InfTextGtkView.

 

show

Whether to highlight the current line of non-local users.

 

Types and Values

struct InfTextGtkView

struct InfTextGtkView;

InfTextGtkView is an opaque data type. You should only access it via the public API functions.


struct InfTextGtkViewClass

struct InfTextGtkViewClass {
};

This structure does not contain any public fields.

Property Details

The “active-user†property

  “active-user†             InfTextUser *

The user for which to show the view.

Flags: Read / Write


The “io†property

  “io†                      InfIo *

The IO object to schedule timeouts.

Flags: Read / Write / Construct Only


The “show-remote-current-lines†property

  “show-remote-current-lines†gboolean

Whether to highlight the line in which the cursor of non-local users is.

Flags: Read / Write

Default value: TRUE


The “show-remote-cursors†property

  “show-remote-cursors†     gboolean

Whether to show cursors of non-local users.

Flags: Read / Write

Default value: TRUE


The “show-remote-selections†property

  “show-remote-selections†  gboolean

Whether to highlight text selected by non-local users.

Flags: Read / Write

Default value: TRUE


The “user-table†property

  “user-table†              InfUserTable *

The user table containing the users of the session shown in the view.

Flags: Read / Write / Construct Only


The “view†property

  “view†                    GtkTextView *

The underlying GtkTextView.

Flags: Read / Write / Construct Only

libinfinity-0.7.1/docs/reference/libinftextgtk/html/PaxHeaders.26529/InfTextGtkViewport.html0000644000000000000000000000013213055210763026772 xustar0030 mtime=1488261619.096072297 30 atime=1488261619.096072297 30 ctime=1488261619.096072297 libinfinity-0.7.1/docs/reference/libinftextgtk/html/InfTextGtkViewport.html0000644000175000017500000006224313055210763027533 0ustar00arminarmin00000000000000 InfTextGtkViewport: libinftextgtk-0.7 Reference Manual

InfTextGtkViewport

InfTextGtkViewport — Drawing position of remote users into the scrollbar

Stability Level

Unstable, unless otherwise indicated

Properties

InfTextUser * active-user Read / Write
GtkScrolledWindow * scrolled-window Read / Write / Construct Only
gboolean show-user-markers Read / Write
InfUserTable * user-table Read / Write / Construct Only

Types and Values

Object Hierarchy

    GObject
    ╰── InfTextGtkViewport

Includes

#include <libinftextgtk/inf-text-gtk-viewport.h>

Description

InfTextGtkViewport is a helper object which, as long as it is alive, draws the location of the cursor of remote users into the scrollbar of a GtkScrolledWindow containing a GtkTextView.

The function inf_text_gtk_viewport_set_active_user() can be used to skip drawing the location of the user working locally on the document, if there is any.

See InfTextGtkView for drawing the cursor and selected region of remote users into a GtkTextView.

Functions

inf_text_gtk_viewport_new ()

InfTextGtkViewport *
inf_text_gtk_viewport_new (GtkScrolledWindow *scroll,
                           InfUserTable *user_table);

Creates a new InfTextGtkViewport for scroll . This draws the position of remote user's cursors into the scrollbars of scroll .

[constructor]

Parameters

scroll

A GtkScrolledWindow.

 

user_table

The InfUserTable for the text session displayed in viewport .

 

Returns

A new InfTextGtkViewport.

[transfer full]


inf_text_gtk_viewport_get_scrolled_window ()

GtkScrolledWindow *
inf_text_gtk_viewport_get_scrolled_window
                               (InfTextGtkViewport *viewport);

Returns the underlying GtkScrolledWindow.

Parameters

viewport

A InfTextGtkViewport.

 

Returns

The InfTextGtkViewport's GtkScrolledWindow.

[transfer none]


inf_text_gtk_viewport_get_user_table ()

InfUserTable *
inf_text_gtk_viewport_get_user_table (InfTextGtkViewport *viewport);

Returns the InfUserTable containing the users of the session the InfTextGtkViewport's GtkScrolledWindow is displaying.

Parameters

viewport

A InfTextGtkViewport.

 

Returns

The InfTextGtkViewport's InfUserTable.

[transfer none]


inf_text_gtk_viewport_set_active_user ()

void
inf_text_gtk_viewport_set_active_user (InfTextGtkViewport *viewport,
                                       InfTextUser *user);

Sets the user for which perspective to draw the viewport. The cursor position for teh active user is not draws since it is assumed that the viewport's "real" scrollbars match the active user's position.

Parameters

viewport

A InfTextGtkViewport.

 

user

A user from viewport 's user table, or NULL.

[allow-none]

inf_text_gtk_viewport_get_active_user ()

InfTextUser *
inf_text_gtk_viewport_get_active_user (InfTextGtkViewport *viewport);

Returns the active user of viewport . See inf_text_gtk_viewport_set_active_user().

Parameters

viewport

A InfTextGtkViewport.

 

Returns

The active user of viewport .

[transfer none][allow-none]


inf_text_gtk_viewport_set_show_user_markers ()

void
inf_text_gtk_viewport_set_show_user_markers
                               (InfTextGtkViewport *viewport,
                                gboolean show);

If show is TRUE then draw a marker indicating the cursor position of all non-local users with status INF_USER_ACTIVE in the scrollbar of the scrolled window. If show is FALSE then do not draw user markers into the scrollbar.

Parameters

viewport

A InfTextGtkViewport.

 

show

Whether to show the position of non-local users.

 

Types and Values

struct InfTextGtkViewport

struct InfTextGtkViewport;

InfTextGtkViewport is an opaque data type. You should only access it via the public API functions.


struct InfTextGtkViewportClass

struct InfTextGtkViewportClass {
};

This structure does not contain any public fields.

Property Details

The “active-user†property

  “active-user†             InfTextUser *

The user for which to show the viewport.

Flags: Read / Write


The “scrolled-window†property

  “scrolled-window†         GtkScrolledWindow *

The underlying GtkScrolledWindow.

Flags: Read / Write / Construct Only


The “show-user-markers†property

  “show-user-markers†       gboolean

Whether to indicate the position of non-local user's cursors in the scrollbar.

Flags: Read / Write

Default value: TRUE


The “user-table†property

  “user-table†              InfUserTable *

The user table containing the users of the session shown in the viewport.

Flags: Read / Write / Construct Only

See Also

InfTextGtkView

libinfinity-0.7.1/docs/reference/libinftextgtk/html/PaxHeaders.26529/annotation-glossary.html0000644000000000000000000000013213055210763027216 xustar0030 mtime=1488261619.096072297 30 atime=1488261619.096072297 30 ctime=1488261619.096072297 libinfinity-0.7.1/docs/reference/libinftextgtk/html/annotation-glossary.html0000644000175000017500000001140313055210763027747 0ustar00arminarmin00000000000000 Annotation Glossary: libinftextgtk-0.7 Reference Manual

Annotation Glossary

A

allow-none

NULL is OK, both for passing and for returning.

C

constructor

This symbol is a constructor, not a static method.

I

in

Parameter for input. Default is transfer none.

O

out

Parameter for returning results. Default is transfer full.

T

transfer floating

Alias for transfer none, used for objects with floating refs.

transfer full

Free data after the code is done.

transfer none

Don't free data after the code is done.

U

Unstable

Unstable interfaces are experimental or transitional. They are typically used to give outside developers early access to new or rapidly changing technology, or to provide an interim solution to a problem where a more general solution is anticipated. No claims are made about either source or binary compatibility from one minor release to the next. The Unstable interface level is a warning that these interfaces are subject to change without warning and should not be used in unbundled products. Given such caveats, customer impact need not be a factor when considering incompatible changes to an Unstable interface in a major or minor release. Nonetheless, when such changes are introduced, the changes should still be mentioned in the release notes for the affected release.

libinfinity-0.7.1/docs/reference/libinftextgtk/html/PaxHeaders.26529/up-insensitive.png0000644000000000000000000000013213055210763026005 xustar0030 mtime=1488261619.056072387 30 atime=1488261619.056072387 30 ctime=1488261619.056072387 libinfinity-0.7.1/docs/reference/libinftextgtk/html/up-insensitive.png0000644000175000017500000000056613055210763026546 0ustar00arminarmin00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEà 4ÓkMIDAT8Ëí’?/QÅÏ™?[êu$¾€V³î›ÑâHTD³ø”ÛˆBM+¡!™ÂÌ<ˆDã+èô[mdÞ\…·bø{º{sÎ/97˜ªSÖÚ£º®»<ìTõ8ŒcÌÉ¿UU­‘¼‡•WÕÍ,Ë®ÿ”e¹EÑ €žªîÉSïmÛ®æy~û+À9·è½¿0`hŒ9u†ªº`Çñr¿ßùpÎÍ{ïÌ8‘m’ ªJkí€-o$—Dä¢  išË¾'¹; ‡ Jr‡äCð\¨*¿HΑ|JÓtCDÆßo#"ã$IÖ<«êBQ½é£êêÉ]•TKúIEND®B`‚libinfinity-0.7.1/docs/reference/libinftextgtk/html/PaxHeaders.26529/index.html0000644000000000000000000000013213055210763024312 xustar0030 mtime=1488261619.096072297 30 atime=1488261619.096072297 30 ctime=1488261619.096072297 libinfinity-0.7.1/docs/reference/libinftextgtk/html/index.html0000644000175000017500000000444413055210763025052 0ustar00arminarmin00000000000000 libinftextgtk-0.7 Reference Manual: libinftextgtk-0.7 Reference Manual

for libinftextgtk 0.7.0. The latest version of this documentation can be found on-line at http://infinote.0x539.de/libinfinity/API/libinftextgtk/.


libinftextgtk API
InfTextGtkBuffer — Synchronizing a text session with a GtkTextBuffer
InfTextGtkView — Drawing remote cursors and selections in a GtkTextView
InfTextGtkViewport — Drawing position of remote users into the scrollbar
InfTextGtkHueChooser — A GTK+ widget for selecting a hue value
Annotation Glossary
libinfinity-0.7.1/docs/reference/libinftextgtk/html/PaxHeaders.26529/ch01.html0000644000000000000000000000013213055210763023736 xustar0030 mtime=1488261619.096072297 30 atime=1488261619.096072297 30 ctime=1488261619.096072297 libinfinity-0.7.1/docs/reference/libinftextgtk/html/ch01.html0000644000175000017500000000465713055210763024504 0ustar00arminarmin00000000000000 libinftextgtk API: libinftextgtk-0.7 Reference Manual

libinftextgtk API

InfTextGtkBuffer — Synchronizing a text session with a GtkTextBuffer
InfTextGtkView — Drawing remote cursors and selections in a GtkTextView
InfTextGtkViewport — Drawing position of remote users into the scrollbar
InfTextGtkHueChooser — A GTK+ widget for selecting a hue value
libinfinity-0.7.1/docs/reference/libinftextgtk/html/PaxHeaders.26529/libinftextgtk-0.7.devhelp20000644000000000000000000000013213055210763027130 xustar0030 mtime=1488261619.056072387 30 atime=1488261619.056072387 30 ctime=1488261619.056072387 libinfinity-0.7.1/docs/reference/libinftextgtk/html/libinftextgtk-0.7.devhelp20000644000175000017500000002372413055210763027672 0ustar00arminarmin00000000000000 libinfinity-0.7.1/docs/reference/libinftextgtk/html/PaxHeaders.26529/up.png0000644000000000000000000000013213055210763023447 xustar0030 mtime=1488261619.056072387 30 atime=1488261619.056072387 30 ctime=1488261619.056072387 libinfinity-0.7.1/docs/reference/libinftextgtk/html/up.png0000644000175000017500000000040413055210763024177 0ustar00arminarmin00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEà 4ÓkM‘IDAT8Ëí’1 ƒ@DŸ•¶{ƒxa™ƒØÄ;$]r =JR´È1,Ë øSd„-©}0°ÌŸÙÏÂÂÎàüo¹L:m-˜¤QÞOäÀ[› Éäåkå T¸zþMÞ Lè¬Ì,š:ךuÀ!tÁK;æ ðP¦õÌôÀp Ot@£l¼ÿò/̵*á§l}IEND®B`‚libinfinity-0.7.1/docs/reference/libinftextgtk/html/PaxHeaders.26529/home.png0000644000000000000000000000013213055210763023753 xustar0030 mtime=1488261619.056072387 30 atime=1488261619.056072387 30 ctime=1488261619.056072387 libinfinity-0.7.1/docs/reference/libinftextgtk/html/home.png0000644000175000017500000000040013055210763024477 0ustar00arminarmin00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEà 4ÓkMIDAT8ËÝÒ½ AÅñßž¦f`n v`6`/¶`Y€š˜Ü¡`f&k$,Ëá}˜ˆ ÌüßÀ0ü§bŒ+Ô¸aQW~bæ ËOà e˜{‡y N°Á£üö[LáØÌ}.pÇiÀ­÷¨BzüžÆmm Šoæ·.I]7Ì^[úÃô;%:å†ÁVIEND®B`‚libinfinity-0.7.1/docs/reference/libinftextgtk/html/PaxHeaders.26529/right-insensitive.png0000644000000000000000000000013213055210763026476 xustar0030 mtime=1488261619.056072387 30 atime=1488261619.056072387 30 ctime=1488261619.056072387 libinfinity-0.7.1/docs/reference/libinftextgtk/html/right-insensitive.png0000644000175000017500000000056513055210763027236 0ustar00arminarmin00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEà 4ÓkMIDAT8ËÍ’±JÃ`…¿ ‚“‹³«/ S’_$ÄÁÁAqrÐÙW(>€“à‚®©“m¥"]\œ„è(‘49.NÚdÒ3¸ß9Ü{á¯eM#MSI‡Î¹·E¯iHz|3{̲l½3 ,K˜k’ž†ÃáV'@EŸEQlwÀŠçyišî·Äqüçù‘™]KÀíh4:mµÄ¦²,;“t˜¤sç\aƒÆR5/¬7'¹W×õp”’Žs×­I’,Kº1³=àËÌÂ0´j0Wg³ÙØ>€Ý ¦­¯PUÕýïð»¤0 §]?qCÒ«™ùιgþ½~œÉkÄAâ…_IEND®B`‚libinfinity-0.7.1/docs/reference/libinftextgtk/html/PaxHeaders.26529/right.png0000644000000000000000000000013213055210763024140 xustar0030 mtime=1488261619.056072387 30 atime=1488261619.056072387 30 ctime=1488261619.056072387 libinfinity-0.7.1/docs/reference/libinftextgtk/html/right.png0000644000175000017500000000040513055210763024671 0ustar00arminarmin00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEà 4ÓkM’IDAT8ËÕÒ¯aÇñ?›M´½IdErš,¾Ù-¸ÑhîAâIl’Í ¯r’äy§ž}¿ç·s¿X6èæ ö!9¢Ÿ#èD‚ Œr$-¬BrÃ$GÒÀ"$”¹;™á‰æŸÍú—WZêä&–!¸cš·±øŠq \`ðÃÔ軀Oä¾ò=QouføòIEND®B`‚libinfinity-0.7.1/docs/reference/libinftextgtk/html/PaxHeaders.26529/InfTextGtkHueChooser.html0000644000000000000000000000013213055210763027217 xustar0030 mtime=1488261619.096072297 30 atime=1488261619.096072297 30 ctime=1488261619.096072297 libinfinity-0.7.1/docs/reference/libinftextgtk/html/InfTextGtkHueChooser.html0000644000175000017500000005432513055210763027762 0ustar00arminarmin00000000000000 InfTextGtkHueChooser: libinftextgtk-0.7 Reference Manual

InfTextGtkHueChooser

InfTextGtkHueChooser — A GTK+ widget for selecting a hue value

Stability Level

Unstable, unless otherwise indicated

Properties

gdouble hue Read / Write / Construct

Signals

Types and Values

Object Hierarchy

    GObject
    ╰── GInitiallyUnowned
        ╰── GtkWidget
            ╰── InfTextGtkHueChooser

Implemented Interfaces

InfTextGtkHueChooser implements AtkImplementorIface and GtkBuildable.

Includes

#include <libinftextgtk/inf-text-gtk-hue-chooser.h>

Description

InfTextGtkHueChooser is a widget which allows the user to select a hue value without selecting also saturation and lightness at the same time. It only presents the hue circle without the inner triangle.

Functions

inf_text_gtk_hue_chooser_new ()

GtkWidget *
inf_text_gtk_hue_chooser_new (void);

Creates a new InfTextGtkHueChooser widget with the initial hue set to 0.0 (red).

[constructor]

Returns

A newly created InfTextGtkHueChooser.

[transfer floating]


inf_text_gtk_hue_chooser_new_with_hue ()

GtkWidget *
inf_text_gtk_hue_chooser_new_with_hue (gdouble hue);

Creates a new InfTextGtkHueChooser widget with the given hue as initial value. hue must be between 0.0 and 1.0.

[constructor]

Parameters

hue

Initial hue value

 

Returns

A newly created InfTextGtkHueChooser.

[transfer floating]


inf_text_gtk_hue_chooser_set_hue ()

void
inf_text_gtk_hue_chooser_set_hue (InfTextGtkHueChooser *chooser,
                                  gdouble hue);

Sets the current hue value of chooser to hue . hue must be between 0.0 and 1.0.

Parameters

chooser

A InfTextGtkHueChooser.

 

hue

New hue value.

 

inf_text_gtk_hue_chooser_get_hue ()

gdouble
inf_text_gtk_hue_chooser_get_hue (InfTextGtkHueChooser *chooser);

Returns the currently selected hue value of chooser .

Parameters

chooser

A InfTextGtkHueChooser.

 

Returns

The current hue value, a number between 0.0 and 1.0.

Types and Values

struct InfTextGtkHueChooser

struct InfTextGtkHueChooser;

InfTextGtkHueChooser is an opaque data type. You should only access it via the public API functions.


struct InfTextGtkHueChooserClass

struct InfTextGtkHueChooserClass {
  void(*hue_change)(InfTextGtkHueChooser* chooser,
                    gdouble hue);

  void(*move)(InfTextGtkHueChooser* chooser,
              GtkDirectionType direction);
};

This structure contains default signal handlers of the InfTextGtkHueChooser class.

Members

hue_change ()

Default signal handler for the “hue-change†signal.

 

move ()

Default signal handler for the “move†signal.

 

Property Details

The “hue†property

  “hue†                     gdouble

The current hue value.

Flags: Read / Write / Construct

Allowed values: [0,1]

Default value: 0

Signal Details

The “hue-change†signal

void
user_function (InfTextGtkHueChooser *chooser,
               gdouble               hue,
               gpointer              user_data)

This signal is emitted whenever the hue value is changed.

Parameters

chooser

The InfTextGtkHueChooser emitting the signal.

 

hue

The new hue value.

 

user_data

user data set when the signal handler was connected.

 

Flags: Run Last


The “move†signal

void
user_function (InfTextGtkHueChooser *chooser,
               GtkDirectionType      direction,
               gpointer              user_data)

This is an action signal emitted when the selection is moved by the user.

Parameters

chooser

The InfTextGtkHueChooser emitting the signal.

 

direction

The direction in which the move was mode.

 

user_data

user data set when the signal handler was connected.

 

Flags: Action

libinfinity-0.7.1/docs/reference/libinftextgtk/html/PaxHeaders.26529/style.css0000644000000000000000000000013213055210763024167 xustar0030 mtime=1488261619.056072387 30 atime=1488261619.056072387 30 ctime=1488261619.056072387 libinfinity-0.7.1/docs/reference/libinftextgtk/html/style.css0000644000175000017500000002115413055210763024724 0ustar00arminarmin00000000000000body { font-family: cantarell, sans-serif; } .synopsis, .classsynopsis { /* tango:aluminium 1/2 */ background: #eeeeec; background: rgba(238, 238, 236, 0.5); border: solid 1px rgb(238, 238, 236); padding: 0.5em; } .programlisting { /* tango:sky blue 0/1 */ /* fallback for no rgba support */ background: #e6f3ff; border: solid 1px #729fcf; background: rgba(114, 159, 207, 0.1); border: solid 1px rgba(114, 159, 207, 0.2); padding: 0.5em; } .variablelist { padding: 4px; margin-left: 3em; } .variablelist td:first-child { vertical-align: top; } div.gallery-float { float: left; padding: 10px; } div.gallery-float img { border-style: none; } div.gallery-spacer { clear: both; } a, a:visited { text-decoration: none; /* tango:sky blue 2 */ color: #3465a4; } a:hover { text-decoration: underline; /* tango:sky blue 1 */ color: #729fcf; } div.informaltable table { border-collapse: separate; border-spacing: 1em 0.3em; border: none; } div.informaltable table td, div.informaltable table th { vertical-align: top; } .function_type, .variable_type, .property_type, .signal_type, .parameter_name, .struct_member_name, .union_member_name, .define_keyword, .datatype_keyword, .typedef_keyword { text-align: right; } /* dim non-primary columns */ .c_punctuation, .function_type, .variable_type, .property_type, .signal_type, .define_keyword, .datatype_keyword, .typedef_keyword, .property_flags, .signal_flags, .parameter_annotations, .enum_member_annotations, .struct_member_annotations, .union_member_annotations { color: #888a85; } .function_type a, .function_type a:visited, .function_type a:hover, .property_type a, .property_type a:visited, .property_type a:hover, .signal_type a, .signal_type a:visited, .signal_type a:hover, .signal_flags a, .signal_flags a:visited, .signal_flags a:hover { color: #729fcf; } td p { margin: 0.25em; } div.table table { border-collapse: collapse; border-spacing: 0px; /* tango:aluminium 3 */ border: solid 1px #babdb6; } div.table table td, div.table table th { /* tango:aluminium 3 */ border: solid 1px #babdb6; padding: 3px; vertical-align: top; } div.table table th { /* tango:aluminium 2 */ background-color: #d3d7cf; } h4 { color: #555753; margin-top: 1em; margin-bottom: 1em; } hr { /* tango:aluminium 1 */ color: #d3d7cf; background: #d3d7cf; border: none 0px; height: 1px; clear: both; margin: 2.0em 0em 2.0em 0em; } dl.toc dt { padding-bottom: 0.25em; } dl.toc > dt { padding-top: 0.25em; padding-bottom: 0.25em; font-weight: bold; } dl.toc > dl { padding-bottom: 0.5em; } .parameter { font-style: normal; } .footer { padding-top: 3.5em; /* tango:aluminium 3 */ color: #babdb6; text-align: center; font-size: 80%; } .informalfigure, .figure { margin: 1em; } .informalexample, .example { margin-top: 1em; margin-bottom: 1em; } .warning { /* tango:orange 0/1 */ background: #ffeed9; background: rgba(252, 175, 62, 0.1); border-color: #ffb04f; border-color: rgba(252, 175, 62, 0.2); } .note { /* tango:chameleon 0/0.5 */ background: #d8ffb2; background: rgba(138, 226, 52, 0.1); border-color: #abf562; border-color: rgba(138, 226, 52, 0.2); } div.blockquote { border-color: #eeeeec; } .note, .warning, div.blockquote { padding: 0.5em; border-width: 1px; border-style: solid; margin: 2em; } .note p, .warning p { margin: 0; } div.warning h3.title, div.note h3.title { display: none; } p + div.section { margin-top: 1em; } div.refnamediv, div.refsynopsisdiv, div.refsect1, div.refsect2, div.toc, div.section { margin-bottom: 1em; } /* blob links */ h2 .extralinks, h3 .extralinks { float: right; /* tango:aluminium 3 */ color: #babdb6; font-size: 80%; font-weight: normal; } .lineart { color: #d3d7cf; font-weight: normal; } .annotation { /* tango:aluminium 5 */ color: #555753; font-weight: normal; } .structfield { font-style: normal; font-weight: normal; } acronym,abbr { border-bottom: 1px dotted gray; } /* code listings */ .listing_code .programlisting .normal, .listing_code .programlisting .normal a, .listing_code .programlisting .number, .listing_code .programlisting .cbracket, .listing_code .programlisting .symbol { color: #555753; } .listing_code .programlisting .comment, .listing_code .programlisting .linenum { color: #babdb6; } /* tango: aluminium 3 */ .listing_code .programlisting .function, .listing_code .programlisting .function a, .listing_code .programlisting .preproc { color: #204a87; } /* tango: sky blue 3 */ .listing_code .programlisting .string { color: #ad7fa8; } /* tango: plum */ .listing_code .programlisting .keyword, .listing_code .programlisting .usertype, .listing_code .programlisting .type, .listing_code .programlisting .type a { color: #4e9a06; } /* tango: chameleon 3 */ .listing_frame { /* tango:sky blue 1 */ border: solid 1px #729fcf; border: solid 1px rgba(114, 159, 207, 0.2); padding: 0px; } .listing_lines, .listing_code { margin-top: 0px; margin-bottom: 0px; padding: 0.5em; } .listing_lines { /* tango:sky blue 0.5 */ background: #a6c5e3; background: rgba(114, 159, 207, 0.2); /* tango:aluminium 6 */ color: #2e3436; } .listing_code { /* tango:sky blue 0 */ background: #e6f3ff; background: rgba(114, 159, 207, 0.1); } .listing_code .programlisting { /* override from previous */ border: none 0px; padding: 0px; background: none; } .listing_lines pre, .listing_code pre { margin: 0px; } @media screen { /* these have a as a first child, but since there are no parent selectors * we can't use that. */ a.footnote { position: relative; top: 0em ! important; } /* this is needed so that the local anchors are displayed below the naviagtion */ div.footnote a[name], div.refnamediv a[name], div.refsect1 a[name], div.refsect2 a[name], div.index a[name], div.glossary a[name], div.sect1 a[name] { display: inline-block; position: relative; top:-5em; } /* this seems to be a bug in the xsl style sheets when generating indexes */ div.index div.index { top: 0em; } /* make space for the fixed navigation bar and add space at the bottom so that * link targets appear somewhat close to top */ body { padding-top: 2.5em; padding-bottom: 500px; max-width: 60em; } p { max-width: 60em; } /* style and size the navigation bar */ table.navigation#top { position: fixed; background: #e2e2e2; border-bottom: solid 1px #babdb6; border-spacing: 5px; margin-top: 0; margin-bottom: 0; top: 0; left: 0; z-index: 10; } table.navigation#top td { padding-left: 6px; padding-right: 6px; } .navigation a, .navigation a:visited { /* tango:sky blue 3 */ color: #204a87; } .navigation a:hover { /* tango:sky blue 2 */ color: #3465a4; } td.shortcuts { /* tango:sky blue 2 */ color: #3465a4; font-size: 80%; white-space: nowrap; } td.shortcuts .dim { color: #babdb6; } .navigation .title { font-size: 80%; max-width: none; margin: 0px; font-weight: normal; } } @media screen and (min-width: 60em) { /* screen larger than 60em */ body { margin: auto; } } @media screen and (max-width: 60em) { /* screen less than 60em */ #nav_hierarchy { display: none; } #nav_interfaces { display: none; } #nav_prerequisites { display: none; } #nav_derived_interfaces { display: none; } #nav_implementations { display: none; } #nav_child_properties { display: none; } #nav_style_properties { display: none; } #nav_index { display: none; } #nav_glossary { display: none; } .gallery_image { display: none; } .property_flags { display: none; } .signal_flags { display: none; } .parameter_annotations { display: none; } .enum_member_annotations { display: none; } .struct_member_annotations { display: none; } .union_member_annotations { display: none; } /* now that a column is hidden, optimize space */ col.parameters_name { width: auto; } col.parameters_description { width: auto; } col.struct_members_name { width: auto; } col.struct_members_description { width: auto; } col.enum_members_name { width: auto; } col.enum_members_description { width: auto; } col.union_members_name { width: auto; } col.union_members_description { width: auto; } .listing_lines { display: none; } } @media print { table.navigation { visibility: collapse; display: none; } div.titlepage table.navigation { visibility: visible; display: table; background: #e2e2e2; border: solid 1px #babdb6; margin-top: 0; margin-bottom: 0; top: 0; left: 0; height: 3em; } } libinfinity-0.7.1/docs/reference/libinftextgtk/html/PaxHeaders.26529/left.png0000644000000000000000000000013213055210763023755 xustar0030 mtime=1488261619.056072387 30 atime=1488261619.056072387 30 ctime=1488261619.056072387 libinfinity-0.7.1/docs/reference/libinftextgtk/html/left.png0000644000175000017500000000040613055210763024507 0ustar00arminarmin00000000000000‰PNG  IHDRóÿabKGDÿÿÿ ½§“ pHYs × ×B(›xtIMEà 4ÓkM“IDAT8ËÕÒ¯Áa‡ñ?ÁDAPY‘\‚$‹º[p¢+ÐÜIÐIªMlfü('Úì}MpâÙyží{Îá_ª…ž¨¤ÂÞ¥Â}œ^£‘q xZ <Æ=àYjî) <0ù4\~Ó+Púöl#Ü"ÂÕÉ—,QÏ‘ôp ÉÍIÇlswÒÆ>÷•[/]_i0‘3ÃIEND®B`‚libinfinity-0.7.1/docs/reference/libinftextgtk/html/PaxHeaders.26529/InfTextGtkBuffer.html0000644000000000000000000000013213055210763026364 xustar0030 mtime=1488261619.100072288 30 atime=1488261619.100072288 30 ctime=1488261619.100072288 libinfinity-0.7.1/docs/reference/libinftextgtk/html/InfTextGtkBuffer.html0000644000175000017500000021677313055210763027136 0ustar00arminarmin00000000000000 InfTextGtkBuffer: libinftextgtk-0.7 Reference Manual

InfTextGtkBuffer

InfTextGtkBuffer — Synchronizing a text session with a GtkTextBuffer

Stability Level

Unstable, unless otherwise indicated

Properties

InfTextUser * active-user Read / Write
gdouble alpha Read / Write
GtkTextBuffer * buffer Read / Write / Construct Only
gdouble saturation Read / Write
gboolean show-user-colors Read / Write
InfUserTable * user-table Read / Write / Construct Only
gdouble value Read / Write
gboolean wake-on-cursor-movement Read / Write

Types and Values

Object Hierarchy

    GObject
    ╰── InfTextGtkBuffer

Implemented Interfaces

InfTextGtkBuffer implements InfBuffer and InfTextBuffer.

Includes

#include <libinftextgtk/inf-text-gtk-buffer.h>

Description

InfTextGtkBuffer is an implementation of the InfTextBuffer interface. It can therefore be used as a backend for InfTextSessions to store their text. The buffer is implemented by using a GtkTextBuffer as storage. This way the text document can be displayed using a GtkTextView such that only one copy of the text is held in memory, which is used both by the user interface toolkit and the text synchronization functionality.

If external changes are made to the GtkTextBuffer, for example by a user typing into a GtkTextView, then the text is synchronized to other participants of the session. For this purpose, inf_text_gtk_buffer_set_active_user() should be called with a user that was previously joined into the session using inf_session_proxy_join_user(). If there is no local user in the session, no modifications to the buffer must be made because they cannot be synchronized to other participants.

This class also takes care of setting background colors for the text to indicate which user wrote what text, by adding corresponding GtkTextTags to the document. The function inf_text_gtk_buffer_set_show_user_colors() to turn on or off the colored background. Even if background coloring is turned off, the text is still tagged according to the authorship, so that coloring can be turned on at a later point or so that the authorship can still be queried for other means, such as in a "blame" kind of functionality.

Functions

inf_text_gtk_buffer_new ()

InfTextGtkBuffer *
inf_text_gtk_buffer_new (GtkTextBuffer *buffer,
                         InfUserTable *user_table);

Creates a new InfTextGtkBuffer wrapping buffer . It implements the InfTextBuffer interface by using buffer to store the text. User colors are read from the users from user_table .

[constructor]

Parameters

buffer

The underlaying GtkTextBuffer.

 

user_table

The InfUserTable containing the participating users.

 

Returns

A InfTextGtkBuffer.

[transfer full]


inf_text_gtk_buffer_get_text_buffer ()

GtkTextBuffer *
inf_text_gtk_buffer_get_text_buffer (InfTextGtkBuffer *buffer);

Returns the underlaying GtkTextBuffer.

Parameters

buffer

A InfTextGtkBuffer.

 

Returns

A GtkTextBuffer.

[transfer none]


inf_text_gtk_buffer_set_active_user ()

void
inf_text_gtk_buffer_set_active_user (InfTextGtkBuffer *buffer,
                                     InfTextUser *user);

Sets the active user for buffer . The active user is the user by which edits not issued through the InfTextBuffer interface are performed (for example, edits by the user when the underlaying buffer is displayed in a GtkTextView).

Note that such modifications should not be performed when no active user is set. Note also the active user must be available and have the INF_USER_LOCAL flag set.

Parameters

buffer

A InfTextGtkBuffer.

 

user

A InfTextUser, or NULL.

[allow-none]

inf_text_gtk_buffer_get_active_user ()

InfTextUser *
inf_text_gtk_buffer_get_active_user (InfTextGtkBuffer *buffer);

Returns the current active user for buffer .

Parameters

buffer

A InfTextGtkBuffer.

 

Returns

A InfTextUser.

[transfer none][allow-none]


inf_text_gtk_buffer_get_author ()

InfTextUser *
inf_text_gtk_buffer_get_author (InfTextGtkBuffer *buffer,
                                GtkTextIter *location);

Returns the InfTextUser which wrote the character at location . If there is no such user, then NULL is returned.

Parameters

buffer

A InfTextGtkBuffer.

 

location

A GtkTextIter which is not the end iterator.

 

Returns

A InfTextUser, or NULL.

[transfer none][allow-none]


inf_text_gtk_buffer_get_user_for_tag ()

InfTextUser *
inf_text_gtk_buffer_get_user_for_tag (InfTextGtkBuffer *buffer,
                                      GtkTextTag *tag);

If tag is an author tag, i.e. used by buffer to mark text that a certain user has written, then this function returns the InfTextUser whose text is marked by tag . If tag is not an author tag then the function returns NULL.

Parameters

buffer

A InfTextGtkBuffer.

 

tag

A GtkTextTag from buffer 's underlying GtkTextBuffer's tag table.

 

Returns

A InfTextUser, or NULL.

[transfer none][allow-none]


inf_text_gtk_buffer_is_author_toggle ()

gboolean
inf_text_gtk_buffer_is_author_toggle (InfTextGtkBuffer *buffer,
                                      const GtkTextIter *iter,
                                      InfTextUser **user_on,
                                      InfTextUser **user_off);

This function returns TRUE if the author of the text in buffer changes at iter , or FALSE otherwise. If it returns TRUE, then the user who authored the text to the right hand side of iter is stored in user_on (if non-NULL) and the author of the text to the left hand side of iter is stored in user_off (if non-NULL). Both can also be set to NULL if there is unowned text in the buffer or if iter is at the start or end of the buffer.

Parameters

buffer

A InfTextGtkBuffer.

 

iter

A GtkTextIter pointing into buffer 's underlying GtkTextBuffer.

 

user_on

A location to store a InfTextUser, or NULL.

[out][allow-none]

user_off

Another location to store a InfTextUser, or NULL.

[out][allow-none]

Returns

Whether text attribution changes at iter .


inf_text_gtk_buffer_forward_to_author_toggle ()

gboolean
inf_text_gtk_buffer_forward_to_author_toggle
                               (InfTextGtkBuffer *buffer,
                                GtkTextIter *iter,
                                InfTextUser **user_on,
                                InfTextUser **user_off);

Moves iter to the next point in buffer 's underlying GtkTextBuffer where the text has been written by another user. If iter points to the end of the buffer, then the function does nothing and returns FALSE. Otherwise it returns TRUE and sets user_on to the user which has written the text on the right hand side of the location iter has been moved to (if non-NULL) and user_off to the user which has written the left hand side of the location iter has been moved to.

Parameters

buffer

A InfTextGtkBuffer.

 

iter

A GtkTextIter pointing into buffer 's underlying GtkTextBuffer.

 

user_on

A location to store a InfTextUser, or NULL.

[out][allow-none]

user_off

Another location to store a InfTextUser, or NULL.

[out][allow-none]

Returns

TRUE if iter was moved, or FALSE otherwise.


inf_text_gtk_buffer_backward_to_author_toggle ()

gboolean
inf_text_gtk_buffer_backward_to_author_toggle
                               (InfTextGtkBuffer *buffer,
                                GtkTextIter *iter,
                                InfTextUser **user_on,
                                InfTextUser **user_off);

Moves iter to the previous point in buffer 's underlying GtkTextBuffer where the text has been written by another user. If iter points to the beginning of the buffer, then the function does nothing and returns FALSE. Otherwise it returns TRUE and sets user_on to the user which has written the text on the right hand side of the location iter has been moved to (if non-NULL) and user_off to the user which has written the left hand side of the location iter has been moved to.

Parameters

buffer

A InfTextGtkBuffer.

 

iter

A GtkTextIter pointing into buffer 's underlying GtkTextBuffer.

 

user_on

A location to store a InfTextUser, or NULL.

[out][allow-none]

user_off

Another location to store a InfTextUser, or NULL.

[out][allow-none]

Returns

TRUE if iter was moved, or FALSE otherwise.


inf_text_gtk_buffer_set_wake_on_cursor_movement ()

void
inf_text_gtk_buffer_set_wake_on_cursor_movement
                               (InfTextGtkBuffer *buffer,
                                gboolean wake);

This function spcecifies whether movement of the insertion point or selection bound of the underlying text buffer causes the active user (see inf_text_gtk_buffer_set_active_user()) to become active when its status is INF_USER_INACTIVE.

If wake is TRUE, then the user status changes to INF_USER_ACTIVE in that case. If wake is FALSE, then the user status stays INF_USER_INACTIVE, and its caret-position and selection-length properties will be no longer be synchronized to the buffer marks until the user is set active again.

Parameters

buffer

A InfTextGtkBuffer.

 

wake

Whether to make inactive users active on cursor movement.

 

inf_text_gtk_buffer_get_wake_on_cursor_movement ()

gboolean
inf_text_gtk_buffer_get_wake_on_cursor_movement
                               (InfTextGtkBuffer *buffer);

Returns whether movement of the insertion point or selection bound of the underlying text buffer causes whether the active user (see inf_text_gtk_buffer_set_active_user()) to become active when its status is INF_USER_INACTIVE. See also inf_text_gtk_buffer_set_wake_on_cursor_movement().

Parameters

buffer

A InfTextGtkBuffer.

 

Returns

Whether to make inactive users active when the insertion mark is moved.


inf_text_gtk_buffer_ensure_author_tags_priority ()

void
inf_text_gtk_buffer_ensure_author_tags_priority
                               (InfTextGtkBuffer *buffer);

Ensures that all author tags have the lowest priority of all tags in the underlying GtkTextBuffer's tag table. Normally you do not need to use this function if you do not set the priority for your tags explicitely. However, if you do (or are forced to do, because you are using a library that does this, such as GtkSourceView), then you can call this function afterwards to make sure all the user tags have the lowest priority.

Parameters

buffer

A InfTextGtkBuffer.

 

inf_text_gtk_buffer_set_saturation_value ()

void
inf_text_gtk_buffer_set_saturation_value
                               (InfTextGtkBuffer *buffer,
                                gdouble saturation,
                                gdouble value);

Sets the saturation and value to use for user colors in a HSV color model. The hue is defined by each user's individual color. The reason why S and V are set locally the same for all users is that they can be adjusted depending on one's theme: Dark themes want dark user colors, bright themes want bright ones.

Parameters

buffer

A InfTextGtkBuffer.

 

saturation

Saturation to use for user colors.

 

value

Value to use for user colors.

 

inf_text_gtk_buffer_set_fade ()

void
inf_text_gtk_buffer_set_fade (InfTextGtkBuffer *buffer,
                              gdouble alpha);

This functions can be used to show the user background color with limited intensity, such that the background of the GtkTextView showing the buffer partly shines through.

An alpha value of 1.0 means to fully show the user background color, a value of 0.0 means to show the given background color. Values inbetween interpolate linearly between the two colors in RGB color space.

The default value for alpha is 1.0.

Parameters

buffer

A InfTextGtkBuffer.

 

alpha

An alpha value between 0.0 and 1.0.

 

inf_text_gtk_buffer_get_saturation ()

gdouble
inf_text_gtk_buffer_get_saturation (InfTextGtkBuffer *buffer);

Returns the saturation part of the HSV user color.

Parameters

buffer

A InfTextGtkBuffer.

 

Returns

The saturation used for user colors.


inf_text_gtk_buffer_get_value ()

gdouble
inf_text_gtk_buffer_get_value (InfTextGtkBuffer *buffer);

Returns the value part of the HSV user color.

Parameters

buffer

A InfTextGtkBuffer.

 

Returns

The value used for user colors.


inf_text_gtk_buffer_set_show_user_colors ()

void
inf_text_gtk_buffer_set_show_user_colors
                               (InfTextGtkBuffer *buffer,
                                gboolean show);

If show is TRUE (the default), then the user color is used as background for newly written text by that user. Otherwise, newly written text has no background color.

Note that this setting is for newly written text only. If you want to show or hide user colors for existing text use inf_text_gtk_buffer_show_user_colors().

Parameters

buffer

A InfTextGtkBuffer.

 

show

Whether to show user colors or not.

 

inf_text_gtk_buffer_get_show_user_colors ()

gboolean
inf_text_gtk_buffer_get_show_user_colors
                               (InfTextGtkBuffer *buffer);

Returns whether newly written text is attributed with the author's user color or not.

Parameters

buffer

A InfTextGtkBuffer.

 

Returns

TRUE if user color is applied to newly written text, or FALSE otherwise.


inf_text_gtk_buffer_show_user_colors ()

void
inf_text_gtk_buffer_show_user_colors (InfTextGtkBuffer *buffer,
                                      gboolean show,
                                      GtkTextIter *start,
                                      GtkTextIter *end);

If show is FALSE, then don't show user colors (which user wrote what text) as the background of the text, in the range from start to end . If show is TRUE, show user colors if they have previously been hidden via a call to this function with show being FALSE.

Parameters

buffer

A InfTextGtkBuffer.

 

show

Whether to show or hide user colors.

 

start

Beginning of the range for which to show or hide user colors.

[in][transfer none]

end

End of the range for which to show or hide user colors.

[in][transfer none]

Types and Values

struct InfTextGtkBuffer

struct InfTextGtkBuffer;

InfTextGtkBuffer is an opaque data type. You should only access it via the public API functions.


struct InfTextGtkBufferClass

struct InfTextGtkBufferClass {
};

This structure does not contain any public fields.

Property Details

The “active-user†property

  “active-user†             InfTextUser *

The user currently inserting text locally.

Flags: Read / Write


The “alpha†property

  “alpha†                   gdouble

The translucency of the user color.

Flags: Read / Write

Allowed values: [0,1]

Default value: 1


The “buffer†property

  “buffer†                  GtkTextBuffer *

The underlaying GtkTextBuffer.

Flags: Read / Write / Construct Only


The “saturation†property

  “saturation†              gdouble

Saturation of user colors in a HSV color model.

Flags: Read / Write

Allowed values: [0,1]

Default value: 0.35


The “show-user-colors†property

  “show-user-colors†        gboolean

Whether to show user colors initially for newly written text.

Flags: Read / Write

Default value: TRUE


The “user-table†property

  “user-table†              InfUserTable *

A user table of the participating users.

Flags: Read / Write / Construct Only


The “value†property

  “value†                   gdouble

Value of user colors in a HSV color model.

Flags: Read / Write

Allowed values: [0,1]

Default value: 1


The “wake-on-cursor-movement†property

  “wake-on-cursor-movement† gboolean

Whether to make inactive users active when the insertion mark in the TextBuffer moves.

Flags: Read / Write

Default value: FALSE

See Also

InfTextBuffer

libinfinity-0.7.1/docs/reference/libinftextgtk/PaxHeaders.26529/Makefile.in0000644000000000000000000000013213051241007023405 xustar0030 mtime=1487225351.797148713 30 atime=1487225351.797148713 30 ctime=1488261617.756075311 libinfinity-0.7.1/docs/reference/libinftextgtk/Makefile.in0000644000175000017500000006734213051241007024153 0ustar00arminarmin00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 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@ # -*- mode: makefile -*- #################################### # Everything below here is generic # #################################### VPATH = @srcdir@ am__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) 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@ subdir = docs/reference/libinftextgtk ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/gtk-doc.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/libinfinity/inf-config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = SOURCES = DIST_SOURCES = am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/gtk-doc.make DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ 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@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIRNAME = @DATADIRNAME@ 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@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ GTKDOC_CHECK = @GTKDOC_CHECK@ GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ GTKDOC_MKPDF = @GTKDOC_MKPDF@ GTKDOC_REBASE = @GTKDOC_REBASE@ HTML_DIR = @HTML_DIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INSTOBJEXT = @INSTOBJEXT@ INTLLIBS = @INTLLIBS@ INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBINFINITY_API_VERSION = @LIBINFINITY_API_VERSION@ LIBINFINITY_LIBTOOL_VERSION = @LIBINFINITY_LIBTOOL_VERSION@ LIBINFINITY_VERSION = @LIBINFINITY_VERSION@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGFMT_OPTS = @MSGFMT_OPTS@ 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@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ 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@ avahi_CFLAGS = @avahi_CFLAGS@ avahi_LIBS = @avahi_LIBS@ 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@ gio_CFLAGS = @gio_CFLAGS@ gio_LIBS = @gio_LIBS@ gtk_requirement = @gtk_requirement@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infgtk_CFLAGS = @infgtk_CFLAGS@ infgtk_LIBS = @infgtk_LIBS@ infinity_CFLAGS = @infinity_CFLAGS@ infinity_LIBS = @infinity_LIBS@ infinoted_CFLAGS = @infinoted_CFLAGS@ infinoted_LIBS = @infinoted_LIBS@ infodir = @infodir@ inftext_CFLAGS = @inftext_CFLAGS@ inftext_LIBS = @inftext_LIBS@ inftextgtk_CFLAGS = @inftextgtk_CFLAGS@ inftextgtk_LIBS = @inftextgtk_LIBS@ install_sh = @install_sh@ libdaemon_CFLAGS = @libdaemon_CFLAGS@ libdaemon_LIBS = @libdaemon_LIBS@ 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@ runstatedir = @runstatedir@ 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@ # We require automake 1.6 at least. AUTOMAKE_OPTIONS = 1.6 # This is a blank Makefile.am for using gtk-doc. # Copy this to your project's API docs directory and modify the variables to # suit your project. See the GTK+ Makefiles in gtk+/docs/reference for examples # of using the various options. # The name of the module, e.g. 'glib'. DOC_MODULE = libinftextgtk-$(LIBINFINITY_API_VERSION) # The top-level SGML file. You can change this if you want to. DOC_MAIN_SGML_FILE = $(DOC_MODULE)-docs.sgml # The directory containing the source code. Relative to $(srcdir). # gtk-doc will search all .c & .h files beneath here for inline comments # documenting the functions and macros. # e.g. DOC_SOURCE_DIR=../../../gtk DOC_SOURCE_DIR = $(top_srcdir)/libinftextgtk # Extra options to pass to gtkdoc-scangobj. Not normally needed. SCANGOBJ_OPTIONS = # Extra options to supply to gtkdoc-scan. # e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED" SCAN_OPTIONS = --rebuild-types # Extra options to supply to gtkdoc-mkdb. # e.g. MKDB_OPTIONS=--sgml-mode --output-format=xml MKDB_OPTIONS = --sgml-mode --output-format=xml # Extra options to supply to gtkdoc-mktmpl # e.g. MKTMPL_OPTIONS=--only-section-tmpl MKTMPL_OPTIONS = # Extra options to supply to gtkdoc-fixref. Not normally needed. # e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html FIXXREF_OPTIONS = \ --extra-dir=../libinfinity/html \ --extra-dir=../libinftext/html \ --extra-dir=../libinfgtk/html # Used for dependencies. The docs will be rebuilt if any of these change. # e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h # e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c HFILE_GLOB = \ $(top_srcdir)/libinftextgtk/*.h CFILE_GLOB = \ $(top_srcdir)/libinftextgtk/*.c # Header files to ignore when scanning. # e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h IGNORE_HFILES = # Images to copy into HTML directory. # e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png HTML_IMAGES = # Extra SGML files that are included by $(DOC_MAIN_SGML_FILE). # e.g. content_files=running.sgml building.sgml changes-2.0.sgml content_files = \ ../version.xml # SGML files where gtk-doc abbrevations (#GtkWidget) are expanded # These files must be listed here *and* in content_files # e.g. expand_content_files=running.sgml expand_content_files = # CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library. # Only needed if you are using gtkdoc-scangobj to dynamically query widget # signals and properties. # e.g. INCLUDES=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS) # e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib) #INCLUDES=$(inftextgtk_CFLAGS) AM_CPPFLAGS = $(inftextgtk_CFLAGS) GTKDOC_LIBS = \ $(inftextgtk_LIBS) \ $(top_builddir)/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(top_builddir)/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ $(top_builddir)/libinfgtk/libinfgtk-$(LIBINFINITY_API_VERSION).la \ $(top_builddir)/libinftextgtk/libinftextgtk-$(LIBINFINITY_API_VERSION).la @GTK_DOC_USE_LIBTOOL_FALSE@GTKDOC_CC = $(CC) $(INCLUDES) $(GTKDOC_DEPS_CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) @GTK_DOC_USE_LIBTOOL_TRUE@GTKDOC_CC = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(INCLUDES) $(GTKDOC_DEPS_CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) @GTK_DOC_USE_LIBTOOL_FALSE@GTKDOC_LD = $(CC) $(GTKDOC_DEPS_LIBS) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) @GTK_DOC_USE_LIBTOOL_TRUE@GTKDOC_LD = $(LIBTOOL) --tag=CC --mode=link $(CC) $(GTKDOC_DEPS_LIBS) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) @GTK_DOC_USE_LIBTOOL_FALSE@GTKDOC_RUN = @GTK_DOC_USE_LIBTOOL_TRUE@GTKDOC_RUN = $(LIBTOOL) --mode=execute # We set GPATH here; this gives us semantics for GNU make # which are more like other make's VPATH, when it comes to # whether a source that is a target of one rule is then # searched for in VPATH/GPATH. # GPATH = $(srcdir) TARGET_DIR = $(HTML_DIR)/$(DOC_MODULE) SETUP_FILES = \ $(content_files) \ $(expand_content_files) \ $(DOC_MAIN_SGML_FILE) \ $(DOC_MODULE)-sections.txt \ $(DOC_MODULE)-overrides.txt # This includes the standard gtk-doc make rules, copied by gtkdocize. # Other files to distribute # e.g. EXTRA_DIST += version.xml.in EXTRA_DIST = $(HTML_IMAGES) $(SETUP_FILES) DOC_STAMPS = setup-build.stamp scan-build.stamp sgml-build.stamp \ html-build.stamp pdf-build.stamp \ sgml.stamp html.stamp pdf.stamp SCANOBJ_FILES = \ $(DOC_MODULE).args \ $(DOC_MODULE).hierarchy \ $(DOC_MODULE).interfaces \ $(DOC_MODULE).prerequisites \ $(DOC_MODULE).signals REPORT_FILES = \ $(DOC_MODULE)-undocumented.txt \ $(DOC_MODULE)-undeclared.txt \ $(DOC_MODULE)-unused.txt CLEANFILES = $(SCANOBJ_FILES) $(REPORT_FILES) $(DOC_STAMPS) gtkdoc-check.test @GTK_DOC_BUILD_HTML_FALSE@HTML_BUILD_STAMP = @GTK_DOC_BUILD_HTML_TRUE@HTML_BUILD_STAMP = html-build.stamp @GTK_DOC_BUILD_PDF_FALSE@PDF_BUILD_STAMP = @GTK_DOC_BUILD_PDF_TRUE@PDF_BUILD_STAMP = pdf-build.stamp #### setup #### GTK_DOC_V_SETUP = $(GTK_DOC_V_SETUP_$(V)) GTK_DOC_V_SETUP_ = $(GTK_DOC_V_SETUP_$(AM_DEFAULT_VERBOSITY)) GTK_DOC_V_SETUP_0 = @echo " DOC Preparing build"; #### scan #### GTK_DOC_V_SCAN = $(GTK_DOC_V_SCAN_$(V)) GTK_DOC_V_SCAN_ = $(GTK_DOC_V_SCAN_$(AM_DEFAULT_VERBOSITY)) GTK_DOC_V_SCAN_0 = @echo " DOC Scanning header files"; GTK_DOC_V_INTROSPECT = $(GTK_DOC_V_INTROSPECT_$(V)) GTK_DOC_V_INTROSPECT_ = $(GTK_DOC_V_INTROSPECT_$(AM_DEFAULT_VERBOSITY)) GTK_DOC_V_INTROSPECT_0 = @echo " DOC Introspecting gobjects"; #### xml #### GTK_DOC_V_XML = $(GTK_DOC_V_XML_$(V)) GTK_DOC_V_XML_ = $(GTK_DOC_V_XML_$(AM_DEFAULT_VERBOSITY)) GTK_DOC_V_XML_0 = @echo " DOC Building XML"; #### html #### GTK_DOC_V_HTML = $(GTK_DOC_V_HTML_$(V)) GTK_DOC_V_HTML_ = $(GTK_DOC_V_HTML_$(AM_DEFAULT_VERBOSITY)) GTK_DOC_V_HTML_0 = @echo " DOC Building HTML"; GTK_DOC_V_XREF = $(GTK_DOC_V_XREF_$(V)) GTK_DOC_V_XREF_ = $(GTK_DOC_V_XREF_$(AM_DEFAULT_VERBOSITY)) GTK_DOC_V_XREF_0 = @echo " DOC Fixing cross-references"; #### pdf #### GTK_DOC_V_PDF = $(GTK_DOC_V_PDF_$(V)) GTK_DOC_V_PDF_ = $(GTK_DOC_V_PDF_$(AM_DEFAULT_VERBOSITY)) GTK_DOC_V_PDF_0 = @echo " DOC Building PDF"; # Files not to distribute # for --rebuild-types in $(SCAN_OPTIONS), e.g. $(DOC_MODULE).types # for --rebuild-sections in $(SCAN_OPTIONS) e.g. $(DOC_MODULE)-sections.txt DISTCLEANFILES = libinftextgtk-$(LIBINFINITY_API_VERSION).types version.xml all: all-am .SUFFIXES: $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/gtk-doc.make $(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) --foreign docs/reference/libinftextgtk/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign docs/reference/libinftextgtk/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_srcdir)/gtk-doc.make $(am__empty): $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs tags TAGS: ctags CTAGS: cscope cscopelist: 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 $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-hook check-am: all-am check: check-am @ENABLE_GTK_DOC_FALSE@all-local: all-am: Makefile all-local installdirs: install: 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) -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am distclean: distclean-am -rm -f Makefile distclean-am: clean-am distclean-generic distclean-local dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-data-local install-dvi: install-dvi-am install-dvi-am: install-exec-am: 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 -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic \ maintainer-clean-local mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-generic mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-local .MAKE: install-am install-strip .PHONY: all all-am all-local check check-am clean clean-generic \ clean-libtool clean-local cscopelist-am ctags-am dist-hook \ distclean distclean-generic distclean-libtool distclean-local \ distdir dvi dvi-am html html-am info info-am install \ install-am install-data install-data-am install-data-local \ 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-ps \ install-ps-am install-strip installcheck installcheck-am \ installdirs maintainer-clean maintainer-clean-generic \ maintainer-clean-local mostlyclean mostlyclean-generic \ mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \ uninstall-am uninstall-local .PRECIOUS: Makefile gtkdoc-check.test: Makefile $(AM_V_GEN)echo "#!/bin/sh -e" > $@; \ echo "$(GTKDOC_CHECK_PATH) || exit 1" >> $@; \ chmod +x $@ all-gtk-doc: $(HTML_BUILD_STAMP) $(PDF_BUILD_STAMP) .PHONY: all-gtk-doc @ENABLE_GTK_DOC_TRUE@all-local: all-gtk-doc docs: $(HTML_BUILD_STAMP) $(PDF_BUILD_STAMP) $(REPORT_FILES): sgml-build.stamp setup-build.stamp: -$(GTK_DOC_V_SETUP)if test "$(abs_srcdir)" != "$(abs_builddir)" ; then \ files=`echo $(SETUP_FILES) $(DOC_MODULE).types`; \ if test "x$$files" != "x" ; then \ for file in $$files ; do \ destdir=`dirname $(abs_builddir)/$$file`; \ test -d "$$destdir" || mkdir -p "$$destdir"; \ test -f $(abs_srcdir)/$$file && \ cp -pf $(abs_srcdir)/$$file $(abs_builddir)/$$file || true; \ done; \ fi; \ fi $(AM_V_at)touch setup-build.stamp scan-build.stamp: setup-build.stamp $(HFILE_GLOB) $(CFILE_GLOB) $(GTK_DOC_V_SCAN)_source_dir='' ; \ for i in $(DOC_SOURCE_DIR) ; do \ _source_dir="$${_source_dir} --source-dir=$$i" ; \ done ; \ gtkdoc-scan --module=$(DOC_MODULE) --ignore-headers="$(IGNORE_HFILES)" $${_source_dir} $(SCAN_OPTIONS) $(EXTRA_HFILES) $(GTK_DOC_V_INTROSPECT)if grep -l '^..*$$' $(DOC_MODULE).types > /dev/null 2>&1 ; then \ scanobj_options=""; \ gtkdoc-scangobj 2>&1 --help | grep >/dev/null "\-\-verbose"; \ if test "$$?" = "0"; then \ if test "x$(V)" = "x1"; then \ scanobj_options="--verbose"; \ fi; \ fi; \ CC="$(GTKDOC_CC)" LD="$(GTKDOC_LD)" RUN="$(GTKDOC_RUN)" CFLAGS="$(GTKDOC_CFLAGS) $(CFLAGS)" LDFLAGS="$(GTKDOC_LIBS) $(LDFLAGS)" \ gtkdoc-scangobj $(SCANGOBJ_OPTIONS) $$scanobj_options --module=$(DOC_MODULE); \ else \ for i in $(SCANOBJ_FILES) ; do \ test -f $$i || touch $$i ; \ done \ fi $(AM_V_at)touch scan-build.stamp $(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(DOC_MODULE)-sections.txt $(DOC_MODULE)-overrides.txt: scan-build.stamp @true sgml-build.stamp: setup-build.stamp $(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(HFILE_GLOB) $(CFILE_GLOB) $(DOC_MODULE)-sections.txt $(DOC_MODULE)-overrides.txt $(expand_content_files) xml/gtkdocentities.ent $(GTK_DOC_V_XML)_source_dir='' ; \ for i in $(DOC_SOURCE_DIR) ; do \ _source_dir="$${_source_dir} --source-dir=$$i" ; \ done ; \ gtkdoc-mkdb --module=$(DOC_MODULE) --output-format=xml --expand-content-files="$(expand_content_files)" --main-sgml-file=$(DOC_MAIN_SGML_FILE) $${_source_dir} $(MKDB_OPTIONS) $(AM_V_at)touch sgml-build.stamp sgml.stamp: sgml-build.stamp @true xml/gtkdocentities.ent: Makefile $(GTK_DOC_V_XML)$(MKDIR_P) $(@D) && ( \ echo ""; \ echo ""; \ echo ""; \ echo ""; \ echo ""; \ echo ""; \ echo ""; \ ) > $@ html-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) $(expand_content_files) $(GTK_DOC_V_HTML)rm -rf html && mkdir html && \ mkhtml_options=""; \ gtkdoc-mkhtml 2>&1 --help | grep >/dev/null "\-\-verbose"; \ if test "$$?" = "0"; then \ if test "x$(V)" = "x1"; then \ mkhtml_options="$$mkhtml_options --verbose"; \ fi; \ fi; \ gtkdoc-mkhtml 2>&1 --help | grep >/dev/null "\-\-path"; \ if test "$$?" = "0"; then \ mkhtml_options="$$mkhtml_options --path=\"$(abs_srcdir)\""; \ fi; \ cd html && gtkdoc-mkhtml $$mkhtml_options $(MKHTML_OPTIONS) $(DOC_MODULE) ../$(DOC_MAIN_SGML_FILE) -@test "x$(HTML_IMAGES)" = "x" || \ for file in $(HTML_IMAGES) ; do \ if test -f $(abs_srcdir)/$$file ; then \ cp $(abs_srcdir)/$$file $(abs_builddir)/html; \ fi; \ if test -f $(abs_builddir)/$$file ; then \ cp $(abs_builddir)/$$file $(abs_builddir)/html; \ fi; \ done; $(GTK_DOC_V_XREF)gtkdoc-fixxref --module=$(DOC_MODULE) --module-dir=html --html-dir=$(HTML_DIR) $(FIXXREF_OPTIONS) $(AM_V_at)touch html-build.stamp pdf-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) $(expand_content_files) $(GTK_DOC_V_PDF)rm -f $(DOC_MODULE).pdf && \ mkpdf_options=""; \ gtkdoc-mkpdf 2>&1 --help | grep >/dev/null "\-\-verbose"; \ if test "$$?" = "0"; then \ if test "x$(V)" = "x1"; then \ mkpdf_options="$$mkpdf_options --verbose"; \ fi; \ fi; \ if test "x$(HTML_IMAGES)" != "x"; then \ for img in $(HTML_IMAGES); do \ part=`dirname $$img`; \ echo $$mkpdf_options | grep >/dev/null "\-\-imgdir=$$part "; \ if test $$? != 0; then \ mkpdf_options="$$mkpdf_options --imgdir=$$part"; \ fi; \ done; \ fi; \ gtkdoc-mkpdf --path="$(abs_srcdir)" $$mkpdf_options $(DOC_MODULE) $(DOC_MAIN_SGML_FILE) $(MKPDF_OPTIONS) $(AM_V_at)touch pdf-build.stamp ############## clean-local: @rm -f *~ *.bak @rm -rf .libs @if echo $(SCAN_OPTIONS) | grep -q "\-\-rebuild-types" ; then \ rm -f $(DOC_MODULE).types; \ fi @if echo $(SCAN_OPTIONS) | grep -q "\-\-rebuild-sections" ; then \ rm -f $(DOC_MODULE)-sections.txt; \ fi distclean-local: @rm -rf xml html $(REPORT_FILES) $(DOC_MODULE).pdf \ $(DOC_MODULE)-decl-list.txt $(DOC_MODULE)-decl.txt @if test "$(abs_srcdir)" != "$(abs_builddir)" ; then \ rm -f $(SETUP_FILES) $(DOC_MODULE).types; \ fi maintainer-clean-local: @rm -rf xml html install-data-local: @installfiles=`echo $(builddir)/html/*`; \ if test "$$installfiles" = '$(builddir)/html/*'; \ then echo 1>&2 'Nothing to install' ; \ else \ if test -n "$(DOC_MODULE_VERSION)"; then \ installdir="$(DESTDIR)$(TARGET_DIR)-$(DOC_MODULE_VERSION)"; \ else \ installdir="$(DESTDIR)$(TARGET_DIR)"; \ fi; \ $(mkinstalldirs) $${installdir} ; \ for i in $$installfiles; do \ echo ' $(INSTALL_DATA) '$$i ; \ $(INSTALL_DATA) $$i $${installdir}; \ done; \ if test -n "$(DOC_MODULE_VERSION)"; then \ mv -f $${installdir}/$(DOC_MODULE).devhelp2 \ $${installdir}/$(DOC_MODULE)-$(DOC_MODULE_VERSION).devhelp2; \ fi; \ $(GTKDOC_REBASE) --relative --dest-dir=$(DESTDIR) --html-dir=$${installdir}; \ fi uninstall-local: @if test -n "$(DOC_MODULE_VERSION)"; then \ installdir="$(DESTDIR)$(TARGET_DIR)-$(DOC_MODULE_VERSION)"; \ else \ installdir="$(DESTDIR)$(TARGET_DIR)"; \ fi; \ rm -rf $${installdir} # # Require gtk-doc when making dist # @HAVE_GTK_DOC_TRUE@dist-check-gtkdoc: docs @HAVE_GTK_DOC_FALSE@dist-check-gtkdoc: @HAVE_GTK_DOC_FALSE@ @echo "*** gtk-doc is needed to run 'make dist'. ***" @HAVE_GTK_DOC_FALSE@ @echo "*** gtk-doc was not found when 'configure' ran. ***" @HAVE_GTK_DOC_FALSE@ @echo "*** please install gtk-doc and rerun 'configure'. ***" @HAVE_GTK_DOC_FALSE@ @false dist-hook: dist-check-gtkdoc all-gtk-doc dist-hook-local @mkdir $(distdir)/html @cp ./html/* $(distdir)/html @-cp ./$(DOC_MODULE).pdf $(distdir)/ @-cp ./$(DOC_MODULE).types $(distdir)/ @-cp ./$(DOC_MODULE)-sections.txt $(distdir)/ @cd $(distdir) && rm -f $(DISTCLEANFILES) @$(GTKDOC_REBASE) --online --relative --html-dir=$(distdir)/html .PHONY : dist-hook-local docs # Comment this out if you want your docs-status tested during 'make check' #TESTS = $(GTKDOC_CHECK) # 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: libinfinity-0.7.1/docs/reference/libinftextgtk/PaxHeaders.26529/Makefile.am0000644000000000000000000000013113034342512023377 xustar0030 mtime=1483851082.013718339 30 atime=1483851082.013718339 29 ctime=1488261617.75207532 libinfinity-0.7.1/docs/reference/libinftextgtk/Makefile.am0000644000175000017500000000677613034342512024152 0ustar00arminarmin00000000000000## Process this file with automake to produce Makefile.in # We require automake 1.6 at least. AUTOMAKE_OPTIONS = 1.6 # This is a blank Makefile.am for using gtk-doc. # Copy this to your project's API docs directory and modify the variables to # suit your project. See the GTK+ Makefiles in gtk+/docs/reference for examples # of using the various options. # The name of the module, e.g. 'glib'. DOC_MODULE=libinftextgtk-$(LIBINFINITY_API_VERSION) # The top-level SGML file. You can change this if you want to. DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml # The directory containing the source code. Relative to $(srcdir). # gtk-doc will search all .c & .h files beneath here for inline comments # documenting the functions and macros. # e.g. DOC_SOURCE_DIR=../../../gtk DOC_SOURCE_DIR=$(top_srcdir)/libinftextgtk # Extra options to pass to gtkdoc-scangobj. Not normally needed. SCANGOBJ_OPTIONS= # Extra options to supply to gtkdoc-scan. # e.g. SCAN_OPTIONS=--deprecated-guards="GTK_DISABLE_DEPRECATED" SCAN_OPTIONS=--rebuild-types # Extra options to supply to gtkdoc-mkdb. # e.g. MKDB_OPTIONS=--sgml-mode --output-format=xml MKDB_OPTIONS=--sgml-mode --output-format=xml # Extra options to supply to gtkdoc-mktmpl # e.g. MKTMPL_OPTIONS=--only-section-tmpl MKTMPL_OPTIONS= # Extra options to supply to gtkdoc-fixref. Not normally needed. # e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html FIXXREF_OPTIONS = \ --extra-dir=../libinfinity/html \ --extra-dir=../libinftext/html \ --extra-dir=../libinfgtk/html # Used for dependencies. The docs will be rebuilt if any of these change. # e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h # e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c HFILE_GLOB = \ $(top_srcdir)/libinftextgtk/*.h CFILE_GLOB = \ $(top_srcdir)/libinftextgtk/*.c # Header files to ignore when scanning. # e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h IGNORE_HFILES = # Images to copy into HTML directory. # e.g. HTML_IMAGES=$(top_srcdir)/gtk/stock-icons/stock_about_24.png HTML_IMAGES= # Extra SGML files that are included by $(DOC_MAIN_SGML_FILE). # e.g. content_files=running.sgml building.sgml changes-2.0.sgml content_files = \ ../version.xml # SGML files where gtk-doc abbrevations (#GtkWidget) are expanded # These files must be listed here *and* in content_files # e.g. expand_content_files=running.sgml expand_content_files= # CFLAGS and LDFLAGS for compiling gtkdoc-scangobj with your library. # Only needed if you are using gtkdoc-scangobj to dynamically query widget # signals and properties. # e.g. INCLUDES=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS) # e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib) #INCLUDES=$(inftextgtk_CFLAGS) AM_CPPFLAGS=$(inftextgtk_CFLAGS) GTKDOC_LIBS = \ $(inftextgtk_LIBS) \ $(top_builddir)/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(top_builddir)/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ $(top_builddir)/libinfgtk/libinfgtk-$(LIBINFINITY_API_VERSION).la \ $(top_builddir)/libinftextgtk/libinftextgtk-$(LIBINFINITY_API_VERSION).la # This includes the standard gtk-doc make rules, copied by gtkdocize. include $(top_srcdir)/gtk-doc.make # Other files to distribute # e.g. EXTRA_DIST += version.xml.in EXTRA_DIST += # Files not to distribute # for --rebuild-types in $(SCAN_OPTIONS), e.g. $(DOC_MODULE).types # for --rebuild-sections in $(SCAN_OPTIONS) e.g. $(DOC_MODULE)-sections.txt DISTCLEANFILES = libinftextgtk-$(LIBINFINITY_API_VERSION).types version.xml # Comment this out if you want your docs-status tested during 'make check' #TESTS = $(GTKDOC_CHECK) libinfinity-0.7.1/docs/reference/libinftextgtk/PaxHeaders.26529/libinftextgtk-0.7-overrides.txt0000644000000000000000000000013212401204470027262 xustar0030 mtime=1409616184.022250756 30 atime=1409616184.022250756 30 ctime=1488261617.760075302 libinfinity-0.7.1/docs/reference/libinftextgtk/libinftextgtk-0.7-overrides.txt0000644000175000017500000000000012401204470030002 0ustar00arminarmin00000000000000libinfinity-0.7.1/docs/reference/libinftextgtk/PaxHeaders.26529/libinftextgtk-0.7-docs.sgml0000644000000000000000000000013213034342512026336 xustar0030 mtime=1483851082.013718339 30 atime=1483851082.013718339 30 ctime=1488261617.756075311 libinfinity-0.7.1/docs/reference/libinftextgtk/libinftextgtk-0.7-docs.sgml0000644000175000017500000000211513034342512027067 0ustar00arminarmin00000000000000 ]> libinftextgtk-&api_version; Reference Manual for libinftextgtk &version;. The latest version of this documentation can be found on-line at http://infinote.0x539.de/libinfinity/API/libinftextgtk/. libinftextgtk API libinfinity-0.7.1/docs/reference/PaxHeaders.26529/version.xml0000644000000000000000000000012713045432620020703 xustar0029 mtime=1486239120.41814751 29 atime=1486239120.41814751 29 ctime=1488261590.87213497 libinfinity-0.7.1/docs/reference/version.xml0000644000175000017500000000000513045432620021424 0ustar00arminarmin000000000000000.7.0libinfinity-0.7.1/docs/PaxHeaders.26529/Makefile.am0000644000000000000000000000013212400102201016545 xustar0030 mtime=1409320065.087133093 30 atime=1409320065.087133093 30 ctime=1488261589.952136983 libinfinity-0.7.1/docs/Makefile.am0000644000175000017500000000002412400102201017273 0ustar00arminarmin00000000000000SUBDIRS = reference libinfinity-0.7.1/PaxHeaders.26529/libinfgtk0000644000000000000000000000013213055210725015477 xustar0030 mtime=1488261589.332138339 30 atime=1488261589.224138575 30 ctime=1488261589.332138339 libinfinity-0.7.1/libinfgtk/0000755000175000017500000000000013055210725016306 5ustar00arminarmin00000000000000libinfinity-0.7.1/libinfgtk/PaxHeaders.26529/inf-gtk-acl-sheet-view.c0000644000000000000000000000013213034342512022067 xustar0030 mtime=1483851082.017718362 30 atime=1483851082.017718362 30 ctime=1488261589.312138383 libinfinity-0.7.1/libinfgtk/inf-gtk-acl-sheet-view.c0000644000175000017500000005450413034342512022631 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include /** * SECTION:inf-gtk-acl-sheet-view * @title: InfGtkAclSheetView * @short_description: A widget showing a #InfAclSheet * @include: libinfgtk/inf-gtk-acl-sheet-view.h * @stability: Unstable * * #InfGtkAclSheetView is a widget that can show a #InfAclSheet in the user * interface. Optionally, it also allows the user to edit the sheet. **/ typedef struct _InfGtkAclSheetViewPrivate InfGtkAclSheetViewPrivate; struct _InfGtkAclSheetViewPrivate { GtkListStore* sheet_store; GtkWidget* tree_view; GtkCellRendererToggle* default_renderer; GtkCellRendererToggle* yes_renderer; GtkCellRendererToggle* no_renderer; InfAclSheet* sheet; gboolean editable; InfAclMask permission_mask; }; enum { PROP_0, PROP_SHEET, PROP_EDITABLE, PROP_SHOW_DEFAULT, PROP_PERMISSION_MASK }; enum { SHEET_CHANGED, LAST_SIGNAL }; #define INF_GTK_ACL_SHEET_VIEW_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INF_GTK_TYPE_ACL_SHEET_VIEW, InfGtkAclSheetViewPrivate)) static guint acl_sheet_view_signals[LAST_SIGNAL]; G_DEFINE_TYPE_WITH_CODE(InfGtkAclSheetView, inf_gtk_acl_sheet_view, GTK_TYPE_GRID, G_ADD_PRIVATE(InfGtkAclSheetView)) static void inf_gtk_acl_sheet_view_default_toggled_cb(GtkCellRenderer* cell, const gchar* path_str, gpointer user_data) { InfGtkAclSheetView* view; InfGtkAclSheetViewPrivate* priv; GtkTreeModel* model; GtkTreeIter iter; gboolean result; InfAclSetting setting; view = INF_GTK_ACL_SHEET_VIEW(user_data); priv = INF_GTK_ACL_SHEET_VIEW_PRIVATE(view); model = GTK_TREE_MODEL(priv->sheet_store); result = gtk_tree_model_get_iter_from_string(model, &iter, path_str); g_assert(result == TRUE); g_assert(priv->sheet != NULL); gtk_tree_model_get(model, &iter, 1, &setting, -1); if(inf_acl_mask_has(&priv->sheet->mask, setting)) { inf_acl_mask_and1(&priv->sheet->mask, setting); g_signal_emit(G_OBJECT(view), acl_sheet_view_signals[SHEET_CHANGED], 0); g_object_notify(G_OBJECT(view), "sheet"); } } static void inf_gtk_acl_sheet_view_yes_toggled_cb(GtkCellRenderer* cell, const gchar* path_str, gpointer user_data) { InfGtkAclSheetView* view; InfGtkAclSheetViewPrivate* priv; GtkTreeModel* model; GtkTreeIter iter; gboolean result; InfAclSetting setting; view = INF_GTK_ACL_SHEET_VIEW(user_data); priv = INF_GTK_ACL_SHEET_VIEW_PRIVATE(view); model = GTK_TREE_MODEL(priv->sheet_store); result = gtk_tree_model_get_iter_from_string(model, &iter, path_str); g_assert(result == TRUE); g_assert(priv->sheet != NULL); gtk_tree_model_get(model, &iter, 1, &setting, -1); if(!inf_acl_mask_has(&priv->sheet->mask, setting) || !inf_acl_mask_has(&priv->sheet->perms, setting)) { inf_acl_mask_or1(&priv->sheet->mask, setting); inf_acl_mask_or1(&priv->sheet->perms, setting); g_signal_emit(G_OBJECT(view), acl_sheet_view_signals[SHEET_CHANGED], 0); g_object_notify(G_OBJECT(view), "sheet"); } } static void inf_gtk_acl_sheet_view_no_toggled_cb(GtkCellRenderer* cell, const gchar* path_str, gpointer user_data) { InfGtkAclSheetView* view; InfGtkAclSheetViewPrivate* priv; GtkTreeModel* model; GtkTreeIter iter; gboolean result; InfAclSetting setting; view = INF_GTK_ACL_SHEET_VIEW(user_data); priv = INF_GTK_ACL_SHEET_VIEW_PRIVATE(view); model = GTK_TREE_MODEL(priv->sheet_store); result = gtk_tree_model_get_iter_from_string(model, &iter, path_str); g_assert(result == TRUE); g_assert(priv->sheet != NULL); gtk_tree_model_get(model, &iter, 1, &setting, -1); if(!inf_acl_mask_has(&priv->sheet->mask, setting) || inf_acl_mask_has(&priv->sheet->perms, setting)) { inf_acl_mask_or1(&priv->sheet->mask, setting); inf_acl_mask_and1(&priv->sheet->perms, setting); g_signal_emit(G_OBJECT(view), acl_sheet_view_signals[SHEET_CHANGED], 0); g_object_notify(G_OBJECT(view), "sheet"); } } static void inf_gtk_acl_sheet_view_default_cell_data_func(GtkTreeViewColumn* column, GtkCellRenderer* cell, GtkTreeModel* tree, GtkTreeIter* iter, gpointer user_data) { InfGtkAclSheetView* view; InfGtkAclSheetViewPrivate* priv; InfAclSetting setting; view = INF_GTK_ACL_SHEET_VIEW(user_data); priv = INF_GTK_ACL_SHEET_VIEW_PRIVATE(view); gtk_tree_model_get(tree, iter, 1, &setting, -1); if(priv->sheet == NULL || !inf_acl_mask_has(&priv->sheet->mask, setting)) g_object_set(cell, "active", TRUE, NULL); else g_object_set(cell, "active", FALSE, NULL); } static void inf_gtk_acl_sheet_view_yes_cell_data_func(GtkTreeViewColumn* column, GtkCellRenderer* cell, GtkTreeModel* tree, GtkTreeIter* iter, gpointer user_data) { InfGtkAclSheetView* view; InfGtkAclSheetViewPrivate* priv; InfAclSetting setting; view = INF_GTK_ACL_SHEET_VIEW(user_data); priv = INF_GTK_ACL_SHEET_VIEW_PRIVATE(view); gtk_tree_model_get(tree, iter, 1, &setting, -1); if(priv->sheet != NULL && inf_acl_mask_has(&priv->sheet->mask, setting) && inf_acl_mask_has(&priv->sheet->perms, setting)) { g_object_set(cell, "active", TRUE, NULL); } else { g_object_set(cell, "active", FALSE, NULL); } } static void inf_gtk_acl_sheet_view_no_cell_data_func(GtkTreeViewColumn* column, GtkCellRenderer* cell, GtkTreeModel* tree, GtkTreeIter* iter, gpointer user_data) { InfGtkAclSheetView* view; InfGtkAclSheetViewPrivate* priv; InfAclSetting setting; view = INF_GTK_ACL_SHEET_VIEW(user_data); priv = INF_GTK_ACL_SHEET_VIEW_PRIVATE(view); gtk_tree_model_get(tree, iter, 1, &setting, -1); if(priv->sheet != NULL && inf_acl_mask_has(&priv->sheet->mask, setting) && !inf_acl_mask_has(&priv->sheet->perms, setting)) { g_object_set(cell, "active", TRUE, NULL); } else { g_object_set(cell, "active", FALSE, NULL); } } static void inf_gtk_acl_sheet_view_update_editable(InfGtkAclSheetView* view) { InfGtkAclSheetViewPrivate* priv; gboolean activatable; guint i; GtkTreeViewColumn* column; GList* list; GList* item; GtkCellRendererToggle* cell; priv = INF_GTK_ACL_SHEET_VIEW_PRIVATE(view); if(priv->editable == TRUE && priv->sheet != NULL) activatable = TRUE; else activatable = FALSE; for(i = 1; i < 4; ++i) { column = gtk_tree_view_get_column(GTK_TREE_VIEW(priv->tree_view), i); list = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(column)); for(item = list; item != NULL; item = item->next) { g_assert(GTK_IS_CELL_RENDERER_TOGGLE(item->data)); cell = GTK_CELL_RENDERER_TOGGLE(item->data); g_object_set(G_OBJECT(cell), "activatable", activatable, NULL); } g_list_free(list); } } /* * GObject overrides */ static void inf_gtk_acl_sheet_view_init(InfGtkAclSheetView* view) { InfGtkAclSheetViewPrivate* priv; priv = INF_GTK_ACL_SHEET_VIEW_PRIVATE(view); priv->sheet = NULL; priv->editable = FALSE; inf_acl_mask_clear(&priv->permission_mask); gtk_widget_init_template(GTK_WIDGET(view)); gtk_tree_selection_set_mode( gtk_tree_view_get_selection(GTK_TREE_VIEW(priv->tree_view)), GTK_SELECTION_NONE ); gtk_tree_sortable_set_sort_column_id( GTK_TREE_SORTABLE(priv->sheet_store), 0, GTK_SORT_ASCENDING ); gtk_tree_view_column_set_cell_data_func( gtk_tree_view_get_column(GTK_TREE_VIEW(priv->tree_view), 1), GTK_CELL_RENDERER(priv->default_renderer), inf_gtk_acl_sheet_view_default_cell_data_func, view, NULL ); gtk_tree_view_column_set_cell_data_func( gtk_tree_view_get_column(GTK_TREE_VIEW(priv->tree_view), 2), GTK_CELL_RENDERER(priv->yes_renderer), inf_gtk_acl_sheet_view_yes_cell_data_func, view, NULL ); gtk_tree_view_column_set_cell_data_func( gtk_tree_view_get_column(GTK_TREE_VIEW(priv->tree_view), 3), GTK_CELL_RENDERER(priv->no_renderer), inf_gtk_acl_sheet_view_no_cell_data_func, view, NULL ); inf_gtk_acl_sheet_view_set_permission_mask(view, &INF_ACL_MASK_ALL); } static void inf_gtk_acl_sheet_view_dispose(GObject* object) { InfGtkAclSheetView* view; InfGtkAclSheetViewPrivate* priv; view = INF_GTK_ACL_SHEET_VIEW(object); priv = INF_GTK_ACL_SHEET_VIEW_PRIVATE(view); if(priv->sheet != NULL) inf_gtk_acl_sheet_view_set_sheet(view, NULL); G_OBJECT_CLASS(inf_gtk_acl_sheet_view_parent_class)->dispose(object); } static void inf_gtk_acl_sheet_view_finalize(GObject* object) { InfGtkAclSheetView* view; InfGtkAclSheetViewPrivate* priv; view = INF_GTK_ACL_SHEET_VIEW(object); priv = INF_GTK_ACL_SHEET_VIEW_PRIVATE(view); G_OBJECT_CLASS(inf_gtk_acl_sheet_view_parent_class)->finalize(object); } static void inf_gtk_acl_sheet_view_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfGtkAclSheetView* view; InfGtkAclSheetViewPrivate* priv; view = INF_GTK_ACL_SHEET_VIEW(object); priv = INF_GTK_ACL_SHEET_VIEW_PRIVATE(view); switch(prop_id) { case PROP_SHEET: inf_gtk_acl_sheet_view_set_sheet( view, (InfAclSheet*)g_value_get_boxed(value) ); break; case PROP_EDITABLE: inf_gtk_acl_sheet_view_set_editable(view, g_value_get_boolean(value)); break; case PROP_SHOW_DEFAULT: inf_gtk_acl_sheet_view_set_show_default(view, g_value_get_boolean(value)); break; case PROP_PERMISSION_MASK: inf_gtk_acl_sheet_view_set_permission_mask( view, (const InfAclMask*)g_value_get_boxed(value) ); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void inf_gtk_acl_sheet_view_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfGtkAclSheetView* view; InfGtkAclSheetViewPrivate* priv; view = INF_GTK_ACL_SHEET_VIEW(object); priv = INF_GTK_ACL_SHEET_VIEW_PRIVATE(view); switch(prop_id) { case PROP_SHEET: g_value_set_boxed(value, priv->sheet); break; case PROP_EDITABLE: g_value_set_boolean(value, priv->editable); break; case PROP_SHOW_DEFAULT: g_value_set_boolean(value, inf_gtk_acl_sheet_view_get_show_default(view)); break; case PROP_PERMISSION_MASK: g_value_set_boxed(value, &priv->permission_mask); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } /* * GType registration */ static void inf_gtk_acl_sheet_view_class_init(InfGtkAclSheetViewClass* sheet_view_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(sheet_view_class); object_class->dispose = inf_gtk_acl_sheet_view_dispose; object_class->finalize = inf_gtk_acl_sheet_view_finalize; object_class->set_property = inf_gtk_acl_sheet_view_set_property; object_class->get_property = inf_gtk_acl_sheet_view_get_property; sheet_view_class->sheet_changed = NULL; gtk_widget_class_set_template_from_resource( GTK_WIDGET_CLASS(object_class), "/de/0x539/libinfgtk/ui/infgtkaclsheetview.ui" ); gtk_widget_class_bind_template_child_private( GTK_WIDGET_CLASS(object_class), InfGtkAclSheetView, sheet_store ); gtk_widget_class_bind_template_child_private( GTK_WIDGET_CLASS(object_class), InfGtkAclSheetView, tree_view ); gtk_widget_class_bind_template_child_private( GTK_WIDGET_CLASS(object_class), InfGtkAclSheetView, default_renderer ); gtk_widget_class_bind_template_child_private( GTK_WIDGET_CLASS(object_class), InfGtkAclSheetView, yes_renderer ); gtk_widget_class_bind_template_child_private( GTK_WIDGET_CLASS(object_class), InfGtkAclSheetView, no_renderer ); gtk_widget_class_bind_template_callback( GTK_WIDGET_CLASS(object_class), inf_gtk_acl_sheet_view_default_toggled_cb ); gtk_widget_class_bind_template_callback( GTK_WIDGET_CLASS(object_class), inf_gtk_acl_sheet_view_yes_toggled_cb ); gtk_widget_class_bind_template_callback( GTK_WIDGET_CLASS(object_class), inf_gtk_acl_sheet_view_no_toggled_cb ); /** * InfGtkAclSheetView::sheet-changed: * @view: The #InfGtkAclSheetView that emitted the signal. * * This signal is emitted when the #InfAclSheet displayed by @view was * changed by the user. */ acl_sheet_view_signals[SHEET_CHANGED] = g_signal_new( "sheet-changed", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfGtkAclSheetViewClass, sheet_changed), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0 ); g_object_class_install_property( object_class, PROP_SHEET, g_param_spec_boxed( "sheet", "Sheet", "The ACL sheet the widget is displaying", INF_TYPE_ACL_SHEET, G_PARAM_READWRITE | G_PARAM_CONSTRUCT ) ); g_object_class_install_property( object_class, PROP_EDITABLE, g_param_spec_boolean( "editable", "Editable", "Whether the sheet can be edited by the user or not", FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT ) ); g_object_class_install_property( object_class, PROP_SHOW_DEFAULT, g_param_spec_boolean( "show-default", "Show default", "Whether to show the \"default\" column", TRUE, G_PARAM_READWRITE ) ); g_object_class_install_property( object_class, PROP_PERMISSION_MASK, g_param_spec_boxed( "permission-mask", "Permission mask", "Specifies which permissions to show in the sheet view", INF_TYPE_ACL_MASK, G_PARAM_READWRITE ) ); } /* * Public API. */ /** * inf_gtk_acl_sheet_view_new: (constructor) * * Creates a new #InfGtkAclSheetView. To show a sheet in the view, call * inf_gtk_acl_sheet_view_set_sheet(). * * Returns: (transfer full): A new #InfGtkAclSheetView. */ GtkWidget* inf_gtk_acl_sheet_view_new(void) { GObject* object; object = g_object_new(INF_GTK_TYPE_ACL_SHEET_VIEW, NULL); return GTK_WIDGET(object); } /** * inf_gtk_acl_sheet_view_set_sheet: * @view: A #InfGtkAclSheetView. * @sheet: (allow-none): The #InfAclSheet to show, or %NULL. * * Sets the @sheet to be displayed by @view. */ void inf_gtk_acl_sheet_view_set_sheet(InfGtkAclSheetView* view, const InfAclSheet* sheet) { InfGtkAclSheetViewPrivate* priv; GtkTreeModel* model; GtkTreeIter iter; GtkTreePath* path; g_return_if_fail(INF_GTK_IS_ACL_SHEET_VIEW(view)); priv = INF_GTK_ACL_SHEET_VIEW_PRIVATE(view); if(priv->sheet != NULL) inf_acl_sheet_free(priv->sheet); if(sheet != NULL) priv->sheet = inf_acl_sheet_copy(sheet); else priv->sheet = NULL; model = GTK_TREE_MODEL(priv->sheet_store); if(gtk_tree_model_get_iter_first(model, &iter)) { path = gtk_tree_path_new_first(); do { gtk_tree_model_row_changed(model, path, &iter); gtk_tree_path_next(path); } while(gtk_tree_model_iter_next(model, &iter)); gtk_tree_path_free(path); } if(priv->sheet == NULL) gtk_widget_set_sensitive(priv->tree_view, FALSE); else gtk_widget_set_sensitive(priv->tree_view, TRUE); inf_gtk_acl_sheet_view_update_editable(view); g_signal_emit(G_OBJECT(view), acl_sheet_view_signals[SHEET_CHANGED], 0); g_object_notify(G_OBJECT(view), "sheet"); } /** * inf_gtk_acl_sheet_view_get_sheet: * @view: A #InfGtkAclSheetView. * * Returns the sheet that is currently being displayed by @view, or %NULL if * there is no sheet displayed. * * Returns: (transfer none) (allow-none): A #InfAclSheet owned by @view, or * %NULL. */ const InfAclSheet* inf_gtk_acl_sheet_view_get_sheet(InfGtkAclSheetView* view) { g_return_val_if_fail(INF_GTK_IS_ACL_SHEET_VIEW(view), NULL); return INF_GTK_ACL_SHEET_VIEW_PRIVATE(view)->sheet; } /** * inf_gtk_acl_sheet_view_set_editable: * @view: A #InfGtkAclSheetView. * @editable: Whether to make the sheet editable or not. * * Sets whether the sheet being displayed by @view can be edited by the user * or not. */ void inf_gtk_acl_sheet_view_set_editable(InfGtkAclSheetView* view, gboolean editable) { InfGtkAclSheetViewPrivate* priv; g_return_if_fail(INF_GTK_IS_ACL_SHEET_VIEW(view)); priv = INF_GTK_ACL_SHEET_VIEW_PRIVATE(view); if(priv->editable != editable) { priv->editable = editable; inf_gtk_acl_sheet_view_update_editable(view); g_object_notify(G_OBJECT(view), "editable"); } } /** * inf_gtk_acl_sheet_view_get_editable: * @view: A #InfGtkAclSheetView. * * Returns whether the sheet being displayed by @view can be edited by the * user or not. * * Returns: %TRUE when the sheet can be edited or %FALSE otherwise. */ gboolean inf_gtk_acl_sheet_view_get_editable(InfGtkAclSheetView* view) { g_return_val_if_fail(INF_GTK_IS_ACL_SHEET_VIEW(view), FALSE); return INF_GTK_ACL_SHEET_VIEW_PRIVATE(view)->editable; } /** * inf_gtk_acl_sheet_view_set_show_default: * @view: A #InfGtkAclSheetView. * @show: Whether to show the default column. * * Specifies whether the "default" column is shown, and whether it is * allowed to change certain permissions to the default value or not. The * ACL sheet for the default account of a directory's root node is not * allowed to have default permissions. In this case this function should be * called to hide the default column from the user interface. */ void inf_gtk_acl_sheet_view_set_show_default(InfGtkAclSheetView* view, gboolean show) { InfGtkAclSheetViewPrivate* priv; GtkTreeViewColumn* column; g_return_if_fail(INF_GTK_IS_ACL_SHEET_VIEW(view)); priv = INF_GTK_ACL_SHEET_VIEW_PRIVATE(view); column = gtk_tree_view_get_column(GTK_TREE_VIEW(priv->tree_view), 1); if(gtk_tree_view_column_get_visible(column) != show) { gtk_tree_view_column_set_visible(column, show); g_object_notify(G_OBJECT(view), "show-default"); } } /** * inf_gtk_acl_sheet_view_get_show_default: * @view: A #InfGtkAclSheetView. * * Returns whether the "default" column is shown. * * Returns: %TRUE if the "default" column is shown or %FALSE otherwise. */ gboolean inf_gtk_acl_sheet_view_get_show_default(InfGtkAclSheetView* view) { InfGtkAclSheetViewPrivate* priv; GtkTreeViewColumn* column; g_return_val_if_fail(INF_GTK_IS_ACL_SHEET_VIEW(view), FALSE); priv = INF_GTK_ACL_SHEET_VIEW_PRIVATE(view); column = gtk_tree_view_get_column(GTK_TREE_VIEW(priv->tree_view), 1); return gtk_tree_view_column_get_visible(column); } /** * inf_gtk_acl_sheet_view_set_permission_mask: * @view: A #InfGtkAclSheetView. * @mask: A #InfAclMask with the permissions to show. * * Sets which permissions of the sheet to show. Only the permissions that * are enabled in @mask ar being shown. By default all permissions are shown. */ void inf_gtk_acl_sheet_view_set_permission_mask(InfGtkAclSheetView* view, const InfAclMask* mask) { InfGtkAclSheetViewPrivate* priv; GtkTreeModel* model; InfAclMask add; InfAclMask remove; GEnumClass* enum_class; guint i; GtkTreeIter iter; gboolean has_element; InfAclSetting setting; priv = INF_GTK_ACL_SHEET_VIEW_PRIVATE(view); model = GTK_TREE_MODEL(priv->sheet_store); g_return_if_fail(INF_GTK_IS_ACL_SHEET_VIEW(view)); g_return_if_fail(mask != NULL); inf_acl_mask_neg(&priv->permission_mask, &add); inf_acl_mask_and(mask, &add, &add); inf_acl_mask_neg(mask, &remove); inf_acl_mask_and(&priv->permission_mask, &remove, &remove); if(!inf_acl_mask_empty(&remove)) { has_element = gtk_tree_model_get_iter_first(model, &iter); g_assert(has_element == TRUE); while(has_element == TRUE) { gtk_tree_model_get(model, &iter, 1, &setting, -1); if(inf_acl_mask_has(&remove, setting)) has_element = gtk_list_store_remove(priv->sheet_store, &iter); else has_element = gtk_tree_model_iter_next(model, &iter); } } if(!inf_acl_mask_empty(&add)) { enum_class = G_ENUM_CLASS(g_type_class_ref(INF_TYPE_ACL_SETTING)); for(i = 0; i < enum_class->n_values; ++i) { if(inf_acl_mask_has(&add, enum_class->values[i].value)) { gtk_list_store_insert_with_values( priv->sheet_store, NULL, -1, 0, enum_class->values[i].value_nick, 1, enum_class->values[i].value, -1 ); } } g_type_class_unref(enum_class); } if(!inf_acl_mask_equal(&priv->permission_mask, mask)) { priv->permission_mask = *mask; g_object_notify(G_OBJECT(view), "permission-mask"); } } /** * inf_gtk_acl_sheet_view_get_permission_mask: * @view: A #InfGtkAclSheetView. * * Returns a #InfAclMask specifies which permissions are currently being * shown by @view. * * Returns: (transfer none): A #InfAclMask owned by @view. It must not be * freed. */ const InfAclMask* inf_gtk_acl_sheet_view_get_permission_mask(InfGtkAclSheetView* view) { g_return_val_if_fail(INF_GTK_IS_ACL_SHEET_VIEW(view), 0); return &INF_GTK_ACL_SHEET_VIEW_PRIVATE(view)->permission_mask; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfgtk/PaxHeaders.26529/inf-gtk-browser-model-sort.c0000644000000000000000000000013213034342512023020 xustar0030 mtime=1483851082.017718362 30 atime=1483851082.017718362 30 ctime=1488261589.316138375 libinfinity-0.7.1/libinfgtk/inf-gtk-browser-model-sort.c0000644000175000017500000001720713034342512023561 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include typedef struct _InfGtkBrowserModelSortPrivate InfGtkBrowserModelSortPrivate; struct _InfGtkBrowserModelSortPrivate { InfGtkBrowserModel* child_model; }; #define INF_GTK_BROWSER_MODEL_SORT_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INF_GTK_TYPE_BROWSER_MODEL_SORT, InfGtkBrowserModelSortPrivate)) static void inf_gtk_browser_model_sort_browser_model_iface_init(InfGtkBrowserModelInterface* iface); G_DEFINE_TYPE_WITH_CODE(InfGtkBrowserModelSort, inf_gtk_browser_model_sort, GTK_TYPE_TREE_MODEL_SORT, G_ADD_PRIVATE(InfGtkBrowserModelSort) G_IMPLEMENT_INTERFACE(INF_GTK_TYPE_BROWSER_MODEL, inf_gtk_browser_model_sort_browser_model_iface_init)) static void inf_gtk_browser_model_sort_set_browser_cb(InfGtkBrowserModel* model, GtkTreePath* path, GtkTreeIter* iter, InfBrowser* old_browser, InfBrowser* new_browser, gpointer user_data) { GtkTreeModelSort* model_sort; GtkTreePath* own_path; GtkTreeIter own_iter; model_sort = GTK_TREE_MODEL_SORT(user_data); own_path = gtk_tree_model_sort_convert_child_path_to_path(model_sort, path); gtk_tree_model_sort_convert_child_iter_to_iter(model_sort, &own_iter, iter); inf_gtk_browser_model_set_browser( INF_GTK_BROWSER_MODEL(user_data), own_path, &own_iter, old_browser, new_browser ); gtk_tree_path_free(own_path); } static void inf_gtk_browser_model_sort_sync_child_model(InfGtkBrowserModelSort* model, InfGtkBrowserModel* child_model) { InfGtkBrowserModelSortPrivate* priv; priv = INF_GTK_BROWSER_MODEL_SORT_PRIVATE(model); if(priv->child_model != NULL) { inf_signal_handlers_disconnect_by_func( priv->child_model, G_CALLBACK(inf_gtk_browser_model_sort_set_browser_cb), model ); g_object_unref(priv->child_model); } priv->child_model = child_model; if(child_model != NULL) { g_object_ref(child_model); g_signal_connect_after( G_OBJECT(child_model), "set-browser", G_CALLBACK(inf_gtk_browser_model_sort_set_browser_cb), model ); } } static void inf_gtk_browser_model_sort_notify_model_cb(GObject* object, GParamSpec* pspec, gpointer user_data) { GtkTreeModel* child_model; child_model = gtk_tree_model_sort_get_model( GTK_TREE_MODEL_SORT(object) ); inf_gtk_browser_model_sort_sync_child_model( INF_GTK_BROWSER_MODEL_SORT(object), INF_GTK_BROWSER_MODEL(child_model) ); } /* * GObject overrides */ static void inf_gtk_browser_model_sort_init(InfGtkBrowserModelSort* model_sort) { InfGtkBrowserModelSortPrivate* priv; priv = INF_GTK_BROWSER_MODEL_SORT_PRIVATE(model_sort); /* Keep child model in sync with the one from GtkTreeModelSort */ g_signal_connect( model_sort, "notify::model", G_CALLBACK(inf_gtk_browser_model_sort_notify_model_cb), NULL ); } static void inf_gtk_browser_model_sort_constructed(GObject* object) { G_OBJECT_CLASS(inf_gtk_browser_model_sort_parent_class)->constructed( object ); /* Set initial model, we do not get notified for this */ inf_gtk_browser_model_sort_sync_child_model( INF_GTK_BROWSER_MODEL_SORT(object), INF_GTK_BROWSER_MODEL( gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(object)) ) ); } static void inf_gtk_browser_model_sort_dispose(GObject* object) { InfGtkBrowserModelSort* model_sort; InfGtkBrowserModelSortPrivate* priv; model_sort = INF_GTK_BROWSER_MODEL_SORT(object); priv = INF_GTK_BROWSER_MODEL_SORT_PRIVATE(model_sort); /* Release own child model, since we won't get notified anymore when the * parent's dispose runs. We disconnect the signal handler before chaining * up. */ inf_gtk_browser_model_sort_sync_child_model(model_sort, NULL); inf_signal_handlers_disconnect_by_func( object, G_CALLBACK(inf_gtk_browser_model_sort_notify_model_cb), NULL ); G_OBJECT_CLASS(inf_gtk_browser_model_sort_parent_class)->dispose(object); } /* * InfGtkBrowserModel implementation. */ static void inf_gtk_browser_model_sort_resolve(InfGtkBrowserModel* model, InfDiscovery* discovery, InfDiscoveryInfo* info) { GtkTreeModel* child_model; child_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(model)); inf_gtk_browser_model_resolve( INF_GTK_BROWSER_MODEL(child_model), discovery, info ); } static gboolean inf_gtk_browser_model_sort_browser_iter_to_tree_iter(InfGtkBrowserModel* mdl, InfBrowser* browser, const InfBrowserIter* it, GtkTreeIter* tree_iter) { GtkTreeModel* child_model; GtkTreeIter child_iter; gboolean result; child_model = gtk_tree_model_sort_get_model(GTK_TREE_MODEL_SORT(mdl)); result = inf_gtk_browser_model_browser_iter_to_tree_iter( INF_GTK_BROWSER_MODEL(child_model), browser, it, &child_iter ); if(result == TRUE) { gtk_tree_model_sort_convert_child_iter_to_iter( GTK_TREE_MODEL_SORT(mdl), tree_iter, &child_iter ); return TRUE; } else { return FALSE; } } /* * GType registration */ static void inf_gtk_browser_model_sort_class_init( InfGtkBrowserModelSortClass* browser_model_sort_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(browser_model_sort_class); object_class->constructed = inf_gtk_browser_model_sort_constructed; object_class->dispose = inf_gtk_browser_model_sort_dispose; } static void inf_gtk_browser_model_sort_browser_model_iface_init( InfGtkBrowserModelInterface* iface) { iface->set_browser = NULL; iface->resolve = inf_gtk_browser_model_sort_resolve; /* inf_gtk_browser_model_sort_browser_model_browser_iter_to_tree_iter would * be consistent, but a _bit_ too long to fit properly into 80 chars ;) */ iface->browser_iter_to_tree_iter = inf_gtk_browser_model_sort_browser_iter_to_tree_iter; } /* * Public API. */ /** * inf_gtk_browser_model_sort_new: (constructor) * @child_model: A #InfGtkBrowserModel. * * Creates a new #InfGtkBrowserModelSort, sorting @child_model. * * Returns: (transfer full): A new #InfGtkBrowserModelSort. **/ InfGtkBrowserModelSort* inf_gtk_browser_model_sort_new(InfGtkBrowserModel* child_model) { GObject* object; object = g_object_new( INF_GTK_TYPE_BROWSER_MODEL_SORT, "model", child_model, NULL ); return INF_GTK_BROWSER_MODEL_SORT(object); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfgtk/PaxHeaders.26529/inf-gtk-certificate-manager.h0000644000000000000000000000013213034342512023151 xustar0030 mtime=1483851082.021718383 30 atime=1483851082.021718383 30 ctime=1488261589.300138409 libinfinity-0.7.1/libinfgtk/inf-gtk-certificate-manager.h0000644000175000017500000000477013034342512023713 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_GTK_CERTIFICATE_MANAGER_H__ #define __INF_GTK_CERTIFICATE_MANAGER_H__ #include #include #include G_BEGIN_DECLS #define INF_GTK_TYPE_CERTIFICATE_MANAGER (inf_gtk_certificate_manager_get_type()) #define INF_GTK_CERTIFICATE_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_GTK_TYPE_CERTIFICATE_MANAGER, InfGtkCertificateManager)) #define INF_GTK_CERTIFICATE_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INF_GTK_TYPE_CERTIFICATE_MANAGER, InfGtkCertificateManagerClass)) #define INF_GTK_IS_CERTIFICATE_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_GTK_TYPE_CERTIFICATE_MANAGER)) #define INF_GTK_IS_CERTIFICATE_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INF_GTK_TYPE_CERTIFICATE_MANAGER)) #define INF_GTK_CERTIFICATE_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INF_GTK_TYPE_CERTIFICATE_MANAGER, InfGtkCertificateManagerClass)) typedef struct _InfGtkCertificateManager InfGtkCertificateManager; typedef struct _InfGtkCertificateManagerClass InfGtkCertificateManagerClass; struct _InfGtkCertificateManagerClass { InfCertificateVerifyClass parent_class; }; struct _InfGtkCertificateManager { InfCertificateVerify parent; }; GType inf_gtk_certificate_manager_get_type(void) G_GNUC_CONST; InfGtkCertificateManager* inf_gtk_certificate_manager_new(GtkWindow* parent_window, InfXmppManager* xmpp_manager, const gchar* known_hosts_file); G_END_DECLS #endif /* __INF_GTK_CERTIFICATE_MANAGER_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfgtk/PaxHeaders.26529/inf-gtk-browser-model.h0000644000000000000000000000013213034342512022040 xustar0030 mtime=1483851082.017718362 30 atime=1483851082.017718362 30 ctime=1488261589.292138427 libinfinity-0.7.1/libinfgtk/inf-gtk-browser-model.h0000644000175000017500000001577013034342512022604 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_GTK_BROWSER_MODEL_H__ #define __INF_GTK_BROWSER_MODEL_H__ #include #include #include #include G_BEGIN_DECLS #define INF_GTK_TYPE_BROWSER_MODEL (inf_gtk_browser_model_get_type()) #define INF_GTK_BROWSER_MODEL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_GTK_TYPE_BROWSER_MODEL, InfGtkBrowserModel)) #define INF_GTK_IS_BROWSER_MODEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_GTK_TYPE_BROWSER_MODEL)) #define INF_GTK_BROWSER_MODEL_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), INF_GTK_TYPE_BROWSER_MODEL, InfGtkBrowserModelInterface)) #define INF_GTK_TYPE_BROWSER_MODEL_STATUS (inf_gtk_browser_model_status_get_type()) /** * InfGtkBrowserModel: * * #InfGtkBrowserModel is an opaque data type. You should only access it * via the public API functions. */ typedef struct _InfGtkBrowserModel InfGtkBrowserModel; typedef struct _InfGtkBrowserModelInterface InfGtkBrowserModelInterface; /** * InfGtkBrowserModelStatus: * @INF_GTK_BROWSER_MODEL_INVALID: Invalid state. A healthy item should not * have this status. * @INF_GTK_BROWSER_MODEL_DISCOVERED: The item was discovered with a * #InfDiscovery, but no attempt has been made at connecting to it. * @INF_GTK_BROWSER_MODEL_RESOLVING: The item was discovered with a * #InfDiscovery and is currently being resolved, see inf_discovery_resolve(). * @INF_GTK_BROWSER_MODEL_DISCONNECTED: A connection attempt to the remote * site was not successful, or the connection was lost. The connection * parameters are known, but currently no connection is established. * @INF_GTK_BROWSER_MODEL_CONNECTING: A connection attempt to the remote site * is currently in progress. * @INF_GTK_BROWSER_MODEL_CONNECTED: A connection to the remote site has been * established and its directory can be browsed. * @INF_GTK_BROWSER_MODEL_ERROR: An error has occured with this item. The * column with index %INF_GTK_BROWSER_MODEL_COL_ERROR has more information * about the error that occurred. * * The different statuses an item in the #InfGtkBrowserModel can have. The * status of an item is only defined for toplevel items in the tree. */ typedef enum _InfGtkBrowserModelStatus { INF_GTK_BROWSER_MODEL_INVALID, INF_GTK_BROWSER_MODEL_DISCOVERED, INF_GTK_BROWSER_MODEL_RESOLVING, INF_GTK_BROWSER_MODEL_DISCONNECTED, INF_GTK_BROWSER_MODEL_CONNECTING, INF_GTK_BROWSER_MODEL_CONNECTED, INF_GTK_BROWSER_MODEL_ERROR } InfGtkBrowserModelStatus; /** * InfGtkBrowserModelColumn: * @INF_GTK_BROWSER_MODEL_COL_DISCOVERY_INFO: The #InfDiscoveryInfo of a * discovered toplevel item, or %NULL if the item was not discovered. * @INF_GTK_BROWSER_MODEL_COL_DISCOVERY: The #InfDiscovery object that the * item has been discovered with, if any. * @INF_GTK_BROWSER_MODEL_COL_BROWSER: The #InfBrowser with which this item * is being browsed, or %NULL if no browser is available. * @INF_GTK_BROWSER_MODEL_COL_STATUS: The status of this item. This column is * only valid for toplevel items, i.e. for connections to directories. * @INF_GTK_BROWSER_MODEL_COL_NAME: The name of the item as a simple string. * @INF_GTK_BROWSER_MODEL_COL_ERROR: If an error has occurred with the item, * for example the connection failed, or a node exploration failed, this * column contains a #GError with more error information. * @INF_GTK_BROWSER_MODEL_COL_NODE: The #InfBrowserIter pointing to the * corresponding node of the #InfBrowser. * @INF_GTK_BROWSER_MODEL_NUM_COLS: The total number of columns of a * #InfGtkBrowserModel. * * The various #GtkTreeModel columns that a tree model implementing * #InfGtkBrowserModel must support. */ typedef enum _InfGtkBrowserModelColumn { INF_GTK_BROWSER_MODEL_COL_DISCOVERY_INFO, INF_GTK_BROWSER_MODEL_COL_DISCOVERY, INF_GTK_BROWSER_MODEL_COL_BROWSER, INF_GTK_BROWSER_MODEL_COL_STATUS, /* only toplevel */ INF_GTK_BROWSER_MODEL_COL_NAME, INF_GTK_BROWSER_MODEL_COL_ERROR, INF_GTK_BROWSER_MODEL_COL_NODE, INF_GTK_BROWSER_MODEL_NUM_COLS } InfGtkBrowserModelColumn; /** * InfGtkBrowserModelInterface: * @set_browser: Default signal handler of the * #InfGtkBrowserModel::set-browser signal. * @resolve: Virtual function for resolving a discovered infinote service. * @browser_iter_to_tree_iter: Virtual function for converting a * #InfBrowserIter to a #GtkTreeIter. * * This structure contains virtual functions and signal handlers of the * #InfGtkBrowserModel interface. */ struct _InfGtkBrowserModelInterface { /*< private >*/ GTypeInterface parent; /*< public >*/ /* signals */ void(*set_browser)(InfGtkBrowserModel* model, GtkTreePath* path, GtkTreeIter* iter, InfBrowser* old_browser, InfBrowser* new_browser); /* virtual functions */ void(*resolve)(InfGtkBrowserModel* model, InfDiscovery* discovery, InfDiscoveryInfo* info); gboolean(*browser_iter_to_tree_iter)(InfGtkBrowserModel* model, InfBrowser* browser, const InfBrowserIter* iter, GtkTreeIter* tree_iter); }; GType inf_gtk_browser_model_status_get_type(void) G_GNUC_CONST; GType inf_gtk_browser_model_get_type(void) G_GNUC_CONST; void inf_gtk_browser_model_set_browser(InfGtkBrowserModel* model, GtkTreePath* path, GtkTreeIter* iter, InfBrowser* old_browser, InfBrowser* new_browser); void inf_gtk_browser_model_resolve(InfGtkBrowserModel* model, InfDiscovery* discovery, InfDiscoveryInfo* info); gboolean inf_gtk_browser_model_browser_iter_to_tree_iter(InfGtkBrowserModel* model, InfBrowser* browser, const InfBrowserIter* iter, GtkTreeIter* tree_iter); G_END_DECLS #endif /* __INF_GTK_BROWSER_MODEL_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfgtk/PaxHeaders.26529/inf-gtk-permissions-dialog.c0000644000000000000000000000013213034342512023062 xustar0030 mtime=1483851082.021718383 30 atime=1483851082.021718383 30 ctime=1488261589.332138339 libinfinity-0.7.1/libinfgtk/inf-gtk-permissions-dialog.c0000644000175000017500000025214713034342512023627 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-gtk-permissions-dialog * @title: InfGtkPermissionsDialog * @short_description: A dialog to view and modify the ACL of a directory * node * @include: libinfgtk/inf-gtk-permissions-dialog.h * @stability: Unstable * * #InfGtkPermissionsDialog is a dialog widget which allows to view and * modify the ACL of a node in a infinote directory. It shows a list of all * available users and allows the permissions for each of them to be changed, * using a #InfGtkAclSheetView widget. * * If the "can-query-acl" permission is not granted for the local user, the * dialog only shows the permissions for the default user and the local user. * The dialog also comes with a status text to inform the user why certain * functionality is not available. * * The dialog class reacts to changes to the ACL in real time, and also if the * node that is being monitored is removed. **/ #include #include #include #include #include #include #include #include enum { INF_GTK_PERMISSIONS_DIALOG_COLUMN_ID = 0, INF_GTK_PERMISSIONS_DIALOG_COLUMN_NAME = 1 }; typedef struct _InfGtkPermissionsDialogPendingSheet InfGtkPermissionsDialogPendingSheet; struct _InfGtkPermissionsDialogPendingSheet { InfGtkPermissionsDialog* dialog; GtkTreeRowReference* row; InfAclSheet sheet; InfAclAccountId last_combo_changed_id; InfRequest* lookup_request; }; typedef struct _InfGtkPermissionsDialogPrivate InfGtkPermissionsDialogPrivate; struct _InfGtkPermissionsDialogPrivate { InfBrowser* browser; InfBrowserIter browser_iter; GtkListStore* account_store; /* If accounts is NULL, then the account list is not available. Note that we * only need the account list when the user adds a new sheet, to present her * the available users to choose from. If the list is not available, we * perform a reverse lookup. */ InfRequest* query_acl_account_list_request; gboolean account_list_queried; InfAclAccount* accounts; guint n_accounts; InfRequest* query_acl_request; GSList* set_acl_requests; GSList* remove_acl_account_requests; GSList* lookup_acl_account_requests; GSList* pending_sheets; GtkMenu* popup_menu; InfAclAccountId popup_account; GtkWidget* status_text; GtkWidget* tree_view; GtkWidget* sheet_view; GtkWidget* add_button; GtkWidget* remove_button; GtkCellRenderer* renderer; }; enum { PROP_0, PROP_BROWSER, PROP_BROWSER_ITER }; #define INF_GTK_PERMISSIONS_DIALOG_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INF_GTK_TYPE_PERMISSIONS_DIALOG, InfGtkPermissionsDialogPrivate)) G_DEFINE_TYPE_WITH_CODE(InfGtkPermissionsDialog, inf_gtk_permissions_dialog, GTK_TYPE_DIALOG, G_ADD_PRIVATE(InfGtkPermissionsDialog)) /* * Private functionality */ static void inf_gtk_permissions_dialog_update(InfGtkPermissionsDialog* dialog, const GError* error); static void inf_gtk_permissions_dialog_update_sheet(InfGtkPermissionsDialog* dialog); static gboolean inf_gtk_permissions_dialog_find_account(InfGtkPermissionsDialog* dialog, InfAclAccountId account, GtkTreeIter* out_iter) { InfGtkPermissionsDialogPrivate* priv; gpointer row_account_id; GtkTreeModel* model; GtkTreeIter iter; priv = INF_GTK_PERMISSIONS_DIALOG_PRIVATE(dialog); model = GTK_TREE_MODEL(priv->account_store); if(gtk_tree_model_get_iter_first(model, &iter)) { do { gtk_tree_model_get( model, &iter, INF_GTK_PERMISSIONS_DIALOG_COLUMN_ID, &row_account_id, -1 ); if(row_account_id == INF_ACL_ACCOUNT_ID_TO_POINTER(account)) { if(out_iter != NULL) *out_iter = iter; return TRUE; } } while(gtk_tree_model_iter_next(model, &iter)); } return FALSE; } static InfGtkPermissionsDialogPendingSheet* inf_gtk_permissions_dialog_find_pending_sheet(InfGtkPermissionsDialog* dialog, GtkTreeIter* iter) { InfGtkPermissionsDialogPrivate* priv; GtkTreeModel* model; GtkTreePath* path; GSList* item; InfGtkPermissionsDialogPendingSheet* pending; GtkTreePath* pending_path; priv = INF_GTK_PERMISSIONS_DIALOG_PRIVATE(dialog); model = GTK_TREE_MODEL(priv->account_store); path = gtk_tree_model_get_path(model, iter); for(item = priv->pending_sheets; item != NULL; item = item->next) { pending = (InfGtkPermissionsDialogPendingSheet*)item->data; pending_path = gtk_tree_row_reference_get_path(pending->row); g_assert(pending_path != NULL); if(gtk_tree_path_compare(path, pending_path) == 0) { gtk_tree_path_free(path); gtk_tree_path_free(pending_path); return pending; } gtk_tree_path_free(pending_path); } gtk_tree_path_free(path); return NULL; } static void inf_gtk_permissions_dialog_set_acl_finished_cb(InfRequest* request, const InfRequestResult* result, const GError* error, gpointer user_data) { InfGtkPermissionsDialog* dialog; InfGtkPermissionsDialogPrivate* priv; dialog = INF_GTK_PERMISSIONS_DIALOG(user_data); priv = INF_GTK_PERMISSIONS_DIALOG_PRIVATE(dialog); if(error != NULL) { /* Show the error message */ inf_gtk_permissions_dialog_update(dialog, error); /* Reset sheet to what we had before making the request */ inf_gtk_permissions_dialog_update_sheet(dialog); } if(g_slist_find(priv->set_acl_requests, request) != NULL) { priv->set_acl_requests = g_slist_remove(priv->set_acl_requests, request); g_object_unref(request); } } static void inf_gtk_permissions_dialog_selection_changed_cb(GtkTreeSelection* selection, gpointer user_data) { InfGtkPermissionsDialog* dialog; dialog = INF_GTK_PERMISSIONS_DIALOG(user_data); /* Update the sheet that is displayed */ inf_gtk_permissions_dialog_update_sheet(dialog); /* Also update the account list itself -- if the previously selected entry * does not have any permissions set, for example because the user set * everything to default, then remove the account from the account list. */ inf_gtk_permissions_dialog_update(dialog, NULL); } static void inf_gtk_permissions_dialog_sheet_changed_cb(InfGtkAclSheetView* sheet_view, gpointer user_data) { InfGtkPermissionsDialog* dialog; InfGtkPermissionsDialogPrivate* priv; const InfAclSheet* sheet; InfAclSheetSet sheet_set; InfRequest* request; GtkTreeSelection* selection; gboolean has_selection; GtkTreeIter iter; InfGtkPermissionsDialogPendingSheet* pending; dialog = INF_GTK_PERMISSIONS_DIALOG(user_data); priv = INF_GTK_PERMISSIONS_DIALOG_PRIVATE(dialog); sheet = inf_gtk_acl_sheet_view_get_sheet( INF_GTK_ACL_SHEET_VIEW(priv->sheet_view) ); /* This can be NULL during destruction, when the sheet view is reset. */ if(sheet != NULL) { /* If the sheet does not have an ID set, the lookup is still in progress. * In that case, we run the ACL setting once we have looked up the ID. */ if(sheet->account != 0) { sheet_set.own_sheets = NULL; sheet_set.sheets = sheet; sheet_set.n_sheets = 1; request = inf_browser_set_acl( priv->browser, &priv->browser_iter, &sheet_set, inf_gtk_permissions_dialog_set_acl_finished_cb, dialog ); if(request != NULL) { priv->set_acl_requests = g_slist_prepend(priv->set_acl_requests, request); g_object_ref(request); } } else { /* Must be a pending sheet */ selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(priv->tree_view)); has_selection = gtk_tree_selection_get_selected(selection, NULL, &iter); g_assert(has_selection); pending = inf_gtk_permissions_dialog_find_pending_sheet(dialog, &iter); g_assert(pending != NULL); pending->sheet = *sheet; } } } static int inf_gtk_permissions_dialog_account_sort_func(GtkTreeModel* model, GtkTreeIter* a, GtkTreeIter* b, gpointer user_data) { InfGtkPermissionsDialog* dialog; InfGtkPermissionsDialogPrivate* priv; InfAclAccountId default_id; gpointer account_a_id_ptr; gpointer account_b_id_ptr; InfAclAccountId account_a_id; InfAclAccountId account_b_id; const gchar* account_a_id_str; const gchar* account_b_id_str; gchar* account_a_name; gchar* account_b_name; int result; dialog = INF_GTK_PERMISSIONS_DIALOG(user_data); priv = INF_GTK_PERMISSIONS_DIALOG_PRIVATE(dialog); gtk_tree_model_get( model, a, INF_GTK_PERMISSIONS_DIALOG_COLUMN_ID, &account_a_id_ptr, INF_GTK_PERMISSIONS_DIALOG_COLUMN_NAME, &account_a_name, -1 ); gtk_tree_model_get( model, b, INF_GTK_PERMISSIONS_DIALOG_COLUMN_ID, &account_b_id_ptr, INF_GTK_PERMISSIONS_DIALOG_COLUMN_NAME, &account_b_name, -1 ); account_a_id = INF_ACL_ACCOUNT_POINTER_TO_ID(account_a_id_ptr); account_b_id = INF_ACL_ACCOUNT_POINTER_TO_ID(account_b_id_ptr); account_a_id_str = inf_acl_account_id_to_string(account_a_id); account_b_id_str = inf_acl_account_id_to_string(account_b_id); /* default sorts before anything */ default_id = inf_acl_account_id_from_string("default"); if(account_a_id == default_id) { if(account_b_id == default_id) result = 0; else result = -1; } else if(account_b_id == default_id) { result = 1; } /* Next, accounts with user name and ID sort before accounts without * one of the two*/ else if(account_a_name != NULL && account_a_id != 0) { if(account_b_name != NULL && account_b_id != 0) result = g_utf8_collate(account_a_name, account_b_name); else result = -1; } else if(account_b_name != NULL && account_b_id != 0) { result = 1; } /* Next, accounts with ID but no user name are preferred. Such accounts * have a lookup pending, but the sheet is synchronized. */ else if(account_a_name == NULL && account_a_id != 0) { if(account_b_name == NULL && account_b_id != 0) result = g_utf8_collate(account_a_id_str, account_b_id_str); else result = -1; } else if(account_b_name == NULL && account_b_id != 0) { result = 1; } /* Next, accounts with user name but no ID. These are recently added * entries, and the ID lookup is still in progress. The sheets are * not yet synchronized. If the ID lookup fails, the entry is removed. */ else if(account_a_name != NULL && account_a_id == 0) { if(account_b_name != NULL && account_b_id == 0) result = g_utf8_collate(account_a_name, account_b_name); else result = -1; } else if(account_b_name != NULL && account_b_id == 0) { result = 1; } /* Now, it would mean that both A and B do have neither ID nor name * set. This cannot be, since this can only happen with newly created * entries, but these entries get a name set immediately. */ else { g_assert_not_reached(); result = 0; } g_free(account_a_name); g_free(account_b_name); return result; } static void inf_gtk_permissions_dialog_lookup_by_name_finished_cb( InfRequest* request, const InfRequestResult* result, const GError* error, gpointer user_data); static void inf_gtk_permissions_dialog_remove_pending_sheet( InfGtkPermissionsDialog* dialog, InfGtkPermissionsDialogPendingSheet* pending) { InfGtkPermissionsDialogPrivate* priv; GtkTreePath* path; GtkTreeIter iter; gboolean has_iter; priv = INF_GTK_PERMISSIONS_DIALOG_PRIVATE(dialog); if(pending->lookup_request != NULL) { inf_signal_handlers_disconnect_by_func( G_OBJECT(pending->lookup_request), G_CALLBACK(inf_gtk_permissions_dialog_lookup_by_name_finished_cb), pending ); g_object_unref(pending->lookup_request); } /* Remove sheet from the list, so that when gtk_list_store_remove() causes * an update (due to the tree selection changing), there is no invalid * pending sheet in the list anymore. */ priv->pending_sheets = g_slist_remove(priv->pending_sheets, pending); /* Remove the entry from the list, except the pending sheet was realized, * i.e. the ID was looked up. */ if(pending->row != NULL) { path = gtk_tree_row_reference_get_path(pending->row); g_assert(path != NULL); has_iter = gtk_tree_model_get_iter( GTK_TREE_MODEL(priv->account_store), &iter, path ); g_assert(has_iter == TRUE); gtk_list_store_remove(priv->account_store, &iter); gtk_tree_path_free(path); gtk_tree_row_reference_free(pending->row); } g_slice_free(InfGtkPermissionsDialogPendingSheet, pending); } static void inf_gtk_permissions_dialog_realize_pending_sheet( InfGtkPermissionsDialog* dialog, InfGtkPermissionsDialogPendingSheet* pending, InfAclAccountId id, const gchar* name) { InfGtkPermissionsDialogPrivate* priv; GtkTreeIter iter; GtkTreePath* path; gboolean has_iter; InfAclSheet pending_sheet; InfAclSheetSet sheet_set; InfRequest* request; priv = INF_GTK_PERMISSIONS_DIALOG_PRIVATE(dialog); pending_sheet = pending->sheet; pending_sheet.account = id; if(inf_gtk_permissions_dialog_find_account(dialog, id, &iter)) { /* An entry with that ID exists already. Don't try to merge it with the * pending sheet here, but just discard the pending sheet. */ path = gtk_tree_model_get_path( GTK_TREE_MODEL(priv->account_store), &iter ); /* When selecting the already existing entry, block the * selection-changed handler, so that it does not already cause an * update of the dialog. We do the update after we have also removed * the pending sheet */ inf_signal_handlers_block_by_func( G_OBJECT(gtk_tree_view_get_selection(GTK_TREE_VIEW(priv->tree_view))), G_CALLBACK(inf_gtk_permissions_dialog_selection_changed_cb), dialog ); gtk_tree_view_set_cursor( GTK_TREE_VIEW(priv->tree_view), path, gtk_tree_view_get_column(GTK_TREE_VIEW(priv->tree_view), 0), FALSE ); inf_gtk_permissions_dialog_remove_pending_sheet(dialog, pending); inf_signal_handlers_unblock_by_func( G_OBJECT(gtk_tree_view_get_selection(GTK_TREE_VIEW(priv->tree_view))), G_CALLBACK(inf_gtk_permissions_dialog_selection_changed_cb), dialog ); gtk_tree_path_free(path); /* Update currently displayed sheet, since we have changed the selection * with blocked selection-changed signal handler */ inf_gtk_permissions_dialog_update_sheet(dialog); } else { path = gtk_tree_row_reference_get_path(pending->row); g_assert(path != NULL); has_iter = gtk_tree_model_get_iter( GTK_TREE_MODEL(priv->account_store), &iter, path ); g_assert(has_iter == TRUE); /* Set the entry in the list store */ gtk_list_store_set( priv->account_store, &iter, INF_GTK_PERMISSIONS_DIALOG_COLUMN_ID, INF_ACL_ACCOUNT_ID_TO_POINTER(id), INF_GTK_PERMISSIONS_DIALOG_COLUMN_NAME, name, -1 ); /* Remove the pending item. Free the tree row reference before, so that * inf_gtk_permissions_dialog_remove_pending_sheet does not remove the * realized entry from the list store. */ gtk_tree_row_reference_free(pending->row); pending->row = NULL; inf_gtk_permissions_dialog_remove_pending_sheet(dialog, pending); /* Set the realized sheet on the sheet view. This is important, so that * when the sheet view emits its changed signal, the account ID is no * longer set to 0. */ inf_signal_handlers_block_by_func( G_OBJECT(priv->sheet_view), G_CALLBACK(inf_gtk_permissions_dialog_sheet_changed_cb), dialog ); inf_gtk_acl_sheet_view_set_sheet( INF_GTK_ACL_SHEET_VIEW(priv->sheet_view), &pending_sheet ); inf_signal_handlers_unblock_by_func( G_OBJECT(priv->sheet_view), G_CALLBACK(inf_gtk_permissions_dialog_sheet_changed_cb), dialog ); /* If there are alreay options set, then set the corresponding ACL. Note * that in principle our "changed" signal handler would do that, but we * have blocked it above. This allows us to reduce network traffic when the * mask is empty. */ if(!inf_acl_mask_empty(&pending_sheet.mask)) { sheet_set.own_sheets = NULL; sheet_set.sheets = &pending_sheet; sheet_set.n_sheets = 1; request = inf_browser_set_acl( priv->browser, &priv->browser_iter, &sheet_set, inf_gtk_permissions_dialog_set_acl_finished_cb, dialog ); if(request != NULL) { priv->set_acl_requests = g_slist_prepend(priv->set_acl_requests, request); g_object_ref(request); } } /* Update the widget itself, since the add and remove buttons might * change their sensitivity after the realization. */ inf_gtk_permissions_dialog_update(dialog, NULL); } } static void inf_gtk_permissions_dialog_lookup_by_name_finished_cb( InfRequest* request, const InfRequestResult* result, const GError* error, gpointer user_data) { InfGtkPermissionsDialogPendingSheet* pending; InfGtkPermissionsDialog* dialog; InfGtkPermissionsDialogPrivate* priv; const InfAclAccount* accounts; guint n_accounts; pending = (InfGtkPermissionsDialogPendingSheet*)user_data; dialog = pending->dialog; priv = INF_GTK_PERMISSIONS_DIALOG_PRIVATE(dialog); if(pending->lookup_request != NULL) { g_object_unref(pending->lookup_request); pending->lookup_request = NULL; } if(error != NULL) { g_warning("Failed to reverse lookup: %s", error->message); inf_gtk_permissions_dialog_remove_pending_sheet(dialog, pending); } else { inf_request_result_get_lookup_acl_accounts( result, NULL, &accounts, &n_accounts ); if(n_accounts > 0) { /* There is at least one user with the given name. If there are more, * we cannot distinguish between them, so just take the first */ if(n_accounts > 1) { g_warning( "Multiple accounts with the same name \"%s\"", accounts[0].name ); } inf_gtk_permissions_dialog_realize_pending_sheet( dialog, pending, accounts[0].id, accounts[0].name ); } else { /* There is no user with this name */ inf_gtk_permissions_dialog_remove_pending_sheet(dialog, pending); } } } static void inf_gtk_permissions_dialog_lookup_acl_accounts_finished_cb( InfRequest* request, const InfRequestResult* result, const GError* error, gpointer user_data); static void inf_gtk_permissions_dialog_remove_lookup_acl_accounts_request( InfGtkPermissionsDialog* dialog, InfRequest* request) { InfGtkPermissionsDialogPrivate* priv; priv = INF_GTK_PERMISSIONS_DIALOG_PRIVATE(dialog); inf_signal_handlers_disconnect_by_func( request, G_CALLBACK(inf_gtk_permissions_dialog_lookup_acl_accounts_finished_cb), dialog ); /* Can finish instantly */ if(g_slist_find(priv->lookup_acl_account_requests, request) != NULL) { priv->lookup_acl_account_requests = g_slist_remove(priv->lookup_acl_account_requests, request); g_object_unref(request); } } static void inf_gtk_permissions_dialog_lookup_acl_accounts_finished_cb( InfRequest* request, const InfRequestResult* result, const GError* error, gpointer user_data) { InfGtkPermissionsDialog* dialog; InfGtkPermissionsDialogPrivate* priv; const InfAclAccount* accounts; guint n_accounts; guint i; GtkTreeIter iter; InfAclAccountId account_id; dialog = INF_GTK_PERMISSIONS_DIALOG(user_data); priv = INF_GTK_PERMISSIONS_DIALOG_PRIVATE(dialog); if(error != NULL) { /* TODO: Should we show this in the dialog? */ g_warning("Failed to look up accounts: %s\n", error->message); } else { inf_request_result_get_lookup_acl_accounts( result, NULL, &accounts, &n_accounts ); for(i = 0; i < n_accounts; ++i) { if(accounts[i].name != NULL) { account_id = accounts[i].id; if(inf_gtk_permissions_dialog_find_account(dialog, account_id, &iter)) { gtk_list_store_set( GTK_LIST_STORE(priv->account_store), &iter, INF_GTK_PERMISSIONS_DIALOG_COLUMN_NAME, accounts[i].name, -1 ); } } } } inf_gtk_permissions_dialog_remove_lookup_acl_accounts_request( dialog, request ); } static void inf_gtk_permissions_dialog_fill_account_list(InfGtkPermissionsDialog* dialog, const InfAclAccountId* ids, guint n_ids) { InfGtkPermissionsDialogPrivate* priv; GtkTreeModel* model; gboolean* have_accounts; GtkTreeIter iter; gpointer account_id_ptr; InfAclAccountId account_id; gboolean has_row; guint i, j; InfAclAccountId* lookup_ids; guint n_lookup_ids; guint lookup_index; const gchar* new_account_name; InfAclMask perms; const InfAclAccount* default_account; const InfAclAccount* local_account; InfRequest* request; priv = INF_GTK_PERMISSIONS_DIALOG_PRIVATE(dialog); model = GTK_TREE_MODEL(priv->account_store); /* Remove all accounts that are not present in the given account list. * Flag accounts that we have found, and then add all the un-flagged ones. * This way we keep the overlapping accounts in the list, which should * provide a smooth user experience, for example when an item in the list * is selected it is not removed and re-added. */ have_accounts = g_malloc(n_ids * sizeof(gboolean)); for(i = 0; i < n_ids; ++i) have_accounts[i] = FALSE; n_lookup_ids = n_ids; has_row = gtk_tree_model_get_iter_first(model, &iter); while(has_row) { gtk_tree_model_get( model, &iter, INF_GTK_PERMISSIONS_DIALOG_COLUMN_ID, &account_id_ptr, -1 ); account_id = INF_ACL_ACCOUNT_POINTER_TO_ID(account_id_ptr); if(account_id == 0) { /* This is a pending account, keep it */ has_row = gtk_tree_model_iter_next(model, &iter); } else { for(i = 0; i < n_ids; ++i) if(account_id == ids[i]) break; if(i < n_ids) { have_accounts[i] = TRUE; has_row = gtk_tree_model_iter_next(model, &iter); g_assert(n_lookup_ids > 0); --n_lookup_ids; } else { inf_signal_handlers_block_by_func( gtk_tree_view_get_selection(GTK_TREE_VIEW(priv->tree_view)), G_CALLBACK(inf_gtk_permissions_dialog_selection_changed_cb), dialog ); has_row = gtk_list_store_remove(priv->account_store, &iter); inf_signal_handlers_unblock_by_func( gtk_tree_view_get_selection(GTK_TREE_VIEW(priv->tree_view)), G_CALLBACK(inf_gtk_permissions_dialog_selection_changed_cb), dialog ); } } } if(n_lookup_ids > 0) lookup_ids = g_malloc(sizeof(InfAclAccountId) * n_lookup_ids); lookup_index = 0; default_account = inf_browser_get_acl_default_account(priv->browser); local_account = inf_browser_get_acl_local_account(priv->browser); for(i = 0; i < n_ids; ++i) { if(!have_accounts[i]) { if(ids[i] == default_account->id) { new_account_name = default_account->name; } else if(local_account != NULL && ids[i] == local_account->id) { new_account_name = local_account->name; } else { /* If we have queried the account list, lookup the account in the * queried list. */ new_account_name = NULL; for(j = 0; j < priv->n_accounts; ++j) { if(priv->accounts[j].id == ids[i]) { new_account_name = priv->accounts[j].name; break; } } } gtk_list_store_insert_with_values( priv->account_store, NULL, -1, INF_GTK_PERMISSIONS_DIALOG_COLUMN_ID, INF_ACL_ACCOUNT_ID_TO_POINTER(ids[i]), INF_GTK_PERMISSIONS_DIALOG_COLUMN_NAME, new_account_name, -1 ); /* If we don't know the account name, we need to look it up. */ if(new_account_name == NULL && ids[i] != default_account->id) lookup_ids[lookup_index++] = ids[i]; } } /* Lookup accounts with unknown name, if we can. */ if(lookup_index > 0) { g_assert(lookup_index <= n_lookup_ids); inf_acl_mask_set1(&perms, INF_ACL_CAN_QUERY_ACCOUNT_LIST); inf_browser_check_acl( priv->browser, &priv->browser_iter, local_account ? local_account->id : 0, &perms, &perms ); if(inf_acl_mask_has(&perms, INF_ACL_CAN_QUERY_ACCOUNT_LIST)) { request = inf_browser_lookup_acl_accounts( priv->browser, lookup_ids, lookup_index, inf_gtk_permissions_dialog_lookup_acl_accounts_finished_cb, dialog ); if(request != NULL) { g_object_ref(request); priv->lookup_acl_account_requests = g_slist_prepend( priv->lookup_acl_account_requests, request ); } } } if(n_lookup_ids > 0) g_free(lookup_ids); g_free(have_accounts); } static void inf_gtk_permissions_dialog_update_sheet(InfGtkPermissionsDialog* dialog) { InfGtkPermissionsDialogPrivate* priv; GtkTreeSelection* selection; GtkTreeModel* model; GtkTreeIter iter; gpointer account_id_ptr; InfAclAccountId account_id; InfAclAccountId default_id; const InfAclSheetSet* sheet_set; const InfAclSheet* sheet; InfAclSheet default_sheet; InfAclMask show_mask; InfAclMask neg_mask; InfGtkPermissionsDialogPendingSheet* pending; InfBrowserIter test_iter; priv = INF_GTK_PERMISSIONS_DIALOG_PRIVATE(dialog); selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(priv->tree_view)); inf_signal_handlers_block_by_func( G_OBJECT(priv->sheet_view), G_CALLBACK(inf_gtk_permissions_dialog_sheet_changed_cb), dialog ); if(!gtk_tree_selection_get_selected(selection, &model, &iter)) { inf_gtk_acl_sheet_view_set_sheet( INF_GTK_ACL_SHEET_VIEW(priv->sheet_view), NULL ); account_id = 0; } else { gtk_tree_model_get( model, &iter, INF_GTK_PERMISSIONS_DIALOG_COLUMN_ID, &account_id_ptr, -1 ); account_id = INF_ACL_ACCOUNT_POINTER_TO_ID(account_id_ptr); if(account_id != 0) { sheet = NULL; sheet_set = inf_browser_get_acl(priv->browser, &priv->browser_iter); if(sheet_set != NULL) { sheet = inf_acl_sheet_set_find_const_sheet(sheet_set, account_id); } } else { /* It is (must be) a pending sheet */ pending = inf_gtk_permissions_dialog_find_pending_sheet(dialog, &iter); g_assert(pending != NULL); sheet = &pending->sheet; } if(sheet != NULL) { inf_gtk_acl_sheet_view_set_sheet( INF_GTK_ACL_SHEET_VIEW(priv->sheet_view), sheet ); } else { /* No sheet: set default sheet (all permissions masked out) */ default_sheet.account = account_id; inf_acl_mask_clear(&default_sheet.mask); inf_acl_mask_clear(&default_sheet.perms); inf_gtk_acl_sheet_view_set_sheet( INF_GTK_ACL_SHEET_VIEW(priv->sheet_view), &default_sheet ); } } /* Block default column if this is the default sheet of the root node */ test_iter = priv->browser_iter; show_mask = INF_ACL_MASK_ALL; if(!inf_browser_get_parent(priv->browser, &test_iter)) { /* This is the root node. Block default column if this is the default * account. */ default_id = inf_acl_account_id_from_string("default"); if(account_id == default_id) { inf_gtk_acl_sheet_view_set_show_default( INF_GTK_ACL_SHEET_VIEW(priv->sheet_view), FALSE ); } else { inf_gtk_acl_sheet_view_set_show_default( INF_GTK_ACL_SHEET_VIEW(priv->sheet_view), TRUE ); } } else { /* This is a leaf node. Show the default column, and block non-root * permissions. */ inf_gtk_acl_sheet_view_set_show_default( INF_GTK_ACL_SHEET_VIEW(priv->sheet_view), TRUE ); /* Remove root-only permissions */ inf_acl_mask_neg(&INF_ACL_MASK_ROOT, &neg_mask); inf_acl_mask_and(&show_mask, &neg_mask, &show_mask); } /* If the node is a subdirectory, we don't hide the permissions that * only work for leaf nodes, since they are applied to all leaf nodes in * the subdirectory, unless overridden. */ if(!inf_browser_is_subdirectory(priv->browser, &priv->browser_iter)) { inf_acl_mask_neg(&INF_ACL_MASK_SUBDIRECTORY, &neg_mask); inf_acl_mask_and(&show_mask, &neg_mask, &show_mask); } inf_gtk_acl_sheet_view_set_permission_mask( INF_GTK_ACL_SHEET_VIEW(priv->sheet_view), &show_mask ); inf_signal_handlers_unblock_by_func( G_OBJECT(priv->sheet_view), G_CALLBACK(inf_gtk_permissions_dialog_sheet_changed_cb), dialog ); } static void inf_gtk_permissions_dialog_node_removed_cb(InfBrowser* browser, const InfBrowserIter* iter, InfRequest* request, gpointer user_data) { InfGtkPermissionsDialog* dialog; InfGtkPermissionsDialogPrivate* priv; dialog = INF_GTK_PERMISSIONS_DIALOG(user_data); priv = INF_GTK_PERMISSIONS_DIALOG_PRIVATE(dialog); if(inf_browser_is_ancestor(browser, iter, &priv->browser_iter)) inf_gtk_permissions_dialog_set_node(dialog, NULL, NULL); } static void inf_gtk_permissions_dialog_acl_account_added_cb(InfBrowser* browser, const InfAclAccount* account, InfRequest* request, gpointer user_data) { InfGtkPermissionsDialog* dialog; InfGtkPermissionsDialogPrivate* priv; dialog = INF_GTK_PERMISSIONS_DIALOG(user_data); priv = INF_GTK_PERMISSIONS_DIALOG_PRIVATE(dialog); /* Add the new user to the user list. Note that this is also called when * the given user was updated, in which case we need to call row_changed, * since its name might have changed. */ if(account->id != 0 && account->name != NULL && priv->accounts != NULL) { priv->accounts = g_realloc( priv->accounts, (priv->n_accounts + 1) * sizeof(InfAclAccount) ); priv->accounts[priv->n_accounts].id = account->id; priv->accounts[priv->n_accounts].name = g_strdup(account->name); ++priv->n_accounts; /* Need to update because the add button sensitivity might change */ inf_gtk_permissions_dialog_update(dialog, NULL); } } static void inf_gtk_permissions_dialog_acl_account_removed_cb(InfBrowser* browser, const InfAclAccount* account, InfRequest* request, gpointer user_data) { InfGtkPermissionsDialog* dialog; InfGtkPermissionsDialogPrivate* priv; gboolean have_account; GtkTreeIter iter; guint i; dialog = INF_GTK_PERMISSIONS_DIALOG(user_data); priv = INF_GTK_PERMISSIONS_DIALOG_PRIVATE(dialog); g_assert(account->id != 0); if(priv->popup_menu != NULL && account->id == priv->popup_account) gtk_menu_popdown(priv->popup_menu); g_assert(priv->popup_menu == NULL); g_assert(priv->popup_account == 0); /* The account should not be in the list anymore, since all ACL sheets for * this account should have been removed first. However, it can happen when * the removed account is selected, and therefore not removed when the ACL * update is notified. Therefore, we remove the entry here even if it is * selected, since the account no longer exists. */ have_account = inf_gtk_permissions_dialog_find_account(dialog, account->id, &iter); if(have_account == TRUE) { /* It is important that we block this signal handler here, otherwise * the selection might be changed while we delete the currently selected * account, which can trigger an update and iteration in the list store * while the call to gtk_list_store_remove() has not yet completed. */ inf_signal_handlers_block_by_func( gtk_tree_view_get_selection(GTK_TREE_VIEW(priv->tree_view)), G_CALLBACK(inf_gtk_permissions_dialog_selection_changed_cb), dialog ); gtk_list_store_remove(priv->account_store, &iter); inf_signal_handlers_unblock_by_func( gtk_tree_view_get_selection(GTK_TREE_VIEW(priv->tree_view)), G_CALLBACK(inf_gtk_permissions_dialog_selection_changed_cb), dialog ); inf_gtk_permissions_dialog_update_sheet(dialog); } /* Update account list */ if(priv->accounts != NULL) { for(i = 0; i < priv->n_accounts; ++i) { if(priv->accounts[i].id == account->id) { priv->accounts[i] = priv->accounts[priv->n_accounts - 1]; --priv->n_accounts; priv->accounts = g_realloc( priv->accounts, sizeof(InfAclAccount) * priv->n_accounts ); break; } } } /* Need to update because the add button sensitivity might change, and * the selected account might change. */ inf_gtk_permissions_dialog_update(dialog, NULL); } static void inf_gtk_permissions_dialog_acl_changed_cb(InfBrowser* browser, const InfBrowserIter* iter, const InfAclSheetSet* sheet_set, InfRequest* request, gpointer user_data) { InfGtkPermissionsDialog* dialog; InfGtkPermissionsDialogPrivate* priv; dialog = INF_GTK_PERMISSIONS_DIALOG(user_data); priv = INF_GTK_PERMISSIONS_DIALOG_PRIVATE(dialog); /* If the node we are currently viewing had its ACL changed, show the * new ACL. */ if(iter->node == priv->browser_iter.node) inf_gtk_permissions_dialog_update_sheet(dialog); /* If the node or one of its ancestors had their ACL changed, update the * view, since we might have been granted or revoked rights to see the * user list or the ACL for this node, or the non-default ACL sheets * have changed. */ if(inf_browser_is_ancestor(browser, iter, &priv->browser_iter)) inf_gtk_permissions_dialog_update(dialog, NULL); } static void inf_gtk_permissions_dialog_renderer_editing_started_cb(GtkCellRenderer* r, GtkCellEditable* edit, const gchar* path, gpointer user_data) { /* In the editing_canceled signal handler, we need to know the path of the * cell that was edited. However, it does not provide a path parameter. * Therefore, store the path here in the cell renderer. * * Normally, we could simply query the selected row, however the row can * be deselected without the editing actually being cancelled, for example * when focusing another widget. */ g_object_set_data_full( G_OBJECT(r), "inf-gtk-permissions-dialog-path", g_strdup(path), g_free ); } static void inf_gtk_permissions_dialog_renderer_editing_canceled_cb(GtkCellRenderer* r, gpointer user_data) { InfGtkPermissionsDialog* dialog; InfGtkPermissionsDialogPrivate* priv; gchar* path_str; GtkTreePath* path; GtkTreeIter iter; gboolean has_selected; InfGtkPermissionsDialogPendingSheet* pending; dialog = INF_GTK_PERMISSIONS_DIALOG(user_data); priv = INF_GTK_PERMISSIONS_DIALOG_PRIVATE(dialog); /* Remove the editing facility of the cell renderer */ g_object_set( G_OBJECT(priv->renderer), "model", NULL, "editable", FALSE, NULL ); path_str = g_object_steal_data( G_OBJECT(r), "inf-gtk-permissions-dialog-path" ); /* Remove the pending sheet */ path = gtk_tree_path_new_from_string(path_str); g_free(path_str); has_selected = gtk_tree_model_get_iter( GTK_TREE_MODEL(priv->account_store), &iter, path ); g_assert(has_selected == TRUE); pending = inf_gtk_permissions_dialog_find_pending_sheet(dialog, &iter); g_assert(pending != NULL); inf_gtk_permissions_dialog_remove_pending_sheet(dialog, pending); } static void inf_gtk_permissions_dialog_renderer_changed_cb(GtkCellRendererCombo* combo, const gchar* path_str, GtkTreeIter* combo_iter, gpointer user_data) { InfGtkPermissionsDialog* dialog; InfGtkPermissionsDialogPrivate* priv; GtkTreePath* path; GtkTreeIter view_iter; gboolean has_path; InfGtkPermissionsDialogPendingSheet* pending; GtkTreeModel* model; gpointer id_ptr; dialog = INF_GTK_PERMISSIONS_DIALOG(user_data); priv = INF_GTK_PERMISSIONS_DIALOG_PRIVATE(dialog); path = gtk_tree_path_new_from_string(path_str); has_path = gtk_tree_model_get_iter( GTK_TREE_MODEL(priv->account_store), &view_iter, path ); g_assert(has_path); gtk_tree_path_free(path); pending = inf_gtk_permissions_dialog_find_pending_sheet(dialog, &view_iter); g_assert(pending != NULL); g_object_get(G_OBJECT(combo), "model", &model, NULL); g_assert(model != NULL); gtk_tree_model_get( model, combo_iter, INF_GTK_PERMISSIONS_DIALOG_COLUMN_ID, &id_ptr, -1 ); pending->last_combo_changed_id = INF_ACL_ACCOUNT_POINTER_TO_ID(id_ptr); g_object_unref(model); } static void inf_gtk_permissions_dialog_renderer_edited_cb(GtkCellRendererCombo* renderer, const gchar* path_str, const gchar* text, gpointer user_data) { InfGtkPermissionsDialog* dialog; InfGtkPermissionsDialogPrivate* priv; gchar* path_str_obj; GtkTreePath* path; gboolean has_path; GtkTreeIter view_iter; InfGtkPermissionsDialogPendingSheet* pending; GtkTreeModel* model; InfRequest* request; dialog = INF_GTK_PERMISSIONS_DIALOG(user_data); priv = INF_GTK_PERMISSIONS_DIALOG_PRIVATE(dialog); path_str_obj = g_object_steal_data( G_OBJECT(renderer), "inf-gtk-permissions-dialog-path" ); g_assert(strcmp(path_str_obj, path_str) == 0); g_free(path_str_obj); path = gtk_tree_path_new_from_string(path_str); has_path = gtk_tree_model_get_iter( GTK_TREE_MODEL(priv->account_store), &view_iter, path ); g_assert(has_path); gtk_tree_path_free(path); pending = inf_gtk_permissions_dialog_find_pending_sheet(dialog, &view_iter); g_assert(pending != NULL); /* If we selected a user with the combo box, find the corresponding ID */ g_object_get(G_OBJECT(renderer), "model", &model, NULL); /* Remove the editing facility of the cell renderer */ g_object_set( G_OBJECT(priv->renderer), "model", NULL, "editable", FALSE, NULL ); g_assert(model != NULL); if(gtk_tree_model_iter_n_children(model, NULL) > 0) { g_assert(pending->last_combo_changed_id != 0); inf_gtk_permissions_dialog_realize_pending_sheet( dialog, pending, pending->last_combo_changed_id, text ); } else { /* While we don't have an ID, set a name to show in the list */ gtk_list_store_set( priv->account_store, &view_iter, INF_GTK_PERMISSIONS_DIALOG_COLUMN_NAME, text, -1 ); /* Make a reverse lookup for the ID */ request = inf_browser_lookup_acl_account_by_name( priv->browser, text, inf_gtk_permissions_dialog_lookup_by_name_finished_cb, pending ); if(request != NULL) { pending->lookup_request = request; g_object_ref(request); } } g_object_unref(model); } static void inf_gtk_permissions_dialog_add_clicked_cb(GtkButton* button, gpointer user_data) { InfGtkPermissionsDialog* dialog; InfGtkPermissionsDialogPrivate* priv; GtkTreeIter new_iter; GtkTreePath* new_path; InfGtkPermissionsDialogPendingSheet* pending; GtkListStore* store; const InfAclSheetSet* sheet_set; const InfAclSheet* sheet; guint i; dialog = INF_GTK_PERMISSIONS_DIALOG(user_data); priv = INF_GTK_PERMISSIONS_DIALOG_PRIVATE(dialog); /* If we are currently naming another pending sheet, then stop editing * that. */ gtk_cell_renderer_stop_editing(priv->renderer, TRUE); /* Insert a new entry without values */ gtk_list_store_insert_with_values( priv->account_store, &new_iter, -1, INF_GTK_PERMISSIONS_DIALOG_COLUMN_ID, 0, INF_GTK_PERMISSIONS_DIALOG_COLUMN_NAME, NULL, -1 ); new_path = gtk_tree_model_get_path( GTK_TREE_MODEL(priv->account_store), &new_iter ); pending = g_slice_new(InfGtkPermissionsDialogPendingSheet); pending->dialog = dialog; pending->row = gtk_tree_row_reference_new( GTK_TREE_MODEL(priv->account_store), new_path ); pending->sheet.account = 0; inf_acl_mask_clear(&pending->sheet.mask); inf_acl_mask_clear(&pending->sheet.perms); pending->last_combo_changed_id = 0; pending->lookup_request = NULL; priv->pending_sheets = g_slist_prepend(priv->pending_sheets, pending); /* Prepare the cell renderer editing */ store = gtk_list_store_new(2, G_TYPE_POINTER, G_TYPE_STRING); g_object_set( G_OBJECT(priv->renderer), "model", store, "editable", TRUE, "text-column", INF_GTK_PERMISSIONS_DIALOG_COLUMN_NAME, NULL ); /* TODO: If there are more than, say 25 accounts (should be configurable), * then use a free edit instead, and add a GtkEntryCompletion with all the * accounts, and perform a lookup-by-name in our cached list first. */ if(priv->accounts != NULL) { /* Create a list of possible accounts */ g_object_set(G_OBJECT(priv->renderer), "has-entry", FALSE, NULL); sheet_set = inf_browser_get_acl(priv->browser, &priv->browser_iter); for(i = 0; i < priv->n_accounts; ++i) { /* Skip the default user */ if(priv->accounts[i].name != NULL) { sheet = NULL; if(sheet_set != NULL) { sheet = inf_acl_sheet_set_find_const_sheet( sheet_set, priv->accounts[i].id ); } if(sheet == NULL) { gtk_list_store_insert_with_values( store, NULL, -1, INF_GTK_PERMISSIONS_DIALOG_COLUMN_ID, priv->accounts[i].id, INF_GTK_PERMISSIONS_DIALOG_COLUMN_NAME, priv->accounts[i].name, -1 ); } } } /* Otherwise the add button would not be set to sensitive */ g_assert(gtk_tree_model_iter_n_children(GTK_TREE_MODEL(store), NULL) > 0); } else { /* Free editing. Note that we still need to set an (empty) model, * otherwise the editing widget cannot be set by GtkCellRendererCombo. * We could use GtkCellRendererText instead, but then we would need to * juggle around with two cell renderers. */ g_object_set(G_OBJECT(priv->renderer), "has-entry", TRUE, NULL); } /* Sort the name list */ gtk_tree_sortable_set_sort_column_id( GTK_TREE_SORTABLE(store), INF_GTK_PERMISSIONS_DIALOG_COLUMN_NAME, GTK_SORT_ASCENDING ); gtk_tree_sortable_set_sort_func( GTK_TREE_SORTABLE(store), INF_GTK_PERMISSIONS_DIALOG_COLUMN_NAME, inf_gtk_permissions_dialog_account_sort_func, dialog, NULL ); g_object_unref(store); /* Before we present the editing to the user, just select the row. This * runs our signal handler for the selection change, which might remove a * row from the list, which would close down the editing again. */ gtk_tree_selection_select_path( gtk_tree_view_get_selection(GTK_TREE_VIEW(priv->tree_view)), new_path ); /* Obtain the path from the row reference, in case the list store was * altered by the selection change. */ gtk_tree_path_free(new_path); new_path = gtk_tree_row_reference_get_path(pending->row); gtk_tree_view_set_cursor( GTK_TREE_VIEW(priv->tree_view), new_path, gtk_tree_view_get_column(GTK_TREE_VIEW(priv->tree_view), 0), TRUE ); gtk_tree_path_free(new_path); } static void inf_gtk_permissions_dialog_remove_clicked_cb(GtkButton* button, gpointer user_data) { InfGtkPermissionsDialog* dialog; InfGtkPermissionsDialogPrivate* priv; GtkTreeSelection* selection; GtkTreeIter selected_iter; gpointer selected_id_ptr; InfAclAccountId selected_id; InfGtkPermissionsDialogPendingSheet* pending; const InfAclSheetSet* sheet_set; InfAclSheet set_sheet; InfAclSheetSet set_sheet_set; guint i; InfRequest* request; GtkTreeIter move_iter; gboolean could_move; dialog = INF_GTK_PERMISSIONS_DIALOG(user_data); priv = INF_GTK_PERMISSIONS_DIALOG_PRIVATE(dialog); selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(priv->tree_view)); if(!gtk_tree_selection_get_selected(selection, NULL, &selected_iter)) return; gtk_tree_model_get( GTK_TREE_MODEL(priv->account_store), &selected_iter, INF_GTK_PERMISSIONS_DIALOG_COLUMN_ID, &selected_id_ptr, -1 ); selected_id = INF_ACL_ACCOUNT_POINTER_TO_ID(selected_id_ptr); sheet_set = inf_browser_get_acl(priv->browser, &priv->browser_iter); if(selected_id == 0) { /* This is a pending sheet */ pending = inf_gtk_permissions_dialog_find_pending_sheet( dialog, &selected_iter ); g_assert(pending != NULL); inf_gtk_permissions_dialog_remove_pending_sheet(dialog, pending); } else if(sheet_set == NULL || sheet_set->n_sheets == 0) { /* It can be that the entry is only kept in the list because it is still * selected, even though the sheet set is empty. In that case, simply * remove the entry from the list. */ gtk_list_store_remove(priv->account_store, &selected_iter); } else { /* Mask-out all entries */ set_sheet.account = selected_id; inf_acl_mask_clear(&set_sheet.mask); inf_acl_mask_clear(&set_sheet.perms); set_sheet_set.n_sheets = 1; set_sheet_set.own_sheets = NULL; set_sheet_set.sheets = &set_sheet; request = inf_browser_set_acl( priv->browser, &priv->browser_iter, &set_sheet_set, inf_gtk_permissions_dialog_set_acl_finished_cb, dialog ); if(request != NULL) { priv->set_acl_requests = g_slist_prepend(priv->set_acl_requests, request); g_object_ref(request); } /* At this point, the ACL might either have been changed instantly or not. * In both cases, the selected item should not have been removed from the * list store, and our iterator is still valid. * * In any case, we need to change the selection to a different item, * otherwise, once the request finishes, the currently selected entry * would not be removed. Note that there must be at least one other item, * because the default entry is always shown and the default entry cannot * be removed. */ move_iter = selected_iter; could_move = gtk_tree_model_iter_next( GTK_TREE_MODEL(priv->account_store), &move_iter ); if(!could_move) { move_iter = selected_iter; could_move = gtk_tree_model_iter_previous( GTK_TREE_MODEL(priv->account_store), &move_iter ); } g_assert(could_move); gtk_tree_selection_select_iter( GTK_TREE_SELECTION(selection), &move_iter ); } } static void inf_gtk_permissions_dialog_remove_acl_account_finished_cb( InfRequest* request, const InfRequestResult* result, const GError* error, gpointer user_data); static void inf_gtk_permissions_dialog_remove_remove_acl_account_request( InfGtkPermissionsDialog* dialog, InfRequest* request) { InfGtkPermissionsDialogPrivate* priv; priv = INF_GTK_PERMISSIONS_DIALOG_PRIVATE(dialog); g_assert(g_slist_find(priv->remove_acl_account_requests, request) != NULL); g_signal_handlers_disconnect_by_func( request, G_CALLBACK(inf_gtk_permissions_dialog_remove_acl_account_finished_cb), dialog ); priv->remove_acl_account_requests = g_slist_remove(priv->remove_acl_account_requests, request); g_object_unref(request); } static void inf_gtk_permissions_dialog_remove_acl_account_finished_cb( InfRequest* request, const InfRequestResult* result, const GError* error, gpointer user_data) { InfGtkPermissionsDialog* dialog; dialog = INF_GTK_PERMISSIONS_DIALOG(user_data); /* TODO: Should we show this error to the user inside the dialog, or * with a message dialog? */ if(error != NULL) { g_warning("Failed to remove account: %s\n", error->message); } inf_gtk_permissions_dialog_remove_remove_acl_account_request( dialog, request ); } static void inf_gtk_permissions_dialog_popup_delete_account_cb(GtkMenuItem* item, gpointer user_data) { InfGtkPermissionsDialog* dialog; InfGtkPermissionsDialogPrivate* priv; InfRequest* request; dialog = INF_GTK_PERMISSIONS_DIALOG(user_data); priv = INF_GTK_PERMISSIONS_DIALOG_PRIVATE(dialog); g_assert(priv->popup_menu != NULL); g_assert(priv->popup_account != 0); request = inf_browser_remove_acl_account( priv->browser, priv->popup_account, inf_gtk_permissions_dialog_remove_acl_account_finished_cb, dialog ); if(request != NULL) { g_object_ref(request); priv->remove_acl_account_requests = g_slist_prepend( priv->remove_acl_account_requests, request ); } } /* TODO: The popup handling code should be shared between this class and * InfGtkBrowserView. */ static gboolean inf_gtk_permissions_dialog_populate_popup(InfGtkPermissionsDialog* dialog, GtkMenu* menu) { InfGtkPermissionsDialogPrivate* priv; GtkWidget* item; InfBrowserIter root; InfAclMask perms; guint n_accounts; InfAclAccountId default_id; const InfAclAccount* local_account; const InfAclAccount** accounts; gpointer account_id_ptr; InfAclAccountId account_id; GtkTreeSelection* selection; GtkTreeIter iter; priv = INF_GTK_PERMISSIONS_DIALOG_PRIVATE(dialog); g_assert(priv->popup_menu == NULL); /* Make sure that we have permissions to remove accounts */ inf_browser_get_root(priv->browser, &root); inf_acl_mask_set1(&perms, INF_ACL_CAN_REMOVE_ACCOUNT); local_account = inf_browser_get_acl_local_account(priv->browser); inf_browser_check_acl( priv->browser, &root, local_account ? local_account->id : 0, &perms, &perms ); if(!inf_acl_mask_has(&perms, INF_ACL_CAN_REMOVE_ACCOUNT)) return FALSE; /* Make sure the selected account is not the default account or a * pending account. */ selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(priv->tree_view)); if(!gtk_tree_selection_get_selected(selection, NULL, &iter)) return FALSE; gtk_tree_model_get( GTK_TREE_MODEL(priv->account_store), &iter, INF_GTK_PERMISSIONS_DIALOG_COLUMN_ID, &account_id_ptr, -1 ); account_id = INF_ACL_ACCOUNT_POINTER_TO_ID(account_id_ptr); default_id = inf_acl_account_id_from_string("default"); if(account_id == 0 || account_id == default_id) return FALSE; /* Then, show a menu item to remove an account. */ item = gtk_menu_item_new_with_mnemonic(_("_Delete Account")); g_signal_connect( G_OBJECT(item), "activate", G_CALLBACK(inf_gtk_permissions_dialog_popup_delete_account_cb), dialog ); gtk_widget_show(item); gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); /* TODO: These two items need to be added for popdown and stuff, * popup_menu needs to be maintained and tracked. */ priv->popup_menu = menu; priv->popup_account = INF_ACL_ACCOUNT_POINTER_TO_ID(account_id); return TRUE; } static void inf_gtk_permissions_dialog_popup_menu_detach_func(GtkWidget* attach_widget, GtkMenu* menu) { } static void inf_gtk_permissions_dialog_popup_menu_position_func(GtkMenu* menu, gint* x, gint* y, gboolean* push_in, gpointer user_data) { InfGtkPermissionsDialog* dialog; InfGtkPermissionsDialogPrivate* priv; GdkWindow* bin_window; GdkScreen* screen; GtkRequisition menu_req; GdkRectangle monitor; gint monitor_num; gint orig_x; gint orig_y; gint height; GtkTreeSelection* selection; GtkTreeModel* model; GtkTreeIter selected_iter; GtkTreePath* selected_path; GdkRectangle cell_area; dialog = INF_GTK_PERMISSIONS_DIALOG(user_data); priv = INF_GTK_PERMISSIONS_DIALOG_PRIVATE(dialog); /* Place menu below currently selected row */ bin_window = gtk_tree_view_get_bin_window(GTK_TREE_VIEW(priv->tree_view)); gdk_window_get_origin(bin_window, &orig_x, &orig_y); screen = gtk_widget_get_screen(GTK_WIDGET(priv->tree_view)); monitor_num = gdk_screen_get_monitor_at_window(screen, bin_window); if(monitor_num < 0) monitor_num = 0; gtk_menu_set_monitor(menu, monitor_num); gdk_screen_get_monitor_geometry(screen, monitor_num, &monitor); gtk_widget_get_preferred_size(GTK_WIDGET(menu), NULL, &menu_req); height = gdk_window_get_height(bin_window); selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(priv->tree_view)); gtk_tree_selection_get_selected(selection, &model, &selected_iter); selected_path = gtk_tree_model_get_path(model, &selected_iter); gtk_tree_view_get_cell_area( GTK_TREE_VIEW(priv->tree_view), selected_path, gtk_tree_view_get_column(GTK_TREE_VIEW(priv->tree_view), 0), &cell_area ); gtk_tree_path_free(selected_path); g_assert(cell_area.height > 0); if(gtk_widget_get_direction(GTK_WIDGET(priv->tree_view)) == GTK_TEXT_DIR_LTR) { *x = orig_x + cell_area.x + cell_area.width - menu_req.width; } else { *x = orig_x + cell_area.x; } *y = orig_y + cell_area.y + cell_area.height; /* Keep within widget */ if(*y < orig_y) *y = orig_y; if(*y > orig_y + height) *y = orig_y + height; /* Keep on screen */ if(*y + menu_req.height > monitor.y + monitor.height) *y = monitor.y + monitor.height - menu_req.height; if(*y < monitor.y) *y = monitor.y; *push_in = FALSE; } static void inf_gtk_permissions_dialog_popup_selection_done_cb(GtkMenu* menu, gpointer user_data) { InfGtkPermissionsDialog* dialog; InfGtkPermissionsDialogPrivate* priv; dialog = INF_GTK_PERMISSIONS_DIALOG(user_data); priv = INF_GTK_PERMISSIONS_DIALOG_PRIVATE(dialog); g_assert(priv->popup_menu != NULL); priv->popup_menu = NULL; priv->popup_account = 0; } static gboolean inf_gtk_permissions_dialog_show_popup(InfGtkPermissionsDialog* dialog, guint button, /* 0 if triggered by keyboard */ guint32 time) { InfGtkPermissionsDialogPrivate* priv; GtkWidget* menu; gboolean result; priv = INF_GTK_PERMISSIONS_DIALOG_PRIVATE(dialog); menu = gtk_menu_new(); g_signal_connect( G_OBJECT(menu), "selection-done", G_CALLBACK(inf_gtk_permissions_dialog_popup_selection_done_cb), dialog ); gtk_menu_attach_to_widget( GTK_MENU(menu), GTK_WIDGET(priv->tree_view), inf_gtk_permissions_dialog_popup_menu_detach_func ); if(inf_gtk_permissions_dialog_populate_popup(dialog, GTK_MENU(menu))) { result = TRUE; if(button) { gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, button, time); } else { gtk_menu_popup( GTK_MENU(menu), NULL, NULL, inf_gtk_permissions_dialog_popup_menu_position_func, priv->tree_view, button, time ); gtk_menu_shell_select_first(GTK_MENU_SHELL(menu), FALSE); } } else { result = FALSE; gtk_widget_destroy(menu); } return result; } static gboolean inf_gtk_permissions_dialog_button_press_event_cb(GtkWidget* treeview, GdkEventButton* event, gpointer user_data) { InfGtkPermissionsDialog* dialog; GtkTreePath* path; gboolean has_path; dialog = INF_GTK_PERMISSIONS_DIALOG(user_data); if(event->button == 3 && event->window == gtk_tree_view_get_bin_window(GTK_TREE_VIEW(treeview))) { has_path = gtk_tree_view_get_path_at_pos( GTK_TREE_VIEW(treeview), event->x, event->y, &path, NULL, NULL, NULL ); if(has_path) { gtk_tree_selection_select_path( gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview)), path ); gtk_tree_path_free(path); return inf_gtk_permissions_dialog_show_popup( dialog, event->button, event->time ); } } return FALSE; } static gboolean inf_gtk_permissions_dialog_key_press_event_cb(GtkWidget* treeview, GdkEventKey* event, gpointer user_data) { InfGtkPermissionsDialog* dialog; GtkTreeSelection* selection; GtkTreeIter iter; dialog = INF_GTK_PERMISSIONS_DIALOG(user_data); if(event->keyval == GDK_KEY_Menu) { selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview)); if(gtk_tree_selection_get_selected(selection, NULL, &iter)) { return inf_gtk_permissions_dialog_show_popup(dialog, 0, event->time); } } return FALSE; } static void inf_gtk_permissions_dialog_name_data_func(GtkTreeViewColumn* column, GtkCellRenderer* cell, GtkTreeModel* model, GtkTreeIter* iter, gpointer user_data) { gpointer account_id_ptr; InfAclAccountId account_id; const gchar* account_id_str; InfAclAccountId default_id; gchar* account_name; gchar* str; gtk_tree_model_get( model, iter, INF_GTK_PERMISSIONS_DIALOG_COLUMN_ID, &account_id_ptr, INF_GTK_PERMISSIONS_DIALOG_COLUMN_NAME, &account_name, -1 ); account_id = INF_ACL_ACCOUNT_POINTER_TO_ID(account_id_ptr); account_id_str = inf_acl_account_id_to_string(account_id); if(account_name != NULL) { g_object_set(G_OBJECT(cell), "text", account_name, NULL); } else if(account_id_str != NULL) { str = g_strdup_printf("<%s>", account_id_str); g_object_set(G_OBJECT(cell), "text", str, NULL); g_free(str); } else { g_object_set(G_OBJECT(cell), "text", "", NULL); } /* Set red foreground color if either ID or name is missing, meaning we are * still looking them up, or that some information is denied from us by * the server. */ default_id = inf_acl_account_id_from_string("default"); if( (account_id == 0 || account_name == NULL) && account_id != default_id) g_object_set(G_OBJECT(cell), "foreground", "red", NULL); else g_object_set(G_OBJECT(cell), "foreground-set", FALSE, NULL); g_free(account_name); } static void inf_gtk_permissions_dialog_query_acl_account_list_finished_cb( InfRequest* request, const InfRequestResult* res, const GError* error, gpointer user_data) { InfGtkPermissionsDialog* dialog; InfGtkPermissionsDialogPrivate* priv; const InfAclAccount* accounts; guint n_accounts; guint i; InfAclAccountId account_id; GtkTreeIter iter; dialog = INF_GTK_PERMISSIONS_DIALOG(user_data); priv = INF_GTK_PERMISSIONS_DIALOG_PRIVATE(dialog); priv->query_acl_account_list_request = NULL; priv->account_list_queried = TRUE; if(error != NULL) { if(error->domain != inf_directory_error_quark() || error->code != INF_DIRECTORY_ERROR_OPERATION_UNSUPPORTED) { g_warning("Error while querying account list: %s\n", error->message); } } else { inf_request_result_get_query_acl_account_list( res, NULL, &accounts, &n_accounts, NULL ); /* Update user names from local account cache */ for(i = 0; i < n_accounts; ++i) { if(accounts[i].name != NULL) { account_id = accounts[i].id; if(inf_gtk_permissions_dialog_find_account(dialog, account_id, &iter)) { gtk_list_store_set( GTK_LIST_STORE(priv->account_store), &iter, INF_GTK_PERMISSIONS_DIALOG_COLUMN_NAME, accounts[i].name, -1 ); } } } /* Update local account cache */ for(i = 0; i < priv->n_accounts; ++i) g_free(priv->accounts[i].name); priv->accounts = g_realloc( priv->accounts, n_accounts * sizeof(InfAclAccount) ); for(i = 0; i < n_accounts; ++i) { priv->accounts[i].id = accounts[i].id; priv->accounts[i].name = g_strdup(accounts[i].name); } priv->n_accounts = n_accounts; } } static void inf_gtk_permissions_dialog_query_acl_finished_cb(InfRequest* request, const InfRequestResult* res, const GError* error, gpointer user_data) { InfGtkPermissionsDialog* dialog; InfGtkPermissionsDialogPrivate* priv; dialog = INF_GTK_PERMISSIONS_DIALOG(user_data); priv = INF_GTK_PERMISSIONS_DIALOG_PRIVATE(dialog); priv->query_acl_request = NULL; inf_gtk_permissions_dialog_update(dialog, error); } static void inf_gtk_permissions_dialog_update(InfGtkPermissionsDialog* dialog, const GError* error) { InfGtkPermissionsDialogPrivate* priv; gchar* path; gchar* title; InfAclMask perms; GArray* accounts; const InfAclAccount* local_account; const InfAclSheetSet* sheet_set; gboolean has_default; InfAclAccountId default_id; guint i; GtkTreeSelection* selection; GtkTreeIter selected_iter; gpointer selected_id_ptr; GtkTreePath* selected_path; InfAclAccountId selected_id; gboolean has_selected; GSList* item; InfGtkPermissionsDialogPendingSheet* pending; GtkTreePath* pending_path; const gchar* query_acl_str; const gchar* set_acl_str; gchar* error_str; gchar* str; priv = INF_GTK_PERMISSIONS_DIALOG_PRIVATE(dialog); /* Reset all widgets if no node is set */ if(priv->browser == NULL) { gtk_list_store_clear(priv->account_store); gtk_label_set_text(GTK_LABEL(priv->status_text), _("No node selected")); return; } /* Set the dialog title */ path = inf_browser_get_path(priv->browser, &priv->browser_iter); title = g_strdup_printf(_("Permissions for %s"), path); gtk_window_set_title(GTK_WINDOW(dialog), title); g_free(path); g_free(title); inf_acl_mask_set1(&perms, INF_ACL_CAN_QUERY_ACCOUNT_LIST); inf_acl_mask_or1(&perms, INF_ACL_CAN_QUERY_ACL); inf_acl_mask_or1(&perms, INF_ACL_CAN_SET_ACL); local_account = inf_browser_get_acl_local_account(priv->browser); inf_browser_check_acl( priv->browser, &priv->browser_iter, local_account ? local_account->id : 0, &perms, &perms ); /* Request account list */ if(priv->query_acl_account_list_request == NULL && priv->account_list_queried == FALSE) { if(inf_acl_mask_has(&perms, INF_ACL_CAN_QUERY_ACCOUNT_LIST) && inf_acl_mask_has(&perms, INF_ACL_CAN_SET_ACL)) { priv->query_acl_account_list_request = inf_browser_get_pending_request( priv->browser, NULL, "query-acl-account-list" ); if(priv->query_acl_account_list_request == NULL) { priv->query_acl_account_list_request = inf_browser_query_acl_account_list( priv->browser, inf_gtk_permissions_dialog_query_acl_account_list_finished_cb, dialog ); } else { g_signal_connect( G_OBJECT(priv->query_acl_account_list_request), "finished", G_CALLBACK( inf_gtk_permissions_dialog_query_acl_account_list_finished_cb ), dialog ); } } } /* Request ACL */ if(!inf_browser_has_acl(priv->browser, &priv->browser_iter, 0)) { if(inf_acl_mask_has(&perms, INF_ACL_CAN_QUERY_ACL) && priv->query_acl_request == NULL && error == NULL) { priv->query_acl_request = inf_browser_get_pending_request( priv->browser, &priv->browser_iter, "query-acl" ); if(priv->query_acl_request == NULL) { priv->query_acl_request = inf_browser_query_acl( priv->browser, &priv->browser_iter, inf_gtk_permissions_dialog_query_acl_finished_cb, dialog ); } else { g_signal_connect( G_OBJECT(priv->query_acl_request), "finished", G_CALLBACK(inf_gtk_permissions_dialog_query_acl_finished_cb), dialog ); } } } /* Fill the account list widget. If an account is currently selected, * keep it there until the selection changes, even if does not show * up in the ACL sheet (anymore). */ accounts = g_array_new(FALSE, FALSE, sizeof(InfAclAccountId)); sheet_set = inf_browser_get_acl(priv->browser, &priv->browser_iter); default_id = inf_acl_account_id_from_string("default"); selected_id = 0; selected_path = NULL; selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(priv->tree_view)); if(gtk_tree_selection_get_selected(selection, NULL, &selected_iter)) { gtk_tree_model_get( GTK_TREE_MODEL(priv->account_store), &selected_iter, INF_GTK_PERMISSIONS_DIALOG_COLUMN_ID, &selected_id_ptr, -1 ); selected_id = INF_ACL_ACCOUNT_POINTER_TO_ID(selected_id_ptr); selected_path = gtk_tree_model_get_path( GTK_TREE_MODEL(priv->account_store), &selected_iter ); } has_default = FALSE; has_selected = FALSE; if(sheet_set != NULL) { for(i = 0; i < sheet_set->n_sheets; ++i) { g_array_append_val(accounts, sheet_set->sheets[i].account); if(sheet_set->sheets[i].account == default_id) has_default = TRUE; if(sheet_set->sheets[i].account == selected_id) has_selected = TRUE; } } if(has_default == FALSE) g_array_append_val(accounts, default_id); if(selected_id != 0 && selected_id != default_id && has_selected == FALSE) g_array_append_val(accounts, selected_id); /* Remove all non-selected pending sheets that have an empty mask */ for(item = priv->pending_sheets; item != NULL; item = item->next) { pending = (InfGtkPermissionsDialogPendingSheet*)item->data; if(inf_acl_mask_empty(&pending->sheet.mask)) { pending_path = gtk_tree_row_reference_get_path(pending->row); g_assert(pending_path != NULL); if(selected_path == NULL || gtk_tree_path_compare(pending_path, selected_path) != 0) { gtk_tree_path_free(pending_path); inf_gtk_permissions_dialog_remove_pending_sheet(dialog, pending); break; } gtk_tree_path_free(pending_path); } } if(selected_path != NULL) gtk_tree_path_free(selected_path); /* Note that this might remove rows, and therefore * invalidate selected_path */ inf_gtk_permissions_dialog_fill_account_list( dialog, (InfAclAccountId*)accounts->data, accounts->len ); /* Set editability of the sheet view */ if(!inf_acl_mask_has(&perms, INF_ACL_CAN_SET_ACL) || !inf_browser_has_acl(priv->browser, &priv->browser_iter, 0)) { inf_gtk_acl_sheet_view_set_editable( INF_GTK_ACL_SHEET_VIEW(priv->sheet_view), FALSE ); gtk_widget_set_sensitive(priv->add_button, FALSE); gtk_widget_set_sensitive(priv->remove_button, FALSE); set_acl_str = _("Permission is not granted to modify the permission list. It is read-only."); } else { inf_gtk_acl_sheet_view_set_editable( INF_GTK_ACL_SHEET_VIEW(priv->sheet_view), TRUE ); /* Set add button to sensitive if: * we don't have user list OR * we have user list and not all users exist already in the sheet */ if(priv->accounts == NULL || accounts->len < priv->n_accounts) gtk_widget_set_sensitive(priv->add_button, TRUE); else gtk_widget_set_sensitive(priv->add_button, FALSE); /* Set remove button to sensitive if something other than the * default account is selected. */ if(selected_id != default_id) gtk_widget_set_sensitive(priv->remove_button, TRUE); else gtk_widget_set_sensitive(priv->remove_button, FALSE); set_acl_str = _("Permission is granted to modify the permission list."); } g_array_free(accounts, TRUE); /* Update status text */ error_str = NULL; if(error != NULL) { error_str = g_markup_printf_escaped( _("Server Error: %s"), error->message ); query_acl_str = error_str; } else if(priv->query_acl_request != NULL) { query_acl_str = _("Querying current permissions for " "this node from the server..."); } else if(!inf_acl_mask_has(&perms, INF_ACL_CAN_QUERY_ACL) && !inf_browser_has_acl(priv->browser, &priv->browser_iter, 0)) { query_acl_str = _("Permission is not granted to query the " "permission list for this node from the server. " "Showing only default permissions and permissions " "for the own account."); } else { query_acl_str = _("Permissions are granted to query the full " "permission list from the server. " "Showing all permissions."); } str = g_strdup_printf("%s\n\n%s", query_acl_str, set_acl_str); g_free(error_str); gtk_label_set_markup(GTK_LABEL(priv->status_text), str); g_free(str); } static void inf_gtk_permissions_dialog_register(InfGtkPermissionsDialog* dialog) { InfGtkPermissionsDialogPrivate* priv; priv = INF_GTK_PERMISSIONS_DIALOG_PRIVATE(dialog); g_assert(priv->browser != NULL); g_signal_connect( priv->browser, "node-removed", G_CALLBACK(inf_gtk_permissions_dialog_node_removed_cb), dialog ); g_signal_connect( priv->browser, "acl-account-added", G_CALLBACK(inf_gtk_permissions_dialog_acl_account_added_cb), dialog ); g_signal_connect( priv->browser, "acl-account-removed", G_CALLBACK(inf_gtk_permissions_dialog_acl_account_removed_cb), dialog ); g_signal_connect( priv->browser, "acl-changed", G_CALLBACK(inf_gtk_permissions_dialog_acl_changed_cb), dialog ); } static void inf_gtk_permissions_dialog_unregister(InfGtkPermissionsDialog* dialog) { InfGtkPermissionsDialogPrivate* priv; priv = INF_GTK_PERMISSIONS_DIALOG_PRIVATE(dialog); g_assert(priv->browser != NULL); inf_signal_handlers_disconnect_by_func( priv->browser, G_CALLBACK(inf_gtk_permissions_dialog_node_removed_cb), dialog ); inf_signal_handlers_disconnect_by_func( priv->browser, G_CALLBACK(inf_gtk_permissions_dialog_acl_account_added_cb), dialog ); inf_signal_handlers_disconnect_by_func( priv->browser, G_CALLBACK(inf_gtk_permissions_dialog_acl_account_removed_cb), dialog ); inf_signal_handlers_disconnect_by_func( priv->browser, G_CALLBACK(inf_gtk_permissions_dialog_acl_changed_cb), dialog ); } /* * GObject virtual functions */ static void inf_gtk_permissions_dialog_init(InfGtkPermissionsDialog* dialog) { InfGtkPermissionsDialogPrivate* priv; priv = INF_GTK_PERMISSIONS_DIALOG_PRIVATE(dialog); priv->query_acl_account_list_request = NULL; priv->account_list_queried = FALSE; priv->accounts = NULL; priv->n_accounts = 0; priv->query_acl_request = NULL; priv->set_acl_requests = NULL; priv->remove_acl_account_requests = NULL; priv->lookup_acl_account_requests = NULL; priv->pending_sheets = NULL; priv->popup_menu = NULL; priv->popup_account = 0; gtk_widget_init_template(GTK_WIDGET(dialog)); gtk_tree_sortable_set_sort_column_id( GTK_TREE_SORTABLE(priv->account_store), INF_GTK_PERMISSIONS_DIALOG_COLUMN_NAME, GTK_SORT_ASCENDING ); gtk_tree_sortable_set_sort_func( GTK_TREE_SORTABLE(priv->account_store), INF_GTK_PERMISSIONS_DIALOG_COLUMN_NAME, inf_gtk_permissions_dialog_account_sort_func, dialog, NULL ); gtk_tree_view_column_set_cell_data_func( gtk_tree_view_get_column(GTK_TREE_VIEW(priv->tree_view), 0), priv->renderer, inf_gtk_permissions_dialog_name_data_func, NULL, NULL ); } static void inf_gtk_permissions_dialog_constructed(GObject* object) { InfGtkPermissionsDialogPrivate* priv; G_OBJECT_CLASS(inf_gtk_permissions_dialog_parent_class)->constructed( object ); priv = INF_GTK_PERMISSIONS_DIALOG_PRIVATE(object); inf_gtk_permissions_dialog_update( INF_GTK_PERMISSIONS_DIALOG(object), NULL ); } static void inf_gtk_permissions_dialog_dispose(GObject* object) { InfGtkPermissionsDialog* dialog; InfGtkPermissionsDialogPrivate* priv; dialog = INF_GTK_PERMISSIONS_DIALOG(object); priv = INF_GTK_PERMISSIONS_DIALOG_PRIVATE(dialog); while(priv->remove_acl_account_requests != NULL) { inf_gtk_permissions_dialog_remove_remove_acl_account_request( dialog, priv->remove_acl_account_requests->data ); } while(priv->lookup_acl_account_requests != NULL) { inf_gtk_permissions_dialog_remove_lookup_acl_accounts_request( dialog, priv->lookup_acl_account_requests->data ); } if(priv->browser != NULL) { inf_gtk_permissions_dialog_set_node(dialog, NULL, NULL); } g_assert(priv->set_acl_requests == NULL); g_assert(priv->pending_sheets == NULL); G_OBJECT_CLASS(inf_gtk_permissions_dialog_parent_class)->dispose(object); } static void inf_gtk_permissions_dialog_finalize(GObject* object) { InfGtkPermissionsDialog* dialog; InfGtkPermissionsDialogPrivate* priv; guint i; dialog = INF_GTK_PERMISSIONS_DIALOG(object); priv = INF_GTK_PERMISSIONS_DIALOG_PRIVATE(dialog); for(i = 0; i < priv->n_accounts; ++i) g_free(priv->accounts[i].name); g_free(priv->accounts); G_OBJECT_CLASS(inf_gtk_permissions_dialog_parent_class)->finalize(object); } static void inf_gtk_permissions_dialog_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfGtkPermissionsDialog* dialog; InfGtkPermissionsDialogPrivate* priv; dialog = INF_GTK_PERMISSIONS_DIALOG(object); priv = INF_GTK_PERMISSIONS_DIALOG_PRIVATE(dialog); switch(prop_id) { case PROP_BROWSER: g_assert(priv->browser == NULL); /* construct only */ priv->browser = INF_BROWSER(g_value_dup_object(value)); if(priv->browser != NULL) inf_gtk_permissions_dialog_register(dialog); break; case PROP_BROWSER_ITER: priv->browser_iter = *(InfBrowserIter*)g_value_get_boxed(value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void inf_gtk_permissions_dialog_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfGtkPermissionsDialog* dialog; InfGtkPermissionsDialogPrivate* priv; dialog = INF_GTK_PERMISSIONS_DIALOG(object); priv = INF_GTK_PERMISSIONS_DIALOG_PRIVATE(dialog); switch(prop_id) { case PROP_BROWSER: g_value_set_object(value, priv->browser); break; case PROP_BROWSER_ITER: g_value_set_boxed(value, &priv->browser_iter); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } /* * GType registration */ static void inf_gtk_permissions_dialog_class_init( InfGtkPermissionsDialogClass* permissions_dialog_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(permissions_dialog_class); object_class->constructed = inf_gtk_permissions_dialog_constructed; object_class->dispose = inf_gtk_permissions_dialog_dispose; object_class->finalize = inf_gtk_permissions_dialog_finalize; object_class->set_property = inf_gtk_permissions_dialog_set_property; object_class->get_property = inf_gtk_permissions_dialog_get_property; gtk_widget_class_set_template_from_resource( GTK_WIDGET_CLASS(object_class), "/de/0x539/libinfgtk/ui/infgtkpermissionsdialog.ui" ); gtk_widget_class_bind_template_child_private( GTK_WIDGET_CLASS(object_class), InfGtkPermissionsDialog, account_store ); gtk_widget_class_bind_template_child_private( GTK_WIDGET_CLASS(object_class), InfGtkPermissionsDialog, status_text ); gtk_widget_class_bind_template_child_private( GTK_WIDGET_CLASS(object_class), InfGtkPermissionsDialog, tree_view ); gtk_widget_class_bind_template_child_private( GTK_WIDGET_CLASS(object_class), InfGtkPermissionsDialog, sheet_view ); gtk_widget_class_bind_template_child_private( GTK_WIDGET_CLASS(object_class), InfGtkPermissionsDialog, add_button ); gtk_widget_class_bind_template_child_private( GTK_WIDGET_CLASS(object_class), InfGtkPermissionsDialog, remove_button ); gtk_widget_class_bind_template_child_private( GTK_WIDGET_CLASS(object_class), InfGtkPermissionsDialog, renderer ); gtk_widget_class_bind_template_callback( GTK_WIDGET_CLASS(object_class), inf_gtk_permissions_dialog_key_press_event_cb ); gtk_widget_class_bind_template_callback( GTK_WIDGET_CLASS(object_class), inf_gtk_permissions_dialog_button_press_event_cb ); gtk_widget_class_bind_template_callback( GTK_WIDGET_CLASS(object_class), inf_gtk_permissions_dialog_selection_changed_cb ); gtk_widget_class_bind_template_callback( GTK_WIDGET_CLASS(object_class), inf_gtk_permissions_dialog_renderer_editing_started_cb ); gtk_widget_class_bind_template_callback( GTK_WIDGET_CLASS(object_class), inf_gtk_permissions_dialog_renderer_editing_canceled_cb ); gtk_widget_class_bind_template_callback( GTK_WIDGET_CLASS(object_class), inf_gtk_permissions_dialog_renderer_edited_cb ); gtk_widget_class_bind_template_callback( GTK_WIDGET_CLASS(object_class), inf_gtk_permissions_dialog_renderer_changed_cb ); gtk_widget_class_bind_template_callback( GTK_WIDGET_CLASS(object_class), inf_gtk_permissions_dialog_add_clicked_cb ); gtk_widget_class_bind_template_callback( GTK_WIDGET_CLASS(object_class), inf_gtk_permissions_dialog_remove_clicked_cb ); gtk_widget_class_bind_template_callback( GTK_WIDGET_CLASS(object_class), inf_gtk_permissions_dialog_sheet_changed_cb ); g_object_class_install_property( object_class, PROP_BROWSER, g_param_spec_object( "browser", "Browser", "The browser with the node for which to show the permissions", INF_TYPE_BROWSER, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_BROWSER_ITER, g_param_spec_boxed( "browser-iter", "Browser Iter", "An iterator pointing to the node inside the browser for which to show " "the permissions", INF_TYPE_BROWSER_ITER, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); } /* * Public API. */ /** * inf_gtk_permissions_dialog_new: (constructor) * @parent: Parent #GtkWindow of the dialog. * @dialog_flags: Flags for the dialog, see #GtkDialogFlags. * @browser: (allow-none): The #InfBrowser containing the node to show * permissions for, or %NULL. * @iter: (allow-none): An iterator pointing to the node to show permissions * for, or %NULL. * * Creates a new #InfGtkPermissionsDialog, showing the ACL for the node * @iter points to inside @browser. If @browser is %NULL, @iter must be %NULL, * too. In that case no permissions are shown, and the node to be shown can * be set later with inf_gtk_permissions_dialog_set_node(). * * Returns: (transfer full): A new #InfGtkPermissionsDialog. Free with * gtk_widget_destroy() when no longer needed. */ InfGtkPermissionsDialog* inf_gtk_permissions_dialog_new(GtkWindow* parent, GtkDialogFlags dialog_flags, InfBrowser* browser, const InfBrowserIter* iter) { GObject* object; g_return_val_if_fail(parent == NULL || GTK_IS_WINDOW(parent), NULL); g_return_val_if_fail(browser == NULL || INF_IS_BROWSER(browser), NULL); g_return_val_if_fail(browser == NULL || iter != NULL, NULL); object = g_object_new( INF_GTK_TYPE_PERMISSIONS_DIALOG, "browser", browser, "browser-iter", iter, NULL ); if(dialog_flags & GTK_DIALOG_MODAL) gtk_window_set_modal(GTK_WINDOW(object), TRUE); if(dialog_flags & GTK_DIALOG_DESTROY_WITH_PARENT) gtk_window_set_destroy_with_parent(GTK_WINDOW(object), TRUE); gtk_window_set_transient_for(GTK_WINDOW(object), parent); return INF_GTK_PERMISSIONS_DIALOG(object); } /** * inf_gtk_permissions_dialog_set_node: * @dialog: A #InfGtkPermissionsDialog. * @browser: (allow-none): The #InfBrowser containing the node to show * permissions for, or %NULL. * @iter: (allow-none): An iterator pointing to the node to show permissions * for, or %NULL. * * Changes the node the dialog shows permissions for. To unset the node, both * @browser and @iter should be %NULL. */ void inf_gtk_permissions_dialog_set_node(InfGtkPermissionsDialog* dialog, InfBrowser* browser, const InfBrowserIter* iter) { InfGtkPermissionsDialogPrivate* priv; GSList* item; guint i; g_return_if_fail(INF_GTK_IS_PERMISSIONS_DIALOG(dialog)); g_return_if_fail(browser == NULL || INF_IS_BROWSER(browser)); g_return_if_fail((browser == NULL) == (iter == NULL)); priv = INF_GTK_PERMISSIONS_DIALOG_PRIVATE(dialog); if(priv->popup_menu != NULL) gtk_menu_popdown(priv->popup_menu); if(priv->browser != NULL) { if(priv->query_acl_account_list_request != NULL) { inf_signal_handlers_disconnect_by_func( priv->query_acl_account_list_request, G_CALLBACK( inf_gtk_permissions_dialog_query_acl_account_list_finished_cb ), dialog ); priv->query_acl_account_list_request = NULL; } if(priv->query_acl_request != NULL) { inf_signal_handlers_disconnect_by_func( priv->query_acl_request, G_CALLBACK(inf_gtk_permissions_dialog_query_acl_finished_cb), dialog ); priv->query_acl_request = NULL; } for(item = priv->set_acl_requests; item != NULL; item = item->next) { inf_signal_handlers_disconnect_by_func( G_OBJECT(item->data), G_CALLBACK(inf_gtk_permissions_dialog_set_acl_finished_cb), dialog ); g_object_unref(item->data); } g_slist_free(priv->set_acl_requests); priv->set_acl_requests = NULL; while(priv->pending_sheets != NULL) { inf_gtk_permissions_dialog_remove_pending_sheet( dialog, priv->pending_sheets->data ); } } for(i = 0; i < priv->n_accounts; ++i) g_free(priv->accounts[i].name); g_free(priv->accounts); priv->accounts = NULL; priv->n_accounts = 0; /* While clearing the list store, block the selection changed callback of * the treeview, otherwise it would cause * inf_gtk_permissions_dialog_update() to be called, which would fill the * tree view again while it is being cleared. We issue one update at the * end of the node change. */ inf_signal_handlers_block_by_func( gtk_tree_view_get_selection(GTK_TREE_VIEW(priv->tree_view)), G_CALLBACK(inf_gtk_permissions_dialog_selection_changed_cb), dialog ); gtk_list_store_clear(priv->account_store); inf_signal_handlers_unblock_by_func( gtk_tree_view_get_selection(GTK_TREE_VIEW(priv->tree_view)), G_CALLBACK(inf_gtk_permissions_dialog_selection_changed_cb), dialog ); if(priv->browser != browser) { if(priv->browser != NULL) { inf_gtk_permissions_dialog_unregister(dialog); g_object_unref(priv->browser); } priv->browser = browser; if(iter != NULL) priv->browser_iter = *iter; if(priv->browser != NULL) { g_object_ref(priv->browser); inf_gtk_permissions_dialog_register(dialog); } g_object_notify(G_OBJECT(dialog), "browser"); g_object_notify(G_OBJECT(dialog), "browser-iter"); } inf_gtk_permissions_dialog_update(dialog, NULL); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfgtk/PaxHeaders.26529/inf-gtk-account-creation-dialog.c0000644000000000000000000000013213034342512023745 xustar0030 mtime=1483851082.017718362 30 atime=1483851082.017718362 30 ctime=1488261589.312138383 libinfinity-0.7.1/libinfgtk/inf-gtk-account-creation-dialog.c0000644000175000017500000005552313034342512024511 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-gtk-account-creation-dialog * @title: InfGtkAccountCreationDialog * @short_description: A dialog to request a new account on a server. * @include: libinfgtk/inf-gtk-account-creation-dialog.h * @stability: Unstable * * #InfGtkAccountCreationDialog is a dialog widget which allows to request * creation of a new account on an infinote server. If the * "can-create-acl-account" permission is not granted, the dialog shows an * error message instead. **/ #include #include #include #include #include #include #include #include #include typedef struct _InfGtkAccountCreationDialogPrivate InfGtkAccountCreationDialogPrivate; struct _InfGtkAccountCreationDialogPrivate { InfIo* io; InfBrowser* browser; GtkWidget* status_text; GtkWidget* create_account_button; GtkWidget* name_entry; InfAsyncOperation* key_generator; InfRequest* create_account_request; gnutls_x509_privkey_t key; }; typedef struct _InfGtkAccountCreationDialogKeygenResult InfGtkAccountCreationDialogKeygenResult; struct _InfGtkAccountCreationDialogKeygenResult { gnutls_x509_privkey_t key; GError* error; }; enum { PROP_0, PROP_IO, PROP_BROWSER }; enum { ACCOUNT_CREATED, LAST_SIGNAL }; #define INF_GTK_ACCOUNT_CREATION_DIALOG_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INF_GTK_TYPE_ACCOUNT_CREATION_DIALOG, InfGtkAccountCreationDialogPrivate)) static guint account_creation_dialog_signals[LAST_SIGNAL]; G_DEFINE_TYPE_WITH_CODE(InfGtkAccountCreationDialog, inf_gtk_account_creation_dialog, GTK_TYPE_DIALOG, G_ADD_PRIVATE(InfGtkAccountCreationDialog)) static void inf_gtk_account_creation_dialog_keygen_result_free(gpointer data) { InfGtkAccountCreationDialogKeygenResult* result; result = (InfGtkAccountCreationDialogKeygenResult*)data; if(result->key != NULL) gnutls_x509_privkey_deinit(result->key); if(result->error != NULL) g_error_free(result->error); g_slice_free(InfGtkAccountCreationDialogKeygenResult, result); } static int inf_gtk_account_creation_dialog_fill_crq(gnutls_x509_crq_t crq, gnutls_x509_privkey_t key, const gchar* name) { int res; res = gnutls_x509_crq_set_key(crq, key); if(res != GNUTLS_E_SUCCESS) return res; res = gnutls_x509_crq_set_key_usage(crq, GNUTLS_KEY_DIGITAL_SIGNATURE); if(res != GNUTLS_E_SUCCESS) return res; res = gnutls_x509_crq_set_version(crq, 3); if(res != GNUTLS_E_SUCCESS) return res; res = gnutls_x509_crq_set_dn_by_oid( crq, GNUTLS_OID_X520_COMMON_NAME, 0, name, strlen(name) ); if(res != GNUTLS_E_SUCCESS) return res; /* gnutls_x509_crq_sign2 is deprecated in favor of * gnutls_x509_crq_privkey_sign, but the latter returns the * error code GNUTLS_E_UNIMPLEMENTED_FEATURE, so we keep using * the deprecated version for now. */ res = gnutls_x509_crq_sign2(crq, key, GNUTLS_DIG_SHA1, 0); if(res != GNUTLS_E_SUCCESS) return res; return GNUTLS_E_SUCCESS; } static gnutls_x509_crq_t inf_gtk_account_creation_dialog_create_crq(gnutls_x509_privkey_t key, const gchar* name, GError** error) { int res; gnutls_x509_crq_t crq; res = gnutls_x509_crq_init(&crq); if(res != GNUTLS_E_SUCCESS) { inf_gnutls_set_error(error, res); return NULL; } res = inf_gtk_account_creation_dialog_fill_crq(crq, key, name); if(res != GNUTLS_E_SUCCESS) { gnutls_x509_crq_deinit(crq); inf_gnutls_set_error(error, res); return NULL; } return crq; } static void inf_gtk_account_creation_dialog_set_activatable( InfGtkAccountCreationDialog* dialog, gboolean activatable) { InfGtkAccountCreationDialogPrivate* priv; priv = INF_GTK_ACCOUNT_CREATION_DIALOG_PRIVATE(dialog); if(activatable) { /*gtk_widget_set_sensitive(priv->name_entry, TRUE);*/ gtk_widget_set_sensitive(priv->create_account_button, TRUE); } else { /*gtk_widget_set_sensitive(priv->name_entry, FALSE);*/ gtk_widget_set_sensitive(priv->create_account_button, FALSE); } } static void inf_gtk_account_creation_dialog_update(InfGtkAccountCreationDialog* dialog, const GError* error) { InfGtkAccountCreationDialogPrivate* priv; InfBrowserStatus status; InfBrowserIter iter; InfAclMask perms; const gchar* text; gchar* markup; gboolean activatable; const InfAclAccount* local_account; priv = INF_GTK_ACCOUNT_CREATION_DIALOG_PRIVATE(dialog); activatable = TRUE; text = NULL; if(priv->browser == NULL) { text = _("Not connected to a server"); activatable = FALSE; } else { g_object_get(G_OBJECT(priv->browser), "status", &status, NULL); if(status != INF_BROWSER_OPEN) { text = _("Not connected to a server"); activatable = FALSE; } else { inf_browser_get_root(priv->browser, &iter); inf_acl_mask_set1(&perms, INF_ACL_CAN_CREATE_ACCOUNT); local_account = inf_browser_get_acl_local_account(priv->browser); inf_browser_check_acl( priv->browser, &iter, local_account != NULL ? local_account->id : 0, &perms, &perms ); if(!inf_acl_mask_has(&perms, INF_ACL_CAN_CREATE_ACCOUNT)) { text = _("Permissions to create an account are not granted"); activatable = FALSE; } } } if(error != NULL) { g_assert(priv->create_account_request == NULL); g_assert(priv->key_generator == NULL); if(priv->key != NULL) { gnutls_x509_privkey_deinit(priv->key); priv->key = NULL; } /* Overwrite text with error message */ text = error->message; } if(activatable == TRUE) if(gtk_entry_get_text(GTK_ENTRY(priv->name_entry))[0] == '\0') activatable = FALSE; if(text != NULL) { markup = g_markup_printf_escaped("%s", text); gtk_label_set_markup(GTK_LABEL(priv->status_text), markup); g_free(markup); inf_gtk_account_creation_dialog_set_activatable(dialog, activatable); } else { if(priv->key_generator != NULL) { gtk_label_set_text( GTK_LABEL(priv->status_text), _("A private key is being generated. " "This process might take a few seconds...") ); inf_gtk_account_creation_dialog_set_activatable(dialog, FALSE); } else if(priv->create_account_request != NULL) { gtk_label_set_text( GTK_LABEL(priv->status_text), _("New account is being requested from the server. " "Usually, this should not take very long.") ); inf_gtk_account_creation_dialog_set_activatable(dialog, FALSE); } else { inf_gtk_account_creation_dialog_set_activatable(dialog, activatable); } } } static void inf_gtk_account_creation_dialog_entry_changed_cb(GtkEntry* entry, gpointer user_data) { InfGtkAccountCreationDialog* dialog; dialog = INF_GTK_ACCOUNT_CREATION_DIALOG(user_data); inf_gtk_account_creation_dialog_update(dialog, NULL); } static void inf_gtk_account_creation_dialog_create_account_finished_cb( InfRequest* request, const InfRequestResult* result, const GError* error, gpointer user_data) { InfGtkAccountCreationDialog* dialog; InfGtkAccountCreationDialogPrivate* priv; const InfAclAccount* account; InfCertificateChain* chain; gnutls_x509_privkey_t key; dialog = INF_GTK_ACCOUNT_CREATION_DIALOG(user_data); priv = INF_GTK_ACCOUNT_CREATION_DIALOG_PRIVATE(dialog); g_assert(priv->key != NULL); if(priv->create_account_request != NULL) { g_object_unref(priv->create_account_request); priv->create_account_request = NULL; } if(error != NULL) { inf_gtk_account_creation_dialog_update(dialog, error); } else { inf_request_result_get_create_acl_account( result, NULL, &account, &chain ); key = priv->key; priv->key = NULL; inf_gtk_account_creation_dialog_update(dialog, NULL); g_signal_emit( G_OBJECT(dialog), account_creation_dialog_signals[ACCOUNT_CREATED], 0, key, chain, account ); gnutls_x509_privkey_deinit(key); } } static void inf_gtk_account_creation_dialog_keygen_run(gpointer* run_data, GDestroyNotify* run_notify, gpointer user_data) { InfGtkAccountCreationDialogKeygenResult* result; result = g_slice_new(InfGtkAccountCreationDialogKeygenResult); result->error = NULL; result->key = inf_cert_util_create_private_key( GNUTLS_PK_RSA, 4096, &result->error ); *run_data = result; *run_notify = inf_gtk_account_creation_dialog_keygen_result_free; } static void inf_gtk_account_creation_dialog_keygen_done(gpointer run_data, gpointer user_data) { InfGtkAccountCreationDialog* dialog; InfGtkAccountCreationDialogPrivate* priv; InfGtkAccountCreationDialogKeygenResult* result; gnutls_x509_crq_t crq; InfRequest* request; dialog = INF_GTK_ACCOUNT_CREATION_DIALOG(user_data); priv = INF_GTK_ACCOUNT_CREATION_DIALOG_PRIVATE(dialog); result = (InfGtkAccountCreationDialogKeygenResult*)run_data; priv->key_generator = NULL; if(result->key != NULL) { priv->key = result->key; result->key = NULL; g_assert(priv->create_account_request == NULL); g_assert(result->error == NULL); crq = inf_gtk_account_creation_dialog_create_crq( priv->key, gtk_entry_get_text(GTK_ENTRY(priv->name_entry)), &result->error ); if(crq != NULL) { request = inf_browser_create_acl_account( priv->browser, crq, inf_gtk_account_creation_dialog_create_account_finished_cb, dialog ); gnutls_x509_crq_deinit(crq); if(request != NULL) { priv->create_account_request = request; g_object_ref(priv->create_account_request); inf_gtk_account_creation_dialog_update(dialog, NULL); } } else { inf_gtk_account_creation_dialog_update(dialog, result->error); } } else { inf_gtk_account_creation_dialog_update(dialog, result->error); } } static void inf_gtk_account_creation_dialog_generate_clicked_cb(GtkButton* button, gpointer user_data) { InfGtkAccountCreationDialog* dialog; InfGtkAccountCreationDialogPrivate* priv; GError* error; dialog = INF_GTK_ACCOUNT_CREATION_DIALOG(user_data); priv = INF_GTK_ACCOUNT_CREATION_DIALOG_PRIVATE(dialog); g_assert(priv->io != NULL); g_assert(priv->key_generator == NULL); priv->key_generator = inf_async_operation_new( priv->io, inf_gtk_account_creation_dialog_keygen_run, inf_gtk_account_creation_dialog_keygen_done, dialog ); error = NULL; inf_async_operation_start(priv->key_generator, &error); if(error != NULL) { priv->key_generator = NULL; inf_gtk_account_creation_dialog_update(dialog, error); g_error_free(error); } else { inf_gtk_account_creation_dialog_update(dialog, NULL); } } static void inf_gtk_account_creation_dialog_acl_changed_cb(InfBrowser* browser, const InfBrowserIter* iter, const InfAclSheetSet* sheetset, InfRequest* request, gpointer user_data) { InfGtkAccountCreationDialog* dialog; InfBrowserIter root_iter; dialog = INF_GTK_ACCOUNT_CREATION_DIALOG(user_data); inf_browser_get_root(browser, &root_iter); if(root_iter.node_id == iter->node_id && root_iter.node == iter->node) inf_gtk_account_creation_dialog_update(dialog, NULL); } static void inf_gtk_account_creation_dialog_notify_status_cb(GObject* object, GParamSpec* pspec, gpointer user_data) { InfGtkAccountCreationDialog* dialog; dialog = INF_GTK_ACCOUNT_CREATION_DIALOG(user_data); inf_gtk_account_creation_dialog_update(dialog, NULL); } /* * GObject virtual functions */ static void inf_gtk_account_creation_dialog_init(InfGtkAccountCreationDialog* dialog) { InfGtkAccountCreationDialogPrivate* priv; priv = INF_GTK_ACCOUNT_CREATION_DIALOG_PRIVATE(dialog); priv->io = NULL; priv->browser = NULL; priv->key_generator = NULL; priv->create_account_request = NULL; priv->key = NULL; gtk_widget_init_template(GTK_WIDGET(dialog)); gtk_widget_grab_default(priv->create_account_button); } static void inf_gtk_account_creation_dialog_constructed(GObject* object) { G_OBJECT_CLASS(inf_gtk_account_creation_dialog_parent_class)->constructed( object ); inf_gtk_account_creation_dialog_update( INF_GTK_ACCOUNT_CREATION_DIALOG(object), NULL ); } static void inf_gtk_account_creation_dialog_dispose(GObject* object) { InfGtkAccountCreationDialog* dialog; InfGtkAccountCreationDialogPrivate* priv; dialog = INF_GTK_ACCOUNT_CREATION_DIALOG(object); priv = INF_GTK_ACCOUNT_CREATION_DIALOG_PRIVATE(dialog); if(priv->browser != NULL) { inf_gtk_account_creation_dialog_set_browser(dialog, NULL); } g_assert(priv->key == NULL); G_OBJECT_CLASS(inf_gtk_account_creation_dialog_parent_class)->dispose(object); } static void inf_gtk_account_creation_dialog_finalize(GObject* object) { InfGtkAccountCreationDialog* dialog; InfGtkAccountCreationDialogPrivate* priv; dialog = INF_GTK_ACCOUNT_CREATION_DIALOG(object); priv = INF_GTK_ACCOUNT_CREATION_DIALOG_PRIVATE(dialog); G_OBJECT_CLASS(inf_gtk_account_creation_dialog_parent_class)->finalize(object); } static void inf_gtk_account_creation_dialog_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfGtkAccountCreationDialog* dialog; InfGtkAccountCreationDialogPrivate* priv; dialog = INF_GTK_ACCOUNT_CREATION_DIALOG(object); priv = INF_GTK_ACCOUNT_CREATION_DIALOG_PRIVATE(dialog); switch(prop_id) { case PROP_IO: g_assert(priv->io == NULL); /* construct/only */ priv->io = INF_IO(g_value_dup_object(value)); break; case PROP_BROWSER: inf_gtk_account_creation_dialog_set_browser( dialog, INF_BROWSER(g_value_get_object(value)) ); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void inf_gtk_account_creation_dialog_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfGtkAccountCreationDialog* dialog; InfGtkAccountCreationDialogPrivate* priv; dialog = INF_GTK_ACCOUNT_CREATION_DIALOG(object); priv = INF_GTK_ACCOUNT_CREATION_DIALOG_PRIVATE(dialog); switch(prop_id) { case PROP_IO: g_value_set_object(value, priv->io); break; case PROP_BROWSER: g_value_set_object(value, priv->browser); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } /* * GType registration */ static void inf_gtk_account_creation_dialog_class_init( InfGtkAccountCreationDialogClass* account_creation_dialog_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(account_creation_dialog_class); object_class->constructed = inf_gtk_account_creation_dialog_constructed; object_class->dispose = inf_gtk_account_creation_dialog_dispose; object_class->finalize = inf_gtk_account_creation_dialog_finalize; object_class->set_property = inf_gtk_account_creation_dialog_set_property; object_class->get_property = inf_gtk_account_creation_dialog_get_property; account_creation_dialog_class->account_created = NULL; gtk_widget_class_set_template_from_resource( GTK_WIDGET_CLASS(object_class), "/de/0x539/libinfgtk/ui/infgtkaccountcreationdialog.ui" ); gtk_widget_class_bind_template_child_private( GTK_WIDGET_CLASS(object_class), InfGtkAccountCreationDialog, status_text ); gtk_widget_class_bind_template_child_private( GTK_WIDGET_CLASS(object_class), InfGtkAccountCreationDialog, create_account_button ); gtk_widget_class_bind_template_child_private( GTK_WIDGET_CLASS(object_class), InfGtkAccountCreationDialog, name_entry ); gtk_widget_class_bind_template_callback( GTK_WIDGET_CLASS(object_class), inf_gtk_account_creation_dialog_entry_changed_cb ); gtk_widget_class_bind_template_callback( GTK_WIDGET_CLASS(object_class), inf_gtk_account_creation_dialog_generate_clicked_cb ); g_object_class_install_property( object_class, PROP_IO, g_param_spec_object( "io", "Io", "The InfIo object to schedule asynchronous operations", INF_TYPE_IO, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_BROWSER, g_param_spec_object( "browser", "Browser", "The infinote directory for which to create an account", INF_TYPE_BROWSER, G_PARAM_READWRITE | G_PARAM_CONSTRUCT ) ); /** * InfGtkAccountCreationDialog::account-created: * @dialog: The #InfGtkAccountCreationDialog emitting the signal. * @key: A newly generated private key that the user certificate is * signed with. * @certificate: A certificate signed by the server associated to the new * account. * @account: The newly created account. * * This signal is emitted whenever a new account has been created with the * dialog. Along with the created account, the login credentials are * provided. Note that the private key is owned by the dialog, and will be * deleted after the signal was emitted. */ account_creation_dialog_signals[ACCOUNT_CREATED] = g_signal_new( "account-created", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfGtkAccountCreationDialogClass, account_created), NULL, NULL, NULL, G_TYPE_NONE, 3, G_TYPE_POINTER, /* gnutls_x509_privkey_t */ INF_TYPE_CERTIFICATE_CHAIN | G_SIGNAL_TYPE_STATIC_SCOPE, INF_TYPE_ACL_ACCOUNT | G_SIGNAL_TYPE_STATIC_SCOPE ); } /* * Public API. */ /** * inf_gtk_account_creation_dialog_new: (constructor) * @parent: Parent #GtkWindow of the dialog. * @dialog_flags: Flags for the dialog, see #GtkDialogFlags. * @io: A #InfIo object to schedule asynchronous operations. * @browser: The #InfBrowser for which to create a new account. * * Creates a new #InfGtkAccountCreationDialog, which can be used to generate * a new account on the infinote directory represented by the given browser. * * Returns: (transfer full): A new #InfGtkAccountCreationDialog. Free with * gtk_widget_destroy() when no longer needed. */ InfGtkAccountCreationDialog* inf_gtk_account_creation_dialog_new(GtkWindow* parent, GtkDialogFlags dialog_flags, InfIo* io, InfBrowser* browser) { GObject* object; g_return_val_if_fail(parent == NULL || GTK_IS_WINDOW(parent), NULL); g_return_val_if_fail(INF_IS_IO(io), NULL); g_return_val_if_fail(browser == NULL || INF_IS_BROWSER(browser), NULL); object = g_object_new( INF_GTK_TYPE_ACCOUNT_CREATION_DIALOG, "io", io, "browser", browser, NULL ); if(dialog_flags & GTK_DIALOG_MODAL) gtk_window_set_modal(GTK_WINDOW(object), TRUE); if(dialog_flags & GTK_DIALOG_DESTROY_WITH_PARENT) gtk_window_set_destroy_with_parent(GTK_WINDOW(object), TRUE); gtk_window_set_transient_for(GTK_WINDOW(object), parent); return INF_GTK_ACCOUNT_CREATION_DIALOG(object); } /** * inf_gtk_account_creation_dialog_set_browser: * @dlg: A #InfGtkAccountCreationDialog. * @browser: The #InfBrowser for which to create a new account, or %NULL. * * Changes the browser for which to create a new account. */ void inf_gtk_account_creation_dialog_set_browser(InfGtkAccountCreationDialog* dlg, InfBrowser* browser) { InfGtkAccountCreationDialogPrivate* priv; GSList* item; g_return_if_fail(INF_GTK_IS_ACCOUNT_CREATION_DIALOG(dlg)); g_return_if_fail(browser == NULL || INF_IS_BROWSER(browser)); priv = INF_GTK_ACCOUNT_CREATION_DIALOG_PRIVATE(dlg); if(priv->browser != NULL) { if(priv->key != NULL) { gnutls_x509_privkey_deinit(priv->key); priv->key = NULL; } if(priv->key_generator != NULL) { inf_async_operation_free(priv->key_generator); priv->key_generator = NULL; } if(priv->create_account_request != NULL) { inf_signal_handlers_disconnect_by_func( priv->create_account_request, G_CALLBACK( inf_gtk_account_creation_dialog_create_account_finished_cb ), dlg ); g_object_unref(priv->create_account_request); priv->create_account_request = NULL; } inf_signal_handlers_disconnect_by_func( priv->browser, G_CALLBACK(inf_gtk_account_creation_dialog_acl_changed_cb), dlg ); inf_signal_handlers_disconnect_by_func( priv->browser, G_CALLBACK(inf_gtk_account_creation_dialog_notify_status_cb), dlg ); g_object_unref(priv->browser); } priv->browser = browser; if(priv->browser != NULL) { g_object_ref(priv->browser); g_signal_connect( G_OBJECT(priv->browser), "acl-changed", G_CALLBACK(inf_gtk_account_creation_dialog_acl_changed_cb), dlg ); g_signal_connect( G_OBJECT(priv->browser), "notify::status", G_CALLBACK(inf_gtk_account_creation_dialog_notify_status_cb), dlg ); } g_object_notify(G_OBJECT(dlg), "browser"); inf_gtk_account_creation_dialog_update(dlg, NULL); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfgtk/PaxHeaders.26529/inf-gtk-chat.c0000644000000000000000000000013213034342512020171 xustar0030 mtime=1483851082.021718383 30 atime=1483851082.021718383 30 ctime=1488261589.328138348 libinfinity-0.7.1/libinfgtk/inf-gtk-chat.c0000644000175000017500000007443313034342512020736 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include #include #include #include /* For strlen() */ /** * SECTION:inf-gtk-chat * @title: InfGtkChat * @short_description: Gtk interface to #InfChatSession * @include: libinfgtk/inf-gtk-chat.h * @stability: Unstable * * #InfGtkChat is a widget showing a #InfChatSession conversation. Use * inf_gtk_chat_set_session() to set the session whose conversation to show * in the widget. If you have a local user in the session you can also call * inf_gtk_chat_set_active_user(). In this case the input text entry is made * available and messages are sent via that user. **/ /* This is a small hack to get the scrolling in the textview right */ typedef enum _InfGtkChatVMode { /* VMode is disabled, always keep bottom row constant */ INF_GTK_CHAT_VMODE_DISABLED, /* VMode is enabled, keep top row constant for next line addition */ INF_GTK_CHAT_VMODE_ENABLED, /* VMode is set, keep top row constant */ INF_GTK_CHAT_VMODE_SET } InfGtkChatVMode; typedef struct _InfGtkChatEntryKeyPressEventCbForeachData InfGtkChatEntryKeyPressEventCbForeachData; struct _InfGtkChatEntryKeyPressEventCbForeachData { gchar* match; guint count; guint index; InfUser* result; InfUser* first; }; typedef struct _InfGtkChatPrivate InfGtkChatPrivate; struct _InfGtkChatPrivate { GtkWidget* chat_view; GtkWidget* chat_entry; GtkWidget* send_button; GtkAdjustment* scroll_vadj; InfChatSession* session; InfChatBuffer* buffer; InfUser* active_user; gdouble voffset; InfGtkChatVMode vmode; GtkTextTag* tag_normal; GtkTextTag* tag_system; GtkTextTag* tag_emote; GtkTextTag* tag_backlog; /* Tab completion */ gchar* completion_text; guint completion_start; guint completion_end; guint completion_index; }; enum { PROP_0, PROP_SESSION, PROP_ACTIVE_USER }; #define INF_GTK_CHAT_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INF_GTK_TYPE_CHAT, InfGtkChatPrivate)) G_DEFINE_TYPE_WITH_CODE(InfGtkChat, inf_gtk_chat, GTK_TYPE_GRID, G_ADD_PRIVATE(InfGtkChat)) /* * Message representation */ /* Copied from InfChatSession. TODO: Should go as a public helper function * in libinfinity. */ static gchar* inf_gtk_chat_strdup_strftime(const char* format, const struct tm* tm, gsize* len) { gsize alloc; gchar* str; size_t result; alloc = 64; str = g_malloc(alloc * sizeof(gchar)); result = strftime(str, alloc, format, tm); while(result == 0 && alloc < 1024) { alloc *= 2; str = g_realloc(str, alloc * sizeof(gchar)); result = strftime(str, alloc, format, tm); } if(result == 0) { g_free(str); return NULL; } if(len) *len = result; return str; } static void inf_gtk_chat_add_message(InfGtkChat* chat, const InfChatBufferMessage* message) { InfGtkChatPrivate* priv; GtkTextBuffer* buffer; GtkTextIter insert_pos; const gchar* formatter; time_t cur_time; struct tm cur_time_tm; struct tm given_time_tm; gchar* time_str; gchar* loc_text; gchar* text; GtkTextTag* tag; gdouble scroll_val; gdouble scroll_upper; gdouble scroll_page_size; priv = INF_GTK_CHAT_PRIVATE(chat); buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(priv->chat_view)); cur_time = time(NULL); cur_time_tm = *localtime(&cur_time); given_time_tm = *localtime(&message->time); /* Show date if text was not logged today */ if(cur_time_tm.tm_yday != given_time_tm.tm_yday || cur_time_tm.tm_year != given_time_tm.tm_year) { formatter = "%x %X"; } else { formatter = "%X"; } time_str = inf_gtk_chat_strdup_strftime(formatter, &given_time_tm, NULL); switch(message->type) { case INF_CHAT_BUFFER_MESSAGE_NORMAL: tag = priv->tag_normal; text = g_strdup_printf( "[%s] <%s> %.*s", time_str, inf_user_get_name(message->user), (int)message->length, message->text ); break; case INF_CHAT_BUFFER_MESSAGE_EMOTE: tag = priv->tag_emote; text = g_strdup_printf( "[%s] * %s %.*s", time_str, inf_user_get_name(message->user), (int)message->length, message->text ); break; case INF_CHAT_BUFFER_MESSAGE_USERJOIN: tag = priv->tag_system; loc_text = g_strdup_printf(_("%s has joined"), inf_user_get_name(message->user)); text = g_strdup_printf("[%s] %s", time_str, loc_text); g_free(loc_text); break; case INF_CHAT_BUFFER_MESSAGE_USERPART: tag = priv->tag_system; loc_text = g_strdup_printf(_("%s has left"), inf_user_get_name(message->user)); text = g_strdup_printf("[%s] %s", time_str, loc_text); g_free(loc_text); break; default: g_assert_not_reached(); break; } g_free(time_str); /* Always apply backlog tag if it's a backlog message */ if(message->flags & INF_CHAT_BUFFER_MESSAGE_BACKLOG) tag = priv->tag_backlog; g_object_get( G_OBJECT(priv->scroll_vadj), "value", &scroll_val, "upper", &scroll_upper, "page-size", &scroll_page_size, NULL ); gtk_text_buffer_get_end_iter(buffer, &insert_pos); gtk_text_buffer_insert_with_tags(buffer, &insert_pos, text, -1, tag, NULL); gtk_text_buffer_insert(buffer, &insert_pos, "\n", 1); if(scroll_val != scroll_upper - scroll_page_size && scroll_upper - scroll_page_size > 0 && priv->vmode == INF_GTK_CHAT_VMODE_ENABLED) { /* This is a kind of hack to keep the view where it is, otherwise * inf_gtk_chat_adjustment_changed_cb() would try to keep the distance * to the bottom row constant, moving the viewport by the newly * added row. */ priv->vmode = INF_GTK_CHAT_VMODE_SET; } } /* like the g_utf8_next_char macro, but without the cast to char* at the end */ #define inf_utf8_next_char(p) ((p) + g_utf8_skip[*(const guchar *)(p)]) static void inf_gtk_chat_send_message(InfGtkChat* chat, const gchar* text, gsize bytes) { InfGtkChatPrivate* priv; const gchar* orig_text; priv = INF_GTK_CHAT_PRIVATE(chat); g_assert(priv->session != NULL); g_assert(priv->buffer != NULL); g_assert(priv->active_user != NULL); if(g_str_has_prefix(text, "/me") && (text[3] == '\0' || g_unichar_isspace(g_utf8_get_char(text+3)))) { orig_text = text; text += 3; while(g_unichar_isspace(g_utf8_get_char(text))) text = inf_utf8_next_char(text); inf_chat_buffer_add_emote_message( priv->buffer, priv->active_user, text, bytes - (text - orig_text), time(NULL), 0 ); } else { inf_chat_buffer_add_message( priv->buffer, priv->active_user, text, bytes, time(NULL), 0 ); } } static void inf_gtk_chat_commit_message(InfGtkChat* chat) { InfGtkChatPrivate* priv; GtkEntryBuffer* entry_buffer; gsize bytes; const gchar* text; const gchar* pos; priv = INF_GTK_CHAT_PRIVATE(chat); entry_buffer = gtk_entry_get_buffer(GTK_ENTRY(priv->chat_entry)); bytes = gtk_entry_buffer_get_bytes(entry_buffer); text = gtk_entry_buffer_get_text(entry_buffer); while( (pos = memchr(text, '\n', bytes)) != NULL) { /* Skip \r\n */ if(pos > text && *(pos - 1) == '\r') inf_gtk_chat_send_message(chat, text, pos - text - 1); else inf_gtk_chat_send_message(chat, text, pos - text); bytes -= ((pos - text) + 1); text = pos + 1; } inf_gtk_chat_send_message(chat, text, bytes); gtk_entry_set_text(GTK_ENTRY(priv->chat_entry), ""); } /* * Signal handlers */ static void inf_gtk_chat_entry_activate_cb(GtkEntry* entry, gpointer user_data) { const gchar* text; text = gtk_entry_get_text(entry); if(text != NULL && *text != '\0') inf_gtk_chat_commit_message(INF_GTK_CHAT(user_data)); } static void inf_gtk_chat_entry_changed_cb(GtkEntry* entry, gpointer user_data) { InfGtkChat* chat; InfGtkChatPrivate* priv; const gchar* text; chat = INF_GTK_CHAT(user_data); priv = INF_GTK_CHAT_PRIVATE(chat); text = gtk_entry_get_text(entry); gtk_widget_set_sensitive( priv->send_button, text != NULL && *text != '\0' ); /* Reset tab completion */ g_free(priv->completion_text); priv->completion_text = NULL; } static void inf_gtk_chat_entry_key_press_event_cb_foreach_func(InfUser* user, gpointer user_data) { InfGtkChatEntryKeyPressEventCbForeachData* data; gchar* normalized; gchar* casefold; data = (InfGtkChatEntryKeyPressEventCbForeachData*)user_data; if(inf_user_get_status(user) != INF_USER_UNAVAILABLE) { normalized = g_utf8_normalize(inf_user_get_name(user), -1, G_NORMALIZE_ALL); casefold = g_utf8_casefold(normalized, -1); g_free(normalized); if(g_str_has_prefix(casefold, data->match)) { if(data->count == data->index) data->result = user; ++data->count; if(data->first == NULL) data->first = user; } g_free(casefold); } } static gboolean inf_gtk_chat_entry_key_press_event_cb(GtkWidget* widget, GdkEventKey* event, gpointer user_data) { InfGtkChat* chat; InfGtkChatPrivate* priv; guint index; guint begin; const gchar* text; gchar* normalized; InfGtkChatEntryKeyPressEventCbForeachData foreach_data; InfUser* complete; int position; chat = INF_GTK_CHAT(user_data); priv = INF_GTK_CHAT_PRIVATE(chat); /* This must not be pressed for tab completion to be triggered: */ #define MASK (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK) if(event->keyval == GDK_KEY_Tab && (event->state & MASK) == 0) { index = gtk_editable_get_position(GTK_EDITABLE(widget)); if(priv->completion_text != NULL && index != priv->completion_end) { /* Cursor was moved since last completion attempt: Reset completion */ g_free(priv->completion_text); priv->completion_text = NULL; } else if(priv->completion_text != NULL) { /* Otherwise complete next in row */ if(priv->completion_end > 0) ++priv->completion_index; } if(priv->completion_text == NULL) { /* No previous completion, so find completion text and completion * starting point. */ begin = index; text = gtk_entry_get_text(GTK_ENTRY(priv->chat_entry)); while(begin > 0) { begin = g_utf8_prev_char(&text[begin]) - text; if(g_unichar_isspace(g_utf8_get_char(&text[begin]))) { begin = inf_utf8_next_char(&text[begin]) - text; break; } } if(begin < index) { normalized = g_utf8_normalize( &text[begin], index - begin, G_NORMALIZE_ALL ); priv->completion_text = g_utf8_casefold(normalized, -1); g_free(normalized); priv->completion_end = index; priv->completion_start = begin; } } if(priv->completion_text != NULL) { foreach_data.match = priv->completion_text; foreach_data.count = 0; foreach_data.index = priv->completion_index; foreach_data.result = NULL; foreach_data.first = NULL; inf_user_table_foreach_user( inf_session_get_user_table(INF_SESSION(priv->session)), inf_gtk_chat_entry_key_press_event_cb_foreach_func, &foreach_data ); complete = foreach_data.result; if(complete == NULL) { if(foreach_data.first != NULL) { /* wrap around */ complete = foreach_data.first; priv->completion_index = 0; } } if(complete == NULL) { /* No match: Reset completion, don't do anything */ g_free(priv->completion_text); priv->completion_text = NULL; } else { inf_signal_handlers_block_by_func( G_OBJECT(priv->chat_entry), G_CALLBACK(inf_gtk_chat_entry_changed_cb), chat ); if(priv->completion_start != priv->completion_end) { gtk_editable_delete_text( GTK_EDITABLE(widget), priv->completion_start, priv->completion_end ); } position = priv->completion_start; gtk_editable_insert_text( GTK_EDITABLE(priv->chat_entry), inf_user_get_name(complete), -1, &position ); if(priv->completion_start == 0) { gtk_editable_insert_text( GTK_EDITABLE(priv->chat_entry), ": ", 2, &position ); } else { gtk_editable_insert_text( GTK_EDITABLE(priv->chat_entry), " ", 1, &position ); } priv->completion_end = position; gtk_editable_set_position(GTK_EDITABLE(priv->chat_entry), position); inf_signal_handlers_unblock_by_func( G_OBJECT(priv->chat_entry), G_CALLBACK(inf_gtk_chat_entry_changed_cb), chat ); } } return TRUE; } return FALSE; } static void inf_gtk_chat_send_button_clicked_cb(GtkButton* button, gpointer user_data) { inf_gtk_chat_commit_message(INF_GTK_CHAT(user_data)); } static void inf_gtk_chat_buffer_add_message_cb(InfChatBuffer* buffer, const InfChatBufferMessage* message, gpointer user_data) { inf_gtk_chat_add_message(INF_GTK_CHAT(user_data), message); } static void inf_gtk_chat_user_notify_status_cb(GObject* object, GParamSpec* pspec, gpointer user_data) { if(inf_user_get_status(INF_USER(object)) == INF_USER_UNAVAILABLE) inf_gtk_chat_set_active_user(INF_GTK_CHAT(user_data), NULL); } static void inf_gtk_chat_user_notify_flags_cb(GObject* object, GParamSpec* pspec, gpointer user_data) { if( (inf_user_get_flags(INF_USER(object)) & INF_USER_LOCAL) == 0) inf_gtk_chat_set_active_user(INF_GTK_CHAT(user_data), NULL); } static void inf_gtk_chat_adjustment_changed_cb(GObject* object, gpointer user_data) { InfGtkChatPrivate* priv; InfGtkChatVMode prev_mode; gdouble value; gdouble new_value; gdouble upper; gdouble page_size; gdouble max; priv = INF_GTK_CHAT_PRIVATE(user_data); g_object_get( object, "value", &value, "upper", &upper, "page-size", &page_size, NULL ); max = (upper > page_size) ? (upper - page_size) : 0.0; if(priv->vmode != INF_GTK_CHAT_VMODE_SET) { prev_mode = priv->vmode; new_value = (max > priv->voffset) ? (max - priv->voffset) : 0.0; if(value != new_value) { gtk_adjustment_set_value(GTK_ADJUSTMENT(object), new_value); /* Undo effect of signal handler: We only enable vmode operation if * the adjustment value was changed independently, for example by the * user moving the scrollbar. */ priv->vmode = prev_mode; } } else { priv->voffset = (max > value) ? (max - value) : 0.0; priv->vmode = INF_GTK_CHAT_VMODE_ENABLED; } } static void inf_gtk_chat_adjustment_value_changed_cb(GObject* object, gpointer user_data) { InfGtkChatPrivate* priv; gdouble value; gdouble upper; gdouble page_size; gdouble max; priv = INF_GTK_CHAT_PRIVATE(user_data); g_object_get( object, "value", &value, "upper", &upper, "page-size", &page_size, NULL ); max = (upper > page_size) ? (upper - page_size) : 0.0; priv->voffset = (max > value) ? (max - value) : 0.0; /* Enable vmode as soon as we scroll away from the bottom of the textview. * This keeps the viewport constant when adding new rows but the scroll * position not being at the bottom of the view. Due to some strange GTK+ * weirdness this does not work when initially populating the buffer with * backlog messages, so we enable this explicitely after the scrollbar is * moved away from the very bottom of the view. */ if(priv->vmode == INF_GTK_CHAT_VMODE_DISABLED) priv->vmode = INF_GTK_CHAT_VMODE_ENABLED; } static gboolean inf_gtk_chat_textview_focus_in_cb(GtkWidget* widget, GdkEvent* event, gpointer user_data) { InfGtkChat* chat; InfGtkChatPrivate* priv; chat = INF_GTK_CHAT(user_data); priv = INF_GTK_CHAT_PRIVATE(chat); gtk_widget_grab_focus(priv->chat_entry); return TRUE; } static void inf_gtk_chat_entry_cope_clipboard_cb(GtkEntry* entry, gpointer user_data) { InfGtkChat* chat; InfGtkChatPrivate* priv; int cursor_position; int selection_bound; GtkTextBuffer* buffer; GtkClipboard* clipboard; chat = INF_GTK_CHAT(user_data); priv = INF_GTK_CHAT_PRIVATE(chat); g_object_get( G_OBJECT(entry), "cursor-position", &cursor_position, "selection-bound", &selection_bound, NULL ); if(cursor_position == selection_bound) { buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(priv->chat_view)); clipboard = gtk_clipboard_get_for_display( gtk_widget_get_display(priv->chat_view), GDK_SELECTION_CLIPBOARD ); gtk_text_buffer_copy_clipboard(buffer, clipboard); } } /* * GObject overrides */ static void inf_gtk_chat_init(InfGtkChat* chat) { InfGtkChatPrivate* priv; priv = INF_GTK_CHAT_PRIVATE(chat); priv->session = NULL; priv->buffer = NULL; priv->active_user = NULL; priv->voffset = 0.0; priv->vmode = INF_GTK_CHAT_VMODE_DISABLED; /* Actually they are invalid as long as completion_text is NULL, but * let's be sure */ priv->completion_text = NULL; priv->completion_start = 0; priv->completion_end = 0; priv->completion_index = 0; gtk_widget_init_template(GTK_WIDGET(chat)); /* Connect signals to handle copying. We don't want the textview to be * able to have focus, however we want ctrl+c to copy its text. Therefore, * whenever the textview receives focus, we give the focus to the text * entry, and when the text entry is copying text, and does not have an * own selection, we copy the textview's text instead. */ g_signal_connect( priv->chat_view, "focus-in-event", G_CALLBACK(inf_gtk_chat_textview_focus_in_cb), chat ); g_signal_connect( priv->chat_entry, "copy-clipboard", G_CALLBACK(inf_gtk_chat_entry_cope_clipboard_cb), chat ); } static void inf_gtk_chat_dispose(GObject* object) { InfGtkChat* chat; InfGtkChatPrivate* priv; chat = INF_GTK_CHAT(object); priv = INF_GTK_CHAT_PRIVATE(chat); if(priv->session != NULL) inf_gtk_chat_set_session(chat, NULL); G_OBJECT_CLASS(inf_gtk_chat_parent_class)->dispose(object); } static void inf_gtk_chat_finalize(GObject* object) { InfGtkChat* chat; InfGtkChatPrivate* priv; chat = INF_GTK_CHAT(object); priv = INF_GTK_CHAT_PRIVATE(chat); g_free(priv->completion_text); G_OBJECT_CLASS(inf_gtk_chat_parent_class)->finalize(object); } static void inf_gtk_chat_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfGtkChat* chat; InfGtkChatPrivate* priv; chat = INF_GTK_CHAT(object); priv = INF_GTK_CHAT_PRIVATE(chat); switch(prop_id) { case PROP_SESSION: inf_gtk_chat_set_session( chat, INF_CHAT_SESSION(g_value_get_object(value)) ); break; case PROP_ACTIVE_USER: inf_gtk_chat_set_active_user(chat, INF_USER(g_value_get_object(value))); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void inf_gtk_chat_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfGtkChat* chat; InfGtkChatPrivate* priv; chat = INF_GTK_CHAT(object); priv = INF_GTK_CHAT_PRIVATE(chat); switch(prop_id) { case PROP_SESSION: g_value_set_object(value, priv->session); break; case PROP_ACTIVE_USER: g_value_set_object(value, priv->active_user); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } /* * GType registration */ static void inf_gtk_chat_class_init(InfGtkChatClass* chat_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(chat_class); object_class->dispose = inf_gtk_chat_dispose; object_class->finalize = inf_gtk_chat_finalize; object_class->set_property = inf_gtk_chat_set_property; object_class->get_property = inf_gtk_chat_get_property; gtk_widget_class_set_template_from_resource( GTK_WIDGET_CLASS(chat_class), "/de/0x539/libinfgtk/ui/infgtkchat.ui" ); gtk_widget_class_bind_template_child_private( GTK_WIDGET_CLASS(chat_class), InfGtkChat, scroll_vadj ); gtk_widget_class_bind_template_child_private( GTK_WIDGET_CLASS(chat_class), InfGtkChat, chat_view ); gtk_widget_class_bind_template_child_private( GTK_WIDGET_CLASS(chat_class), InfGtkChat, chat_entry ); gtk_widget_class_bind_template_child_private( GTK_WIDGET_CLASS(chat_class), InfGtkChat, send_button ); gtk_widget_class_bind_template_child_private( GTK_WIDGET_CLASS(chat_class), InfGtkChat, tag_normal ); gtk_widget_class_bind_template_child_private( GTK_WIDGET_CLASS(chat_class), InfGtkChat, tag_system ); gtk_widget_class_bind_template_child_private( GTK_WIDGET_CLASS(chat_class), InfGtkChat, tag_emote ); gtk_widget_class_bind_template_child_private( GTK_WIDGET_CLASS(chat_class), InfGtkChat, tag_backlog ); gtk_widget_class_bind_template_callback( GTK_WIDGET_CLASS(chat_class), inf_gtk_chat_adjustment_changed_cb ); gtk_widget_class_bind_template_callback( GTK_WIDGET_CLASS(chat_class), inf_gtk_chat_adjustment_value_changed_cb ); gtk_widget_class_bind_template_callback( GTK_WIDGET_CLASS(chat_class), inf_gtk_chat_send_button_clicked_cb ); gtk_widget_class_bind_template_callback( GTK_WIDGET_CLASS(chat_class), inf_gtk_chat_entry_activate_cb ); gtk_widget_class_bind_template_callback( GTK_WIDGET_CLASS(chat_class), inf_gtk_chat_entry_changed_cb ); gtk_widget_class_bind_template_callback( GTK_WIDGET_CLASS(chat_class), inf_gtk_chat_entry_key_press_event_cb ); g_object_class_install_property( object_class, PROP_SESSION, g_param_spec_object( "session", "Session", "The chat session this widget is displaying", INF_TYPE_CHAT_SESSION, G_PARAM_READWRITE ) ); g_object_class_install_property( object_class, PROP_ACTIVE_USER, g_param_spec_object( "active-user", "Active user", "The user outgoing messages come from", INF_TYPE_USER, G_PARAM_READWRITE ) ); } /* * Public API. */ /** * inf_gtk_chat_new: (constructor) * * Creates a new #InfGtkChat. To show a chat conversation set a session to * show via inf_gtk_chat_set_session(). * * Returns: (transfer floating): A new #InfGtkChat. */ GtkWidget* inf_gtk_chat_new(void) { GObject* object; object = g_object_new(INF_GTK_TYPE_CHAT, NULL); return GTK_WIDGET(object); } /** * inf_gtk_chat_set_session: * @chat: A #InfGtkChat. * @session: The #InfChatSession to set. * * Sets the chat session to show in the chat widget. If there is a previous * session set the chat view will be cleared before showing the new session. * If the previous session had an active user set it will be unset. If * @session is %NULL this function just clears the chat view and unsets the * active user, if any. */ void inf_gtk_chat_set_session(InfGtkChat* chat, InfChatSession* session) { InfGtkChatPrivate* priv; guint i; g_return_if_fail(INF_GTK_IS_CHAT(chat)); g_return_if_fail(session == NULL || INF_IS_CHAT_SESSION(session)); priv = INF_GTK_CHAT_PRIVATE(chat); /* Notify "active-user" and "session" simultanously */ g_object_freeze_notify(G_OBJECT(chat)); if(priv->session != NULL) { g_assert(priv->buffer != NULL); /* Remove active user, if any */ if(priv->active_user != NULL) inf_gtk_chat_set_active_user(chat, NULL); inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->buffer), G_CALLBACK(inf_gtk_chat_buffer_add_message_cb), chat ); g_object_unref(priv->session); g_object_unref(priv->buffer); gtk_text_buffer_set_text( gtk_text_view_get_buffer(GTK_TEXT_VIEW(priv->chat_view)), "", 0 ); } priv->session = session; if(session != NULL) { g_object_ref(session); priv->buffer = INF_CHAT_BUFFER(inf_session_get_buffer(INF_SESSION(session))); g_object_ref(priv->buffer); g_signal_connect_after( G_OBJECT(priv->buffer), "add-message", G_CALLBACK(inf_gtk_chat_buffer_add_message_cb), chat ); /* Show messages from oldest to newest */ for(i = 0; i < inf_chat_buffer_get_n_messages(priv->buffer); ++i) { inf_gtk_chat_add_message( chat, inf_chat_buffer_get_message(priv->buffer, i) ); } } else { priv->buffer = NULL; } g_object_notify(G_OBJECT(chat), "session"); g_object_thaw_notify(G_OBJECT(chat)); } /** * inf_gtk_chat_set_active_user: * @chat: A #InfGtkChat. * @user: A local #InfUser which joined chat's session. * * Sets the active user for the chat. This must be a user in the chat's * session's user table and it must have the %INF_USER_LOCAL flag set, i.e. * you need to have it joined before using inf_session_proxy_join_user(). * * If an active user is set the chat's text entry is made sensitive and the * user can type chat messages. They are sent to the session as originated by * @user. If @user's status changes to %INF_USER_UNAVAILABLE or the * %INF_USER_LOCAL flag is removed the active user will be unset * automatically. * * This cannot be called when the chat has no session set yet. * Use inf_gtk_chat_set_session() first. */ void inf_gtk_chat_set_active_user(InfGtkChat* chat, InfUser* user) { InfGtkChatPrivate* priv; const gchar* text; g_return_if_fail(INF_GTK_IS_CHAT(chat)); g_return_if_fail(user == NULL || INF_IS_USER(user)); priv = INF_GTK_CHAT_PRIVATE(chat); g_return_if_fail(priv->session != NULL); g_return_if_fail( user == NULL || inf_user_get_status(user) != INF_USER_UNAVAILABLE ); g_return_if_fail( user == NULL || (inf_user_get_flags(user) & INF_USER_LOCAL) != 0 ); g_return_if_fail( user == NULL || inf_user_table_lookup_user_by_id( inf_session_get_user_table(INF_SESSION(priv->session)), inf_user_get_id(user) ) == user ); if(priv->active_user != NULL) { inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->active_user), G_CALLBACK(inf_gtk_chat_user_notify_status_cb), chat ); inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->active_user), G_CALLBACK(inf_gtk_chat_user_notify_flags_cb), chat ); g_object_unref(priv->active_user); } priv->active_user = user; if(user != NULL) { g_object_ref(user); g_signal_connect( G_OBJECT(user), "notify::status", G_CALLBACK(inf_gtk_chat_user_notify_status_cb), chat ); g_signal_connect( G_OBJECT(user), "notify::flags", G_CALLBACK(inf_gtk_chat_user_notify_flags_cb), chat ); gtk_widget_set_sensitive(priv->chat_entry, TRUE); text = gtk_entry_get_text(GTK_ENTRY(priv->chat_entry)); gtk_widget_set_sensitive( priv->send_button, text != NULL && *text != '\0' ); /* TODO: Only do this when there currently is no focus child: */ /* TODO: Doesn't work anyway: */ #if 0 gtk_container_set_focus_child( GTK_CONTAINER( gtk_widget_get_parent(gtk_widget_get_parent(priv->entry)) ), gtk_widget_get_parent(priv->entry) ); gtk_container_set_focus_child( GTK_CONTAINER(gtk_widget_get_parent(priv->entry)), priv->entry ); #endif } else { gtk_widget_set_sensitive(priv->chat_entry, FALSE); gtk_widget_set_sensitive(priv->send_button, FALSE); } g_object_notify(G_OBJECT(chat), "active-user"); } /** * inf_gtk_chat_get_active_user: * @chat: A #InfGtkChat. * * Returns the active user for @chat as set with * inf_gtk_chat_set_active_user(). * * Returns: (transfer none) (allow-none): The chat's active user, or * %NULL if there is none. */ InfUser* inf_gtk_chat_get_active_user(InfGtkChat* chat) { g_return_val_if_fail(INF_GTK_IS_CHAT(chat), NULL); return INF_GTK_CHAT_PRIVATE(chat)->active_user; } /* TODO: I don't like this API because it allows users to do crap with the * entry such as setting it to be sensitive when it shouldn't be. It's * currently used to set the focus on the entry widget after setting the * active user for which I did not find another way... IMHO doing * gtk_container_set_focus_child() should be enough, but it isn't. I'm not * sure what the problem is... maybe we should replace it by * inf_gtk_chat_entry_grab_focus() or something. */ /** * inf_gtk_chat_get_entry: * @chat: A #InfGtkChat. * * Returns the chat's text input entry. * * Returns: (transfer none): The chat's #GtkEntry. This is owned by the chat, * so you don't need to free it. */ GtkWidget* inf_gtk_chat_get_entry(InfGtkChat* chat) { g_return_val_if_fail(INF_GTK_IS_CHAT(chat), NULL); return INF_GTK_CHAT_PRIVATE(chat)->chat_entry; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfgtk/PaxHeaders.26529/inf-gtk-browser-view.c0000644000000000000000000000013213034342512021705 xustar0030 mtime=1483851082.017718362 30 atime=1483851082.017718362 30 ctime=1488261589.320138365 libinfinity-0.7.1/libinfgtk/inf-gtk-browser-view.c0000644000175000017500000022525013034342512022445 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include #include #include #include #include #define INF_GTK_BROWSER_VIEW_INITIAL_EXPANSION \ "inf-gtk-browser-view-initial-exploration" #define INF_GTK_BROWSER_VIEW_ERROR_COLOR "#db1515" typedef struct _InfGtkBrowserViewBrowser InfGtkBrowserViewBrowser; struct _InfGtkBrowserViewBrowser { InfGtkBrowserView* view; InfBrowser* browser; GtkTreeRowReference* reference; GSList* explores; GSList* syncs; /* Whether we expand the root node automatically */ gboolean initial_root_expansion; }; typedef struct _InfGtkBrowserViewExplore InfGtkBrowserViewExplore; struct _InfGtkBrowserViewExplore { InfGtkBrowserViewBrowser* view_browser; GtkTreeRowReference* reference; InfRequest* request; }; typedef struct _InfGtkBrowserViewSync InfGtkBrowserViewSync; struct _InfGtkBrowserViewSync { InfGtkBrowserViewBrowser* view_browser; GtkTreeRowReference* reference; InfSessionProxy* proxy; }; typedef struct _InfGtkBrowserViewPrivate InfGtkBrowserViewPrivate; struct _InfGtkBrowserViewPrivate { GtkTreeViewColumn* column; /* Note that progress and status_text are never visible at the same time */ GtkCellRenderer* renderer_icon; GtkCellRenderer* renderer_name; GtkCellRenderer* renderer_progress; GtkCellRenderer* renderer_status; /* This is just bookkeeping because we connect to their signals, and need * to disconnect when the view is disposed, or a browser removed. */ GSList* browsers; /* Pending discovery info resolves */ GSList* info_resolvs; }; enum { PROP_0, PROP_MODEL }; enum { ACTIVATE, SELECTION_CHANGED, POPULATE_POPUP, LAST_SIGNAL }; #define INF_GTK_BROWSER_VIEW_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INF_GTK_TYPE_BROWSER_VIEW, InfGtkBrowserViewPrivate)) /* We do some rather complex stuff here because we don't get the iter when * a row is deleted. This would be nice to disconnect browser signals for * example (we need the iter to access the browser to disconnect the signals), * but it is not possible. * * Instead, we keep an array of browsers in the model including * TreeRowReferences where they are in the tree. When a row is removed, we * check which TreeRowReferences got invalid and delete the corresponding * browsers from our array. The same holds for explore requests and * session synchronizations. */ static guint view_signals[LAST_SIGNAL]; G_DEFINE_TYPE_WITH_CODE(InfGtkBrowserView, inf_gtk_browser_view, GTK_TYPE_TREE_VIEW, G_ADD_PRIVATE(InfGtkBrowserView)) /* * Utility functions */ static InfGtkBrowserViewBrowser* inf_gtk_browser_view_find_view_browser(InfGtkBrowserView* view, InfBrowser* browser) { InfGtkBrowserViewPrivate* priv; GSList* item; InfGtkBrowserViewBrowser* view_browser; priv = INF_GTK_BROWSER_VIEW_PRIVATE(view); for(item = priv->browsers; item != NULL; item = item->next) { view_browser = (InfGtkBrowserViewBrowser*)item->data; if(view_browser->browser == browser) return view_browser; } return NULL; } static InfGtkBrowserViewExplore* inf_gtk_browser_view_find_explore(InfGtkBrowserView* view, InfGtkBrowserViewBrowser* view_browser, InfRequest* request) { GSList* item; InfGtkBrowserViewExplore* explore; for(item = view_browser->explores; item != NULL; item = item->next) { explore = (InfGtkBrowserViewExplore*)item->data; if(explore->request == request) return explore; } return NULL; } static InfGtkBrowserViewSync* inf_gtk_browser_view_find_sync(InfGtkBrowserView* view, InfGtkBrowserViewBrowser* view_browser, InfSessionProxy* proxy) { GSList* item; InfGtkBrowserViewSync* sync; for(item = view_browser->syncs; item != NULL; item = item->next) { sync = (InfGtkBrowserViewSync*)item->data; if(sync->proxy == proxy) return sync; } return NULL; } static void inf_gtk_browser_view_redraw_row(InfGtkBrowserView* view, GtkTreePath* path, GtkTreeIter* iter) { InfGtkBrowserViewPrivate* priv; GdkRectangle cell_area; /* The actual data in the model has not been changed, otherwise the model * would have emitted the row-changed signal and the treeview would redraw * itself automatically. What actually has changed is just what we * display, for example the progress bar of the exploration of a node. This * does not belong to the model because the model does not care about * exploration progress, but we want to show it to the user nevertheless. * I am not sure whether this is a problem in our design or a limitation * in the GTK+ treeview and friends. */ priv = INF_GTK_BROWSER_VIEW_PRIVATE(view); if(gtk_widget_get_realized(GTK_WIDGET(view))) { gtk_tree_view_get_cell_area( GTK_TREE_VIEW(view), path, priv->column, &cell_area ); if(cell_area.height != 0) { gtk_widget_queue_draw_area( GTK_WIDGET(view), cell_area.x, cell_area.y, cell_area.width, cell_area.height ); } } } static void inf_gtk_browser_view_redraw_for_reference(InfGtkBrowserView* view, GtkTreeRowReference* reference) { InfGtkBrowserViewPrivate* priv; GtkTreeModel* model; GtkTreePath* path; GtkTreeIter iter; priv = INF_GTK_BROWSER_VIEW_PRIVATE(view); path = gtk_tree_row_reference_get_path(reference); g_assert(path != NULL); model = gtk_tree_view_get_model(GTK_TREE_VIEW(view)); gtk_tree_model_get_iter(model, &iter, path); inf_gtk_browser_view_redraw_row(view, path, &iter); gtk_tree_path_free(path); } /* * Callbacks from InfGtkBrowserViewObjects */ /* Required by inf_gtk_browser_view_session_synchronization_complete_cb */ static void inf_gtk_browser_view_sync_removed(InfGtkBrowserView* view, InfGtkBrowserViewSync* sync); /* Required by inf_gtk_browser_view_explore_request_finished_cb */ static void inf_gtk_browser_view_explore_removed(InfGtkBrowserView* view, InfGtkBrowserViewExplore* expl); static void inf_gtk_browser_view_session_synchronization_progress_cb(InfSession* session, InfXmlConnection* c, gdouble percentage, gpointer user_data) { InfGtkBrowserViewSync* sync; sync = (InfGtkBrowserViewSync*)user_data; inf_gtk_browser_view_redraw_for_reference( sync->view_browser->view, sync->reference ); } static void inf_gtk_browser_view_session_synchronization_complete_cb(InfSession* session, InfXmlConnection* c, gpointer user_data) { InfGtkBrowserViewSync* sync; sync = (InfGtkBrowserViewSync*)user_data; inf_gtk_browser_view_sync_removed(sync->view_browser->view, sync); } static void inf_gtk_browser_view_session_synchronization_failed_cb(InfSession* session, InfXmlConnection* c, const GError* error, gpointer user_data) { /* TODO: Show the error in the view. I am not completely sure how to * achieve this. Probably, InfGtkBrowserModel needs to handle this signal * and set the error column. */ InfGtkBrowserViewSync* sync; sync = (InfGtkBrowserViewSync*)user_data; inf_gtk_browser_view_sync_removed(sync->view_browser->view, sync); } static void inf_gtk_browser_view_explore_request_notify_progress_cb(GObject* request, GParamSpec* pspec, gpointer user_data) { InfGtkBrowserViewExplore* explore; InfGtkBrowserView* view; GtkTreeModel* model; GtkTreePath* path; GtkTreeIter iter; GSList* initial_expansion_list; explore = (InfGtkBrowserViewExplore*)user_data; view = explore->view_browser->view; model = gtk_tree_view_get_model(GTK_TREE_VIEW(view)); path = gtk_tree_row_reference_get_path(explore->reference); g_assert(path != NULL); gtk_tree_model_get_iter(model, &iter, path); inf_gtk_browser_view_redraw_row(view, path, &iter); initial_expansion_list = g_object_steal_data( G_OBJECT(explore->request), INF_GTK_BROWSER_VIEW_INITIAL_EXPANSION ); /*printf("progress-cb on view %p, initial expansion %p\n", explore->view_browser->view, initial_expansion);*/ /* Expand initial exploration of the root node if we are told to * do so. This is the case if we issued the discovery resolv. */ /* The model might be a filter model in which case the first discovered * node might not be contained in the model. We expand as soon as we have * any children. If we don't have any, then we can't expand of course. The * extra g_object_set_data does not need to be undone since the request * most likely vanishes anyway after exploration. */ if(g_slist_find(initial_expansion_list, view) != NULL && gtk_tree_model_iter_has_child(model, &iter)) { initial_expansion_list = g_slist_remove( initial_expansion_list, view ); gtk_tree_view_expand_row(GTK_TREE_VIEW(view), path, FALSE); } g_object_set_data_full( G_OBJECT(explore->request), INF_GTK_BROWSER_VIEW_INITIAL_EXPANSION, initial_expansion_list, (GDestroyNotify)g_slist_free ); gtk_tree_path_free(path); } static void inf_gtk_browser_view_explore_request_finished_cb(InfRequest* request, const InfRequestResult* res, const GError* error, gpointer user_data) { InfGtkBrowserViewExplore* explore; explore = (InfGtkBrowserViewExplore*)user_data; /* Note that InfGtkBrowserStore listens on the request signals as well, and * it sets error on the node if there is an error. So we do not need to * handle the error here. */ inf_gtk_browser_view_explore_removed(explore->view_browser->view, explore); } /* * InfGtkBrowserViewSync, InfGtkBrowserViewExplore */ static void inf_gtk_browser_view_sync_added(InfGtkBrowserView* view, InfBrowser* browser, InfSessionProxy* proxy, GtkTreePath* path, GtkTreeIter* iter) { InfGtkBrowserViewPrivate* priv; InfGtkBrowserViewBrowser* view_browser; InfSession* session; InfGtkBrowserViewSync* sync; priv = INF_GTK_BROWSER_VIEW_PRIVATE(view); g_object_get(G_OBJECT(proxy), "session", &session, NULL); view_browser = inf_gtk_browser_view_find_view_browser(view, browser); g_assert(view_browser != NULL); g_assert(inf_gtk_browser_view_find_sync(view, view_browser, proxy) == NULL); g_assert( inf_session_get_synchronization_status( session, infc_browser_get_connection(INFC_BROWSER(browser)) ) != INF_SESSION_SYNC_NONE ); sync = g_slice_new(InfGtkBrowserViewSync); sync->view_browser = view_browser; sync->proxy = proxy; g_object_ref(proxy); sync->reference = gtk_tree_row_reference_new_proxy( G_OBJECT(priv->column), gtk_tree_view_get_model(GTK_TREE_VIEW(view)), path ); g_assert(sync->reference != NULL); view_browser->syncs = g_slist_prepend(view_browser->syncs, sync); g_signal_connect_after( G_OBJECT(session), "synchronization-progress", G_CALLBACK(inf_gtk_browser_view_session_synchronization_progress_cb), sync ); g_signal_connect_after( G_OBJECT(session), "synchronization-complete", G_CALLBACK(inf_gtk_browser_view_session_synchronization_complete_cb), sync ); g_signal_connect_after( G_OBJECT(session), "synchronization-failed", G_CALLBACK(inf_gtk_browser_view_session_synchronization_failed_cb), sync ); g_object_unref(session); inf_gtk_browser_view_redraw_row(view, path, iter); } static void inf_gtk_browser_view_sync_removed(InfGtkBrowserView* view, InfGtkBrowserViewSync* sync) { InfGtkBrowserViewPrivate* priv; InfSession* session; GtkTreePath* path; GtkTreeModel* model; GtkTreeIter iter; priv = INF_GTK_BROWSER_VIEW_PRIVATE(view); g_object_get(G_OBJECT(sync->proxy), "session", &session, NULL); /* Redraw if the reference is still valid. Note that if the node is removed * while the corresponding session is synchronized, then the reference is * not valid at this point. */ path = gtk_tree_row_reference_get_path(sync->reference); if(path != NULL) { model = gtk_tree_view_get_model(GTK_TREE_VIEW(view)); gtk_tree_model_get_iter(model, &iter, path); inf_gtk_browser_view_redraw_row(view, path, &iter); gtk_tree_path_free(path); } inf_signal_handlers_disconnect_by_func( G_OBJECT(session), G_CALLBACK(inf_gtk_browser_view_session_synchronization_progress_cb), sync ); inf_signal_handlers_disconnect_by_func( G_OBJECT(session), G_CALLBACK(inf_gtk_browser_view_session_synchronization_complete_cb), sync ); inf_signal_handlers_disconnect_by_func( G_OBJECT(session), G_CALLBACK(inf_gtk_browser_view_session_synchronization_failed_cb), sync ); g_object_unref(session); gtk_tree_row_reference_free(sync->reference); g_object_unref(sync->proxy); sync->view_browser->syncs = g_slist_remove(sync->view_browser->syncs, sync); g_slice_free(InfGtkBrowserViewSync, sync); } static void inf_gtk_browser_view_explore_added(InfGtkBrowserView* view, InfBrowser* browser, InfRequest* request, GtkTreePath* path, GtkTreeIter* iter) { InfGtkBrowserViewPrivate* priv; InfGtkBrowserViewBrowser* view_browser; InfGtkBrowserViewExplore* explore; priv = INF_GTK_BROWSER_VIEW_PRIVATE(view); view_browser = inf_gtk_browser_view_find_view_browser(view, browser); g_assert(view_browser != NULL); g_assert( inf_gtk_browser_view_find_explore(view, view_browser, request) == NULL ); explore = g_slice_new(InfGtkBrowserViewExplore); explore->view_browser = view_browser; explore->request = request; g_object_ref(request); explore->reference = gtk_tree_row_reference_new_proxy( G_OBJECT(priv->column), gtk_tree_view_get_model(GTK_TREE_VIEW(view)), path ); g_assert(explore->reference != NULL); view_browser->explores = g_slist_prepend(view_browser->explores, explore); g_signal_connect_after( G_OBJECT(request), "notify::progress", G_CALLBACK(inf_gtk_browser_view_explore_request_notify_progress_cb), explore ); g_signal_connect_after( G_OBJECT(request), "finished", G_CALLBACK(inf_gtk_browser_view_explore_request_finished_cb), explore ); /* TODO: Watch failed? */ inf_gtk_browser_view_redraw_row(view, path, iter); } static void inf_gtk_browser_view_explore_removed(InfGtkBrowserView* view, InfGtkBrowserViewExplore* expl) { InfGtkBrowserViewPrivate* priv; GtkTreePath* path; GtkTreeModel* model; GtkTreeIter iter; priv = INF_GTK_BROWSER_VIEW_PRIVATE(view); /* Redraw if the reference is still valid. Note that if the node is removed * while being explored, then the reference is not valid at this point. */ path = gtk_tree_row_reference_get_path(expl->reference); if(path != NULL) { model = gtk_tree_view_get_model(GTK_TREE_VIEW(view)); gtk_tree_model_get_iter(model, &iter, path); inf_gtk_browser_view_redraw_row(view, path, &iter); gtk_tree_path_free(path); } inf_signal_handlers_disconnect_by_func( G_OBJECT(expl->request), G_CALLBACK(inf_gtk_browser_view_explore_request_notify_progress_cb), expl ); inf_signal_handlers_disconnect_by_func( G_OBJECT(expl->request), G_CALLBACK(inf_gtk_browser_view_explore_request_finished_cb), expl ); gtk_tree_row_reference_free(expl->reference); g_object_unref(expl->request); expl->view_browser->explores = g_slist_remove(expl->view_browser->explores, expl); g_slice_free(InfGtkBrowserViewExplore, expl); } /* * Callbacks from browser */ static void inf_gtk_browser_view_begin_request_explore_node_cb(InfBrowser* browser, InfBrowserIter* iter, InfRequest* request, gpointer user_data) { InfGtkBrowserViewBrowser* view_browser; InfGtkBrowserView* view; GtkTreeModel* model; GtkTreeIter tree_iter; GtkTreePath* path; gboolean result; view_browser = (InfGtkBrowserViewBrowser*)user_data; view = view_browser->view; model = gtk_tree_view_get_model(GTK_TREE_VIEW(view)); result = inf_gtk_browser_model_browser_iter_to_tree_iter( INF_GTK_BROWSER_MODEL(model), browser, iter, &tree_iter ); /*printf("Begin-explore cb for view %p, result %d\n", view_browser->view, result);*/ /* The model might be a filter model that does not contain the node * being explored, so do not assert here. */ if(result == TRUE) { path = gtk_tree_model_get_path(model, &tree_iter); inf_gtk_browser_view_explore_added( view, browser, request, path, &tree_iter ); gtk_tree_path_free(path); } } static void inf_gtk_browser_view_subscribe_session_cb(InfBrowser* browser, InfBrowserIter* iter, InfSessionProxy* proxy, InfRequest* request, gpointer user_data) { InfGtkBrowserViewBrowser* view_browser; InfGtkBrowserView* view; InfSession* session; GtkTreeModel* model; GtkTreeIter tree_iter; GtkTreePath* path; gboolean result; view_browser = (InfGtkBrowserViewBrowser*)user_data; view = view_browser->view; model = gtk_tree_view_get_model(GTK_TREE_VIEW(view)); g_object_get(G_OBJECT(proxy), "session", &session, NULL); /* Note that we do not check sync-ins here. This is because sync-ins can * only be created along with new nodes, in which case we already add the * synchronization in row_inserted_cb(). Perhaps we could still * double-check here, just to be sure, though... */ if(iter != NULL && inf_session_get_status(session) == INF_SESSION_SYNCHRONIZING) { result = inf_gtk_browser_model_browser_iter_to_tree_iter( INF_GTK_BROWSER_MODEL(model), browser, iter, &tree_iter ); /* The model might be a filter model that does not contain the session * being synchronized, so do not assert here. */ if(result == TRUE) { path = gtk_tree_model_get_path(model, &tree_iter); inf_gtk_browser_view_sync_added( view, browser, proxy, path, &tree_iter ); gtk_tree_path_free(path); } } g_object_unref(session); } static void inf_gtk_browser_view_acl_changed_cb(InfBrowser* browser, const InfBrowserIter* iter, const InfAclSheetSet* sheet_set, InfRequest* request, gpointer user_data) { InfGtkBrowserViewBrowser* view_browser; InfGtkBrowserView* view; GtkTreeModel* model; GtkTreeIter tree_iter; GtkTreeIter parent_iter; GtkTreePath* path; gboolean result; const InfAclAccount* account; InfAclAccountId account_id; InfAclMask mask; InfRequest* pending_request; view_browser = (InfGtkBrowserViewBrowser*)user_data; view = view_browser->view; model = gtk_tree_view_get_model(GTK_TREE_VIEW(view)); result = inf_gtk_browser_model_browser_iter_to_tree_iter( INF_GTK_BROWSER_MODEL(model), browser, iter, &tree_iter ); /* The model might be a filter model that does not contain the session * being synchronized, so do not assert here. */ if(result == TRUE) { /* If this node is a subdirectory node, then explore it if its parent * is expanded. If it is the root node, then always explore it. */ if(gtk_tree_model_iter_parent(model, &parent_iter, &tree_iter) == TRUE) { path = gtk_tree_model_get_path(model, &parent_iter); result = gtk_tree_view_row_expanded(GTK_TREE_VIEW(view), path); gtk_tree_path_free(path); } else { result = TRUE; } account = inf_browser_get_acl_local_account(browser); inf_acl_mask_set1(&mask, INF_ACL_CAN_EXPLORE_NODE); account_id = 0; if(account != NULL) account_id = account->id; if(result == TRUE && /* row expanded or root node */ inf_browser_is_subdirectory(browser, iter) == TRUE && inf_browser_get_explored(browser, iter) == FALSE && inf_browser_check_acl(browser, iter, account_id, &mask, NULL)) { pending_request = inf_browser_get_pending_request( browser, iter, "explore-node" ); if(pending_request == NULL) inf_browser_explore(browser, iter, NULL, NULL); } /* Redraw to show the new ACL. Since the ACL might propagate recursively, * simply redraw the whole widget. */ gtk_widget_queue_draw(GTK_WIDGET(view)); } } /* * Browser management */ /* This function recursively walks down iter and all its children and * inserts running explore requests and synchronizations into the view. */ static void inf_gtk_browser_view_walk_requests(InfGtkBrowserView* view, InfBrowser* browser, InfBrowserIter* iter) { InfGtkBrowserViewPrivate* priv; InfRequest* request; GObject* object; InfSessionProxy* proxy; InfSession* session; GtkTreeModel* model; GtkTreeIter tree_iter; GtkTreePath* path; InfBrowserIter child_iter; InfXmlConnection* connection; gboolean result; priv = INF_GTK_BROWSER_VIEW_PRIVATE(view); /* TODO: Carry both path and iter through the recursion, so we do not need * to make expensive gtk_tree_model_get_path calls */ /* Hm. Perhaps this isn't a good idea after all, since normally there are * not too much ongoing syncs/explores. */ if(inf_browser_is_subdirectory(browser, iter)) { if(inf_browser_get_explored(browser, iter)) { child_iter = *iter; if(inf_browser_get_child(browser, &child_iter)) { do { inf_gtk_browser_view_walk_requests(view, browser, &child_iter); } while(inf_browser_get_next(browser, &child_iter)); } } request = inf_browser_get_pending_request(browser, iter, "explore-node"); if(request != NULL) { model = gtk_tree_view_get_model(GTK_TREE_VIEW(view)); result = inf_gtk_browser_model_browser_iter_to_tree_iter( INF_GTK_BROWSER_MODEL(model), browser, iter, &tree_iter ); /* The model might be a filter model that does not contain the node * being explored, so do not assert here. */ if(result == TRUE) { path = gtk_tree_model_get_path(model, &tree_iter); inf_gtk_browser_view_explore_added( view, browser, request, path, &tree_iter ); gtk_tree_path_free(path); } } } else if(INFC_IS_BROWSER(browser)) { /* Show synchronization status on client side only, on server side * there is nothing to report. */ proxy = INF_SESSION_PROXY( infc_browser_iter_get_sync_in(INFC_BROWSER(browser), iter) ); if(proxy == NULL) proxy = inf_browser_get_session(browser, iter); if(proxy != NULL) { g_object_get(G_OBJECT(proxy), "session", &session, NULL); connection = infc_browser_get_connection(INFC_BROWSER(browser)); g_assert(connection != NULL); if(inf_session_get_synchronization_status(session, connection) != INF_SESSION_SYNC_NONE) { model = gtk_tree_view_get_model(GTK_TREE_VIEW(view)); result = inf_gtk_browser_model_browser_iter_to_tree_iter( INF_GTK_BROWSER_MODEL(model), browser, iter, &tree_iter ); /* The model might be a filter model that does not contain the session * being synchronized, so do not assert here. */ if(result == TRUE) { path = gtk_tree_model_get_path(model, &tree_iter); inf_gtk_browser_view_sync_added( view, browser, proxy, path, &tree_iter ); gtk_tree_path_free(path); } } g_object_unref(session); } } } static void inf_gtk_browser_view_initial_root_explore(InfGtkBrowserView* view, GtkTreePath* path, GtkTreeIter* iter) { InfGtkBrowserViewPrivate* priv; InfRequest* request; GSList* initial_expansion_list; InfGtkBrowserViewBrowser* view_browser; GtkTreeModel* model; InfBrowser* browser; InfBrowserIter* browser_iter; InfBrowserStatus browser_status; const InfAclAccount* account; InfAclAccountId acc_id; InfAclMask mask; priv = INF_GTK_BROWSER_VIEW_PRIVATE(view); model = gtk_tree_view_get_model(GTK_TREE_VIEW(view)); gtk_tree_model_get( model, iter, INF_GTK_BROWSER_MODEL_COL_BROWSER, &browser, INF_GTK_BROWSER_MODEL_COL_NODE, &browser_iter, -1 ); view_browser = inf_gtk_browser_view_find_view_browser(view, browser); g_assert(view_browser != NULL); g_object_get(G_OBJECT(browser), "status", &browser_status, NULL); if(browser_status == INF_BROWSER_OPEN) { if(inf_browser_get_explored(browser, browser_iter) == FALSE) { request = inf_browser_get_pending_request( INF_BROWSER(browser), browser_iter, "explore-node" ); /* Explore root node if it is not already explored */ inf_acl_mask_set1(&mask, INF_ACL_CAN_EXPLORE_NODE); account = inf_browser_get_acl_local_account(browser); acc_id = 0; if(account != NULL) acc_id = account->id; if(request == NULL && inf_browser_check_acl(browser, browser_iter, acc_id, &mask, NULL)) { request = inf_browser_explore(browser, browser_iter, NULL, NULL); } if(view_browser->initial_root_expansion == TRUE) { /* Expand the root node */ if(!gtk_tree_model_iter_has_child(model, iter)) { /* The root node does not yet have a child. If it is not yet fully * explored (i.e., request != NULL), then remember to do it as soon * as the first note is created. Otherwise, there is nothing to * expand. */ if(request != NULL) { /* Remember to do initial root expansion when the node has been * explored. */ initial_expansion_list = g_object_steal_data( G_OBJECT(request), INF_GTK_BROWSER_VIEW_INITIAL_EXPANSION ); if(g_slist_find(initial_expansion_list, view) == NULL) { initial_expansion_list = g_slist_prepend( initial_expansion_list, view ); } g_object_set_data_full( G_OBJECT(request), INF_GTK_BROWSER_VIEW_INITIAL_EXPANSION, initial_expansion_list, (GDestroyNotify)g_slist_free ); } } else { /* We can expand it right away */ gtk_tree_view_expand_row(GTK_TREE_VIEW(view), path, FALSE); } /* Handled expansion flag, so unset, could otherwise lead to another * try of expanding the root node. */ view_browser->initial_root_expansion = FALSE; } } else { if(view_browser->initial_root_expansion == TRUE) { gtk_tree_view_expand_row(GTK_TREE_VIEW(view), path, FALSE); /* Handled expansion flag, so unset, could otherwise lead to another * try of expanding the root node. */ view_browser->initial_root_expansion = FALSE; } } } inf_browser_iter_free(browser_iter); g_object_unref(browser); } static void inf_gtk_browser_view_browser_added(InfGtkBrowserView* view, InfBrowser* browser, GtkTreePath* path, GtkTreeIter* iter) { InfGtkBrowserViewPrivate* priv; InfGtkBrowserViewBrowser* view_browser; GtkTreeModel* model; InfBrowserStatus browser_status; InfBrowserIter* browser_iter; InfDiscoveryInfo* info; priv = INF_GTK_BROWSER_VIEW_PRIVATE(view); model = gtk_tree_view_get_model(GTK_TREE_VIEW(view)); view_browser = g_slice_new(InfGtkBrowserViewBrowser); view_browser->view = view; view_browser->browser = browser; g_object_ref(browser); view_browser->explores = NULL; view_browser->syncs = NULL; view_browser->initial_root_expansion = TRUE; view_browser->reference = gtk_tree_row_reference_new_proxy( G_OBJECT(priv->column), model, path ); priv->browsers = g_slist_prepend(priv->browsers, view_browser); g_signal_connect( G_OBJECT(browser), "begin-request::explore-node", G_CALLBACK(inf_gtk_browser_view_begin_request_explore_node_cb), view_browser ); g_signal_connect_after( G_OBJECT(browser), "subscribe-session", G_CALLBACK(inf_gtk_browser_view_subscribe_session_cb), view_browser ); g_signal_connect_after( G_OBJECT(browser), "acl-changed", G_CALLBACK(inf_gtk_browser_view_acl_changed_cb), view_browser ); /* TODO: Watch a signal to be notified when a sync-in begins. */ gtk_tree_model_get( model, iter, INF_GTK_BROWSER_MODEL_COL_DISCOVERY_INFO, &info, -1 ); /* Initially expand the root node in this view if we resolved it. */ if(info != NULL && g_slist_find(priv->info_resolvs, info) != NULL) { /*printf("Set initial root expansion for view %p\n", view);*/ /* TODO: Remember to unset the flag when an error happens or the * corresponding browser is disconnected for another reason before we * actually get to explore anything. */ view_browser->initial_root_expansion = TRUE; priv->info_resolvs = g_slist_remove(priv->info_resolvs, info); } /* Initial explore if connection is already open */ g_object_get(G_OBJECT(browser), "status", &browser_status, NULL); if(browser_status == INF_BROWSER_OPEN) { gtk_tree_model_get( model, iter, INF_GTK_BROWSER_MODEL_COL_NODE, &browser_iter, -1 ); /* Look for running explore requests, insert into array of running * explore requests to show their progress. */ /* TODO: We do not need this anymore when we get insertion callbacks * from the model for each node in the newly added browser. See * inf_gtk_browser_store_set_browser_impl() in inf-gtk-browser-store.c. */ inf_gtk_browser_view_walk_requests(view, browser, browser_iter); /* Explore root node initially if not already explored */ inf_gtk_browser_view_initial_root_explore(view, path, iter); inf_browser_iter_free(browser_iter); } } static void inf_gtk_browser_view_browser_removed(InfGtkBrowserView* view, InfGtkBrowserViewBrowser* view_browser) { InfGtkBrowserViewPrivate* priv; priv = INF_GTK_BROWSER_VIEW_PRIVATE(view); while(view_browser->explores != NULL) inf_gtk_browser_view_explore_removed(view, view_browser->explores->data); while(view_browser->syncs != NULL) inf_gtk_browser_view_sync_removed(view, view_browser->syncs->data); inf_signal_handlers_disconnect_by_func( G_OBJECT(view_browser->browser), G_CALLBACK(inf_gtk_browser_view_begin_request_explore_node_cb), view_browser ); inf_signal_handlers_disconnect_by_func( G_OBJECT(view_browser->browser), G_CALLBACK(inf_gtk_browser_view_subscribe_session_cb), view_browser ); inf_signal_handlers_disconnect_by_func( G_OBJECT(view_browser->browser), G_CALLBACK(inf_gtk_browser_view_acl_changed_cb), view_browser ); gtk_tree_row_reference_free(view_browser->reference); g_object_unref(view_browser->browser); priv->browsers = g_slist_remove(priv->browsers, view_browser); g_slice_free(InfGtkBrowserViewBrowser, view_browser); } /* * TreeModel callbacks */ static void inf_gtk_browser_view_set_browser_cb(InfGtkBrowserModel* model, GtkTreePath* path, GtkTreeIter* iter, InfBrowser* old_browser, InfBrowser* new_browser, gpointer user_data) { InfGtkBrowserView* view; InfGtkBrowserViewBrowser* view_browser; view = INF_GTK_BROWSER_VIEW(user_data); /* Find the old browser for this item, if there is any, and remove it. */ view_browser = inf_gtk_browser_view_find_view_browser(view, old_browser); if(view_browser != NULL) inf_gtk_browser_view_browser_removed(view, view_browser); /* Add a view browser for the new item */ if(new_browser != NULL) inf_gtk_browser_view_browser_added(view, new_browser, path, iter); } static void inf_gtk_browser_view_row_inserted_cb(GtkTreeModel* model, GtkTreePath* path, GtkTreeIter* iter, gpointer user_data) { InfGtkBrowserView* view; InfGtkBrowserViewPrivate* priv; GtkTreeIter parent_iter; InfBrowser* browser; InfBrowserIter* browser_iter; InfRequest* request; InfGtkBrowserViewBrowser* view_browser; InfGtkBrowserViewExplore* explore; gboolean explored; GtkTreePath* parent_path; const InfAclAccount* account; InfAclAccountId acc_id; InfAclMask mask; GObject* object; InfSessionProxy* proxy; InfSession* session; InfXmlConnection* connection; view = INF_GTK_BROWSER_VIEW(user_data); priv = INF_GTK_BROWSER_VIEW_PRIVATE(view); gtk_tree_row_reference_inserted(G_OBJECT(priv->column), path); if(gtk_tree_model_iter_parent(model, &parent_iter, iter) == TRUE) { /* Inner node. Explore if the parent node is expanded. */ gtk_tree_model_get( model, iter, INF_GTK_BROWSER_MODEL_COL_BROWSER, &browser, INF_GTK_BROWSER_MODEL_COL_NODE, &browser_iter, -1 ); g_assert(browser != NULL); if(inf_browser_is_subdirectory(browser, browser_iter)) { /* Perhaps some other code already explored this. */ request = inf_browser_get_pending_request( INF_BROWSER(browser), browser_iter, "explore-node" ); if(request == NULL) { explored = inf_browser_get_explored(browser, browser_iter); inf_acl_mask_set1(&mask, INF_ACL_CAN_EXPLORE_NODE); account = inf_browser_get_acl_local_account(browser); acc_id = 0; if(account != NULL) acc_id = account->id; if(explored == FALSE && inf_browser_check_acl(browser, browser_iter, acc_id, &mask, NULL)) { parent_path = gtk_tree_path_copy(path); gtk_tree_path_up(parent_path); if(gtk_tree_view_row_expanded(GTK_TREE_VIEW(view), parent_path)) { inf_browser_explore(browser, browser_iter, NULL, NULL); } gtk_tree_path_free(parent_path); } } else { view_browser = inf_gtk_browser_view_find_view_browser(view, browser); g_assert(view_browser != NULL); explore = inf_gtk_browser_view_find_explore( view, view_browser, request ); /* TODO: The correct way to do this would probably be to ignore * the begin-explore signal of the browser if row-inserted for the * row being explored has not yet been received by the view. We * could then omit this nasty check. */ if(explore == NULL) { inf_gtk_browser_view_explore_added( view, browser, request, path, iter ); } } } else if(INFC_IS_BROWSER(browser)) { /* Show synchronization status on client side only, on server side * there is nothing to report. */ proxy = INF_SESSION_PROXY( infc_browser_iter_get_sync_in(INFC_BROWSER(browser), browser_iter) ); if(proxy == NULL) proxy = inf_browser_get_session(browser, browser_iter); if(proxy != NULL) { g_object_get(G_OBJECT(proxy), "session", &session, NULL); connection = infc_browser_get_connection(INFC_BROWSER(browser)); g_assert(connection != NULL); if(inf_session_get_synchronization_status(session, connection) != INF_SESSION_SYNC_NONE) { inf_gtk_browser_view_sync_added(view, browser, proxy, path, iter); } g_object_unref(session); } } inf_browser_iter_free(browser_iter); g_object_unref(G_OBJECT(browser)); } } static void inf_gtk_browser_view_row_changed_cb(GtkTreeModel* model, GtkTreePath* path, GtkTreeIter* iter, gpointer user_data) { InfGtkBrowserView* view; InfGtkBrowserViewPrivate* priv; GtkTreeIter parent_iter; InfGtkBrowserModelStatus status; InfDiscoveryInfo* info; InfBrowser* browser; view = INF_GTK_BROWSER_VIEW(user_data); priv = INF_GTK_BROWSER_VIEW_PRIVATE(view); if(gtk_tree_model_iter_parent(model, &parent_iter, iter) == FALSE) { gtk_tree_model_get( model, iter, INF_GTK_BROWSER_MODEL_COL_STATUS, &status, INF_GTK_BROWSER_MODEL_COL_DISCOVERY_INFO, &info, INF_GTK_BROWSER_MODEL_COL_BROWSER, &browser, -1 ); /* Explore root node as soon as the connection is ready. The second * condition is required since this might be called before * set_browser_cb. */ if(status == INF_GTK_BROWSER_MODEL_CONNECTED && inf_gtk_browser_view_find_view_browser(view, browser) != NULL) { inf_gtk_browser_view_initial_root_explore(view, path, iter); } /* Remove pending resolv when there was an error while resolving. On * success, a browser will be created and we remove the pending resolve * in the set-browser signal handler. */ if(info != NULL && status == INF_GTK_BROWSER_MODEL_ERROR) priv->info_resolvs = g_slist_remove(priv->info_resolvs, info); if(browser != NULL) g_object_unref(browser); } } static void inf_gtk_browser_view_row_deleted_cb(GtkTreeModel* model, GtkTreePath* path, gpointer user_data) { InfGtkBrowserView* view; InfGtkBrowserViewPrivate* priv; GSList* top_item; InfGtkBrowserViewBrowser* view_browser; GtkTreePath* browser_path; GSList* item; InfGtkBrowserViewExplore* explore; InfGtkBrowserViewSync* sync; view = INF_GTK_BROWSER_VIEW(user_data); priv = INF_GTK_BROWSER_VIEW_PRIVATE(view); gtk_tree_row_reference_deleted(G_OBJECT(priv->column), path); for(top_item = priv->browsers; top_item != NULL; ) { view_browser = (InfGtkBrowserViewBrowser*)top_item->data; top_item = top_item->next; if(gtk_tree_row_reference_valid(view_browser->reference) == FALSE) { inf_gtk_browser_view_browser_removed(view, view_browser); } else { /* If a child of this browser was removed, then explores and syncs * of that browser might be affected. */ browser_path = gtk_tree_row_reference_get_path(view_browser->reference); g_assert(browser_path != NULL); if(gtk_tree_path_is_descendant(path, browser_path)) { for(item = view_browser->explores; item != NULL; ) { explore = (InfGtkBrowserViewExplore*)item->data; item = item->next; if(gtk_tree_row_reference_valid(explore->reference) == FALSE) inf_gtk_browser_view_explore_removed(view, explore); } for(item = view_browser->syncs; item != NULL; ) { sync = (InfGtkBrowserViewSync*)item->data; item = item->next; if(gtk_tree_row_reference_valid(sync->reference) == FALSE) inf_gtk_browser_view_sync_removed(view, sync); } } gtk_tree_path_free(browser_path); } } } static void inf_gtk_browser_view_rows_reordered_cb(GtkTreeModel* model, GtkTreePath* path, GtkTreeIter* iter, gint* new_order, gpointer user_data) { InfGtkBrowserView* view; InfGtkBrowserViewPrivate* priv; view = INF_GTK_BROWSER_VIEW(user_data); priv = INF_GTK_BROWSER_VIEW_PRIVATE(view); gtk_tree_row_reference_reordered( G_OBJECT(priv->column), path, iter, new_order ); } /* * TreeModel management */ static void inf_gtk_browser_view_set_model(InfGtkBrowserView* view, InfGtkBrowserModel* model) { InfGtkBrowserViewPrivate* priv; GtkTreeModel* current_model; GtkTreeIter iter; InfBrowser* browser; GtkTreePath* path; priv = INF_GTK_BROWSER_VIEW_PRIVATE(view); current_model = gtk_tree_view_get_model(GTK_TREE_VIEW(view)); if(current_model != NULL) { while(priv->browsers != NULL) inf_gtk_browser_view_browser_removed(view, priv->browsers->data); /* We are no longer waiting for resolvs from that model */ g_slist_free(priv->info_resolvs); priv->info_resolvs = NULL; inf_signal_handlers_disconnect_by_func( G_OBJECT(current_model), G_CALLBACK(inf_gtk_browser_view_row_inserted_cb), view ); inf_signal_handlers_disconnect_by_func( G_OBJECT(current_model), G_CALLBACK(inf_gtk_browser_view_row_deleted_cb), view ); inf_signal_handlers_disconnect_by_func( G_OBJECT(current_model), G_CALLBACK(inf_gtk_browser_view_row_changed_cb), view ); inf_signal_handlers_disconnect_by_func( G_OBJECT(current_model), G_CALLBACK(inf_gtk_browser_view_rows_reordered_cb), view ); inf_signal_handlers_disconnect_by_func( G_OBJECT(current_model), G_CALLBACK(inf_gtk_browser_view_set_browser_cb), view ); } gtk_tree_view_set_model( GTK_TREE_VIEW(view), GTK_TREE_MODEL(model) ); if(model != NULL) { gtk_tree_view_set_search_column( GTK_TREE_VIEW(view), INF_GTK_BROWSER_MODEL_COL_NAME ); /* Add initial browsers */ if(gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter) == TRUE) { path = gtk_tree_path_new_first(); do { gtk_tree_model_get( GTK_TREE_MODEL(model), &iter, INF_GTK_BROWSER_MODEL_COL_BROWSER, &browser, -1 ); if(browser != NULL) { inf_gtk_browser_view_browser_added(view, browser, path, &iter); g_object_unref(browser); } gtk_tree_path_next(path); } while(gtk_tree_model_iter_next(GTK_TREE_MODEL(model), &iter) == TRUE); } g_signal_connect( G_OBJECT(model), "row-inserted", G_CALLBACK(inf_gtk_browser_view_row_inserted_cb), view ); g_signal_connect( G_OBJECT(model), "row-deleted", G_CALLBACK(inf_gtk_browser_view_row_deleted_cb), view ); g_signal_connect( G_OBJECT(model), "row-changed", G_CALLBACK(inf_gtk_browser_view_row_changed_cb), view ); g_signal_connect( G_OBJECT(model), "rows-reordered", G_CALLBACK(inf_gtk_browser_view_rows_reordered_cb), view ); g_signal_connect_after( G_OBJECT(model), "set-browser", G_CALLBACK(inf_gtk_browser_view_set_browser_cb), view ); } } /* * TreeView callbacks */ static void inf_gtk_browser_view_row_expanded(GtkTreeView* tree_view, GtkTreeIter* iter, GtkTreePath* path) { GtkTreeModel* model; InfBrowser* browser; InfBrowserIter* browser_iter; InfRequest* pending_request; const InfAclAccount* account; InfAclAccountId acc_id; InfAclMask mask; GtkTreeViewClass* parent_class; model = gtk_tree_view_get_model(tree_view); gtk_tree_model_get( model, iter, INF_GTK_BROWSER_MODEL_COL_BROWSER, &browser, INF_GTK_BROWSER_MODEL_COL_NODE, &browser_iter, -1 ); g_assert(browser != NULL); /* Explore all child nodes that are not yet explored */ if(inf_browser_get_child(browser, browser_iter)) { account = inf_browser_get_acl_local_account(browser); inf_acl_mask_set1(&mask, INF_ACL_CAN_EXPLORE_NODE); acc_id = 0; if(account != NULL) acc_id = account->id; do { if(inf_browser_is_subdirectory(browser, browser_iter) == TRUE && inf_browser_get_explored(browser, browser_iter) == FALSE && inf_browser_check_acl(browser, browser_iter, acc_id, &mask, NULL)) { pending_request = inf_browser_get_pending_request( browser, browser_iter, "explore-node" ); if(pending_request == NULL) inf_browser_explore(browser, browser_iter, NULL, NULL); } } while(inf_browser_get_next(browser, browser_iter)); } inf_browser_iter_free(browser_iter); g_object_unref(browser); parent_class = GTK_TREE_VIEW_CLASS(inf_gtk_browser_view_parent_class); if(parent_class->row_expanded != NULL) parent_class->row_expanded(tree_view, iter, path); } static void inf_gtk_browser_view_row_activated(GtkTreeView* tree_view, GtkTreePath* path, GtkTreeViewColumn* column) { InfGtkBrowserView* view; InfGtkBrowserViewPrivate* priv; GtkTreeModel* model; InfGtkBrowserModelStatus status; InfDiscovery* discovery; InfDiscoveryInfo* info; GtkTreeIter iter; InfBrowser* browser; InfBrowserIter* browser_iter; InfBrowserStatus browser_status; InfXmlConnection* connection; InfXmlConnectionStatus xml_status; GError* error; InfGtkBrowserViewBrowser* view_browser; GtkTreeViewClass* parent_class; view = INF_GTK_BROWSER_VIEW(tree_view); priv = INF_GTK_BROWSER_VIEW_PRIVATE(view); /* Connect to host, if not already */ if(gtk_tree_path_get_depth(path) == 1) { model = gtk_tree_view_get_model(tree_view); gtk_tree_model_get_iter(model, &iter, path); gtk_tree_model_get( model, &iter, INF_GTK_BROWSER_MODEL_COL_STATUS, &status, INF_GTK_BROWSER_MODEL_COL_DISCOVERY, &discovery, INF_GTK_BROWSER_MODEL_COL_DISCOVERY_INFO, &info, INF_GTK_BROWSER_MODEL_COL_BROWSER, &browser, -1 ); if(browser != NULL && INFC_IS_BROWSER(browser)) { g_assert(infc_browser_get_connection(INFC_BROWSER(browser)) != NULL); g_object_get(G_OBJECT(browser), "status", &browser_status, NULL); if(browser_status == INF_BROWSER_CLOSED) { connection = infc_browser_get_connection(INFC_BROWSER(browser)); g_assert(connection != NULL); g_object_get(G_OBJECT(connection), "status", &xml_status, NULL); if(xml_status == INF_XML_CONNECTION_CLOSED) { error = NULL; if(!inf_xml_connection_open(connection, &error)) { /* TODO: We can't properly report error here. Actually, we should * not do this, but just emit signal activate here, for others * to open the connection if necessary. */ g_warning("Failed to reconnect: %s\n", error->message); g_error_free(error); } view_browser = inf_gtk_browser_view_find_view_browser(view, browser); g_assert(view_browser != NULL); view_browser->initial_root_expansion = TRUE; } } } else if(discovery != NULL) { if(status == INF_GTK_BROWSER_MODEL_DISCOVERED || status == INF_GTK_BROWSER_MODEL_ERROR) { /* TODO: This method should not exist. Instead, we should just * emit ACTIVATE and make others resolve stuff there. */ inf_gtk_browser_model_resolve( INF_GTK_BROWSER_MODEL(model), discovery, info ); /* Remember that we resolved that info, to do the initial root node * expansion. */ priv->info_resolvs = g_slist_prepend(priv->info_resolvs, info); /*printf("Add info %p to info resolvs of view %p\n", info, view);*/ } } if(discovery != NULL) g_object_unref(G_OBJECT(discovery)); if(browser != NULL) g_object_unref(browser); } else { model = gtk_tree_view_get_model(tree_view); gtk_tree_model_get_iter(model, &iter, path); gtk_tree_model_get( model, &iter, INF_GTK_BROWSER_MODEL_COL_BROWSER, &browser, INF_GTK_BROWSER_MODEL_COL_NODE, &browser_iter, -1 ); if(inf_browser_is_subdirectory(browser, browser_iter)) { gtk_tree_view_expand_row(tree_view, path, FALSE); } else { /* Notify */ g_signal_emit( G_OBJECT(view), view_signals[ACTIVATE], 0, &iter ); } inf_browser_iter_free(browser_iter); g_object_unref(G_OBJECT(browser)); } parent_class = GTK_TREE_VIEW_CLASS(inf_gtk_browser_view_parent_class); if(parent_class->row_activated != NULL) parent_class->row_activated(tree_view, path, column); } static void inf_gtk_browser_view_selection_changed_cb(GtkTreeSelection* selection, gpointer user_data) { InfGtkBrowserView* view; GtkTreeIter selected_iter; view = INF_GTK_BROWSER_VIEW(user_data); if(gtk_tree_selection_get_selected(selection, NULL, &selected_iter)) g_signal_emit(view, view_signals[SELECTION_CHANGED], 0, &selected_iter); else g_signal_emit(view, view_signals[SELECTION_CHANGED], 0, NULL); } /* * Popup menu */ static void inf_gtk_browser_view_popup_menu_detach_func(GtkWidget* attach_widget, GtkMenu* menu) { } static void inf_gtk_browser_view_popup_menu_position_func(GtkMenu* menu, gint* x, gint* y, gboolean* push_in, gpointer user_data) { InfGtkBrowserView* view; InfGtkBrowserViewPrivate* priv; GdkWindow* bin_window; GdkScreen* screen; GtkRequisition menu_req; GdkRectangle monitor; gint monitor_num; gint orig_x; gint orig_y; gint height; GtkTreeSelection* selection; GtkTreeModel* model; GtkTreeIter selected_iter; GtkTreePath* selected_path; GdkRectangle cell_area; view = INF_GTK_BROWSER_VIEW(user_data); priv = INF_GTK_BROWSER_VIEW_PRIVATE(view); /* Place menu below currently selected row */ bin_window = gtk_tree_view_get_bin_window(GTK_TREE_VIEW(view)); gdk_window_get_origin(bin_window, &orig_x, &orig_y); screen = gtk_widget_get_screen(GTK_WIDGET(view)); monitor_num = gdk_screen_get_monitor_at_window(screen, bin_window); if(monitor_num < 0) monitor_num = 0; gtk_menu_set_monitor(menu, monitor_num); gdk_screen_get_monitor_geometry(screen, monitor_num, &monitor); gtk_widget_get_preferred_size(GTK_WIDGET(menu), NULL, &menu_req); height = gdk_window_get_height(bin_window); selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view)); gtk_tree_selection_get_selected(selection, &model, &selected_iter); selected_path = gtk_tree_model_get_path(model, &selected_iter); gtk_tree_view_get_cell_area( GTK_TREE_VIEW(view), selected_path, priv->column, &cell_area ); gtk_tree_path_free(selected_path); g_assert(cell_area.height > 0); if(gtk_widget_get_direction(GTK_WIDGET(view)) == GTK_TEXT_DIR_LTR) *x = orig_x + cell_area.x + cell_area.width - menu_req.width; else *x = orig_x + cell_area.x; *y = orig_y + cell_area.y + cell_area.height; /* Keep within widget */ if(*y < orig_y) *y = orig_y; if(*y > orig_y + height) *y = orig_y + height; /* Keep on screen */ if(*y + menu_req.height > monitor.y + monitor.height) *y = monitor.y + monitor.height - menu_req.height; if(*y < monitor.y) *y = monitor.y; *push_in = FALSE; } static gboolean inf_gtk_browser_view_show_popup(InfGtkBrowserView* view, guint button, /* 0 if triggered by keyboard */ guint32 time) { GtkWidget* menu; GList* children; gboolean result; menu = gtk_menu_new(); gtk_menu_attach_to_widget( GTK_MENU(menu), GTK_WIDGET(view), inf_gtk_browser_view_popup_menu_detach_func ); g_signal_emit(view, view_signals[POPULATE_POPUP], 0, menu); /* Only show menu if items have been added to it */ children = gtk_container_get_children(GTK_CONTAINER(menu)); if(children != NULL) { result = TRUE; if(button) { gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, button, time); } else { gtk_menu_popup( GTK_MENU(menu), NULL, NULL, inf_gtk_browser_view_popup_menu_position_func, view, button, time ); gtk_menu_shell_select_first(GTK_MENU_SHELL(menu), FALSE); } } else { result = FALSE; gtk_widget_destroy(menu); } g_list_free(children); return result; } static gboolean inf_gtk_browser_view_button_press_event(GtkWidget* treeview, GdkEventButton* event) { GtkTreePath* path; gboolean has_path; GtkWidgetClass* parent_class; if(event->button == 3 && event->window == gtk_tree_view_get_bin_window(GTK_TREE_VIEW(treeview))) { has_path = gtk_tree_view_get_path_at_pos( GTK_TREE_VIEW(treeview), event->x, event->y, &path, NULL, NULL, NULL ); if(has_path) { gtk_tree_selection_select_path( gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview)), path ); gtk_tree_path_free(path); return inf_gtk_browser_view_show_popup( INF_GTK_BROWSER_VIEW(treeview), event->button, event->time ); } } parent_class = GTK_WIDGET_CLASS(inf_gtk_browser_view_parent_class); return parent_class->button_press_event(treeview, event); } static gboolean inf_gtk_browser_view_key_press_event(GtkWidget* treeview, GdkEventKey* event) { GtkTreeSelection* selection; GtkTreeIter iter; GtkWidgetClass* parent_class; if(event->keyval == GDK_KEY_Menu) { selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview)); if(gtk_tree_selection_get_selected(selection, NULL, &iter)) { return inf_gtk_browser_view_show_popup( INF_GTK_BROWSER_VIEW(treeview), 0, event->time ); } } parent_class = GTK_WIDGET_CLASS(inf_gtk_browser_view_parent_class); return parent_class->key_press_event(treeview, event); } /* * CellDataFuncs */ static void inf_gtk_browser_view_icon_data_func(GtkTreeViewColumn* column, GtkCellRenderer* renderer, GtkTreeModel* model, GtkTreeIter* iter, gpointer user_data) { GtkTreeIter iter_parent; InfGtkBrowserModelStatus status; InfDiscovery* discovery; InfBrowser* browser; InfBrowserIter* browser_iter; InfAclMask mask; const InfAclAccount* account; InfAclAccountId acc_id; const gchar* icon_name; if(gtk_tree_model_iter_parent(model, &iter_parent, iter)) { /* Inner node */ gtk_tree_model_get( model, iter, INF_GTK_BROWSER_MODEL_COL_BROWSER, &browser, INF_GTK_BROWSER_MODEL_COL_NODE, &browser_iter, -1 ); /* TODO: Set error icon if an error occured? */ /* TODO: Set icon depending on note type, perhaps also on whether * we are subscribed or not. */ account = inf_browser_get_acl_local_account(browser); acc_id = 0; if(account != NULL) acc_id = account->id; if(inf_browser_is_subdirectory(browser, browser_iter)) { inf_acl_mask_set1(&mask, INF_ACL_CAN_EXPLORE_NODE); if(inf_browser_check_acl(browser, browser_iter, acc_id, &mask, NULL)) icon_name = "folder"; else /* Would be nice to have a more appropriate icon for this */ icon_name = "dialog-password"; g_object_set(G_OBJECT(renderer), "icon-name", icon_name, NULL); } else { inf_acl_mask_set1(&mask, INF_ACL_CAN_SUBSCRIBE_SESSION); if(inf_browser_check_acl(browser, browser_iter, acc_id, &mask, NULL)) icon_name = "text-x-generic"; /* appropriate? */ else /* Would be nice to have a more appropriate icon for this */ icon_name = "dialog-password"; g_object_set(G_OBJECT(renderer), "icon-name", icon_name, NULL); } inf_browser_iter_free(browser_iter); g_object_unref(G_OBJECT(browser)); } else { /* toplevel */ /* TODO: Set icon depending on discovery type (LAN, jabber, direct) */ /*gtk_tree_model_get( model, iter, INF_GTK_BROWSER_MODEL_COL_DISCOVERY, &discovery, INF_GTK_BROWSER_MODEL_COL_BROWSER, &browser, -1 );*/ gtk_tree_model_get( model, iter, INF_GTK_BROWSER_MODEL_COL_STATUS, &status, -1 ); switch(status) { case INF_GTK_BROWSER_MODEL_INVALID: /* This can happen when the cell data func is called between the * resetting of an item and its removal from the tree. But in any case * it will be removed soon, so no need to do anything here. */ icon_name = NULL; break; case INF_GTK_BROWSER_MODEL_DISCONNECTED: case INF_GTK_BROWSER_MODEL_DISCOVERED: case INF_GTK_BROWSER_MODEL_RESOLVING: case INF_GTK_BROWSER_MODEL_CONNECTING: icon_name = "network-offline"; break; case INF_GTK_BROWSER_MODEL_CONNECTED: /* TODO: Could choose to show network-transmit and/or * network-transmit-received when there is activitiy */ icon_name = "network-idle"; break; case INF_GTK_BROWSER_MODEL_ERROR: icon_name = "network-error"; break; default: g_assert_not_reached(); break; } g_object_set(G_OBJECT(renderer), "icon-name", icon_name, NULL); /*if(discovery != NULL) g_object_unref(G_OBJECT(discovery)); if(browser != NULL) g_object_unref(G_OBJECT(browser));*/ } } static void inf_gtk_browser_view_name_data_func(GtkTreeViewColumn* column, GtkCellRenderer* renderer, GtkTreeModel* model, GtkTreeIter* iter, gpointer user_data) { GtkTreeIter iter_parent; InfcBrowser* browser; InfBrowserIter* browser_iter; const gchar* name; gchar* top_name; if(gtk_tree_model_iter_parent(model, &iter_parent, iter)) { /* Inner node */ gtk_tree_model_get( model, iter, INF_GTK_BROWSER_MODEL_COL_BROWSER, &browser, INF_GTK_BROWSER_MODEL_COL_NODE, &browser_iter, -1 ); /* TODO: Use another foreground color (or even background color?) when * we are subscribed or have sent a subscription request. */ name = inf_browser_get_node_name(INF_BROWSER(browser), browser_iter); g_object_set(G_OBJECT(renderer), "text", name, NULL); inf_browser_iter_free(browser_iter); g_object_unref(G_OBJECT(browser)); } else { /* Toplevel */ gtk_tree_model_get( model, iter, INF_GTK_BROWSER_MODEL_COL_NAME, &top_name, -1 ); g_object_set(G_OBJECT(renderer), "text", top_name, NULL); g_free(top_name); } } static void inf_gtk_browser_view_progress_data_func(GtkTreeViewColumn* column, GtkCellRenderer* renderer, GtkTreeModel* model, GtkTreeIter* iter, gpointer user_data) { InfBrowser* browser; InfBrowserStatus browser_status; InfBrowserIter* browser_iter; InfRequest* request; GObject* object; InfSessionProxy* proxy; InfSession* session; InfXmlConnection* connection; gdouble progress; gboolean progress_set; progress_set = FALSE; gtk_tree_model_get( model, iter, INF_GTK_BROWSER_MODEL_COL_BROWSER, &browser, -1 ); if(browser != NULL) { g_object_get(G_OBJECT(browser), "status", &browser_status, NULL); if(browser_status == INF_BROWSER_OPEN) { gtk_tree_model_get( model, iter, INF_GTK_BROWSER_MODEL_COL_NODE, &browser_iter, -1 ); if(inf_browser_is_subdirectory(browser, browser_iter)) { request = inf_browser_get_pending_request( browser, browser_iter, "explore-node" ); if(request != NULL) { g_object_get( G_OBJECT(request), "progress", &progress, NULL ); /* Progress can be at 1.0 if the all nodes have been explored but * the request has not finished yet, since the tag by * the server has not yet arrived. In that case we still don't show * the progress bar anymore, since from the client's perspective * everything has finished and all explored nodes are usable. */ if(progress < 1.0) { g_object_set( G_OBJECT(renderer), "visible", TRUE, "value", (gint)(progress * 100 + 0.5), "text", _("Exploring..."), NULL ); progress_set = TRUE; } } } else if(INFC_IS_BROWSER(browser)) { /* Show progress of either sync-in or synchronization * due to subscription. Note that we only do this for * InfcBrowser objects, not InfdDirectory objects. For an * InfdDirectory during sync-in the node is not yet created, * and synchronization to individual clients we cannot show * easily in the GUI. */ proxy = INF_SESSION_PROXY( infc_browser_iter_get_sync_in(INFC_BROWSER(browser), browser_iter)); if(proxy == NULL) proxy = inf_browser_get_session(browser, browser_iter); if(proxy != NULL) { connection = infc_browser_get_connection(INFC_BROWSER(browser)); g_assert(connection != NULL); g_object_get(G_OBJECT(proxy), "session", &session, NULL); if(inf_session_get_synchronization_status(session, connection) != INF_SESSION_SYNC_NONE) { progress = inf_session_get_synchronization_progress( session, connection ); g_object_set( G_OBJECT(renderer), "visible", TRUE, "value", (gint)(progress * 100 + 0.5), "text", _("Synchronizing..."), NULL ); progress_set = TRUE; } g_object_unref(session); } } inf_browser_iter_free(browser_iter); } g_object_unref(browser); } if(!progress_set) { g_object_set( G_OBJECT(renderer), "visible", FALSE, NULL ); } } static void inf_gtk_browser_view_status_data_func(GtkTreeViewColumn* column, GtkCellRenderer* renderer, GtkTreeModel* model, GtkTreeIter* iter, gpointer user_data) { GtkTreeIter iter_parent; InfGtkBrowserModelStatus status; GError* error; if(gtk_tree_model_iter_parent(model, &iter_parent, iter)) { gtk_tree_model_get( model, iter, INF_GTK_BROWSER_MODEL_COL_ERROR, &error, -1 ); if(error != NULL) { g_object_set( G_OBJECT(renderer), "text", error->message, "foreground", INF_GTK_BROWSER_VIEW_ERROR_COLOR, "visible", TRUE, NULL ); } else { g_object_set(G_OBJECT(renderer), "visible", FALSE, NULL); } } else { gtk_tree_model_get( model, iter, INF_GTK_BROWSER_MODEL_COL_STATUS, &status, INF_GTK_BROWSER_MODEL_COL_ERROR, &error, -1 ); switch(status) { case INF_GTK_BROWSER_MODEL_INVALID: /* This can happen when the cell data func is called between the * resetting of an item and its removal from the tree. But in any case * it will be removed soon, so no need to do anything here. */ break; case INF_GTK_BROWSER_MODEL_DISCOVERED: case INF_GTK_BROWSER_MODEL_DISCONNECTED: g_object_set( G_OBJECT(renderer), "text", _("Not connected"), "foreground", "black", "visible", FALSE, /* Don't show */ NULL ); break; case INF_GTK_BROWSER_MODEL_RESOLVING: case INF_GTK_BROWSER_MODEL_CONNECTING: g_object_set( G_OBJECT(renderer), "text", _("Connecting..."), "foreground", "black", "visible", TRUE, NULL ); break; case INF_GTK_BROWSER_MODEL_CONNECTED: g_object_set( G_OBJECT(renderer), "text", _("Connected"), "foreground", "black", "visible", FALSE, /* Don't show */ NULL ); break; case INF_GTK_BROWSER_MODEL_ERROR: g_assert(error != NULL); g_object_set( G_OBJECT(renderer), "text", error->message, "foreground", INF_GTK_BROWSER_VIEW_ERROR_COLOR, "visible", TRUE, NULL ); break; default: g_assert_not_reached(); break; } } } /* * GObject overrides */ static void inf_gtk_browser_view_init(InfGtkBrowserView* view) { InfGtkBrowserViewPrivate* priv; GtkTreeSelection* selection; priv = INF_GTK_BROWSER_VIEW_PRIVATE(view); priv->column = gtk_tree_view_column_new(); selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view)); priv->renderer_icon = gtk_cell_renderer_pixbuf_new(); priv->renderer_name = gtk_cell_renderer_text_new(); priv->renderer_progress = gtk_cell_renderer_progress_new(); priv->renderer_status = gtk_cell_renderer_text_new(); priv->browsers = NULL; priv->info_resolvs = NULL; g_object_set(G_OBJECT(priv->renderer_status), "xpad", 10, NULL); gtk_tree_view_column_pack_start(priv->column, priv->renderer_icon, FALSE); gtk_tree_view_column_pack_start(priv->column, priv->renderer_name, FALSE); gtk_tree_view_column_pack_start( priv->column, priv->renderer_progress, FALSE ); gtk_tree_view_column_pack_start(priv->column, priv->renderer_status, TRUE); gtk_tree_view_column_set_cell_data_func( priv->column, priv->renderer_icon, inf_gtk_browser_view_icon_data_func, NULL, NULL ); gtk_tree_view_column_set_cell_data_func( priv->column, priv->renderer_name, inf_gtk_browser_view_name_data_func, NULL, NULL ); gtk_tree_view_column_set_cell_data_func( priv->column, priv->renderer_progress, inf_gtk_browser_view_progress_data_func, NULL, NULL ); gtk_tree_view_column_set_cell_data_func( priv->column, priv->renderer_status, inf_gtk_browser_view_status_data_func, NULL, NULL ); g_signal_connect( selection, "changed", G_CALLBACK(inf_gtk_browser_view_selection_changed_cb), view ); gtk_tree_view_append_column(GTK_TREE_VIEW(view), priv->column); gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), FALSE); } static void inf_gtk_browser_view_dispose(GObject* object) { InfGtkBrowserView* view; InfGtkBrowserViewPrivate* priv; view = INF_GTK_BROWSER_VIEW(object); priv = INF_GTK_BROWSER_VIEW_PRIVATE(view); inf_gtk_browser_view_set_model(view, NULL); G_OBJECT_CLASS(inf_gtk_browser_view_parent_class)->dispose(object); } static void inf_gtk_browser_view_finalize(GObject* object) { InfGtkBrowserView* view; InfGtkBrowserViewPrivate* priv; view = INF_GTK_BROWSER_VIEW(object); priv = INF_GTK_BROWSER_VIEW_PRIVATE(view); g_assert(priv->browsers == NULL); G_OBJECT_CLASS(inf_gtk_browser_view_parent_class)->finalize(object); } static void inf_gtk_browser_view_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfGtkBrowserView* view; view = INF_GTK_BROWSER_VIEW(object); switch(prop_id) { case PROP_MODEL: if (g_value_get_object(value) != NULL) g_assert(INF_GTK_IS_BROWSER_MODEL(g_value_get_object(value))); inf_gtk_browser_view_set_model( view, INF_GTK_BROWSER_MODEL(g_value_get_object(value)) ); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void inf_gtk_browser_view_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfGtkBrowserView* view; view = INF_GTK_BROWSER_VIEW(object); switch(prop_id) { case PROP_MODEL: g_value_set_object( value, G_OBJECT(gtk_tree_view_get_model(GTK_TREE_VIEW(view))) ); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } /* * GtkObject / GtkWidget overrides */ static void inf_gtk_browser_view_destroy(GtkWidget* object) { InfGtkBrowserView* view; InfGtkBrowserViewPrivate* priv; view = INF_GTK_BROWSER_VIEW(object); priv = INF_GTK_BROWSER_VIEW_PRIVATE(view); inf_gtk_browser_view_set_model(view, NULL); if(GTK_WIDGET_CLASS(inf_gtk_browser_view_parent_class)->destroy) GTK_WIDGET_CLASS(inf_gtk_browser_view_parent_class)->destroy(object); } /* * GType registration */ static void inf_gtk_browser_view_class_init(InfGtkBrowserViewClass* view_class) { GObjectClass* object_class; GtkWidgetClass* widget_class; GtkTreeViewClass* tree_class; object_class = G_OBJECT_CLASS(view_class); widget_class = GTK_WIDGET_CLASS(view_class); tree_class = GTK_TREE_VIEW_CLASS(view_class); object_class->dispose = inf_gtk_browser_view_dispose; object_class->finalize = inf_gtk_browser_view_finalize; object_class->set_property = inf_gtk_browser_view_set_property; object_class->get_property = inf_gtk_browser_view_get_property; widget_class->destroy = inf_gtk_browser_view_destroy; widget_class->button_press_event = inf_gtk_browser_view_button_press_event; widget_class->key_press_event = inf_gtk_browser_view_key_press_event; tree_class->row_expanded = inf_gtk_browser_view_row_expanded; tree_class->row_activated = inf_gtk_browser_view_row_activated; view_class->activate = NULL; view_class->selection_changed = NULL; view_class->populate_popup = NULL; g_object_class_override_property(object_class, PROP_MODEL, "model"); view_signals[ACTIVATE] = g_signal_new( "activate", G_TYPE_FROM_CLASS(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfGtkBrowserViewClass, activate), NULL, NULL, g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE, 1, GTK_TYPE_TREE_ITER | G_SIGNAL_TYPE_STATIC_SCOPE ); view_signals[SELECTION_CHANGED] = g_signal_new( "selection-changed", G_TYPE_FROM_CLASS(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfGtkBrowserViewClass, selection_changed), NULL, NULL, g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE, 1, GTK_TYPE_TREE_ITER | G_SIGNAL_TYPE_STATIC_SCOPE ); view_signals[POPULATE_POPUP] = g_signal_new( "populate-popup", G_TYPE_FROM_CLASS(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfGtkBrowserViewClass, populate_popup), NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GTK_TYPE_MENU ); } /* * Public API. */ /** * inf_gtk_browser_view_new: (constructor) * * Creates a new #InfGtkBrowserView. * * Returns: (transfer floating): A new #InfGtkBrowserView. **/ GtkWidget* inf_gtk_browser_view_new(void) { GObject* object; object = g_object_new(INF_GTK_TYPE_BROWSER_VIEW, NULL); return GTK_WIDGET(object); } /** * inf_gtk_browser_view_new_with_model: (constructor) * @model: A #InfGtkBrowserModel. * * Creates a new #InfGtkBrowserView showing @model. * * Returns: (transfer floating): A new #InfGtkBrowserView. **/ GtkWidget* inf_gtk_browser_view_new_with_model(InfGtkBrowserModel* model) { GObject* object; object = g_object_new(INF_GTK_TYPE_BROWSER_VIEW, "model", model, NULL); return GTK_WIDGET(object); } /** * inf_gtk_browser_view_get_selected: * @view: A #InfGtkBrowserView. * @iter: (out): An uninitialized #GtkTreeIter. * * Sets @iter to point to the currently selected row in the browser view. If * no row is selected, @iter is left untouched and %FALSE is returned. * * Returns: Whether @iter was set. **/ gboolean inf_gtk_browser_view_get_selected(InfGtkBrowserView* view, GtkTreeIter* iter) { GtkTreeSelection* selection; g_return_val_if_fail(INF_GTK_IS_BROWSER_VIEW(view), FALSE); selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view)); return gtk_tree_selection_get_selected(selection, NULL, iter); } /** * inf_gtk_browser_view_set_selected: * @view: A #InfGtkBrowserView. * @iter: (transfer none): A #GtkTreeIter pointing to a row in @view. * * Sets the currently selected row to be @iter. If necessary, rows will be * expanded so that @iter is visible. */ void inf_gtk_browser_view_set_selected(InfGtkBrowserView* view, GtkTreeIter* iter) { GtkTreeSelection* selection; GtkTreePath* path; g_return_if_fail(INF_GTK_IS_BROWSER_VIEW(view)); g_return_if_fail(iter != NULL); selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view)); path = gtk_tree_model_get_path( gtk_tree_view_get_model(GTK_TREE_VIEW(view)), iter ); g_assert(path != NULL); gtk_tree_view_expand_to_path(GTK_TREE_VIEW(view), path); gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(view), path, NULL, FALSE, 0.0f, 0.0f); gtk_tree_path_free(path); gtk_tree_selection_select_iter(selection, iter); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfgtk/PaxHeaders.26529/Makefile.in0000644000000000000000000000013213051241010017604 xustar0030 mtime=1487225352.021149426 30 atime=1487225352.021149426 30 ctime=1488261589.308138392 libinfinity-0.7.1/libinfgtk/Makefile.in0000644000175000017500000014476013051241010020352 0ustar00arminarmin00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 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__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) 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@ @HAVE_INTROSPECTION_TRUE@am__append_1 = \ @HAVE_INTROSPECTION_TRUE@ $(gir_DATA) \ @HAVE_INTROSPECTION_TRUE@ $(typelib_DATA) subdir = libinfgtk ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/gtk-doc.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(libinfgtk_0_7_la_HEADERS) \ $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/libinfinity/inf-config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(girdir)" \ "$(DESTDIR)$(typelibdir)" "$(DESTDIR)$(libinfgtk_0_7_ladir)" LTLIBRARIES = $(lib_LTLIBRARIES) am__DEPENDENCIES_1 = am__DEPENDENCIES_2 = ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) libinfgtk_0_7_la_DEPENDENCIES = $(am__DEPENDENCIES_2) am__objects_1 = libinfgtk_0_7_la-inf-gtk-account-creation-dialog.lo \ libinfgtk_0_7_la-inf-gtk-acl-sheet-view.lo \ libinfgtk_0_7_la-inf-gtk-browser-model.lo \ libinfgtk_0_7_la-inf-gtk-browser-model-filter.lo \ libinfgtk_0_7_la-inf-gtk-browser-model-sort.lo \ libinfgtk_0_7_la-inf-gtk-browser-store.lo \ libinfgtk_0_7_la-inf-gtk-browser-view.lo \ libinfgtk_0_7_la-inf-gtk-certificate-dialog.lo \ libinfgtk_0_7_la-inf-gtk-certificate-manager.lo \ libinfgtk_0_7_la-inf-gtk-certificate-view.lo \ libinfgtk_0_7_la-inf-gtk-chat.lo \ libinfgtk_0_7_la-inf-gtk-connection-view.lo \ libinfgtk_0_7_la-inf-gtk-io.lo \ libinfgtk_0_7_la-inf-gtk-permissions-dialog.lo \ libinfgtk_0_7_la-inf-gtk-resources.lo am_libinfgtk_0_7_la_OBJECTS = $(am__objects_1) libinfgtk_0_7_la_OBJECTS = $(am_libinfgtk_0_7_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libinfgtk_0_7_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libinfgtk_0_7_la_LDFLAGS) $(LDFLAGS) \ -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) -I$(top_builddir)/libinfinity 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_CC_1 = 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_CCLD_1 = SOURCES = $(libinfgtk_0_7_la_SOURCES) DIST_SOURCES = $(libinfgtk_0_7_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(gir_DATA) $(typelib_DATA) HEADERS = $(libinfgtk_0_7_la_HEADERS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ 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@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIRNAME = @DATADIRNAME@ 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@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ GTKDOC_CHECK = @GTKDOC_CHECK@ GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ GTKDOC_MKPDF = @GTKDOC_MKPDF@ GTKDOC_REBASE = @GTKDOC_REBASE@ HTML_DIR = @HTML_DIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INSTOBJEXT = @INSTOBJEXT@ INTLLIBS = @INTLLIBS@ INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBINFINITY_API_VERSION = @LIBINFINITY_API_VERSION@ LIBINFINITY_LIBTOOL_VERSION = @LIBINFINITY_LIBTOOL_VERSION@ LIBINFINITY_VERSION = @LIBINFINITY_VERSION@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGFMT_OPTS = @MSGFMT_OPTS@ 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@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ 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@ avahi_CFLAGS = @avahi_CFLAGS@ avahi_LIBS = @avahi_LIBS@ 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@ gio_CFLAGS = @gio_CFLAGS@ gio_LIBS = @gio_LIBS@ gtk_requirement = @gtk_requirement@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infgtk_CFLAGS = @infgtk_CFLAGS@ infgtk_LIBS = @infgtk_LIBS@ infinity_CFLAGS = @infinity_CFLAGS@ infinity_LIBS = @infinity_LIBS@ infinoted_CFLAGS = @infinoted_CFLAGS@ infinoted_LIBS = @infinoted_LIBS@ infodir = @infodir@ inftext_CFLAGS = @inftext_CFLAGS@ inftext_LIBS = @inftext_LIBS@ inftextgtk_CFLAGS = @inftextgtk_CFLAGS@ inftextgtk_LIBS = @inftextgtk_LIBS@ install_sh = @install_sh@ libdaemon_CFLAGS = @libdaemon_CFLAGS@ libdaemon_LIBS = @libdaemon_LIBS@ 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@ runstatedir = @runstatedir@ 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@ # TODO: Find a way to have the version number set automatically. lib_LTLIBRARIES = libinfgtk-0.7.la cppflags = \ -I$(top_srcdir) \ $(infgtk_CFLAGS) \ $(infinity_CFLAGS) ldflags = \ -no-undefined \ -version-info $(LIBINFINITY_LIBTOOL_VERSION) libadd = \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(infgtk_LIBS) \ $(infinity_LIBS) headers = \ inf-gtk-account-creation-dialog.h \ inf-gtk-acl-sheet-view.h \ inf-gtk-browser-model.h \ inf-gtk-browser-model-filter.h \ inf-gtk-browser-model-sort.h \ inf-gtk-browser-store.h \ inf-gtk-browser-view.h \ inf-gtk-certificate-dialog.h \ inf-gtk-certificate-manager.h \ inf-gtk-certificate-view.h \ inf-gtk-chat.h \ inf-gtk-connection-view.h \ inf-gtk-io.h \ inf-gtk-permissions-dialog.h \ inf-gtk-resources.h sources = \ inf-gtk-account-creation-dialog.c \ inf-gtk-acl-sheet-view.c \ inf-gtk-browser-model.c \ inf-gtk-browser-model-filter.c \ inf-gtk-browser-model-sort.c \ inf-gtk-browser-store.c \ inf-gtk-browser-view.c \ inf-gtk-certificate-dialog.c \ inf-gtk-certificate-manager.c \ inf-gtk-certificate-view.c \ inf-gtk-chat.c \ inf-gtk-connection-view.c \ inf-gtk-io.c \ inf-gtk-permissions-dialog.c \ inf-gtk-resources.c resources = \ resources/ui/infgtkaccountcreationdialog.ui \ resources/ui/infgtkaclsheetview.ui \ resources/ui/infgtkcertificatedialog.ui \ resources/ui/infgtkcertificateview.ui \ resources/ui/infgtkchat.ui \ resources/ui/infgtkconnectionview.ui \ resources/ui/infgtkpermissionsdialog.ui BUILT_SOURCES = inf-gtk-resources.h inf-gtk-resources.c CLEANFILES = inf-gtk-resources.h inf-gtk-resources.c $(am__append_1) libinfgtk_0_7_la_CPPFLAGS = $(cppflags) libinfgtk_0_7_la_LDFLAGS = $(ldflags) libinfgtk_0_7_la_LIBADD = $(libadd) libinfgtk_0_7_la_HEADERS = $(headers) libinfgtk_0_7_la_SOURCES = $(sources) libinfgtk_0_7_ladir = \ $(includedir)/libinfgtk-$(LIBINFINITY_API_VERSION)/libinfgtk EXTRA_DIST = \ resources/infgtk.gresources.xml \ $(resources) @HAVE_INTROSPECTION_TRUE@INTROSPECTION_GIRS = InfGtk-0.7.gir @HAVE_INTROSPECTION_TRUE@INTROSPECTION_SCANNER_ENV = CC="${CC}" @HAVE_INTROSPECTION_TRUE@INTROSPECTION_COMPILER_ARGS = \ @HAVE_INTROSPECTION_TRUE@ --includedir=${top_srcdir}/libinfinity \ @HAVE_INTROSPECTION_TRUE@ --includedir=${top_builddir}/libinfinity @HAVE_INTROSPECTION_TRUE@InfGtk_0_7_gir_SCANNERFLAGS = \ @HAVE_INTROSPECTION_TRUE@ -I${top_srcdir} \ @HAVE_INTROSPECTION_TRUE@ --add-include-path=$(top_srcdir)/libinfinity \ @HAVE_INTROSPECTION_TRUE@ --add-include-path=$(top_builddir)/libinfinity \ @HAVE_INTROSPECTION_TRUE@ -n InfGtk \ @HAVE_INTROSPECTION_TRUE@ --identifier-prefix=InfGtk @HAVE_INTROSPECTION_TRUE@InfGtk_0_7_gir_NAMESPACE = InfGtk @HAVE_INTROSPECTION_TRUE@InfGtk_0_7_gir_VERSION = 0.7 @HAVE_INTROSPECTION_TRUE@InfGtk_0_7_gir_CFLAGS = $(infgtk_CFLAGS) $(infinity_CFLAGS) @HAVE_INTROSPECTION_TRUE@InfGtk_0_7_gir_LIBS = libinfgtk-0.7.la @HAVE_INTROSPECTION_TRUE@InfGtk_0_7_gir_FILES = \ @HAVE_INTROSPECTION_TRUE@ $(libinfgtk_0_7_la_SOURCES) \ @HAVE_INTROSPECTION_TRUE@ $(libinfgtk_0_7_la_HEADERS) @HAVE_INTROSPECTION_TRUE@InfGtk_0_7_gir_INCLUDES = Infinity-0.7 Gtk-3.0 @HAVE_INTROSPECTION_TRUE@InfGtk_0_7_gir_PACKAGES = gtk+-3.0 @HAVE_INTROSPECTION_TRUE@InfGtk_0_7_gir_EXPORT_PACKAGES = libinfgtk-0.7 @HAVE_INTROSPECTION_TRUE@girdir = $(datadir)/gir-1.0 @HAVE_INTROSPECTION_TRUE@gir_DATA = InfGtk-0.7.gir @HAVE_INTROSPECTION_TRUE@typelibdir = $(libdir)/girepository-1.0 @HAVE_INTROSPECTION_TRUE@typelib_DATA = InfGtk-0.7.typelib all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(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) --foreign libinfgtk/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign libinfgtk/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: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libinfgtk-0.7.la: $(libinfgtk_0_7_la_OBJECTS) $(libinfgtk_0_7_la_DEPENDENCIES) $(EXTRA_libinfgtk_0_7_la_DEPENDENCIES) $(AM_V_CCLD)$(libinfgtk_0_7_la_LINK) -rpath $(libdir) $(libinfgtk_0_7_la_OBJECTS) $(libinfgtk_0_7_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libinfgtk_0_7_la-inf-gtk-account-creation-dialog.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libinfgtk_0_7_la-inf-gtk-acl-sheet-view.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libinfgtk_0_7_la-inf-gtk-browser-model-filter.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libinfgtk_0_7_la-inf-gtk-browser-model-sort.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libinfgtk_0_7_la-inf-gtk-browser-model.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libinfgtk_0_7_la-inf-gtk-browser-store.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libinfgtk_0_7_la-inf-gtk-browser-view.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libinfgtk_0_7_la-inf-gtk-certificate-dialog.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libinfgtk_0_7_la-inf-gtk-certificate-manager.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libinfgtk_0_7_la-inf-gtk-certificate-view.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libinfgtk_0_7_la-inf-gtk-chat.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libinfgtk_0_7_la-inf-gtk-connection-view.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libinfgtk_0_7_la-inf-gtk-io.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libinfgtk_0_7_la-inf-gtk-permissions-dialog.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libinfgtk_0_7_la-inf-gtk-resources.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.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 -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.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 -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.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 $@ $< libinfgtk_0_7_la-inf-gtk-account-creation-dialog.lo: inf-gtk-account-creation-dialog.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfgtk_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libinfgtk_0_7_la-inf-gtk-account-creation-dialog.lo -MD -MP -MF $(DEPDIR)/libinfgtk_0_7_la-inf-gtk-account-creation-dialog.Tpo -c -o libinfgtk_0_7_la-inf-gtk-account-creation-dialog.lo `test -f 'inf-gtk-account-creation-dialog.c' || echo '$(srcdir)/'`inf-gtk-account-creation-dialog.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libinfgtk_0_7_la-inf-gtk-account-creation-dialog.Tpo $(DEPDIR)/libinfgtk_0_7_la-inf-gtk-account-creation-dialog.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='inf-gtk-account-creation-dialog.c' object='libinfgtk_0_7_la-inf-gtk-account-creation-dialog.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) $(libinfgtk_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libinfgtk_0_7_la-inf-gtk-account-creation-dialog.lo `test -f 'inf-gtk-account-creation-dialog.c' || echo '$(srcdir)/'`inf-gtk-account-creation-dialog.c libinfgtk_0_7_la-inf-gtk-acl-sheet-view.lo: inf-gtk-acl-sheet-view.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfgtk_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libinfgtk_0_7_la-inf-gtk-acl-sheet-view.lo -MD -MP -MF $(DEPDIR)/libinfgtk_0_7_la-inf-gtk-acl-sheet-view.Tpo -c -o libinfgtk_0_7_la-inf-gtk-acl-sheet-view.lo `test -f 'inf-gtk-acl-sheet-view.c' || echo '$(srcdir)/'`inf-gtk-acl-sheet-view.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libinfgtk_0_7_la-inf-gtk-acl-sheet-view.Tpo $(DEPDIR)/libinfgtk_0_7_la-inf-gtk-acl-sheet-view.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='inf-gtk-acl-sheet-view.c' object='libinfgtk_0_7_la-inf-gtk-acl-sheet-view.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) $(libinfgtk_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libinfgtk_0_7_la-inf-gtk-acl-sheet-view.lo `test -f 'inf-gtk-acl-sheet-view.c' || echo '$(srcdir)/'`inf-gtk-acl-sheet-view.c libinfgtk_0_7_la-inf-gtk-browser-model.lo: inf-gtk-browser-model.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfgtk_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libinfgtk_0_7_la-inf-gtk-browser-model.lo -MD -MP -MF $(DEPDIR)/libinfgtk_0_7_la-inf-gtk-browser-model.Tpo -c -o libinfgtk_0_7_la-inf-gtk-browser-model.lo `test -f 'inf-gtk-browser-model.c' || echo '$(srcdir)/'`inf-gtk-browser-model.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libinfgtk_0_7_la-inf-gtk-browser-model.Tpo $(DEPDIR)/libinfgtk_0_7_la-inf-gtk-browser-model.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='inf-gtk-browser-model.c' object='libinfgtk_0_7_la-inf-gtk-browser-model.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) $(libinfgtk_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libinfgtk_0_7_la-inf-gtk-browser-model.lo `test -f 'inf-gtk-browser-model.c' || echo '$(srcdir)/'`inf-gtk-browser-model.c libinfgtk_0_7_la-inf-gtk-browser-model-filter.lo: inf-gtk-browser-model-filter.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfgtk_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libinfgtk_0_7_la-inf-gtk-browser-model-filter.lo -MD -MP -MF $(DEPDIR)/libinfgtk_0_7_la-inf-gtk-browser-model-filter.Tpo -c -o libinfgtk_0_7_la-inf-gtk-browser-model-filter.lo `test -f 'inf-gtk-browser-model-filter.c' || echo '$(srcdir)/'`inf-gtk-browser-model-filter.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libinfgtk_0_7_la-inf-gtk-browser-model-filter.Tpo $(DEPDIR)/libinfgtk_0_7_la-inf-gtk-browser-model-filter.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='inf-gtk-browser-model-filter.c' object='libinfgtk_0_7_la-inf-gtk-browser-model-filter.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) $(libinfgtk_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libinfgtk_0_7_la-inf-gtk-browser-model-filter.lo `test -f 'inf-gtk-browser-model-filter.c' || echo '$(srcdir)/'`inf-gtk-browser-model-filter.c libinfgtk_0_7_la-inf-gtk-browser-model-sort.lo: inf-gtk-browser-model-sort.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfgtk_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libinfgtk_0_7_la-inf-gtk-browser-model-sort.lo -MD -MP -MF $(DEPDIR)/libinfgtk_0_7_la-inf-gtk-browser-model-sort.Tpo -c -o libinfgtk_0_7_la-inf-gtk-browser-model-sort.lo `test -f 'inf-gtk-browser-model-sort.c' || echo '$(srcdir)/'`inf-gtk-browser-model-sort.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libinfgtk_0_7_la-inf-gtk-browser-model-sort.Tpo $(DEPDIR)/libinfgtk_0_7_la-inf-gtk-browser-model-sort.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='inf-gtk-browser-model-sort.c' object='libinfgtk_0_7_la-inf-gtk-browser-model-sort.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) $(libinfgtk_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libinfgtk_0_7_la-inf-gtk-browser-model-sort.lo `test -f 'inf-gtk-browser-model-sort.c' || echo '$(srcdir)/'`inf-gtk-browser-model-sort.c libinfgtk_0_7_la-inf-gtk-browser-store.lo: inf-gtk-browser-store.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfgtk_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libinfgtk_0_7_la-inf-gtk-browser-store.lo -MD -MP -MF $(DEPDIR)/libinfgtk_0_7_la-inf-gtk-browser-store.Tpo -c -o libinfgtk_0_7_la-inf-gtk-browser-store.lo `test -f 'inf-gtk-browser-store.c' || echo '$(srcdir)/'`inf-gtk-browser-store.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libinfgtk_0_7_la-inf-gtk-browser-store.Tpo $(DEPDIR)/libinfgtk_0_7_la-inf-gtk-browser-store.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='inf-gtk-browser-store.c' object='libinfgtk_0_7_la-inf-gtk-browser-store.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) $(libinfgtk_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libinfgtk_0_7_la-inf-gtk-browser-store.lo `test -f 'inf-gtk-browser-store.c' || echo '$(srcdir)/'`inf-gtk-browser-store.c libinfgtk_0_7_la-inf-gtk-browser-view.lo: inf-gtk-browser-view.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfgtk_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libinfgtk_0_7_la-inf-gtk-browser-view.lo -MD -MP -MF $(DEPDIR)/libinfgtk_0_7_la-inf-gtk-browser-view.Tpo -c -o libinfgtk_0_7_la-inf-gtk-browser-view.lo `test -f 'inf-gtk-browser-view.c' || echo '$(srcdir)/'`inf-gtk-browser-view.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libinfgtk_0_7_la-inf-gtk-browser-view.Tpo $(DEPDIR)/libinfgtk_0_7_la-inf-gtk-browser-view.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='inf-gtk-browser-view.c' object='libinfgtk_0_7_la-inf-gtk-browser-view.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) $(libinfgtk_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libinfgtk_0_7_la-inf-gtk-browser-view.lo `test -f 'inf-gtk-browser-view.c' || echo '$(srcdir)/'`inf-gtk-browser-view.c libinfgtk_0_7_la-inf-gtk-certificate-dialog.lo: inf-gtk-certificate-dialog.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfgtk_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libinfgtk_0_7_la-inf-gtk-certificate-dialog.lo -MD -MP -MF $(DEPDIR)/libinfgtk_0_7_la-inf-gtk-certificate-dialog.Tpo -c -o libinfgtk_0_7_la-inf-gtk-certificate-dialog.lo `test -f 'inf-gtk-certificate-dialog.c' || echo '$(srcdir)/'`inf-gtk-certificate-dialog.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libinfgtk_0_7_la-inf-gtk-certificate-dialog.Tpo $(DEPDIR)/libinfgtk_0_7_la-inf-gtk-certificate-dialog.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='inf-gtk-certificate-dialog.c' object='libinfgtk_0_7_la-inf-gtk-certificate-dialog.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) $(libinfgtk_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libinfgtk_0_7_la-inf-gtk-certificate-dialog.lo `test -f 'inf-gtk-certificate-dialog.c' || echo '$(srcdir)/'`inf-gtk-certificate-dialog.c libinfgtk_0_7_la-inf-gtk-certificate-manager.lo: inf-gtk-certificate-manager.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfgtk_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libinfgtk_0_7_la-inf-gtk-certificate-manager.lo -MD -MP -MF $(DEPDIR)/libinfgtk_0_7_la-inf-gtk-certificate-manager.Tpo -c -o libinfgtk_0_7_la-inf-gtk-certificate-manager.lo `test -f 'inf-gtk-certificate-manager.c' || echo '$(srcdir)/'`inf-gtk-certificate-manager.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libinfgtk_0_7_la-inf-gtk-certificate-manager.Tpo $(DEPDIR)/libinfgtk_0_7_la-inf-gtk-certificate-manager.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='inf-gtk-certificate-manager.c' object='libinfgtk_0_7_la-inf-gtk-certificate-manager.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) $(libinfgtk_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libinfgtk_0_7_la-inf-gtk-certificate-manager.lo `test -f 'inf-gtk-certificate-manager.c' || echo '$(srcdir)/'`inf-gtk-certificate-manager.c libinfgtk_0_7_la-inf-gtk-certificate-view.lo: inf-gtk-certificate-view.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfgtk_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libinfgtk_0_7_la-inf-gtk-certificate-view.lo -MD -MP -MF $(DEPDIR)/libinfgtk_0_7_la-inf-gtk-certificate-view.Tpo -c -o libinfgtk_0_7_la-inf-gtk-certificate-view.lo `test -f 'inf-gtk-certificate-view.c' || echo '$(srcdir)/'`inf-gtk-certificate-view.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libinfgtk_0_7_la-inf-gtk-certificate-view.Tpo $(DEPDIR)/libinfgtk_0_7_la-inf-gtk-certificate-view.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='inf-gtk-certificate-view.c' object='libinfgtk_0_7_la-inf-gtk-certificate-view.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) $(libinfgtk_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libinfgtk_0_7_la-inf-gtk-certificate-view.lo `test -f 'inf-gtk-certificate-view.c' || echo '$(srcdir)/'`inf-gtk-certificate-view.c libinfgtk_0_7_la-inf-gtk-chat.lo: inf-gtk-chat.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfgtk_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libinfgtk_0_7_la-inf-gtk-chat.lo -MD -MP -MF $(DEPDIR)/libinfgtk_0_7_la-inf-gtk-chat.Tpo -c -o libinfgtk_0_7_la-inf-gtk-chat.lo `test -f 'inf-gtk-chat.c' || echo '$(srcdir)/'`inf-gtk-chat.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libinfgtk_0_7_la-inf-gtk-chat.Tpo $(DEPDIR)/libinfgtk_0_7_la-inf-gtk-chat.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='inf-gtk-chat.c' object='libinfgtk_0_7_la-inf-gtk-chat.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) $(libinfgtk_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libinfgtk_0_7_la-inf-gtk-chat.lo `test -f 'inf-gtk-chat.c' || echo '$(srcdir)/'`inf-gtk-chat.c libinfgtk_0_7_la-inf-gtk-connection-view.lo: inf-gtk-connection-view.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfgtk_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libinfgtk_0_7_la-inf-gtk-connection-view.lo -MD -MP -MF $(DEPDIR)/libinfgtk_0_7_la-inf-gtk-connection-view.Tpo -c -o libinfgtk_0_7_la-inf-gtk-connection-view.lo `test -f 'inf-gtk-connection-view.c' || echo '$(srcdir)/'`inf-gtk-connection-view.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libinfgtk_0_7_la-inf-gtk-connection-view.Tpo $(DEPDIR)/libinfgtk_0_7_la-inf-gtk-connection-view.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='inf-gtk-connection-view.c' object='libinfgtk_0_7_la-inf-gtk-connection-view.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) $(libinfgtk_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libinfgtk_0_7_la-inf-gtk-connection-view.lo `test -f 'inf-gtk-connection-view.c' || echo '$(srcdir)/'`inf-gtk-connection-view.c libinfgtk_0_7_la-inf-gtk-io.lo: inf-gtk-io.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfgtk_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libinfgtk_0_7_la-inf-gtk-io.lo -MD -MP -MF $(DEPDIR)/libinfgtk_0_7_la-inf-gtk-io.Tpo -c -o libinfgtk_0_7_la-inf-gtk-io.lo `test -f 'inf-gtk-io.c' || echo '$(srcdir)/'`inf-gtk-io.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libinfgtk_0_7_la-inf-gtk-io.Tpo $(DEPDIR)/libinfgtk_0_7_la-inf-gtk-io.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='inf-gtk-io.c' object='libinfgtk_0_7_la-inf-gtk-io.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) $(libinfgtk_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libinfgtk_0_7_la-inf-gtk-io.lo `test -f 'inf-gtk-io.c' || echo '$(srcdir)/'`inf-gtk-io.c libinfgtk_0_7_la-inf-gtk-permissions-dialog.lo: inf-gtk-permissions-dialog.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfgtk_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libinfgtk_0_7_la-inf-gtk-permissions-dialog.lo -MD -MP -MF $(DEPDIR)/libinfgtk_0_7_la-inf-gtk-permissions-dialog.Tpo -c -o libinfgtk_0_7_la-inf-gtk-permissions-dialog.lo `test -f 'inf-gtk-permissions-dialog.c' || echo '$(srcdir)/'`inf-gtk-permissions-dialog.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libinfgtk_0_7_la-inf-gtk-permissions-dialog.Tpo $(DEPDIR)/libinfgtk_0_7_la-inf-gtk-permissions-dialog.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='inf-gtk-permissions-dialog.c' object='libinfgtk_0_7_la-inf-gtk-permissions-dialog.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) $(libinfgtk_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libinfgtk_0_7_la-inf-gtk-permissions-dialog.lo `test -f 'inf-gtk-permissions-dialog.c' || echo '$(srcdir)/'`inf-gtk-permissions-dialog.c libinfgtk_0_7_la-inf-gtk-resources.lo: inf-gtk-resources.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfgtk_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libinfgtk_0_7_la-inf-gtk-resources.lo -MD -MP -MF $(DEPDIR)/libinfgtk_0_7_la-inf-gtk-resources.Tpo -c -o libinfgtk_0_7_la-inf-gtk-resources.lo `test -f 'inf-gtk-resources.c' || echo '$(srcdir)/'`inf-gtk-resources.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libinfgtk_0_7_la-inf-gtk-resources.Tpo $(DEPDIR)/libinfgtk_0_7_la-inf-gtk-resources.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='inf-gtk-resources.c' object='libinfgtk_0_7_la-inf-gtk-resources.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) $(libinfgtk_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libinfgtk_0_7_la-inf-gtk-resources.lo `test -f 'inf-gtk-resources.c' || echo '$(srcdir)/'`inf-gtk-resources.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-girDATA: $(gir_DATA) @$(NORMAL_INSTALL) @list='$(gir_DATA)'; test -n "$(girdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(girdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(girdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(girdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(girdir)" || exit $$?; \ done uninstall-girDATA: @$(NORMAL_UNINSTALL) @list='$(gir_DATA)'; test -n "$(girdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(girdir)'; $(am__uninstall_files_from_dir) install-typelibDATA: $(typelib_DATA) @$(NORMAL_INSTALL) @list='$(typelib_DATA)'; test -n "$(typelibdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(typelibdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(typelibdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(typelibdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(typelibdir)" || exit $$?; \ done uninstall-typelibDATA: @$(NORMAL_UNINSTALL) @list='$(typelib_DATA)'; test -n "$(typelibdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(typelibdir)'; $(am__uninstall_files_from_dir) install-libinfgtk_0_7_laHEADERS: $(libinfgtk_0_7_la_HEADERS) @$(NORMAL_INSTALL) @list='$(libinfgtk_0_7_la_HEADERS)'; test -n "$(libinfgtk_0_7_ladir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libinfgtk_0_7_ladir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libinfgtk_0_7_ladir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libinfgtk_0_7_ladir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(libinfgtk_0_7_ladir)" || exit $$?; \ done uninstall-libinfgtk_0_7_laHEADERS: @$(NORMAL_UNINSTALL) @list='$(libinfgtk_0_7_la_HEADERS)'; test -n "$(libinfgtk_0_7_ladir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(libinfgtk_0_7_ladir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ 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-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ 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" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files 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) $(DATA) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(girdir)" "$(DESTDIR)$(typelibdir)" "$(DESTDIR)$(libinfgtk_0_7_ladir)"; 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-libLTLIBRARIES clean-libtool \ 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-girDATA install-libinfgtk_0_7_laHEADERS \ install-typelibDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-libLTLIBRARIES 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-girDATA uninstall-libLTLIBRARIES \ uninstall-libinfgtk_0_7_laHEADERS uninstall-typelibDATA .MAKE: all check install install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libLTLIBRARIES clean-libtool cscopelist-am ctags \ ctags-am 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-girDATA install-html install-html-am \ install-info install-info-am install-libLTLIBRARIES \ install-libinfgtk_0_7_laHEADERS install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ install-typelibDATA installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \ uninstall-girDATA uninstall-libLTLIBRARIES \ uninstall-libinfgtk_0_7_laHEADERS uninstall-typelibDATA .PRECIOUS: Makefile inf-gtk-resources.h: resources/infgtk.gresources.xml $(AM_V_GEN) glib-compile-resources $< \ --target=$@ --sourcedir=$(srcdir)/resources \ --c-name _inf_gtk --generate-header --internal inf-gtk-resources.c: resources/infgtk.gresources.xml $(resources) $(AM_V_GEN) glib-compile-resources $< \ --target=$@ --sourcedir=$(srcdir)/resources \ --c-name _inf_gtk --generate-source --internal @HAVE_INTROSPECTION_TRUE@-include $(INTROSPECTION_MAKEFILE) @HAVE_INTROSPECTION_TRUE@InfGtk-0.7.gir: libinfgtk-0.7.la # 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: libinfinity-0.7.1/libinfgtk/PaxHeaders.26529/inf-gtk-browser-store.h0000644000000000000000000000013213034342512022074 xustar0030 mtime=1483851082.017718362 30 atime=1483851082.017718362 30 ctime=1488261589.296138418 libinfinity-0.7.1/libinfgtk/inf-gtk-browser-store.h0000644000175000017500000000700013034342512022623 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_GTK_BROWSER_STORE_H__ #define __INF_GTK_BROWSER_STORE_H__ #include #include #include #include #include #include G_BEGIN_DECLS #define INF_GTK_TYPE_BROWSER_STORE (inf_gtk_browser_store_get_type()) #define INF_GTK_BROWSER_STORE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_GTK_TYPE_BROWSER_STORE, InfGtkBrowserStore)) #define INF_GTK_BROWSER_STORE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INF_GTK_TYPE_BROWSER_STORE, InfGtkBrowserStoreClass)) #define INF_GTK_IS_BROWSER_STORE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_GTK_TYPE_BROWSER_STORE)) #define INF_GTK_IS_BROWSER_STORE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INF_GTK_TYPE_BROWSER_STORE)) #define INF_GTK_BROWSER_STORE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INF_GTK_TYPE_BROWSER_STORE, InfGtkBrowserStoreClass)) typedef struct _InfGtkBrowserStore InfGtkBrowserStore; typedef struct _InfGtkBrowserStoreClass InfGtkBrowserStoreClass; struct _InfGtkBrowserStoreClass { GObjectClass parent_class; }; struct _InfGtkBrowserStore { GObject parent; }; GType inf_gtk_browser_store_get_type(void) G_GNUC_CONST; InfGtkBrowserStore* inf_gtk_browser_store_new(InfIo* io, InfCommunicationManager* comm_manager); void inf_gtk_browser_store_add_discovery(InfGtkBrowserStore* store, InfDiscovery* discovery); InfBrowser* inf_gtk_browser_store_add_connection(InfGtkBrowserStore* store, InfXmlConnection* connection, const gchar* name); void inf_gtk_browser_store_add_browser(InfGtkBrowserStore* store, InfBrowser* browser, const gchar* name); void inf_gtk_browser_store_remove_browser(InfGtkBrowserStore* store, InfBrowser* browser); void inf_gtk_browser_store_remove_connection(InfGtkBrowserStore* store, InfXmlConnection* connection); void inf_gtk_browser_store_clear_connection_error(InfGtkBrowserStore* store, InfXmlConnection* connection); void inf_gtk_browser_store_set_connection_name(InfGtkBrowserStore* store, InfXmlConnection* connection, const gchar* name); G_END_DECLS #endif /* __INF_GTK_BROWSER_STORE_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfgtk/PaxHeaders.26529/Makefile.am0000644000000000000000000000013213034544714017615 xustar0030 mtime=1483917772.682920565 30 atime=1483917772.682920565 30 ctime=1488261589.288138436 libinfinity-0.7.1/libinfgtk/Makefile.am0000644000175000017500000000653513034544714020360 0ustar00arminarmin00000000000000# TODO: Find a way to have the version number set automatically. lib_LTLIBRARIES = libinfgtk-0.7.la cppflags = \ -I$(top_srcdir) \ $(infgtk_CFLAGS) \ $(infinity_CFLAGS) ldflags = \ -no-undefined \ -version-info $(LIBINFINITY_LIBTOOL_VERSION) libadd = \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(infgtk_LIBS) \ $(infinity_LIBS) headers = \ inf-gtk-account-creation-dialog.h \ inf-gtk-acl-sheet-view.h \ inf-gtk-browser-model.h \ inf-gtk-browser-model-filter.h \ inf-gtk-browser-model-sort.h \ inf-gtk-browser-store.h \ inf-gtk-browser-view.h \ inf-gtk-certificate-dialog.h \ inf-gtk-certificate-manager.h \ inf-gtk-certificate-view.h \ inf-gtk-chat.h \ inf-gtk-connection-view.h \ inf-gtk-io.h \ inf-gtk-permissions-dialog.h \ inf-gtk-resources.h sources = \ inf-gtk-account-creation-dialog.c \ inf-gtk-acl-sheet-view.c \ inf-gtk-browser-model.c \ inf-gtk-browser-model-filter.c \ inf-gtk-browser-model-sort.c \ inf-gtk-browser-store.c \ inf-gtk-browser-view.c \ inf-gtk-certificate-dialog.c \ inf-gtk-certificate-manager.c \ inf-gtk-certificate-view.c \ inf-gtk-chat.c \ inf-gtk-connection-view.c \ inf-gtk-io.c \ inf-gtk-permissions-dialog.c \ inf-gtk-resources.c resources = \ resources/ui/infgtkaccountcreationdialog.ui \ resources/ui/infgtkaclsheetview.ui \ resources/ui/infgtkcertificatedialog.ui \ resources/ui/infgtkcertificateview.ui \ resources/ui/infgtkchat.ui \ resources/ui/infgtkconnectionview.ui \ resources/ui/infgtkpermissionsdialog.ui inf-gtk-resources.h: resources/infgtk.gresources.xml $(AM_V_GEN) glib-compile-resources $< \ --target=$@ --sourcedir=$(srcdir)/resources \ --c-name _inf_gtk --generate-header --internal inf-gtk-resources.c: resources/infgtk.gresources.xml $(resources) $(AM_V_GEN) glib-compile-resources $< \ --target=$@ --sourcedir=$(srcdir)/resources \ --c-name _inf_gtk --generate-source --internal BUILT_SOURCES = inf-gtk-resources.h inf-gtk-resources.c CLEANFILES = inf-gtk-resources.h inf-gtk-resources.c libinfgtk_0_7_la_CPPFLAGS = $(cppflags) libinfgtk_0_7_la_LDFLAGS = $(ldflags) libinfgtk_0_7_la_LIBADD = $(libadd) libinfgtk_0_7_la_HEADERS = $(headers) libinfgtk_0_7_la_SOURCES = $(sources) libinfgtk_0_7_ladir = \ $(includedir)/libinfgtk-$(LIBINFINITY_API_VERSION)/libinfgtk EXTRA_DIST = \ resources/infgtk.gresources.xml \ $(resources) if HAVE_INTROSPECTION -include $(INTROSPECTION_MAKEFILE) INTROSPECTION_GIRS = InfGtk-0.7.gir INTROSPECTION_SCANNER_ENV = CC="${CC}" INTROSPECTION_COMPILER_ARGS = \ --includedir=${top_srcdir}/libinfinity \ --includedir=${top_builddir}/libinfinity InfGtk-0.7.gir: libinfgtk-0.7.la InfGtk_0_7_gir_SCANNERFLAGS = \ -I${top_srcdir} \ --add-include-path=$(top_srcdir)/libinfinity \ --add-include-path=$(top_builddir)/libinfinity \ -n InfGtk \ --identifier-prefix=InfGtk InfGtk_0_7_gir_NAMESPACE = InfGtk InfGtk_0_7_gir_VERSION = 0.7 InfGtk_0_7_gir_CFLAGS = $(infgtk_CFLAGS) $(infinity_CFLAGS) InfGtk_0_7_gir_LIBS = libinfgtk-0.7.la InfGtk_0_7_gir_FILES = \ $(libinfgtk_0_7_la_SOURCES) \ $(libinfgtk_0_7_la_HEADERS) InfGtk_0_7_gir_INCLUDES = Infinity-0.7 Gtk-3.0 InfGtk_0_7_gir_PACKAGES = gtk+-3.0 InfGtk_0_7_gir_EXPORT_PACKAGES = libinfgtk-0.7 girdir = $(datadir)/gir-1.0 gir_DATA = InfGtk-0.7.gir typelibdir = $(libdir)/girepository-1.0 typelib_DATA = InfGtk-0.7.typelib CLEANFILES += \ $(gir_DATA) \ $(typelib_DATA) endif libinfinity-0.7.1/libinfgtk/PaxHeaders.26529/inf-gtk-connection-view.h0000644000000000000000000000013213034342512022366 xustar0030 mtime=1483851082.021718383 30 atime=1483851082.021718383 30 ctime=1488261589.304138401 libinfinity-0.7.1/libinfgtk/inf-gtk-connection-view.h0000644000175000017500000000542513034342512023126 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_GTK_CONNECTION_VIEW_H__ #define __INF_GTK_CONNECTION_VIEW_H__ #include #include G_BEGIN_DECLS #define INF_GTK_TYPE_CONNECTION_VIEW (inf_gtk_connection_view_get_type()) #define INF_GTK_CONNECTION_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_GTK_TYPE_CONNECTION_VIEW, InfGtkConnectionView)) #define INF_GTK_CONNECTION_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INF_GTK_TYPE_CONNECTION_VIEW, InfGtkConnectionViewClass)) #define INF_GTK_IS_CONNECTION_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_GTK_TYPE_CONNECTION_VIEW)) #define INF_GTK_IS_CONNECTION_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INF_GTK_TYPE_CONNECTION_VIEW)) #define INF_GTK_CONNECTION_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INF_GTK_TYPE_CONNECTION_VIEW, InfGtkConnectionViewClass)) #define INF_GTK_TYPE_CONNECTION_VIEW_FLAGS (inf_gtk_connection_view_flags_get_type()) typedef struct _InfGtkConnectionView InfGtkConnectionView; typedef struct _InfGtkConnectionViewClass InfGtkConnectionViewClass; /** * InfGtkConnectionViewClass: * * This structure does not contain any public fields. */ struct _InfGtkConnectionViewClass { /*< private >*/ GtkGridClass parent_class; }; /** * InfGtkConnectionView: * * #InfGtkConnectionView is an opaque data type. You should only access * it via the public API functions. */ struct _InfGtkConnectionView { /*< private >*/ GtkGrid parent; }; GType inf_gtk_connection_view_get_type(void) G_GNUC_CONST; GtkWidget* inf_gtk_connection_view_new(void); GtkWidget* inf_gtk_connection_view_new_with_connection(InfXmppConnection* connection); void inf_gtk_connection_view_set_connection(InfGtkConnectionView* view, InfXmppConnection* connection); G_END_DECLS #endif /* __INF_GTK_CONNECTION_VIEW_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfgtk/PaxHeaders.26529/resources0000644000000000000000000000013213055210725017511 xustar0030 mtime=1488261589.336138331 30 atime=1488261589.288138436 30 ctime=1488261589.336138331 libinfinity-0.7.1/libinfgtk/resources/0000755000175000017500000000000013055210725020320 5ustar00arminarmin00000000000000libinfinity-0.7.1/libinfgtk/resources/PaxHeaders.26529/ui0000644000000000000000000000013213055210725020126 xustar0030 mtime=1488261589.348138304 30 atime=1488261589.288138436 30 ctime=1488261589.348138304 libinfinity-0.7.1/libinfgtk/resources/ui/0000755000175000017500000000000013055210725020735 5ustar00arminarmin00000000000000libinfinity-0.7.1/libinfgtk/resources/ui/PaxHeaders.26529/infgtkconnectionview.ui0000644000000000000000000000013213034342512024774 xustar0030 mtime=1483851082.021718383 30 atime=1483851082.021718383 30 ctime=1488261589.348138304 libinfinity-0.7.1/libinfgtk/resources/ui/infgtkconnectionview.ui0000644000175000017500000002604313034342512025533 0ustar00arminarmin00000000000000 libinfinity-0.7.1/libinfgtk/resources/ui/PaxHeaders.26529/infgtkaclsheetview.ui0000644000000000000000000000013213034342512024425 xustar0030 mtime=1483851082.021718383 30 atime=1483851082.021718383 30 ctime=1488261589.340138322 libinfinity-0.7.1/libinfgtk/resources/ui/infgtkaclsheetview.ui0000644000175000017500000000720013034342512025156 0ustar00arminarmin00000000000000 libinfinity-0.7.1/libinfgtk/resources/ui/PaxHeaders.26529/infgtkcertificatedialog.ui0000644000000000000000000000013213034342512025404 xustar0030 mtime=1483851082.021718383 30 atime=1483851082.021718383 30 ctime=1488261589.340138322 libinfinity-0.7.1/libinfgtk/resources/ui/infgtkcertificatedialog.ui0000644000175000017500000002317613034342512026147 0ustar00arminarmin00000000000000 libinfinity-0.7.1/libinfgtk/resources/ui/PaxHeaders.26529/infgtkcertificateview.ui0000644000000000000000000000013213034342512025117 xustar0030 mtime=1483851082.021718383 30 atime=1483851082.021718383 30 ctime=1488261589.340138322 libinfinity-0.7.1/libinfgtk/resources/ui/infgtkcertificateview.ui0000644000175000017500000003200213034342512025646 0ustar00arminarmin00000000000000 libinfinity-0.7.1/libinfgtk/resources/ui/PaxHeaders.26529/infgtkaccountcreationdialog.ui0000644000000000000000000000013213034342512026303 xustar0030 mtime=1483851082.021718383 30 atime=1483851082.021718383 30 ctime=1488261589.336138331 libinfinity-0.7.1/libinfgtk/resources/ui/infgtkaccountcreationdialog.ui0000644000175000017500000001544313034342512027044 0ustar00arminarmin00000000000000 True False system-run libinfinity-0.7.1/libinfgtk/resources/ui/PaxHeaders.26529/infgtkchat.ui0000644000000000000000000000013213034342512022661 xustar0030 mtime=1483851082.021718383 30 atime=1483851082.021718383 30 ctime=1488261589.344138313 libinfinity-0.7.1/libinfgtk/resources/ui/infgtkchat.ui0000644000175000017500000001062113034342512023413 0ustar00arminarmin00000000000000 normal system #0000ff emote #113322 backlog #606060 chat_tag_table libinfinity-0.7.1/libinfgtk/resources/ui/PaxHeaders.26529/infgtkpermissionsdialog.ui0000644000000000000000000000013213034342512025475 xustar0030 mtime=1483851082.021718383 30 atime=1483851082.021718383 30 ctime=1488261589.348138304 libinfinity-0.7.1/libinfgtk/resources/ui/infgtkpermissionsdialog.ui0000644000175000017500000002764213034342512026242 0ustar00arminarmin00000000000000 libinfinity-0.7.1/libinfgtk/resources/PaxHeaders.26529/infgtk.gresources.xml0000644000000000000000000000013213034342512023747 xustar0030 mtime=1483851082.021718383 30 atime=1483851082.021718383 30 ctime=1488261589.336138331 libinfinity-0.7.1/libinfgtk/resources/infgtk.gresources.xml0000644000175000017500000000110613034342512024477 0ustar00arminarmin00000000000000 ui/infgtkaccountcreationdialog.ui ui/infgtkaclsheetview.ui ui/infgtkcertificatedialog.ui ui/infgtkcertificateview.ui ui/infgtkchat.ui ui/infgtkconnectionview.ui ui/infgtkpermissionsdialog.ui libinfinity-0.7.1/libinfgtk/PaxHeaders.26529/inf-gtk-account-creation-dialog.h0000644000000000000000000000013213034342512023752 xustar0030 mtime=1483851082.017718362 30 atime=1483851082.017718362 30 ctime=1488261589.292138427 libinfinity-0.7.1/libinfgtk/inf-gtk-account-creation-dialog.h0000644000175000017500000000672113034342512024512 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_GTK_ACCOUNT_CREATION_DIALOG_H__ #define __INF_GTK_ACCOUNT_CREATION_DIALOG_H__ #include #include #include #include G_BEGIN_DECLS #define INF_GTK_TYPE_ACCOUNT_CREATION_DIALOG (inf_gtk_account_creation_dialog_get_type()) #define INF_GTK_ACCOUNT_CREATION_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_GTK_TYPE_ACCOUNT_CREATION_DIALOG, InfGtkAccountCreationDialog)) #define INF_GTK_ACCOUNT_CREATION_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INF_GTK_TYPE_ACCOUNT_CREATION_DIALOG, InfGtkAccountCreationDialogClass)) #define INF_GTK_IS_ACCOUNT_CREATION_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_GTK_TYPE_ACCOUNT_CREATION_DIALOG)) #define INF_GTK_IS_ACCOUNT_CREATION_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INF_GTK_TYPE_ACCOUNT_CREATION_DIALOG)) #define INF_GTK_ACCOUNT_CREATION_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INF_GTK_TYPE_ACCOUNT_CREATION_DIALOG, InfGtkAccountCreationDialogClass)) typedef struct _InfGtkAccountCreationDialog InfGtkAccountCreationDialog; typedef struct _InfGtkAccountCreationDialogClass InfGtkAccountCreationDialogClass; /** * InfGtkAccountCreationDialogClass: * @account_created: Default signal handler for the * #InfGtkAccountCreationDialog::account-created signal. * * This structure contains the default signal handlers for the * #InfGtkAccountCreationDialog class. */ struct _InfGtkAccountCreationDialogClass { /*< private >*/ GtkDialogClass parent_class; /*< public >*/ void(*account_created)(InfGtkAccountCreationDialog* dialog, gnutls_x509_privkey_t key, InfCertificateChain* chain, const InfAclAccount* account); }; /** * InfGtkAccountCreationDialog: * * #InfGtkAccountCreationDialog is an opaque data type. You should only access * it via the public API functions. */ struct _InfGtkAccountCreationDialog { /*< private >*/ GtkDialog parent; }; GType inf_gtk_account_creation_dialog_get_type(void) G_GNUC_CONST; InfGtkAccountCreationDialog* inf_gtk_account_creation_dialog_new(GtkWindow* parent, GtkDialogFlags dialog_flags, InfIo* io, InfBrowser* browser); void inf_gtk_account_creation_dialog_set_browser(InfGtkAccountCreationDialog* dlg, InfBrowser* browser); G_END_DECLS #endif /* __INF_GTK_ACCOUNT_CREATION_DIALOG_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfgtk/PaxHeaders.26529/inf-gtk-browser-model-filter.h0000644000000000000000000000013213034342512023323 xustar0030 mtime=1483851082.017718362 30 atime=1483851082.017718362 30 ctime=1488261589.296138418 libinfinity-0.7.1/libinfgtk/inf-gtk-browser-model-filter.h0000644000175000017500000000460413034342512024061 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_GTK_BROWSER_MODEL_FILTER_H__ #define __INF_GTK_BROWSER_MODEL_FILTER_H__ #include #include #include G_BEGIN_DECLS #define INF_GTK_TYPE_BROWSER_MODEL_FILTER (inf_gtk_browser_model_filter_get_type()) #define INF_GTK_BROWSER_MODEL_FILTER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_GTK_TYPE_BROWSER_MODEL_FILTER, InfGtkBrowserModelFilter)) #define INF_GTK_BROWSER_MODEL_FILTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INF_GTK_TYPE_BROWSER_MODEL_FILTER, InfGtkBrowserModelFilterClass)) #define INF_GTK_IS_BROWSER_MODEL_FILTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_GTK_TYPE_BROWSER_MODEL_FILTER)) #define INF_GTK_IS_BROWSER_MODEL_FILTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INF_GTK_TYPE_BROWSER_MODEL_FILTER)) #define INF_GTK_BROWSER_MODEL_FILTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INF_GTK_TYPE_BROWSER_MODEL_FILTER, InfGtkBrowserModelFilterClass)) typedef struct _InfGtkBrowserModelFilter InfGtkBrowserModelFilter; typedef struct _InfGtkBrowserModelFilterClass InfGtkBrowserModelFilterClass; struct _InfGtkBrowserModelFilterClass { GtkTreeModelFilterClass parent_class; }; struct _InfGtkBrowserModelFilter { GtkTreeModelFilter parent; }; GType inf_gtk_browser_model_filter_get_type(void) G_GNUC_CONST; InfGtkBrowserModelFilter* inf_gtk_browser_model_filter_new(InfGtkBrowserModel* child_model); G_END_DECLS #endif /* __INF_GTK_BROWSER_MODEL_FILTER_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfgtk/PaxHeaders.26529/inf-gtk-browser-model-filter.c0000644000000000000000000000013213034342512023316 xustar0030 mtime=1483851082.017718362 30 atime=1483851082.017718362 30 ctime=1488261589.316138375 libinfinity-0.7.1/libinfgtk/inf-gtk-browser-model-filter.c0000644000175000017500000001771313034342512024061 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include typedef struct _InfGtkBrowserModelFilterPrivate InfGtkBrowserModelFilterPrivate; struct _InfGtkBrowserModelFilterPrivate { InfGtkBrowserModel* child_model; }; #define INF_GTK_BROWSER_MODEL_FILTER_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INF_GTK_TYPE_BROWSER_MODEL_FILTER, InfGtkBrowserModelFilterPrivate)) static void inf_gtk_browser_model_filter_browser_model_iface_init(InfGtkBrowserModelInterface* iface); G_DEFINE_TYPE_WITH_CODE(InfGtkBrowserModelFilter, inf_gtk_browser_model_filter, GTK_TYPE_TREE_MODEL_FILTER, G_ADD_PRIVATE(InfGtkBrowserModelFilter) G_IMPLEMENT_INTERFACE(INF_GTK_TYPE_BROWSER_MODEL, inf_gtk_browser_model_filter_browser_model_iface_init)) static void inf_gtk_browser_model_filter_set_browser_cb(InfGtkBrowserModel* model, GtkTreePath* path, GtkTreeIter* iter, InfBrowser* old_browser, InfBrowser* new_browser, gpointer user_data) { GtkTreeModelFilter* model_filter; GtkTreePath* own_path; GtkTreeIter own_iter; gboolean result; model_filter = GTK_TREE_MODEL_FILTER(user_data); result = gtk_tree_model_filter_convert_child_iter_to_iter( model_filter, &own_iter, iter ); if(result == TRUE) { own_path = gtk_tree_model_filter_convert_child_path_to_path( model_filter, path ); g_assert(own_path != NULL); inf_gtk_browser_model_set_browser( INF_GTK_BROWSER_MODEL(user_data), own_path, &own_iter, old_browser, new_browser ); gtk_tree_path_free(own_path); } } static void inf_gtk_browser_model_filter_sync_child_model(InfGtkBrowserModelFilter* model, InfGtkBrowserModel* child_model) { InfGtkBrowserModelFilterPrivate* priv; priv = INF_GTK_BROWSER_MODEL_FILTER_PRIVATE(model); if(priv->child_model != NULL) { inf_signal_handlers_disconnect_by_func( priv->child_model, G_CALLBACK(inf_gtk_browser_model_filter_set_browser_cb), model ); g_object_unref(priv->child_model); } priv->child_model = child_model; if(child_model != NULL) { g_object_ref(child_model); g_signal_connect_after( G_OBJECT(child_model), "set-browser", G_CALLBACK(inf_gtk_browser_model_filter_set_browser_cb), model ); } } static void inf_gtk_browser_model_filter_notify_model_cb(GObject* object, GParamSpec* pspec, gpointer user_data) { GtkTreeModel* child_model; child_model = gtk_tree_model_filter_get_model( GTK_TREE_MODEL_FILTER(object) ); inf_gtk_browser_model_filter_sync_child_model( INF_GTK_BROWSER_MODEL_FILTER(object), INF_GTK_BROWSER_MODEL(child_model) ); } /* * GObject overrides */ static void inf_gtk_browser_model_filter_init(InfGtkBrowserModelFilter* model_filter) { InfGtkBrowserModelFilterPrivate* priv; priv = INF_GTK_BROWSER_MODEL_FILTER_PRIVATE(model_filter); /* Keep child model in sync with the one from GtkTreeModelFilter */ g_signal_connect( model_filter, "notify::model", G_CALLBACK(inf_gtk_browser_model_filter_notify_model_cb), NULL ); } static void inf_gtk_browser_model_filter_constructed(GObject* object) { G_OBJECT_CLASS(inf_gtk_browser_model_filter_parent_class)->constructed( object ); /* Set initial model, we do not get notified for this */ inf_gtk_browser_model_filter_sync_child_model( INF_GTK_BROWSER_MODEL_FILTER(object), INF_GTK_BROWSER_MODEL( gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(object)) ) ); } static void inf_gtk_browser_model_filter_dispose(GObject* object) { InfGtkBrowserModelFilter* model_sort; InfGtkBrowserModelFilterPrivate* priv; model_sort = INF_GTK_BROWSER_MODEL_FILTER(object); priv = INF_GTK_BROWSER_MODEL_FILTER_PRIVATE(model_sort); /* Release own child model, since we won't get notified anymore when the * parent's dispose runs. We disconnect the signal handler before chaining * up. */ inf_gtk_browser_model_filter_sync_child_model(model_sort, NULL); inf_signal_handlers_disconnect_by_func( object, G_CALLBACK(inf_gtk_browser_model_filter_notify_model_cb), NULL ); G_OBJECT_CLASS(inf_gtk_browser_model_filter_parent_class)->dispose(object); } /* * InfGtkBrowserModel implementation. */ static void inf_gtk_browser_model_filter_resolve(InfGtkBrowserModel* model, InfDiscovery* discovery, InfDiscoveryInfo* info) { GtkTreeModel* child_model; child_model = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(model)); inf_gtk_browser_model_resolve( INF_GTK_BROWSER_MODEL(child_model), discovery, info ); } static gboolean inf_gtk_browser_model_filter_browser_iter_to_tree_iter(InfGtkBrowserModel* m, InfBrowser* browser, const InfBrowserIter*i, GtkTreeIter* tree_iter) { GtkTreeModel* child_model; GtkTreeIter child_iter; gboolean result; child_model = gtk_tree_model_filter_get_model(GTK_TREE_MODEL_FILTER(m)); result = inf_gtk_browser_model_browser_iter_to_tree_iter( INF_GTK_BROWSER_MODEL(child_model), browser, i, &child_iter ); if(result == TRUE) { return gtk_tree_model_filter_convert_child_iter_to_iter( GTK_TREE_MODEL_FILTER(m), tree_iter, &child_iter ); } else { return FALSE; } } /* * GType registration */ static void inf_gtk_browser_model_filter_class_init( InfGtkBrowserModelFilterClass* browser_model_filter_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(browser_model_filter_class); object_class->constructed = inf_gtk_browser_model_filter_constructed; object_class->dispose = inf_gtk_browser_model_filter_dispose; } static void inf_gtk_browser_model_filter_browser_model_iface_init( InfGtkBrowserModelInterface* iface) { iface->set_browser = NULL; iface->resolve = inf_gtk_browser_model_filter_resolve; /* inf_gtk_browser_model_filter_browser_model_browser_iter_to_tree_iter * would be consistent, but a _bit_ too long to fit properly into 80 * chars ;) */ iface->browser_iter_to_tree_iter = inf_gtk_browser_model_filter_browser_iter_to_tree_iter; } /* * Public API. */ /** * inf_gtk_browser_model_filter_new: (constructor) * @child_model: A #InfGtkBrowserModel. * * Creates a new #InfGtkBrowserModelFilter, filtering @child_model. * * Returns: (transfer full): A new #InfGtkBrowserModelFilter. **/ InfGtkBrowserModelFilter* inf_gtk_browser_model_filter_new(InfGtkBrowserModel* child_model) { GObject* object; object = g_object_new( INF_GTK_TYPE_BROWSER_MODEL_FILTER, "child-model", child_model, NULL ); return INF_GTK_BROWSER_MODEL_FILTER(object); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfgtk/PaxHeaders.26529/inf-gtk-certificate-dialog.h0000644000000000000000000000013213034342512022776 xustar0030 mtime=1483851082.021718383 30 atime=1483851082.021718383 30 ctime=1488261589.300138409 libinfinity-0.7.1/libinfgtk/inf-gtk-certificate-dialog.h0000644000175000017500000000573213034342512023537 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_GTK_CERTIFICATE_DIALOG_H__ #define __INF_GTK_CERTIFICATE_DIALOG_H__ #include #include #include #include G_BEGIN_DECLS #define INF_GTK_TYPE_CERTIFICATE_DIALOG (inf_gtk_certificate_dialog_get_type()) #define INF_GTK_CERTIFICATE_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_GTK_TYPE_CERTIFICATE_DIALOG, InfGtkCertificateDialog)) #define INF_GTK_CERTIFICATE_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INF_GTK_TYPE_CERTIFICATE_DIALOG, InfGtkCertificateDialogClass)) #define INF_GTK_IS_CERTIFICATE_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_GTK_TYPE_CERTIFICATE_DIALOG)) #define INF_GTK_IS_CERTIFICATE_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INF_GTK_TYPE_CERTIFICATE_DIALOG)) #define INF_GTK_CERTIFICATE_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INF_GTK_TYPE_CERTIFICATE_DIALOG, InfGtkCertificateDialogClass)) typedef struct _InfGtkCertificateDialog InfGtkCertificateDialog; typedef struct _InfGtkCertificateDialogClass InfGtkCertificateDialogClass; /** * InfGtkCertificateDialogClass: * * This structure does not contain any public fields. */ struct _InfGtkCertificateDialogClass { /*< private >*/ GtkDialogClass parent_class; }; /** * InfGtkCertificateDialog: * * #InfGtkCertificateDialog is an opaque data type. You should only access * it via the public API functions. */ struct _InfGtkCertificateDialog { /*< private >*/ GtkDialog parent; }; GType inf_gtk_certificate_dialog_get_type(void) G_GNUC_CONST; InfGtkCertificateDialog* inf_gtk_certificate_dialog_new(GtkWindow* parent, GtkDialogFlags dialog_flags, InfCertificateVerifyFlags verify_flags, const gchar* hostname, InfCertificateChain* certificate_chain, gnutls_x509_crt_t pinned_certificate); G_END_DECLS #endif /* __INF_GTK_CERTIFICATE_DIALOG_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfgtk/PaxHeaders.26529/inf-gtk-io.c0000644000000000000000000000013213034342512017661 xustar0030 mtime=1483851082.021718383 30 atime=1483851082.021718383 30 ctime=1488261589.328138348 libinfinity-0.7.1/libinfgtk/inf-gtk-io.c0000644000175000017500000004374713034342512020432 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include struct _InfIoWatch { InfGtkIo* io; InfNativeSocket* socket; guint id; InfIoWatchFunc func; gpointer user_data; GDestroyNotify notify; /* Additional state to avoid freeing the userdata while running * the callback */ gboolean executing; gboolean disposed; }; struct _InfIoTimeout { InfGtkIo* io; guint id; InfIoTimeoutFunc func; gpointer user_data; GDestroyNotify notify; }; struct _InfIoDispatch { InfGtkIo* io; guint id; InfIoDispatchFunc func; gpointer user_data; GDestroyNotify notify; }; typedef struct _InfGtkIoSharedMutex InfGtkIoSharedMutex; struct _InfGtkIoSharedMutex { GMutex mutex; int ref; }; typedef struct _InfGtkIoUserdata InfGtkIoUserdata; struct _InfGtkIoUserdata { union { InfIoWatch* watch; InfIoTimeout* timeout; InfIoDispatch* dispatch; } shared; InfGtkIoSharedMutex* mutex; }; typedef struct _InfGtkIoPrivate InfGtkIoPrivate; struct _InfGtkIoPrivate { /* TODO: GMainContext */ InfGtkIoSharedMutex* mutex; GSList* watches; GSList* timeouts; GSList* dispatchs; }; #define INF_GTK_IO_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INF_GTK_TYPE_IO, InfGtkIoPrivate)) static void inf_gtk_io_io_iface_init(InfIoInterface* iface); G_DEFINE_TYPE_WITH_CODE(InfGtkIo, inf_gtk_io, G_TYPE_OBJECT, G_ADD_PRIVATE(InfGtkIo) G_IMPLEMENT_INTERFACE(INF_TYPE_IO, inf_gtk_io_io_iface_init)) static void inf_gtk_io_userdata_free(gpointer data) { InfGtkIoUserdata* userdata; userdata = (InfGtkIoUserdata*)data; /* Note that the shared members may already be invalid at this point */ /* Note also that we cannot lock the mutex here, because this function * might or might not be called with it being locked already. However in * this case we can use an atomic operation instead. */ if(g_atomic_int_dec_and_test(&userdata->mutex->ref) == TRUE) { g_mutex_clear(&userdata->mutex->mutex); g_slice_free(InfGtkIoSharedMutex, userdata->mutex); } g_slice_free(InfGtkIoUserdata, userdata); } static InfIoWatch* inf_gtk_io_watch_new(InfGtkIo* io, InfNativeSocket* socket, InfIoWatchFunc func, gpointer user_data, GDestroyNotify notify) { InfIoWatch* watch; watch = g_slice_new(InfIoWatch); watch->io = io; watch->socket = socket; watch->id = 0; watch->func = func; watch->user_data = user_data; watch->notify = notify; watch->executing = FALSE; watch->disposed = FALSE; return watch; } static void inf_gtk_io_watch_free(InfIoWatch* watch) { if(watch->notify) watch->notify(watch->user_data); g_slice_free(InfIoWatch, watch); } static InfIoTimeout* inf_gtk_io_timeout_new(InfGtkIo* io, InfIoTimeoutFunc func, gpointer user_data, GDestroyNotify notify) { InfIoTimeout* timeout; timeout = g_slice_new(InfIoTimeout); timeout->io = io; timeout->id = 0; timeout->func = func; timeout->user_data = user_data; timeout->notify = notify; return timeout; } static void inf_gtk_io_timeout_free(InfIoTimeout* timeout) { if(timeout->notify) timeout->notify(timeout->user_data); g_slice_free(InfIoTimeout, timeout); } static InfIoDispatch* inf_gtk_io_dispatch_new(InfGtkIo* io, InfIoDispatchFunc func, gpointer user_data, GDestroyNotify notify) { InfIoDispatch* dispatch; dispatch = g_slice_new(InfIoDispatch); dispatch->io = io; dispatch->id = 0; dispatch->func = func; dispatch->user_data = user_data; dispatch->notify = notify; return dispatch; } static void inf_gtk_io_dispatch_free(InfIoDispatch* dispatch) { if(dispatch->notify) dispatch->notify(dispatch->user_data); g_slice_free(InfIoDispatch, dispatch); } static InfIoWatch* inf_gtk_io_watch_lookup(InfGtkIo* io, InfNativeSocket* socket) { InfGtkIoPrivate* priv; GSList* item; priv = INF_GTK_IO_PRIVATE(io); for(item = priv->watches; item != NULL; item = g_slist_next(item)) if( ((InfIoWatch*)item->data)->socket == socket) return (InfIoWatch*)item->data; return NULL; } static void inf_gtk_io_init(InfGtkIo* io) { InfGtkIoPrivate* priv; priv = INF_GTK_IO_PRIVATE(io); priv->mutex = g_slice_new(InfGtkIoSharedMutex); g_mutex_init(&priv->mutex->mutex); priv->mutex->ref = 1; priv->watches = NULL; priv->timeouts = NULL; priv->dispatchs = NULL; } static void inf_gtk_io_finalize(GObject* object) { InfGtkIo* io; InfGtkIoPrivate* priv; GSList* item; io = INF_GTK_IO(object); priv = INF_GTK_IO_PRIVATE(io); g_mutex_lock(&priv->mutex->mutex); for(item = priv->watches; item != NULL; item = g_slist_next(item)) { /* We have a stack-ref on the InfGtkIo when exeucting the callback */ g_assert( ((InfIoWatch*)item->data)->executing == FALSE); if( ((InfIoWatch*)item->data)->id != 0) g_source_remove( ((InfIoWatch*)item->data)->id); inf_gtk_io_watch_free((InfIoWatch*)item->data); } g_slist_free(priv->watches); for(item = priv->timeouts; item != NULL; item = g_slist_next(item)) { if( ((InfIoTimeout*)item->data)->id != 0) g_source_remove( ((InfIoTimeout*)item->data)->id); inf_gtk_io_timeout_free((InfIoTimeout*)item->data); } g_slist_free(priv->timeouts); for(item = priv->dispatchs; item != NULL; item = g_slist_next(item)) { if( ((InfIoDispatch*)item->data)->id != 0) g_source_remove( ((InfIoDispatch*)item->data)->id); inf_gtk_io_dispatch_free((InfIoDispatch*)item->data); } g_slist_free(priv->dispatchs); g_mutex_unlock(&priv->mutex->mutex); /* some callback userdata might still have a reference to the mutex, and * wait for the callback function to be called until it is released. The * callback function will do nothing since g_source_is_destroyed() will * return FALSE since we removed all sources above. But we need to keep * the mutex alive so that the callbacks can check. */ if(g_atomic_int_dec_and_test(&priv->mutex->ref)) { g_mutex_clear(&priv->mutex->mutex); g_slice_free(InfGtkIoSharedMutex, priv->mutex); } G_OBJECT_CLASS(inf_gtk_io_parent_class)->finalize(object); } static GIOCondition inf_gtk_io_inf_events_to_glib_events(InfIoEvent events) { GIOCondition cond; cond = 0; if(events & INF_IO_INCOMING) cond |= G_IO_IN; if(events & INF_IO_OUTGOING) cond |= G_IO_OUT; if(events & INF_IO_ERROR) cond |= (G_IO_ERR | G_IO_HUP); return cond; } static InfIoEvent inf_gtk_io_inf_events_from_glib_events(GIOCondition cond) { InfIoEvent event; event = 0; if(cond & G_IO_IN) event |= INF_IO_INCOMING; if(cond & G_IO_OUT) event |= INF_IO_OUTGOING; if(cond & (G_IO_ERR | G_IO_HUP)) event |= INF_IO_ERROR; return event; } static gboolean inf_gtk_io_watch_func(GIOChannel* channel, GIOCondition condition, gpointer user_data) { InfGtkIoUserdata* userdata; InfIoWatch* watch; InfGtkIoPrivate* priv; userdata = (InfGtkIoUserdata*)user_data; g_mutex_lock(&userdata->mutex->mutex); if(!g_source_is_destroyed(g_main_current_source())) { /* At this point we know that InfGtkIo is still alive because otherwise * the source would have been destroyed in _finalize. */ watch = userdata->shared.watch; g_object_ref(watch->io); priv = INF_GTK_IO_PRIVATE(watch->io); g_assert(priv->mutex->ref > 1); /* Both InfGtkIo and we have a reference */ g_assert(g_slist_find(priv->watches, watch) != NULL); watch->executing = TRUE; g_mutex_unlock(&userdata->mutex->mutex); /* Note that at this point the watch object could be removed from the * list, but, since executing is set to TRUE, it is not freed. */ watch->func( watch->socket, inf_gtk_io_inf_events_from_glib_events(condition), watch->user_data ); g_mutex_lock(&userdata->mutex->mutex); watch->executing = FALSE; g_object_unref(watch->io); if(watch->disposed == TRUE) { g_mutex_unlock(&userdata->mutex->mutex); inf_gtk_io_watch_free(watch); } else { g_mutex_unlock(&userdata->mutex->mutex); } } else { g_mutex_unlock(&userdata->mutex->mutex); } return TRUE; } static gboolean inf_gtk_io_timeout_func(gpointer user_data) { InfIoTimeout* timeout; InfGtkIoPrivate* priv; InfGtkIoUserdata* userdata; userdata = (InfGtkIoUserdata*)user_data; g_mutex_lock(&userdata->mutex->mutex); if(!g_source_is_destroyed(g_main_current_source())) { /* At this point we know that InfGtkIo is still alive because otherwise * the source would have been destroyed in _finalize. */ timeout = userdata->shared.timeout; priv = INF_GTK_IO_PRIVATE(timeout->io); g_assert(priv->mutex->ref > 1); /* Both InfGtkIo and we have a reference */ g_assert(g_slist_find(priv->timeouts, timeout) != NULL); priv->timeouts = g_slist_remove(priv->timeouts, timeout); g_mutex_unlock(&userdata->mutex->mutex); timeout->func(timeout->user_data); inf_gtk_io_timeout_free(timeout); } else { g_mutex_unlock(&userdata->mutex->mutex); } return FALSE; } static gboolean inf_gtk_io_dispatch_func(gpointer user_data) { InfIoDispatch* dispatch; InfGtkIoPrivate* priv; InfGtkIoUserdata* userdata; userdata = (InfGtkIoUserdata*)user_data; g_mutex_lock(&userdata->mutex->mutex); if(!g_source_is_destroyed(g_main_current_source())) { /* At this point we know that InfGtkIo is still alive because otherwise * the source would have been destroyed in _finalize. */ dispatch = userdata->shared.dispatch; priv = INF_GTK_IO_PRIVATE(dispatch->io); g_assert(priv->mutex->ref > 1); /* Both InfGtkIo and we have a reference */ g_assert(g_slist_find(priv->dispatchs, dispatch) != NULL); priv->dispatchs = g_slist_remove(priv->dispatchs, dispatch); g_mutex_unlock(&userdata->mutex->mutex); dispatch->func(dispatch->user_data); inf_gtk_io_dispatch_free(dispatch); } else { g_mutex_unlock(&userdata->mutex->mutex); } return FALSE; } static InfIoWatch* inf_gtk_io_io_add_watch(InfIo* io, InfNativeSocket* socket, InfIoEvent events, InfIoWatchFunc func, gpointer user_data, GDestroyNotify notify) { InfGtkIoPrivate* priv; InfIoWatch* watch; InfGtkIoUserdata* data; GIOChannel* channel; priv = INF_GTK_IO_PRIVATE(io); g_mutex_lock(&priv->mutex->mutex); watch = inf_gtk_io_watch_lookup(INF_GTK_IO(io), socket); if(watch != NULL) { g_mutex_unlock(&priv->mutex->mutex); return NULL; } watch = inf_gtk_io_watch_new( INF_GTK_IO(io), socket, func, user_data, notify ); data = g_slice_new(InfGtkIoUserdata); data->shared.watch = watch; data->mutex = priv->mutex; g_atomic_int_inc(&data->mutex->ref); #ifdef G_OS_WIN32 channel = g_io_channel_win32_new_socket(*socket); #else channel = g_io_channel_unix_new(*socket); #endif watch->id = g_io_add_watch_full( channel, G_PRIORITY_DEFAULT, inf_gtk_io_inf_events_to_glib_events(events), inf_gtk_io_watch_func, data, inf_gtk_io_userdata_free ); g_io_channel_unref(channel); priv->watches = g_slist_prepend(priv->watches, watch); g_mutex_unlock(&priv->mutex->mutex); return watch; } static void inf_gtk_io_io_update_watch(InfIo* io, InfIoWatch* watch, InfIoEvent events) { InfGtkIoPrivate* priv; InfGtkIoUserdata* data; GIOChannel* channel; priv = INF_GTK_IO_PRIVATE(io); g_mutex_lock(&priv->mutex->mutex); g_assert(g_slist_find(priv->watches, watch) != NULL); data = g_slice_new(InfGtkIoUserdata); data->shared.watch = watch; data->mutex = priv->mutex; g_atomic_int_inc(&data->mutex->ref); g_mutex_unlock(&priv->mutex->mutex); g_source_remove(watch->id); #ifdef G_OS_WIN32 channel = g_io_channel_win32_new_socket(*watch->socket); #else channel = g_io_channel_unix_new(*watch->socket); #endif watch->id = g_io_add_watch_full( channel, G_PRIORITY_DEFAULT, inf_gtk_io_inf_events_to_glib_events(events), inf_gtk_io_watch_func, data, inf_gtk_io_userdata_free ); g_io_channel_unref(channel); } static void inf_gtk_io_io_remove_watch(InfIo* io, InfIoWatch* watch) { InfGtkIoPrivate* priv; guint watch_id; priv = INF_GTK_IO_PRIVATE(io); g_mutex_lock(&priv->mutex->mutex); g_assert(g_slist_find(priv->watches, watch) != NULL); priv->watches = g_slist_remove(priv->watches, watch); watch_id = watch->id; if(watch->executing) { /* If we are currently running the watch callback then don't free the * watch object right now, because this would destroy the userdata before * the callback finished running. Instead, remember that the watch is * going to be disposed and remove it in the watch func right after * having called the callback. */ watch->disposed = TRUE; g_mutex_unlock(&priv->mutex->mutex); } else { g_mutex_unlock(&priv->mutex->mutex); inf_gtk_io_watch_free(watch); } /* Note that we can do this safely without having locked the mutex because * if the callback function is currently being invoked then its user_data * will not be destroyed immediately. */ g_source_remove(watch_id); } static InfIoTimeout* inf_gtk_io_io_add_timeout(InfIo* io, guint msecs, InfIoTimeoutFunc func, gpointer user_data, GDestroyNotify notify) { InfGtkIoPrivate* priv; InfIoTimeout* timeout; InfGtkIoUserdata* data; priv = INF_GTK_IO_PRIVATE(io); timeout = inf_gtk_io_timeout_new(INF_GTK_IO(io), func, user_data, notify); data = g_slice_new(InfGtkIoUserdata); data->shared.timeout = timeout; data->mutex = priv->mutex; g_mutex_lock(&priv->mutex->mutex); g_atomic_int_inc(&data->mutex->ref); timeout->id = g_timeout_add_full( G_PRIORITY_DEFAULT, msecs, inf_gtk_io_timeout_func, data, inf_gtk_io_userdata_free ); priv->timeouts = g_slist_prepend(priv->timeouts, timeout); g_mutex_unlock(&priv->mutex->mutex); return timeout; } static void inf_gtk_io_io_remove_timeout(InfIo* io, InfIoTimeout* timeout) { InfGtkIoPrivate* priv; priv = INF_GTK_IO_PRIVATE(io); g_mutex_lock(&priv->mutex->mutex); g_assert(g_slist_find(priv->timeouts, timeout) != NULL); priv->timeouts = g_slist_remove(priv->timeouts, timeout); g_mutex_unlock(&priv->mutex->mutex); /* Note that we can do this safely without having locked the mutex because * if the callback function is currently being invoked then its user_data * will not be destroyed immediately. */ g_source_remove(timeout->id); inf_gtk_io_timeout_free(timeout); } static InfIoDispatch* inf_gtk_io_io_add_dispatch(InfIo* io, InfIoDispatchFunc func, gpointer user_data, GDestroyNotify notify) { InfGtkIoPrivate* priv; InfIoDispatch* dispatch; InfGtkIoUserdata* data; priv = INF_GTK_IO_PRIVATE(io); dispatch = inf_gtk_io_dispatch_new(INF_GTK_IO(io), func, user_data, notify); data = g_slice_new(InfGtkIoUserdata); data->shared.dispatch = dispatch; data->mutex = priv->mutex; g_mutex_lock(&priv->mutex->mutex); g_atomic_int_inc(&data->mutex->ref); dispatch->id = g_idle_add_full( G_PRIORITY_DEFAULT_IDLE, inf_gtk_io_dispatch_func, data, inf_gtk_io_userdata_free ); priv->dispatchs = g_slist_prepend(priv->dispatchs, dispatch); g_mutex_unlock(&priv->mutex->mutex); return dispatch; } static void inf_gtk_io_io_remove_dispatch(InfIo* io, InfIoDispatch* dispatch) { InfGtkIoPrivate* priv; priv = INF_GTK_IO_PRIVATE(io); g_mutex_lock(&priv->mutex->mutex); g_assert(g_slist_find(priv->dispatchs, dispatch) != NULL); priv->dispatchs = g_slist_remove(priv->dispatchs, dispatch); g_mutex_unlock(&priv->mutex->mutex); /* Note that we can do this safely without having locked the mutex because * if the callback function is currently being invoked then its user_data * will not be destroyed immediately. */ g_source_remove(dispatch->id); inf_gtk_io_dispatch_free(dispatch); } static void inf_gtk_io_class_init(InfGtkIoClass* io_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(io_class); object_class->finalize = inf_gtk_io_finalize; } static void inf_gtk_io_io_iface_init(InfIoInterface* iface) { iface->add_watch = inf_gtk_io_io_add_watch; iface->update_watch = inf_gtk_io_io_update_watch; iface->remove_watch = inf_gtk_io_io_remove_watch; iface->add_timeout = inf_gtk_io_io_add_timeout; iface->remove_timeout = inf_gtk_io_io_remove_timeout; iface->add_dispatch = inf_gtk_io_io_add_dispatch; iface->remove_dispatch = inf_gtk_io_io_remove_dispatch; } /** * inf_gtk_io_new: (constructor) * * Creates a new #InfGtkIo. * * Returns: (transfer full): A new #InfGtkIo. Free with g_object_unref() * when no longer needed. **/ InfGtkIo* inf_gtk_io_new(void) { GObject* object; object = g_object_new(INF_GTK_TYPE_IO, NULL); return INF_GTK_IO(object); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfgtk/PaxHeaders.26529/inf-gtk-browser-store.c0000644000000000000000000000013213034342512022067 xustar0030 mtime=1483851082.017718362 30 atime=1483851082.017718362 30 ctime=1488261589.320138365 libinfinity-0.7.1/libinfgtk/inf-gtk-browser-store.c0000644000175000017500000022000713034342512022622 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include #include #include #include #include /* The three pointers in GtkTreeIter are used as follows: * * user_data holds a pointer to the GtkTreeModelItem the iter points to. * user_data2 holds the node_id field of the InfBrowserIter, or 0 if the * iter points to the toplevel node. * user_data3 holds the node field of the InfcBrowser, or NULL if the iter * points to the toplevel node. Note that it does not hold the root node of * the item's browser (if present) because the iter should remain valid when * the browser is removed (we set GTK_TREE_MODEL_ITERS_PERSIST). */ typedef struct _InfGtkBrowserStoreItem InfGtkBrowserStoreItem; struct _InfGtkBrowserStoreItem { gchar* name; InfDiscovery* discovery; InfDiscoveryInfo* info; InfBrowser* browser; /* Browser node which is currently to be removed. This is required since * when node-removed is emitted in InfcBrowser the node is still present, * but we need to make sure that the GtkTreeModel functions do as if it * wasn't present anymore. */ gpointer missing; /* Running requests */ GSList* requests; /* Saved node errors (during exploration/subscription) */ GHashTable* node_errors; /* TODO: Determine status at run-time? */ InfGtkBrowserModelStatus status; /* Error on toplevel item */ GError* error; /* Link */ InfGtkBrowserStoreItem* next; }; typedef struct _InfGtkBrowserStoreRequestData InfGtkBrowserStoreRequestData; struct _InfGtkBrowserStoreRequestData { InfGtkBrowserStore* store; InfGtkBrowserStoreItem* item; }; typedef struct _InfGtkBrowserStorePrivate InfGtkBrowserStorePrivate; struct _InfGtkBrowserStorePrivate { gint stamp; InfIo* io; InfCommunicationManager* communication_manager; GSList* discoveries; InfGtkBrowserStoreItem* first_item; InfGtkBrowserStoreItem* last_item; }; enum { PROP_0, PROP_IO, PROP_COMMUNICATION_MANAGER }; #define INF_GTK_BROWSER_STORE_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INF_GTK_TYPE_BROWSER_STORE, InfGtkBrowserStorePrivate)) static void inf_gtk_browser_store_tree_model_iface_init(GtkTreeModelIface* iface); static void inf_gtk_browser_store_browser_model_iface_init(InfGtkBrowserModelInterface* iface); G_DEFINE_TYPE_WITH_CODE(InfGtkBrowserStore, inf_gtk_browser_store, G_TYPE_OBJECT, G_ADD_PRIVATE(InfGtkBrowserStore) G_IMPLEMENT_INTERFACE(GTK_TYPE_TREE_MODEL, inf_gtk_browser_store_tree_model_iface_init) G_IMPLEMENT_INTERFACE(INF_GTK_TYPE_BROWSER_MODEL, inf_gtk_browser_store_browser_model_iface_init)) /* * Utility functions */ static InfGtkBrowserStoreItem* inf_gtk_browser_store_find_item_by_connection(InfGtkBrowserStore* store, InfXmlConnection* connection) { InfGtkBrowserStorePrivate* priv; InfGtkBrowserStoreItem* item; InfcBrowser* browser; priv = INF_GTK_BROWSER_STORE_PRIVATE(store); for(item = priv->first_item; item != NULL; item = item->next) { if(item->browser != NULL && INFC_IS_BROWSER(item->browser)) { browser = INFC_BROWSER(item->browser); if(infc_browser_get_connection(browser) == connection) return item; } } return NULL; } static InfGtkBrowserStoreItem* inf_gtk_browser_store_find_item_by_browser(InfGtkBrowserStore* store, InfBrowser* browser) { InfGtkBrowserStorePrivate* priv; InfGtkBrowserStoreItem* item; priv = INF_GTK_BROWSER_STORE_PRIVATE(store); for(item = priv->first_item; item != NULL; item = item->next) if(item->browser != NULL) if(item->browser == browser) return item; return NULL; } static InfGtkBrowserStoreItem* inf_gtk_browser_store_find_item_by_discovery_info(InfGtkBrowserStore* store, InfDiscoveryInfo* info) { InfGtkBrowserStorePrivate* priv; InfGtkBrowserStoreItem* item; priv = INF_GTK_BROWSER_STORE_PRIVATE(store); for(item = priv->first_item; item != NULL; item = item->next) if(item->info != NULL) if(item->info == info) return item; return NULL; } /* * Callback declarations */ static void inf_gtk_browser_store_browser_notify_status_cb(GObject* object, GParamSpec* pspec, gpointer user_data); static void inf_gtk_browser_store_browser_error_cb(InfBrowser* browser, const GError* error, gpointer user_data); static void inf_gtk_browser_store_node_added_cb(InfBrowser* browser, InfBrowserIter* iter, InfRequest* request, gpointer user_data); static void inf_gtk_browser_store_node_removed_cb(InfBrowser* browser, InfBrowserIter* iter, InfRequest* request, gpointer user_data); static void inf_gtk_browser_store_begin_request_explore_node_cb(InfBrowser* browser, InfBrowserIter* iter, InfRequest* request, gpointer user_data); static void inf_gtk_browser_store_begin_request_subscribe_session_cb(InfBrowser* browser, InfBrowserIter* iter, InfRequest* request, gpointer user_data); static void inf_gtk_browser_store_request_finished_cb(InfRequest* request, const InfRequestResult* result, const GError* error, gpointer user_data); static void inf_gtk_browser_store_request_unrefed_func(gpointer data, GObject* where_the_object_was); /* * InfGtkBrowserStoreItem handling */ static void inf_gtk_browser_store_request_data_free(gpointer data, GClosure* closure) { g_slice_free(InfGtkBrowserStoreRequestData, data); } static void inf_gtk_browser_store_item_request_remove(InfGtkBrowserStoreItem* item, InfRequest* request) { g_object_weak_unref( G_OBJECT(request), inf_gtk_browser_store_request_unrefed_func, item ); inf_signal_handlers_disconnect_by_func( G_OBJECT(request), G_CALLBACK(inf_gtk_browser_store_request_finished_cb), item ); item->requests = g_slist_remove(item->requests, request); } static void inf_gtk_browser_store_item_request_add(InfGtkBrowserStore* store, InfGtkBrowserStoreItem* item, InfRequest* request) { InfGtkBrowserStoreRequestData* data; g_assert(g_slist_find(item->requests, request) == NULL); item->requests = g_slist_prepend(item->requests, request); data = g_slice_new(InfGtkBrowserStoreRequestData); data->store = store; data->item = item; g_signal_connect_data( G_OBJECT(request), "finished", G_CALLBACK(inf_gtk_browser_store_request_finished_cb), data, inf_gtk_browser_store_request_data_free, 0 ); g_object_weak_ref( G_OBJECT(request), inf_gtk_browser_store_request_unrefed_func, item ); } static void inf_gtk_browser_store_request_finished_cb(InfRequest* request, const InfRequestResult* result, const GError* error, gpointer user_data) { InfGtkBrowserStoreRequestData* data; InfGtkBrowserStorePrivate* priv; InfBrowserIter request_iter; gboolean node_exists; GtkTreeIter tree_iter; GtkTreePath* path; data = (InfGtkBrowserStoreRequestData*)user_data; priv = INF_GTK_BROWSER_STORE_PRIVATE(data->store); g_assert(g_slist_find(data->item->requests, request) != NULL); g_assert(data->item->browser != NULL); /* request can be a explore-node or subscribe-session request */ /* TODO: Also remove the request from the store when * it has properly finished? */ if(error != NULL) { node_exists = inf_browser_iter_from_request( data->item->browser, request, &request_iter ); inf_gtk_browser_store_item_request_remove(data->item, request); /* Ignore if node has been removed in the meanwhile */ if(G_LIKELY(node_exists)) { /* Replace previous error */ g_hash_table_insert( data->item->node_errors, GUINT_TO_POINTER(request_iter.node_id), g_error_copy(error) ); tree_iter.stamp = priv->stamp; tree_iter.user_data = data->item; tree_iter.user_data2 = GUINT_TO_POINTER(request_iter.node_id); /* Set NULL for root node because it also refers to the store item as * such if no browser is set. */ if(request_iter.node_id == 0) tree_iter.user_data3 = NULL; else tree_iter.user_data3 = request_iter.node; path = gtk_tree_model_get_path(GTK_TREE_MODEL(data->store), &tree_iter); gtk_tree_model_row_changed(GTK_TREE_MODEL(data->store), path, &tree_iter); gtk_tree_path_free(path); } } } static void inf_gtk_browser_store_request_unrefed_func(gpointer data, GObject* where_the_object_was) { InfGtkBrowserStoreItem* item; item = (InfGtkBrowserStoreItem*)data; /* No need to further unregister */ item->requests = g_slist_remove(item->requests, where_the_object_was); } static void inf_gtk_browser_store_item_set_browser(InfGtkBrowserStore* store, InfGtkBrowserStoreItem* item, GtkTreePath* path, InfBrowser* browser) { GtkTreeIter tree_iter; InfGtkBrowserStorePrivate* priv; priv = INF_GTK_BROWSER_STORE_PRIVATE(store); tree_iter.stamp = priv->stamp; tree_iter.user_data = item; tree_iter.user_data2 = GUINT_TO_POINTER(0); tree_iter.user_data3 = NULL; /* The default signal handler sets the browser in the item and makes the * necessary TreeModel notifications. See * inf_gtk_browser_store_browser_model_set_browser(). */ inf_gtk_browser_model_set_browser( INF_GTK_BROWSER_MODEL(store), path, &tree_iter, item->browser, browser ); } /* takes ownership of name */ static InfGtkBrowserStoreItem* inf_gtk_browser_store_add_item_by_browser(InfGtkBrowserStore* store, InfDiscovery* discovery, InfDiscoveryInfo* info, InfBrowser* browser, gchar* name) { InfGtkBrowserStorePrivate* priv; InfGtkBrowserStoreItem* item; InfGtkBrowserStoreItem* cur; GtkTreePath* path; GtkTreeIter iter; guint index; g_assert( browser == NULL || inf_gtk_browser_store_find_item_by_browser(store, browser) == NULL ); priv = INF_GTK_BROWSER_STORE_PRIVATE(store); item = g_slice_new(InfGtkBrowserStoreItem); item->name = name; item->discovery = discovery; item->info = info; item->status = INF_GTK_BROWSER_MODEL_DISCONNECTED; if(discovery != NULL && info != NULL) item->status = INF_GTK_BROWSER_MODEL_DISCOVERED; item->browser = NULL; item->missing = NULL; item->node_errors = g_hash_table_new_full( NULL, NULL, NULL, (GDestroyNotify)g_error_free ); item->requests = NULL; item->error = NULL; item->next = NULL; index = 0; for(cur = priv->first_item; cur != NULL; cur = cur->next) ++ index; /* Link */ if(priv->first_item == NULL) { priv->first_item = item; priv->last_item = item; } else { priv->last_item->next = item; priv->last_item = item; } path = gtk_tree_path_new_from_indices(index, -1); iter.stamp = priv->stamp; iter.user_data = item; iter.user_data2 = GUINT_TO_POINTER(0); iter.user_data3 = NULL; gtk_tree_model_row_inserted(GTK_TREE_MODEL(store), path, &iter); if(browser != NULL) inf_gtk_browser_store_item_set_browser(store, item, path, browser); gtk_tree_path_free(path); return item; } /* takes ownership of name */ static InfGtkBrowserStoreItem* inf_gtk_browser_store_add_item_by_connection(InfGtkBrowserStore* store, InfDiscovery* discovery, InfDiscoveryInfo* info, InfXmlConnection* connection, gchar* name) { InfGtkBrowserStorePrivate* priv; InfcBrowser* browser; InfGtkBrowserStoreItem* item; g_assert( connection == NULL || inf_gtk_browser_store_find_item_by_connection(store, connection) == NULL ); priv = INF_GTK_BROWSER_STORE_PRIVATE(store); browser = NULL; if(connection != NULL) { browser = infc_browser_new( priv->io, priv->communication_manager, connection ); /* The connection is not set if the browser could not find a "central" * method for the connection's network. I don't think this can happen. */ if(infc_browser_get_connection(browser) == NULL) { g_object_unref(browser); g_free(name); return NULL; } } item = inf_gtk_browser_store_add_item_by_browser( store, discovery, info, INF_BROWSER(browser), name ); if(browser != NULL) g_object_unref(browser); return item; } static void inf_gtk_browser_store_remove_item(InfGtkBrowserStore* store, InfGtkBrowserStoreItem* item) { InfGtkBrowserStorePrivate* priv; InfGtkBrowserStoreItem* prev; InfGtkBrowserStoreItem* cur; GtkTreePath* path; guint index; priv = INF_GTK_BROWSER_STORE_PRIVATE(store); /* Determine index of item, to build a tree path to it */ prev = NULL; index = 0; for(cur = priv->first_item; cur != NULL; cur = cur->next) { if(cur == item) break; prev = cur; ++ index; } /* Item was present in list */ g_assert(cur != NULL); path = gtk_tree_path_new_from_indices(index, -1); /* Note we need to reset the browser before we unlink because * inf_gtk_browser_store_item_set_browser() requires item still being * linked for change notifications. */ /* TODO: This is a bit cumbersome. A better way might be to be able for * the iter parameter to be NULL to indicate that an entry with * its browser has been deleted. However, this would still need to do * lots of the unregistration that is now happening in * inf_gtk_browser_store_item_set_browser(). */ if(item->browser != NULL) { inf_gtk_browser_store_item_set_browser(store, item, path, NULL); g_assert(item->browser == NULL); /* Default handler must run */ } /* Unlink */ if(prev == NULL) priv->first_item = item->next; else prev->next = item->next; if(item->next == NULL) priv->last_item = prev; g_assert(cur != NULL); gtk_tree_model_row_deleted(GTK_TREE_MODEL(store), path); gtk_tree_path_free(path); if(item->error != NULL) g_error_free(item->error); g_hash_table_unref(item->node_errors); g_free(item->name); g_slice_free(InfGtkBrowserStoreItem, item); } /* * Callbacks and signal handlers */ static void inf_gtk_browser_store_discovered_cb(InfDiscovery* discovery, InfDiscoveryInfo* info, gpointer user_data) { inf_gtk_browser_store_add_item_by_browser( INF_GTK_BROWSER_STORE(user_data), discovery, info, NULL, inf_discovery_info_get_service_name(discovery, info) ); } static void inf_gtk_browser_store_undiscovered_cb(InfDiscovery* discovery, InfDiscoveryInfo* info, gpointer user_data) { InfGtkBrowserStore* store; InfGtkBrowserStoreItem* item; store = INF_GTK_BROWSER_STORE(user_data); item = inf_gtk_browser_store_find_item_by_discovery_info(store, info); /* If, after a discovery resove we see that there is already an item for * that connection, then we remove the discovery item, and use the other * item instead. In that case, item can be NULL here. */ if(item != NULL) { if(item->browser == NULL) { inf_gtk_browser_store_remove_item(store, item); } else { g_assert(item->status != INF_GTK_BROWSER_MODEL_DISCOVERED && item->status != INF_GTK_BROWSER_MODEL_RESOLVING); item->discovery = NULL; item->info = NULL; } } } static void inf_gtk_browser_store_browser_error_cb(InfBrowser* browser, const GError* error, gpointer user_data) { InfGtkBrowserStore* store; InfGtkBrowserStoreItem* item; InfGtkBrowserStorePrivate* priv; GtkTreeIter iter; GtkTreePath* path; store = INF_GTK_BROWSER_STORE(user_data); priv = INF_GTK_BROWSER_STORE_PRIVATE(store); item = inf_gtk_browser_store_find_item_by_browser(store, browser); g_assert(item != NULL); /* Overwrite previous error */ if(item->error != NULL) g_error_free(item->error); item->error = g_error_copy(error); /* Don't set error state, this could be a non-fatal error */ /* Notify */ iter.stamp = priv->stamp; iter.user_data = item; iter.user_data2 = GUINT_TO_POINTER(0); iter.user_data3 = NULL; path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &iter); gtk_tree_model_row_changed(GTK_TREE_MODEL(store), path, &iter); gtk_tree_path_free(path); } static void inf_gtk_browser_store_browser_notify_status_cb(GObject* object, GParamSpec* pspec, gpointer user_data) { InfGtkBrowserStore* store; InfGtkBrowserStorePrivate* priv; InfBrowser* browser; InfBrowserStatus status; InfGtkBrowserStoreItem* item; GtkTreeIter iter; GtkTreePath* path; store = INF_GTK_BROWSER_STORE(user_data); priv = INF_GTK_BROWSER_STORE_PRIVATE(user_data); browser = INF_BROWSER(object); item = inf_gtk_browser_store_find_item_by_browser(store, browser); g_assert(item != NULL); iter.stamp = priv->stamp; iter.user_data = item; iter.user_data2 = GUINT_TO_POINTER(0); iter.user_data3 = NULL; path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &iter); g_object_get(G_OBJECT(browser), "status", &status, NULL); switch(status) { case INF_BROWSER_CLOSED: /* TODO: Do we want to go to disconnected state when error is not set? */ item->status = INF_GTK_BROWSER_MODEL_ERROR; /* Set a "Disconnected" error if there is not already one set by * inf_gtk_browser_store_connection_error_cb() that has a more * meaningful error message. */ if(item->error == NULL) { item->error = g_error_new_literal( g_quark_from_static_string("INF_GTK_BROWSER_STORE_ERROR"), 0, _("Disconnected") ); } gtk_tree_model_row_changed(GTK_TREE_MODEL(store), path, &iter); break; case INF_BROWSER_OPENING: if(item->error != NULL) g_error_free(item->error); item->error = NULL; item->status = INF_GTK_BROWSER_MODEL_CONNECTING; gtk_tree_model_row_changed(GTK_TREE_MODEL(store), path, &iter); break; case INF_BROWSER_OPEN: if(item->error != NULL) g_error_free(item->error); item->error = NULL; item->status = INF_GTK_BROWSER_MODEL_CONNECTED; gtk_tree_model_row_changed(GTK_TREE_MODEL(store), path, &iter); break; default: g_assert_not_reached(); break; } gtk_tree_path_free(path); } static void inf_gtk_browser_store_node_added_cb(InfBrowser* browser, InfBrowserIter* iter, InfRequest* request, gpointer user_data) { InfGtkBrowserStore* store; InfGtkBrowserStorePrivate* priv; InfGtkBrowserStoreItem* item; GtkTreeIter tree_iter; GtkTreePath* path; InfBrowserIter test_iter; gboolean test_result; store = INF_GTK_BROWSER_STORE(user_data); priv = INF_GTK_BROWSER_STORE_PRIVATE(store); item = inf_gtk_browser_store_find_item_by_browser(store, browser); tree_iter.stamp = priv->stamp; tree_iter.user_data = item; tree_iter.user_data2 = GUINT_TO_POINTER(iter->node_id); tree_iter.user_data3 = iter->node; if(iter->node_id != 0) { path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &tree_iter); gtk_tree_model_row_inserted(GTK_TREE_MODEL(store), path, &tree_iter); /* If iter is the only node within its parent, we need to emit the * row-has-child-toggled signal. */ test_iter = *iter; test_result = inf_browser_get_parent(browser, &test_iter); g_assert(test_result == TRUE); /* Let tree_iter point to parent row for possible notification */ tree_iter.user_data2 = GUINT_TO_POINTER(test_iter.node_id); /* Also adjust path */ gtk_tree_path_up(path); if(test_iter.node_id == 0) tree_iter.user_data3 = NULL; else tree_iter.user_data3 = test_iter.node; test_result = inf_browser_get_child(browser, &test_iter); g_assert(test_result == TRUE); if(inf_browser_get_next(browser, &test_iter) == FALSE) { gtk_tree_model_row_has_child_toggled( GTK_TREE_MODEL(store), path, &tree_iter ); } gtk_tree_path_free(path); } } static void inf_gtk_browser_store_node_removed_cb(InfBrowser* browser, InfBrowserIter* iter, InfRequest* request, gpointer user_data) { InfGtkBrowserStore* store; InfGtkBrowserStorePrivate* priv; InfGtkBrowserStoreItem* item; GtkTreeIter tree_iter; GtkTreePath* path; InfBrowserIter test_iter; gboolean test_result; store = INF_GTK_BROWSER_STORE(user_data); priv = INF_GTK_BROWSER_STORE_PRIVATE(store); item = inf_gtk_browser_store_find_item_by_browser(store, browser); g_assert(item->missing == NULL); tree_iter.stamp = priv->stamp; tree_iter.user_data = item; tree_iter.user_data2 = GUINT_TO_POINTER(iter->node_id); tree_iter.user_data3 = iter->node; path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &tree_iter); /* This is a small hack to have the item removed from the tree * model before it is removed from the InfcBrowser. */ item->missing = iter->node; if(iter->node_id != 0) { gtk_tree_model_row_deleted(GTK_TREE_MODEL(store), path); /* TODO: Remove requests and node errors from nodes below the removed one */ /* Note that at this point removed node is still in the browser. We have * to emit row-has-child-toggled if it is the only one in its * subdirectory. */ test_iter = *iter; test_result = inf_browser_get_parent(browser, &test_iter); g_assert(test_result == TRUE); /* Let tree_iter point to parent row for possible notification */ tree_iter.user_data2 = GUINT_TO_POINTER(test_iter.node_id); /* Also adjust path */ gtk_tree_path_up(path); if(test_iter.node_id == 0) tree_iter.user_data3 = NULL; else tree_iter.user_data3 = test_iter.node; test_result = inf_browser_get_child(browser, &test_iter); g_assert(test_result == TRUE); if(inf_browser_get_next(browser, &test_iter) == FALSE) { gtk_tree_model_row_has_child_toggled( GTK_TREE_MODEL(store), path, &tree_iter ); } } else { /* The root node was removed. We don't remove the node from the * GtkTreeModel because it still represents the InfBrowser. Remove * all the children, however. */ if(inf_browser_get_explored(browser, iter)) { test_iter = *iter; test_result = inf_browser_get_child(browser, &test_iter); gtk_tree_path_down(path); do { gtk_tree_model_row_deleted(GTK_TREE_MODEL(store), path); } while(inf_browser_get_next(browser, &test_iter)); if(test_result == TRUE) { gtk_tree_path_up(path); gtk_tree_model_row_has_child_toggled( GTK_TREE_MODEL(store), path, &tree_iter ); } } } item->missing = NULL; gtk_tree_path_free(path); } static void inf_gtk_browser_store_begin_request_explore_node_cb(InfBrowser* browser, InfBrowserIter* iter, InfRequest* request, gpointer user_data) { InfGtkBrowserStore* store; InfGtkBrowserStoreItem* item; store = INF_GTK_BROWSER_STORE(user_data); item = inf_gtk_browser_store_find_item_by_browser(store, browser); inf_gtk_browser_store_item_request_add(store, item, request); } static void inf_gtk_browser_store_begin_request_subscribe_session_cb(InfBrowser* browser, InfBrowserIter* iter, InfRequest* request, gpointer user_data) { InfGtkBrowserStore* store; InfGtkBrowserStoreItem* item; /* should not be a chat session, because chat session * has type subscribe-chat */ g_assert(iter != NULL); store = INF_GTK_BROWSER_STORE(user_data); item = inf_gtk_browser_store_find_item_by_browser(store, browser); inf_gtk_browser_store_item_request_add(store, item, request); } static void inf_gtk_browser_store_resolv_complete_func(InfDiscoveryInfo* info, InfXmlConnection* connection, const GError* error, gpointer user_data) { InfGtkBrowserStore* store; InfGtkBrowserStorePrivate* priv; InfGtkBrowserStoreItem* new_item; InfGtkBrowserStoreItem* old_item; GtkTreeIter tree_iter; GtkTreePath* path; InfcBrowser* browser; InfGtkBrowserStoreItem* cur; InfGtkBrowserStoreItem* prev; InfGtkBrowserStoreItem* prev_new; InfGtkBrowserStoreItem* prev_old; gint* order; guint count; guint new_pos; guint old_pos; guint i; store = INF_GTK_BROWSER_STORE(user_data); priv = INF_GTK_BROWSER_STORE_PRIVATE(store); new_item = inf_gtk_browser_store_find_item_by_discovery_info(store, info); g_assert(new_item != NULL); g_assert(new_item->status == INF_GTK_BROWSER_MODEL_RESOLVING); tree_iter.stamp = priv->stamp; tree_iter.user_data = new_item; tree_iter.user_data2 = GUINT_TO_POINTER(0); tree_iter.user_data3 = NULL; if(error != NULL) { new_item->status = INF_GTK_BROWSER_MODEL_ERROR; new_item->error = g_error_copy(error); path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &tree_iter); gtk_tree_model_row_changed(GTK_TREE_MODEL(store), path, &tree_iter); gtk_tree_path_free(path); } else { old_item = inf_gtk_browser_store_find_item_by_connection(store, connection); if(old_item != NULL) { g_assert(old_item != new_item); /* There is already an item with the same connection. This is perhaps * from another discovery or was inserted directly. We remove the * current item and move the existing one to the place of it. */ count = 0; prev = NULL; for(cur = priv->first_item; cur != NULL; cur = cur->next) { if(cur == old_item) { old_pos = count; prev_old = prev; } if(cur == new_item) { new_pos = count; prev_new = prev; } ++ count; prev = cur; } inf_gtk_browser_store_remove_item(store, new_item); if(old_pos > new_pos) -- old_pos; else -- new_pos; -- count; /* Reorder list if the two items were not adjacent */ if(new_pos != old_pos) { /* old item is last element, but it is moved elsewhere */ if(old_item->next == NULL) priv->last_item = prev_old; /* Unlink old_item */ if(prev_old != NULL) prev_old->next = old_item->next; else priv->first_item = old_item->next; /* Relink */ old_item->next = prev_new->next; if(prev_new != NULL) prev_new->next = old_item; else priv->first_item = old_item; /* old_item has been moved to end of list */ if(old_item->next == NULL) priv->last_item = old_item; order = g_malloc(sizeof(gint) * count); if(new_pos < old_pos) { for(i = 0; i < new_pos; ++ i) order[i] = i; order[new_pos] = old_pos; for(i = new_pos + 1; i <= old_pos; ++ i) order[i] = i - 1; for(i = old_pos + 1; i < count; ++ i) order[i] = i; } else { for(i = 0; i < old_pos; ++ i) order[i] = i; for(i = old_pos; i < new_pos; ++ i) order[i] = i + 1; order[new_pos] = old_pos; for(i = new_pos + 1; i < count; ++ i) order[i] = i; } path = gtk_tree_path_new(); gtk_tree_model_rows_reordered( GTK_TREE_MODEL(store), path, NULL, order ); gtk_tree_path_free(path); /* TODO: Perhaps we should emit a signal so that the view can * highlight and scroll to the existing item. And also so that it can * over initial root exploration. */ g_free(order); } } else { path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &tree_iter); browser = infc_browser_new( priv->io, priv->communication_manager, connection ); /* The connection is not set if the browser could not find a "central" * method for the connection's network. */ /* TODO: Set error */ if(infc_browser_get_connection(browser) != NULL) { inf_gtk_browser_store_item_set_browser( store, new_item, path, INF_BROWSER(browser) ); } g_object_unref(G_OBJECT(browser)); gtk_tree_path_free(path); } } } /* * GObject overrides */ static void inf_gtk_browser_store_init(InfGtkBrowserStore* store) { InfGtkBrowserStorePrivate* priv; priv = INF_GTK_BROWSER_STORE_PRIVATE(store); priv->stamp = g_random_int(); priv->io = NULL; priv->communication_manager = NULL; priv->discoveries = NULL; priv->first_item = NULL; priv->last_item = NULL; } static void inf_gtk_browser_store_dispose(GObject* object) { InfGtkBrowserStore* store; InfGtkBrowserStorePrivate* priv; GSList* item; store = INF_GTK_BROWSER_STORE(object); priv = INF_GTK_BROWSER_STORE_PRIVATE(store); while(priv->first_item != NULL) inf_gtk_browser_store_remove_item(store, priv->first_item); g_assert(priv->last_item == NULL); for(item = priv->discoveries; item != NULL; item = g_slist_next(item)) { inf_signal_handlers_disconnect_by_func( G_OBJECT(item->data), G_CALLBACK(inf_gtk_browser_store_discovered_cb), store ); inf_signal_handlers_disconnect_by_func( G_OBJECT(item->data), G_CALLBACK(inf_gtk_browser_store_undiscovered_cb), store ); g_object_unref(G_OBJECT(item->data)); } g_slist_free(priv->discoveries); priv->discoveries = NULL; if(priv->communication_manager != NULL) { g_object_unref(priv->communication_manager); priv->communication_manager = NULL; } if(priv->io != NULL) { g_object_unref(G_OBJECT(priv->io)); priv->io = NULL; } G_OBJECT_CLASS(inf_gtk_browser_store_parent_class)->dispose(object); } static void inf_gtk_browser_store_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfGtkBrowserStore* store; InfGtkBrowserStorePrivate* priv; store = INF_GTK_BROWSER_STORE(object); priv = INF_GTK_BROWSER_STORE_PRIVATE(store); switch(prop_id) { case PROP_IO: g_assert(priv->io == NULL); /* construct only */ priv->io = INF_IO(g_value_dup_object(value)); break; case PROP_COMMUNICATION_MANAGER: g_assert(priv->communication_manager == NULL); /* construct only */ priv->communication_manager = INF_COMMUNICATION_MANAGER(g_value_dup_object(value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void inf_gtk_browser_store_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfGtkBrowserStore* store; InfGtkBrowserStorePrivate* priv; store = INF_GTK_BROWSER_STORE(object); priv = INF_GTK_BROWSER_STORE_PRIVATE(store); switch(prop_id) { case PROP_IO: g_value_set_object(value, priv->io); break; case PROP_COMMUNICATION_MANAGER: g_value_set_object(value, priv->communication_manager); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } /* * GtkTreeModel implementation */ static GtkTreeModelFlags inf_gtk_browser_store_tree_model_get_flags(GtkTreeModel* model) { return GTK_TREE_MODEL_ITERS_PERSIST; } static gint inf_gtk_browser_store_tree_model_get_n_columns(GtkTreeModel* model) { return INF_GTK_BROWSER_MODEL_NUM_COLS; } static GType inf_gtk_browser_store_tree_model_get_column_type(GtkTreeModel* model, gint index) { switch(index) { case INF_GTK_BROWSER_MODEL_COL_DISCOVERY_INFO: return G_TYPE_POINTER; case INF_GTK_BROWSER_MODEL_COL_DISCOVERY: return INF_TYPE_DISCOVERY; case INF_GTK_BROWSER_MODEL_COL_BROWSER: return INFC_TYPE_BROWSER; case INF_GTK_BROWSER_MODEL_COL_STATUS: return INF_GTK_TYPE_BROWSER_MODEL_STATUS; case INF_GTK_BROWSER_MODEL_COL_NAME: return G_TYPE_STRING; case INF_GTK_BROWSER_MODEL_COL_ERROR: return G_TYPE_POINTER; case INF_GTK_BROWSER_MODEL_COL_NODE: return INF_TYPE_BROWSER_ITER; default: g_assert_not_reached(); return G_TYPE_INVALID; } } static gboolean inf_gtk_browser_store_tree_model_get_iter(GtkTreeModel* model, GtkTreeIter* iter, GtkTreePath* path) { InfGtkBrowserStorePrivate* priv; InfGtkBrowserStoreItem* item; InfBrowserIter browser_iter; gint* indices; guint i; guint n; priv = INF_GTK_BROWSER_STORE_PRIVATE(model); if(gtk_tree_path_get_depth(path) == 0) return FALSE; indices = gtk_tree_path_get_indices(path); n = indices[0]; i = 0; for(item = priv->first_item; item != NULL && i < n; item = item->next) ++i; if(item == NULL) return FALSE; /* Depth 1 */ if(gtk_tree_path_get_depth(path) == 1) { iter->stamp = priv->stamp; iter->user_data = item; iter->user_data2 = GUINT_TO_POINTER(0); iter->user_data3 = NULL; return TRUE; } if(item->browser == NULL) return FALSE; inf_browser_get_root(item->browser, &browser_iter); for(n = 1; n < (guint)gtk_tree_path_get_depth(path); ++ n) { if(inf_browser_get_explored(item->browser, &browser_iter) == FALSE) return FALSE; if(inf_browser_get_child(item->browser, &browser_iter) == FALSE) return FALSE; /* skip missing */ if(browser_iter.node == item->missing) ++indices[n]; for(i = 0; i < (guint)indices[n]; ++ i) { if(inf_browser_get_next(item->browser, &browser_iter) == FALSE) return FALSE; /* skip missing */ if(browser_iter.node == item->missing) ++indices[n]; } } iter->stamp = priv->stamp; iter->user_data = item; iter->user_data2 = GUINT_TO_POINTER(browser_iter.node_id); iter->user_data3 = browser_iter.node; return TRUE; } /* TODO: We can also use gtk_tree_path_prepend_index and do tail * recursion. We should find out which is faster. */ static void inf_gtk_browser_store_tree_model_get_path_impl(InfGtkBrowserStore* store, InfGtkBrowserStoreItem* item, InfBrowserIter* iter, GtkTreePath* path) { InfGtkBrowserStorePrivate* priv; InfBrowserIter cur_iter; InfGtkBrowserStoreItem* cur; gboolean result; guint n; cur_iter = *iter; if(inf_browser_get_parent(item->browser, &cur_iter) == FALSE) { priv = INF_GTK_BROWSER_STORE_PRIVATE(store); /* We are on top level, but still need to find the item index */ n = 0; for(cur = priv->first_item; cur != item; cur = cur->next) ++n; gtk_tree_path_append_index(path, n); } else { inf_gtk_browser_store_tree_model_get_path_impl( store, item, &cur_iter, path ); result = inf_browser_get_child(item->browser, &cur_iter); g_assert(result == TRUE); /* skip missing */ if(cur_iter.node == item->missing) { result = inf_browser_get_next(item->browser, &cur_iter); g_assert(result == TRUE); } n = 0; while(cur_iter.node_id != iter->node_id) { result = inf_browser_get_next(item->browser, &cur_iter); g_assert(result == TRUE); /* skip missing */ if(cur_iter.node == item->missing) { result = inf_browser_get_next(item->browser, &cur_iter); g_assert(result == TRUE); } ++n; } gtk_tree_path_append_index(path, n); } } static GtkTreePath* inf_gtk_browser_store_tree_model_get_path(GtkTreeModel* model, GtkTreeIter* iter) { InfGtkBrowserStorePrivate* priv; InfGtkBrowserStoreItem* item; InfGtkBrowserStoreItem* cur; GtkTreePath* path; InfBrowserIter browser_iter; guint n; priv = INF_GTK_BROWSER_STORE_PRIVATE(model); g_assert(iter->stamp == priv->stamp); g_assert(iter->user_data != NULL); item = (InfGtkBrowserStoreItem*)iter->user_data; path = gtk_tree_path_new(); browser_iter.node_id = GPOINTER_TO_UINT(iter->user_data2); browser_iter.node = iter->user_data3; if(browser_iter.node != NULL) { g_assert(item->browser != NULL); inf_gtk_browser_store_tree_model_get_path_impl( INF_GTK_BROWSER_STORE(model), item, &browser_iter, path ); } else { /* toplevel */ n = 0; for(cur = priv->first_item; cur != item; cur = cur->next) ++n; gtk_tree_path_append_index(path, n); } return path; } static void inf_gtk_browser_store_tree_model_get_value(GtkTreeModel* model, GtkTreeIter* iter, gint column, GValue* value) { InfGtkBrowserStorePrivate* priv; InfGtkBrowserStoreItem* item; InfBrowserIter browser_iter; InfBrowserStatus browser_status; GError* error; priv = INF_GTK_BROWSER_STORE_PRIVATE(model); g_assert(iter->stamp == priv->stamp); item = (InfGtkBrowserStoreItem*)iter->user_data; browser_iter.node_id = GPOINTER_TO_UINT(iter->user_data2); browser_iter.node = iter->user_data3; /* If this iterator is the missing one, then it must be the root node, * otherwise this function must not have been called; it would have * been called on a non-existing entry. */ g_assert( item->missing == NULL || browser_iter.node_id == 0 || browser_iter.node != item->missing ); switch(column) { case INF_GTK_BROWSER_MODEL_COL_DISCOVERY_INFO: g_value_init(value, G_TYPE_POINTER); g_value_set_pointer(value, item->info); break; case INF_GTK_BROWSER_MODEL_COL_DISCOVERY: g_value_init(value, G_TYPE_OBJECT); g_value_set_object(value, item->discovery); break; case INF_GTK_BROWSER_MODEL_COL_BROWSER: g_value_init(value, INF_TYPE_BROWSER); g_value_set_object(value, G_OBJECT(item->browser)); break; case INF_GTK_BROWSER_MODEL_COL_STATUS: g_assert(browser_iter.node == NULL); /* only toplevel */ g_value_init(value, INF_GTK_TYPE_BROWSER_MODEL_STATUS); g_value_set_enum(value, item->status); break; case INF_GTK_BROWSER_MODEL_COL_NAME: g_value_init(value, G_TYPE_STRING); if(browser_iter.node == NULL) { g_value_set_string(value, item->name); } else { g_value_set_string( value, inf_browser_get_node_name(INF_BROWSER(item->browser), &browser_iter) ); } break; case INF_GTK_BROWSER_MODEL_COL_ERROR: if(browser_iter.node == NULL) { /* toplevel */ if(item->error != NULL) { /* not a node related error, perhaps connection error */ error = item->error; } else if(item->browser != NULL) { /* error on root node */ g_object_get( G_OBJECT(item->browser), "status", &browser_status, NULL ); if(browser_status == INF_BROWSER_OPEN) { inf_browser_get_root(item->browser, &browser_iter); error = g_hash_table_lookup( item->node_errors, GUINT_TO_POINTER(browser_iter.node_id) ); } else { /* Browser exists but is closed, but there is no connection error * set: no error */ error = NULL; } } else { /* Neither error nor browser set: no error */ error = NULL; } } else { g_assert(item->browser != NULL); g_object_get(G_OBJECT(item->browser), "status", &browser_status, NULL); g_assert(browser_status == INF_BROWSER_OPEN); error = g_hash_table_lookup( item->node_errors, GUINT_TO_POINTER(browser_iter.node_id) ); } g_value_init(value, G_TYPE_POINTER); g_value_set_pointer(value, error); break; case INF_GTK_BROWSER_MODEL_COL_NODE: g_assert(item->browser != NULL); g_object_get(G_OBJECT(item->browser), "status", &browser_status, NULL); g_assert(browser_status == INF_BROWSER_OPEN); if(browser_iter.node == NULL) inf_browser_get_root(item->browser, &browser_iter); g_value_init(value, INF_TYPE_BROWSER_ITER); g_value_set_boxed(value, &browser_iter); break; default: g_assert_not_reached(); break; } } static gboolean inf_gtk_browser_store_tree_model_iter_next(GtkTreeModel* model, GtkTreeIter* iter) { InfGtkBrowserStorePrivate* priv; InfGtkBrowserStoreItem* item; InfBrowserIter browser_iter; priv = INF_GTK_BROWSER_STORE_PRIVATE(model); g_assert(iter->stamp == priv->stamp); item = (InfGtkBrowserStoreItem*)iter->user_data; browser_iter.node_id = GPOINTER_TO_UINT(iter->user_data2); browser_iter.node = iter->user_data3; if(browser_iter.node == NULL) { if(item->next == NULL) return FALSE; iter->user_data = item->next; return TRUE; } else { g_assert(browser_iter.node != item->missing); if(inf_browser_get_next(item->browser, &browser_iter) == FALSE) return FALSE; /* skip missing */ if(browser_iter.node == item->missing) if(inf_browser_get_next(item->browser, &browser_iter) == FALSE) return FALSE; iter->user_data2 = GUINT_TO_POINTER(browser_iter.node_id); iter->user_data3 = browser_iter.node; return TRUE; } } static gboolean inf_gtk_browser_store_tree_model_iter_children(GtkTreeModel* model, GtkTreeIter* iter, GtkTreeIter* parent) { InfGtkBrowserStorePrivate* priv; InfGtkBrowserStoreItem* item; InfBrowserStatus browser_status; InfBrowserIter browser_iter; priv = INF_GTK_BROWSER_STORE_PRIVATE(model); if(parent == NULL) { if(priv->first_item == NULL) return FALSE; iter->stamp = priv->stamp; iter->user_data = priv->first_item; iter->user_data2 = GUINT_TO_POINTER(0); iter->user_data3 = NULL; return TRUE; } else { g_assert(parent->stamp == priv->stamp); item = (InfGtkBrowserStoreItem*)parent->user_data; if(item->browser == NULL) return FALSE; g_object_get(G_OBJECT(item->browser), "status", &browser_status, NULL); if(browser_status != INF_BROWSER_OPEN) return FALSE; browser_iter.node_id = GPOINTER_TO_UINT(parent->user_data2); if(browser_iter.node_id == 0) inf_browser_get_root(item->browser, &browser_iter); else browser_iter.node = parent->user_data3; /* If this iterator is the missing one, then it must be the root node, * otherwise this function must not have been called; it would have * been called on a non-existing entry. */ g_assert( item->missing == NULL || browser_iter.node_id == 0 || browser_iter.node != item->missing ); if(item->missing != NULL && browser_iter.node == item->missing) return FALSE; if(!inf_browser_is_subdirectory(item->browser, &browser_iter)) return FALSE; if(!inf_browser_get_explored(item->browser, &browser_iter)) return FALSE; if(!inf_browser_get_child(item->browser, &browser_iter)) return FALSE; if(browser_iter.node == item->missing) if(!inf_browser_get_next(item->browser, &browser_iter)) return FALSE; iter->stamp = priv->stamp; iter->user_data = item; iter->user_data2 = GUINT_TO_POINTER(browser_iter.node_id); iter->user_data3 = browser_iter.node; return TRUE; } } static gboolean inf_gtk_browser_store_tree_model_iter_has_child(GtkTreeModel* model, GtkTreeIter* iter) { InfGtkBrowserStorePrivate* priv; InfGtkBrowserStoreItem* item; InfBrowserStatus status; InfBrowserIter browser_iter; priv = INF_GTK_BROWSER_STORE_PRIVATE(model); g_assert(iter->stamp == priv->stamp); item = (InfGtkBrowserStoreItem*)iter->user_data; if(item->browser == NULL) return FALSE; browser_iter.node_id = GPOINTER_TO_UINT(iter->user_data2); browser_iter.node = iter->user_data3; g_object_get(G_OBJECT(item->browser), "status", &status, NULL); if(status != INF_BROWSER_OPEN) return FALSE; if(browser_iter.node == NULL) inf_browser_get_root(item->browser, &browser_iter); /* If this iterator is the missing one, then it must be the root node, * otherwise this function must not have been called; it would have * been called on a non-existing entry. */ g_assert( item->missing == NULL || browser_iter.node_id == 0 || browser_iter.node != item->missing ); if(item->missing != NULL && browser_iter.node == item->missing) return FALSE; if(inf_browser_is_subdirectory(item->browser, &browser_iter) == FALSE) return FALSE; if(inf_browser_get_explored(item->browser, &browser_iter) == FALSE) return FALSE; if(!inf_browser_get_child(item->browser, &browser_iter)) return FALSE; if(browser_iter.node == item->missing) if(!inf_browser_get_next(item->browser, &browser_iter)) return FALSE; return TRUE; } static gint inf_gtk_browser_store_tree_model_iter_n_children(GtkTreeModel* model, GtkTreeIter* iter) { InfGtkBrowserStorePrivate* priv; InfGtkBrowserStoreItem* item; InfGtkBrowserStoreItem* cur; InfBrowserIter browser_iter; gboolean result; guint n; priv = INF_GTK_BROWSER_STORE_PRIVATE(model); g_assert(iter == NULL || iter->stamp == priv->stamp); if(iter == NULL) { n = 0; for(cur = priv->first_item; cur != NULL; cur = cur->next) ++n; return n; } else { item = (InfGtkBrowserStoreItem*)iter->user_data; browser_iter.node_id = GPOINTER_TO_UINT(iter->user_data2); browser_iter.node = iter->user_data3; if(browser_iter.node == NULL) inf_browser_get_root(item->browser, &browser_iter); /* If this iterator is the missing one, then it must be the root node, * otherwise this function must not have been called; it would have * been called on a non-existing entry. */ g_assert( item->missing == NULL || browser_iter.node_id == 0 || browser_iter.node != item->missing ); if(item->missing != NULL && browser_iter.node == item->missing) return 0; n = 0; for(result = inf_browser_get_child(item->browser, &browser_iter); result == TRUE; result = inf_browser_get_next(item->browser, &browser_iter)) { if(browser_iter.node != item->missing) ++n; } return n; } } static gboolean inf_gtk_browser_store_tree_model_iter_nth_child(GtkTreeModel* model, GtkTreeIter* iter, GtkTreeIter* parent, gint n) { InfGtkBrowserStorePrivate* priv; InfGtkBrowserStoreItem* item; InfGtkBrowserStoreItem* cur; InfBrowserIter browser_iter; guint i; priv = INF_GTK_BROWSER_STORE_PRIVATE(model); if(parent == NULL) { cur = priv->first_item; if(cur == NULL) return FALSE; for(i = 0; i < (guint)n; ++ i) { cur = cur->next; if(cur == NULL) return FALSE; } iter->stamp = priv->stamp; iter->user_data = cur; iter->user_data2 = GUINT_TO_POINTER(0); iter->user_data3 = NULL; return TRUE; } else { g_assert(parent->stamp == priv->stamp); item = (InfGtkBrowserStoreItem*)parent->user_data; browser_iter.node_id = GPOINTER_TO_UINT(parent->user_data2); if(browser_iter.node_id == 0) inf_browser_get_root(item->browser, &browser_iter); else browser_iter.node = parent->user_data3; /* If this iterator is the missing one, then it must be the root node, * otherwise this function must not have been called; it would have * been called on a non-existing entry. */ g_assert( item->missing == NULL || browser_iter.node_id == 0 || browser_iter.node != item->missing ); if(item->missing != NULL && browser_iter.node == item->missing) return FALSE; if(inf_browser_get_explored(item->browser, &browser_iter) == FALSE) return FALSE; if(inf_browser_get_child(item->browser, &browser_iter) == FALSE) return FALSE; /* skip missing */ if(browser_iter.node == item->missing) ++n; for(i = 0; i < (guint)n; ++ i) { if(inf_browser_get_next(item->browser, &browser_iter) == FALSE) return FALSE; if(browser_iter.node == item->missing) ++n; } iter->stamp = priv->stamp; iter->user_data = item; iter->user_data2 = GUINT_TO_POINTER(browser_iter.node_id); iter->user_data3 = browser_iter.node; return TRUE; } } static gboolean inf_gtk_browser_store_tree_model_iter_parent(GtkTreeModel* model, GtkTreeIter* iter, GtkTreeIter* child) { InfGtkBrowserStorePrivate* priv; InfGtkBrowserStoreItem* item; InfBrowserIter browser_iter; gboolean result; priv = INF_GTK_BROWSER_STORE_PRIVATE(model); g_assert(child->stamp == priv->stamp); item = (InfGtkBrowserStoreItem*)child->user_data; browser_iter.node_id = GPOINTER_TO_UINT(child->user_data2); browser_iter.node = child->user_data3; if(browser_iter.node == NULL) return FALSE; g_assert(browser_iter.node != item->missing); result = inf_browser_get_parent(item->browser, &browser_iter); g_assert(result == TRUE); g_assert(browser_iter.node != item->missing); iter->stamp = priv->stamp; iter->user_data = item; iter->user_data2 = GUINT_TO_POINTER(browser_iter.node_id); iter->user_data3 = browser_iter.node; /* Root node */ if(browser_iter.node_id == 0) iter->user_data3 = NULL; return TRUE; } /* * InfGtkBrowserModel implementation. */ static void inf_gtk_browser_store_browser_model_set_browser(InfGtkBrowserModel* model, GtkTreePath* path, GtkTreeIter* tree_iter, InfBrowser* old_browser, InfBrowser* new_browser) { InfGtkBrowserStorePrivate* priv; InfGtkBrowserStoreItem* item; InfBrowserIter iter; guint n; gboolean had_children; InfBrowserStatus status; priv = INF_GTK_BROWSER_STORE_PRIVATE(model); had_children = FALSE; item = (InfGtkBrowserStoreItem*)tree_iter->user_data; /* cannot set browser in non-toplevel entries */ g_assert(tree_iter->user_data3 == NULL); if(item->browser != NULL) { g_assert(item->browser == old_browser); g_object_get(G_OBJECT(item->browser), "status", &status, NULL); if(status == INF_BROWSER_OPEN) { /* Notify about deleted rows. Notify in reverse order so that indexing * continues to work. Remember whether we had children to emit * row-has-child-toggled later. */ inf_browser_get_root(item->browser, &iter); if(inf_browser_get_explored(item->browser, &iter) && inf_browser_get_child(item->browser, &iter)) { n = 1; while(inf_browser_get_next(item->browser, &iter)) ++ n; gtk_tree_path_append_index(path, n); for(; n > 0; -- n) { had_children = TRUE; gtk_tree_path_prev(path); gtk_tree_model_row_deleted(GTK_TREE_MODEL(model), path); } gtk_tree_path_up(path); } } while(item->requests != NULL) inf_gtk_browser_store_item_request_remove(item, item->requests->data); g_hash_table_remove_all(item->node_errors); inf_signal_handlers_disconnect_by_func( G_OBJECT(item->browser), G_CALLBACK(inf_gtk_browser_store_browser_error_cb), model ); inf_signal_handlers_disconnect_by_func( G_OBJECT(item->browser), G_CALLBACK(inf_gtk_browser_store_browser_notify_status_cb), model ); inf_signal_handlers_disconnect_by_func( G_OBJECT(item->browser), G_CALLBACK(inf_gtk_browser_store_node_added_cb), model ); inf_signal_handlers_disconnect_by_func( G_OBJECT(item->browser), G_CALLBACK(inf_gtk_browser_store_node_removed_cb), model ); inf_signal_handlers_disconnect_by_func( G_OBJECT(item->browser), G_CALLBACK(inf_gtk_browser_store_begin_request_explore_node_cb), model ); inf_signal_handlers_disconnect_by_func( G_OBJECT(item->browser), G_CALLBACK(inf_gtk_browser_store_begin_request_subscribe_session_cb), model ); g_object_unref(G_OBJECT(item->browser)); } /* Reset browser for emitting row-has-child-toggled */ item->browser = NULL; if(had_children) { gtk_tree_model_row_has_child_toggled( GTK_TREE_MODEL(model), path, tree_iter ); } /* Set up new browser */ item->browser = new_browser; if(new_browser != NULL) { g_object_ref(new_browser); g_signal_connect( G_OBJECT(item->browser), "error", G_CALLBACK(inf_gtk_browser_store_browser_error_cb), model ); g_signal_connect( G_OBJECT(item->browser), "notify::status", G_CALLBACK(inf_gtk_browser_store_browser_notify_status_cb), model ); g_signal_connect_after( G_OBJECT(item->browser), "node-added", G_CALLBACK(inf_gtk_browser_store_node_added_cb), model ); g_signal_connect_after( G_OBJECT(item->browser), "node-removed", G_CALLBACK(inf_gtk_browser_store_node_removed_cb), model ); g_signal_connect_after( G_OBJECT(item->browser), "begin-request::explore-node", G_CALLBACK(inf_gtk_browser_store_begin_request_explore_node_cb), model ); g_signal_connect_after( G_OBJECT(item->browser), "begin-request::subscribe-session", G_CALLBACK(inf_gtk_browser_store_begin_request_subscribe_session_cb), model ); /* TODO: Walk browser for requests */ } /* Set status to invalid if there aren't any connection information anymore. * Keep the item if an error is set, so it can be displayed. */ if(item->browser == NULL && item->info == NULL && (item->error == NULL || item->status != INF_GTK_BROWSER_MODEL_ERROR)) { /* This can happen when an API call leads to a browser being unset */ /* Clear non-fatal error */ g_assert(item->status != INF_GTK_BROWSER_MODEL_ERROR); if(item->error != NULL) { g_error_free(item->error); item->error = NULL; } item->status = INF_GTK_BROWSER_MODEL_INVALID; } else if(item->status != INF_GTK_BROWSER_MODEL_ERROR) { /* Set item status according to browser status if there is no * error set. */ if(item->browser != NULL) { g_object_get(G_OBJECT(item->browser), "status", &status, NULL); switch(status) { case INF_BROWSER_CLOSED: item->status = INF_GTK_BROWSER_MODEL_DISCONNECTED; break; case INF_BROWSER_OPENING: item->status = INF_GTK_BROWSER_MODEL_CONNECTING; break; case INF_BROWSER_OPEN: item->status = INF_GTK_BROWSER_MODEL_CONNECTED; break; default: g_assert_not_reached(); break; } } else { /* No browser available. Discovery needs to be set now, otherwise * we would have set the status to invalid above. */ g_assert(item->info != NULL); item->status = INF_GTK_BROWSER_MODEL_DISCOVERED; } } else { /* Error needs to be set in error status */ g_assert(item->error != NULL); } /* TODO: Emit row_inserted for the whole tree in browser, and * row-has-child-toggled where appropriate. */ gtk_tree_model_row_changed(GTK_TREE_MODEL(model), path, tree_iter); if(item->browser != NULL && item->status == INF_GTK_BROWSER_MODEL_CONNECTED) { inf_browser_get_root(item->browser, &iter); if(inf_browser_get_explored(item->browser, &iter) && inf_browser_get_child(item->browser, &iter)) { gtk_tree_model_row_has_child_toggled( GTK_TREE_MODEL(model), path, tree_iter ); } } } static void inf_gtk_browser_store_browser_model_resolve(InfGtkBrowserModel* model, InfDiscovery* discovery, InfDiscoveryInfo* info) { InfGtkBrowserStorePrivate* priv; InfGtkBrowserStoreItem* item; GtkTreeIter tree_iter; GtkTreePath* path; g_assert(INF_GTK_IS_BROWSER_STORE(model)); priv = INF_GTK_BROWSER_STORE_PRIVATE(model); item = inf_gtk_browser_store_find_item_by_discovery_info( INF_GTK_BROWSER_STORE(model), info ); g_assert(item != NULL); g_assert( item->status == INF_GTK_BROWSER_MODEL_DISCOVERED || item->status == INF_GTK_BROWSER_MODEL_ERROR ); if(item->status == INF_GTK_BROWSER_MODEL_ERROR) { g_assert(item->error != NULL); g_error_free(item->error); item->error = NULL; item->status = INF_GTK_BROWSER_MODEL_RESOLVING; } else { item->status = INF_GTK_BROWSER_MODEL_RESOLVING; } tree_iter.stamp = priv->stamp; tree_iter.user_data = item; tree_iter.user_data2 = GUINT_TO_POINTER(0); tree_iter.user_data3 = NULL; path = gtk_tree_model_get_path(GTK_TREE_MODEL(model), &tree_iter); gtk_tree_model_row_changed(GTK_TREE_MODEL(model), path, &tree_iter); gtk_tree_path_free(path); inf_discovery_resolve( discovery, info, inf_gtk_browser_store_resolv_complete_func, model ); } static gboolean inf_gtk_browser_store_browser_iter_to_tree_iter(InfGtkBrowserModel* model, InfBrowser* browser, const InfBrowserIter* iter, GtkTreeIter* tree_iter) { InfGtkBrowserStorePrivate* priv; InfGtkBrowserStoreItem* item; g_assert(INF_GTK_IS_BROWSER_STORE(model)); priv = INF_GTK_BROWSER_STORE_PRIVATE(model); item = inf_gtk_browser_store_find_item_by_browser( INF_GTK_BROWSER_STORE(model), browser ); if(item == NULL || (iter != NULL && item->missing == iter->node)) return FALSE; tree_iter->stamp = priv->stamp; tree_iter->user_data = item; if(iter != NULL && iter->node_id != 0) { tree_iter->user_data2 = GUINT_TO_POINTER(iter->node_id); tree_iter->user_data3 = iter->node; } else { /* Root node */ tree_iter->user_data2 = 0; tree_iter->user_data3 = NULL; } return TRUE; } /* * GType registration */ static void inf_gtk_browser_store_class_init(InfGtkBrowserStoreClass* browser_store_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(browser_store_class); object_class->dispose = inf_gtk_browser_store_dispose; object_class->set_property = inf_gtk_browser_store_set_property; object_class->get_property = inf_gtk_browser_store_get_property; g_object_class_install_property( object_class, PROP_IO, g_param_spec_object( "io", "IO", "The IO object used for the created browsers to schedule timeouts", INF_TYPE_IO, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_COMMUNICATION_MANAGER, g_param_spec_object( "communication-manager", "Communication manager", "The communication manager used for browsing remote directories", INF_COMMUNICATION_TYPE_MANAGER, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); } static void inf_gtk_browser_store_tree_model_iface_init(GtkTreeModelIface* iface) { iface->get_flags = inf_gtk_browser_store_tree_model_get_flags; iface->get_n_columns = inf_gtk_browser_store_tree_model_get_n_columns; iface->get_column_type = inf_gtk_browser_store_tree_model_get_column_type; iface->get_iter = inf_gtk_browser_store_tree_model_get_iter; iface->get_path = inf_gtk_browser_store_tree_model_get_path; iface->get_value = inf_gtk_browser_store_tree_model_get_value; iface->iter_next = inf_gtk_browser_store_tree_model_iter_next; iface->iter_children = inf_gtk_browser_store_tree_model_iter_children; iface->iter_has_child = inf_gtk_browser_store_tree_model_iter_has_child; iface->iter_n_children = inf_gtk_browser_store_tree_model_iter_n_children; iface->iter_nth_child = inf_gtk_browser_store_tree_model_iter_nth_child; iface->iter_parent = inf_gtk_browser_store_tree_model_iter_parent; } static void inf_gtk_browser_store_browser_model_iface_init( InfGtkBrowserModelInterface* iface) { iface->set_browser = inf_gtk_browser_store_browser_model_set_browser; iface->resolve = inf_gtk_browser_store_browser_model_resolve; /* inf_gtk_browser_store_browser_model_browser_iter_to_tree_iter would be * consistent, but a _bit_ too long to fit properly into 80 chars ;) */ iface->browser_iter_to_tree_iter = inf_gtk_browser_store_browser_iter_to_tree_iter; } /* * Public API. */ /** * inf_gtk_browser_store_new: (constructor) * @io: A #InfIo object for the created #InfcBrowser to schedule timeouts. * @comm_manager: The #InfCommunicationManager with which to explore * remote directories. * * Creates a new #InfGtkBrowserStore. * * Returns: (transfer full): A new #InfGtkBrowserStore. **/ InfGtkBrowserStore* inf_gtk_browser_store_new(InfIo* io, InfCommunicationManager* comm_manager) { GObject* object; object = g_object_new( INF_GTK_TYPE_BROWSER_STORE, "io", io, "communication-manager", comm_manager, NULL ); return INF_GTK_BROWSER_STORE(object); } /** * inf_gtk_browser_store_add_discovery: * @store: A #InfGtkBrowserStore. * @discovery: A #InfDiscovery not yet added to @model. * * Adds @discovery to @model. The model will then show up discovered * servers. **/ void inf_gtk_browser_store_add_discovery(InfGtkBrowserStore* store, InfDiscovery* discovery) { InfGtkBrowserStorePrivate* priv; GSList* discovered; GSList* item; InfDiscoveryInfo* info; g_return_if_fail(INF_GTK_IS_BROWSER_STORE(store)); g_return_if_fail(INF_IS_DISCOVERY(discovery)); priv = INF_GTK_BROWSER_STORE_PRIVATE(store); g_return_if_fail(g_slist_find(priv->discoveries, discovery) == NULL); g_object_ref(G_OBJECT(discovery)); priv->discoveries = g_slist_prepend(priv->discoveries, discovery); g_signal_connect( G_OBJECT(discovery), "discovered", G_CALLBACK(inf_gtk_browser_store_discovered_cb), store ); g_signal_connect( G_OBJECT(discovery), "undiscovered", G_CALLBACK(inf_gtk_browser_store_undiscovered_cb), store ); discovered = inf_discovery_get_discovered(discovery, "_infinote._tcp"); for(item = discovered; item != NULL; item = g_slist_next(item)) { info = (InfDiscoveryInfo*)item->data; inf_gtk_browser_store_add_item_by_browser( store, discovery, info, NULL, inf_discovery_info_get_service_name(discovery, info) ); } g_slist_free(discovered); inf_discovery_discover(discovery, "_infinote._tcp"); } /** * inf_gtk_browser_store_add_connection: * @store: A #InfGtkBrowserStore. * @connection: A #InfXmlConnection. * @name: (allow-none): Name for the item, or %NULL. * * This function adds a connection to the @store. @store will show up * an item for the connection if there is not already one. This allows to * browse the explored parts of the directory of the remote site. If @name * is %NULL, then the #InfXmlConnection:remote-id of the connection will be * used. * * The return value is the #InfBrowser for the added connection, or an * existing browser for the connection, if there is any. * * Returns: (transfer none): An #InfBrowser for the new connection. **/ InfBrowser* inf_gtk_browser_store_add_connection(InfGtkBrowserStore* store, InfXmlConnection* connection, const gchar* name) { InfGtkBrowserStorePrivate* priv; InfGtkBrowserStoreItem* item; gchar* remote_id; g_return_val_if_fail(INF_GTK_IS_BROWSER_STORE(store), NULL); g_return_val_if_fail(INF_IS_XML_CONNECTION(connection), NULL); priv = INF_GTK_BROWSER_STORE_PRIVATE(store); item = inf_gtk_browser_store_find_item_by_connection(store, connection); if(item == NULL) { if(name == NULL) { g_object_get(G_OBJECT(connection), "remote-id", &remote_id, NULL); item = inf_gtk_browser_store_add_item_by_connection( store, NULL, NULL, connection, remote_id ); } else { item = inf_gtk_browser_store_add_item_by_connection( store, NULL, NULL, connection, g_strdup(name) ); } } return item->browser; } /** * inf_gtk_browser_store_add_browser: * @store: A #InfGtkBrowserStore. * @browser: A #InfBrowser. * @name: Name for the item. * * This function adds a browser to the @store. @store will show up * an item for the browser if there is not already one. This allows to * browse the explored part of the browser. The @name parameter must not be * %NULL. **/ void inf_gtk_browser_store_add_browser(InfGtkBrowserStore* store, InfBrowser* browser, const gchar* name) { InfGtkBrowserStorePrivate* priv; InfGtkBrowserStoreItem* item; g_return_if_fail(INF_GTK_IS_BROWSER_STORE(store)); g_return_if_fail(INF_IS_BROWSER(browser)); g_return_if_fail(name != NULL); priv = INF_GTK_BROWSER_STORE_PRIVATE(store); item = inf_gtk_browser_store_find_item_by_browser(store, browser); if(item == NULL) { inf_gtk_browser_store_add_item_by_browser( store, NULL, NULL, browser, g_strdup(name) ); } } /** * inf_gtk_browser_store_remove_browser: * @store: A #InfGtkBrowserStore * @browser: A #InfBrowser contained in @store. * * This function removes the entry for the given browser from @store. */ void inf_gtk_browser_store_remove_browser(InfGtkBrowserStore* store, InfBrowser* browser) { InfGtkBrowserStoreItem* item; g_return_if_fail(INF_GTK_IS_BROWSER_STORE(store)); g_return_if_fail(INF_IS_BROWSER(browser)); item = inf_gtk_browser_store_find_item_by_browser(store, browser); g_return_if_fail(item != NULL); inf_gtk_browser_store_remove_item (store, item); } /** * inf_gtk_browser_store_remove_connection: * @store: A #InfGtkBrowserStore. * @connection: A #InfXmlConnection contained in @store. * * This function removes the entry for the given connection from @store. */ void inf_gtk_browser_store_remove_connection(InfGtkBrowserStore* store, InfXmlConnection* connection) { InfGtkBrowserStoreItem* item; g_return_if_fail(INF_GTK_IS_BROWSER_STORE(store)); g_return_if_fail(INF_IS_XML_CONNECTION(connection)); item = inf_gtk_browser_store_find_item_by_connection(store, connection); g_return_if_fail(item != NULL); inf_gtk_browser_store_remove_item (store, item); } /** * inf_gtk_browser_store_clear_connection_error: * @store: A #InfGtkBrowserStore. * @connection: A #InfXmlConnection contained in @store. * * This function clears the error for the entry which belongs to the given * connection. */ void inf_gtk_browser_store_clear_connection_error(InfGtkBrowserStore* store, InfXmlConnection* connection) { InfGtkBrowserStoreItem* item; InfBrowserStatus status; GtkTreeIter iter; GtkTreePath* path; g_return_if_fail(INF_GTK_IS_BROWSER_STORE(store)); g_return_if_fail(INF_IS_XML_CONNECTION(connection)); item = inf_gtk_browser_store_find_item_by_connection(store, connection); g_return_if_fail(item != NULL); if(item->status == INF_GTK_BROWSER_MODEL_ERROR) { g_assert(item->error != NULL); g_error_free(item->error); item->error = NULL; if(item->browser != NULL) { g_object_get(G_OBJECT(item->browser), "status", &status, NULL); switch(status) { case INF_BROWSER_CLOSED: item->status = INF_GTK_BROWSER_MODEL_DISCONNECTED; break; case INF_BROWSER_OPENING: item->status = INF_GTK_BROWSER_MODEL_CONNECTING; break; case INF_BROWSER_OPEN: item->status = INF_GTK_BROWSER_MODEL_CONNECTED; break; default: g_assert_not_reached(); break; } } else if(item->info != NULL) { item->status = INF_GTK_BROWSER_MODEL_DISCOVERED; } else { g_assert_not_reached(); } iter.stamp = INF_GTK_BROWSER_STORE_PRIVATE(store)->stamp; iter.user_data = item; iter.user_data2 = GUINT_TO_POINTER(0); iter.user_data3 = NULL; path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &iter); gtk_tree_model_row_changed(GTK_TREE_MODEL(store), path, &iter); gtk_tree_path_free (path); } } /** * inf_gtk_browser_store_set_connection_name: * @store: A #InfGtkBrowserStore. * @connection: A #InfXmlConnection contained in @store. * @name: The new name to set for the connection. * * This function sets the name of @connection. **/ void inf_gtk_browser_store_set_connection_name(InfGtkBrowserStore* store, InfXmlConnection* connection, const gchar* name) { InfGtkBrowserStoreItem* item; GtkTreeIter iter; GtkTreePath* path; g_return_if_fail(INF_GTK_IS_BROWSER_STORE(store)); g_return_if_fail(INF_IS_XML_CONNECTION(connection)); g_return_if_fail(name != NULL); item = inf_gtk_browser_store_find_item_by_connection(store, connection); g_return_if_fail(item != NULL); g_free (item->name); item->name = g_strdup(name); iter.stamp = INF_GTK_BROWSER_STORE_PRIVATE(store)->stamp; iter.user_data = item; iter.user_data2 = GUINT_TO_POINTER(0); iter.user_data3 = NULL; path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), &iter); gtk_tree_model_row_changed(GTK_TREE_MODEL(store), path, &iter); gtk_tree_path_free(path); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfgtk/PaxHeaders.26529/inf-gtk-resources.h0000644000000000000000000000013013045431556021300 xustar0029 mtime=1486238574.82269088 29 atime=1486238574.82269088 30 ctime=1488261589.308138392 libinfinity-0.7.1/libinfgtk/inf-gtk-resources.h0000644000175000017500000000022713045431556022035 0ustar00arminarmin00000000000000#ifndef __RESOURCE__inf_gtk_H__ #define __RESOURCE__inf_gtk_H__ #include G_GNUC_INTERNAL GResource *_inf_gtk_get_resource (void); #endif libinfinity-0.7.1/libinfgtk/PaxHeaders.26529/inf-gtk-certificate-view.c0000644000000000000000000000013213034342512022504 xustar0030 mtime=1483851082.021718383 30 atime=1483851082.021718383 30 ctime=1488261589.324138357 libinfinity-0.7.1/libinfgtk/inf-gtk-certificate-view.c0000644000175000017500000003003213034342512023234 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include #include #include #include typedef struct _InfGtkCertificateViewPrivate InfGtkCertificateViewPrivate; struct _InfGtkCertificateViewPrivate { gnutls_x509_crt_t certificate; GtkWidget* subject_common_name; GtkWidget* subject_organization; GtkWidget* subject_organizational_unit; GtkWidget* subject_serial_number; GtkWidget* issuer_common_name; GtkWidget* issuer_organization; GtkWidget* issuer_organizational_unit; GtkWidget* activation_time; GtkWidget* expiration_time; GtkWidget* sha1_fingerprint; GtkWidget* sha256_fingerprint; GtkWidget* signature_algorithm; }; enum { PROP_0, PROP_CERTIFICATE }; #define INF_GTK_CERTIFICATE_VIEW_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INF_GTK_TYPE_CERTIFICATE_VIEW, InfGtkCertificateViewPrivate)) G_DEFINE_TYPE_WITH_CODE(InfGtkCertificateView, inf_gtk_certificate_view, GTK_TYPE_GRID, G_ADD_PRIVATE(InfGtkCertificateView)) static void inf_gtk_certificate_view_set_label(GtkLabel* label, const gchar* value) { const gchar* text; gchar* markup; if(value != NULL) { gtk_label_set_text(label, value); } else { text = _(""); markup = g_markup_printf_escaped("%s", text); gtk_label_set_markup(label, markup); g_free(markup); } } static void inf_gtk_certificate_view_set_label_dn_by_oid(gnutls_x509_crt_t cert, GtkLabel* label, const char* oid) { gchar* value; value = inf_cert_util_get_dn_by_oid(cert, oid, 0); inf_gtk_certificate_view_set_label(label, value); g_free(value); } static void inf_gtk_certificate_view_set_label_issuer_dn_by_oid(gnutls_x509_crt_t cert, GtkLabel* label, const gchar* oid) { gchar* value; value = inf_cert_util_get_issuer_dn_by_oid(cert, oid, 0); inf_gtk_certificate_view_set_label(label, value); g_free(value); } static void inf_gtk_certificate_view_init(InfGtkCertificateView* view) { InfGtkCertificateViewPrivate* priv; PangoFontDescription* monospace_desc; gint size; priv = INF_GTK_CERTIFICATE_VIEW_PRIVATE(view); priv->certificate = NULL; gtk_widget_init_template(GTK_WIDGET(view)); } static void inf_gtk_certificate_view_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfGtkCertificateView* view; InfGtkCertificateViewPrivate* priv; view = INF_GTK_CERTIFICATE_VIEW(object); priv = INF_GTK_CERTIFICATE_VIEW_PRIVATE(view); switch(prop_id) { case PROP_CERTIFICATE: inf_gtk_certificate_view_set_certificate( view, (gnutls_x509_crt_t)g_value_get_pointer(value) ); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void inf_gtk_certificate_view_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfGtkCertificateView* view; InfGtkCertificateViewPrivate* priv; view = INF_GTK_CERTIFICATE_VIEW(object); priv = INF_GTK_CERTIFICATE_VIEW_PRIVATE(view); switch(prop_id) { case PROP_CERTIFICATE: g_value_set_pointer(value, priv->certificate); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } /* * GType registration */ static void inf_gtk_certificate_view_class_init( InfGtkCertificateViewClass* certificate_view_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(certificate_view_class); object_class->set_property = inf_gtk_certificate_view_set_property; object_class->get_property = inf_gtk_certificate_view_get_property; gtk_widget_class_set_template_from_resource( GTK_WIDGET_CLASS(certificate_view_class), "/de/0x539/libinfgtk/ui/infgtkcertificateview.ui" ); gtk_widget_class_bind_template_child_private( GTK_WIDGET_CLASS(certificate_view_class), InfGtkCertificateView, subject_common_name ); gtk_widget_class_bind_template_child_private( GTK_WIDGET_CLASS(certificate_view_class), InfGtkCertificateView, subject_organization ); gtk_widget_class_bind_template_child_private( GTK_WIDGET_CLASS(certificate_view_class), InfGtkCertificateView, subject_organizational_unit ); gtk_widget_class_bind_template_child_private( GTK_WIDGET_CLASS(certificate_view_class), InfGtkCertificateView, subject_serial_number ); gtk_widget_class_bind_template_child_private( GTK_WIDGET_CLASS(certificate_view_class), InfGtkCertificateView, issuer_common_name ); gtk_widget_class_bind_template_child_private( GTK_WIDGET_CLASS(certificate_view_class), InfGtkCertificateView, issuer_organization ); gtk_widget_class_bind_template_child_private( GTK_WIDGET_CLASS(certificate_view_class), InfGtkCertificateView, issuer_organizational_unit ); gtk_widget_class_bind_template_child_private( GTK_WIDGET_CLASS(certificate_view_class), InfGtkCertificateView, activation_time ); gtk_widget_class_bind_template_child_private( GTK_WIDGET_CLASS(certificate_view_class), InfGtkCertificateView, expiration_time ); gtk_widget_class_bind_template_child_private( GTK_WIDGET_CLASS(certificate_view_class), InfGtkCertificateView, sha1_fingerprint ); gtk_widget_class_bind_template_child_private( GTK_WIDGET_CLASS(certificate_view_class), InfGtkCertificateView, sha256_fingerprint ); gtk_widget_class_bind_template_child_private( GTK_WIDGET_CLASS(certificate_view_class), InfGtkCertificateView, signature_algorithm ); g_object_class_install_property( object_class, PROP_CERTIFICATE, g_param_spec_pointer( "certificate", "Certificate", "The certificate to show", G_PARAM_READWRITE ) ); } /* * Public API. */ /** * inf_gtk_certificate_view_new: (constructor) * * Creates a new #InfGtkCertificateView. To show a certificate, use * inf_gtk_certificate_view_set_certificate() on the returned widget. * * Returns: (transfer floating): A new #InfGtkCertificateView. */ GtkWidget* inf_gtk_certificate_view_new(void) { GObject* object; object = g_object_new(INF_GTK_TYPE_CERTIFICATE_VIEW, NULL); return GTK_WIDGET(object); } /** * inf_gtk_certificate_view_new_with_certificate: (constructor) * @cert: The certificate to show. * * Creates a new #InfGtkCertificateView showing the given certificate. This * is the same as creating a new certificate view and calling * inf_gtk_certificate_view_set_certificate() afterwards. * * @cert must not be freed as long as the certificate view is showing it. You * can make the view not showing it anymore by calling * inf_gtk_certificate_view_set_certificate() with %NULL as certificate. * * Returns: (transfer floating): A new #InfGtkCertificateView. */ GtkWidget* inf_gtk_certificate_view_new_with_certificate(gnutls_x509_crt_t cert) { GObject* object; object = g_object_new( INF_GTK_TYPE_CERTIFICATE_VIEW, "certificate", cert, NULL ); return GTK_WIDGET(object); } /** * inf_gtk_certificate_view_set_certificate: * @view: A #InfGtkCertificateView. * @cert: The certificate to show. * * Shows the given certificate in @view. * * @cert must not be freed as long as the certificate view is showing it. You * can make the view not showing it anymore by calling * inf_gtk_certificate_view_set_certificate() with %NULL as certificate. */ void inf_gtk_certificate_view_set_certificate(InfGtkCertificateView* view, gnutls_x509_crt_t cert) { InfGtkCertificateViewPrivate* priv; gchar* value; int algo; g_return_if_fail(INF_GTK_IS_CERTIFICATE_VIEW(view)); priv = INF_GTK_CERTIFICATE_VIEW_PRIVATE(view); priv->certificate = cert; if(cert == NULL) { gtk_label_set_text(GTK_LABEL(priv->subject_common_name), NULL); gtk_label_set_text(GTK_LABEL(priv->subject_organization), NULL); gtk_label_set_text(GTK_LABEL(priv->subject_organizational_unit), NULL); gtk_label_set_text(GTK_LABEL(priv->subject_serial_number), NULL); gtk_label_set_text(GTK_LABEL(priv->issuer_common_name), NULL); gtk_label_set_text(GTK_LABEL(priv->issuer_organization), NULL); gtk_label_set_text(GTK_LABEL(priv->issuer_organizational_unit), NULL); gtk_label_set_text(GTK_LABEL(priv->activation_time), NULL); gtk_label_set_text(GTK_LABEL(priv->expiration_time), NULL); gtk_label_set_text(GTK_LABEL(priv->sha1_fingerprint), NULL); gtk_label_set_text(GTK_LABEL(priv->sha256_fingerprint), NULL); gtk_label_set_text(GTK_LABEL(priv->signature_algorithm), NULL); } else { inf_gtk_certificate_view_set_label_dn_by_oid( cert, GTK_LABEL(priv->subject_common_name), GNUTLS_OID_X520_COMMON_NAME ); inf_gtk_certificate_view_set_label_dn_by_oid( cert, GTK_LABEL(priv->subject_organization), GNUTLS_OID_X520_ORGANIZATION_NAME ); inf_gtk_certificate_view_set_label_dn_by_oid( cert, GTK_LABEL(priv->subject_organizational_unit), GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME ); value = inf_cert_util_get_serial_number(cert); inf_gtk_certificate_view_set_label( GTK_LABEL(priv->subject_serial_number), value ); g_free(value); inf_gtk_certificate_view_set_label_issuer_dn_by_oid( cert, GTK_LABEL(priv->issuer_common_name), GNUTLS_OID_X520_COMMON_NAME ); inf_gtk_certificate_view_set_label_issuer_dn_by_oid( cert, GTK_LABEL(priv->issuer_organization), GNUTLS_OID_X520_ORGANIZATION_NAME ); inf_gtk_certificate_view_set_label_issuer_dn_by_oid( cert, GTK_LABEL(priv->issuer_organizational_unit), GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME ); value = inf_cert_util_get_activation_time(cert); inf_gtk_certificate_view_set_label( GTK_LABEL(priv->activation_time), value ); g_free(value); value = inf_cert_util_get_expiration_time(cert); inf_gtk_certificate_view_set_label( GTK_LABEL(priv->expiration_time), value ); g_free(value); value = inf_cert_util_get_fingerprint(cert, GNUTLS_DIG_SHA1); inf_gtk_certificate_view_set_label( GTK_LABEL(priv->sha1_fingerprint), value ); g_free(value); value = inf_cert_util_get_fingerprint(cert, GNUTLS_DIG_SHA256); inf_gtk_certificate_view_set_label( GTK_LABEL(priv->sha256_fingerprint), value ); g_free(value); algo = gnutls_x509_crt_get_signature_algorithm(cert); if(algo < 0) { inf_gtk_certificate_view_set_label( GTK_LABEL(priv->signature_algorithm), gnutls_strerror(algo) ); } else { inf_gtk_certificate_view_set_label( GTK_LABEL(priv->signature_algorithm), gnutls_sign_get_name(algo) ); } } g_object_notify(G_OBJECT(view), "certificate"); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfgtk/PaxHeaders.26529/inf-gtk-browser-view.h0000644000000000000000000000013213034342512021712 xustar0030 mtime=1483851082.021718383 30 atime=1483851082.017718362 30 ctime=1488261589.300138409 libinfinity-0.7.1/libinfgtk/inf-gtk-browser-view.h0000644000175000017500000000604413034342512022450 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_GTK_BROWSER_VIEW_H__ #define __INF_GTK_BROWSER_VIEW_H__ #include #include #include G_BEGIN_DECLS #define INF_GTK_TYPE_BROWSER_VIEW (inf_gtk_browser_view_get_type()) #define INF_GTK_BROWSER_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_GTK_TYPE_BROWSER_VIEW, InfGtkBrowserView)) #define INF_GTK_BROWSER_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INF_GTK_TYPE_BROWSER_VIEW, InfGtkBrowserViewClass)) #define INF_GTK_IS_BROWSER_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_GTK_TYPE_BROWSER_VIEW)) #define INF_GTK_IS_BROWSER_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INF_GTK_TYPE_BROWSER_VIEW)) #define INF_GTK_BROWSER_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INF_GTK_TYPE_BROWSER_VIEW, InfGtkBrowserViewClass)) #define INF_GTK_TYPE_BROWSER_VIEW_STATUS (inf_gtk_browser_view_status_get_type()) typedef struct _InfGtkBrowserView InfGtkBrowserView; typedef struct _InfGtkBrowserViewClass InfGtkBrowserViewClass; struct _InfGtkBrowserViewClass { GtkTreeViewClass parent_class; /* signals */ void (*activate)(InfGtkBrowserView* view, GtkTreeIter* iter); void (*selection_changed)(InfGtkBrowserView* view, GtkTreeIter* iter); void (*populate_popup)(InfGtkBrowserView* view, GtkMenu* menu); #if ! GTK_CHECK_VERSION(2, 91, 0) void (*set_scroll_adjustments)(InfGtkBrowserView* view, GtkAdjustment* hadjustment, GtkAdjustment* vadjustment); #endif }; struct _InfGtkBrowserView { GtkTreeView parent; }; GType inf_gtk_browser_view_get_type(void) G_GNUC_CONST; GtkWidget* inf_gtk_browser_view_new(void); GtkWidget* inf_gtk_browser_view_new_with_model(InfGtkBrowserModel* model); gboolean inf_gtk_browser_view_get_selected(InfGtkBrowserView* view, GtkTreeIter* iter); void inf_gtk_browser_view_set_selected(InfGtkBrowserView* view, GtkTreeIter* iter); G_END_DECLS #endif /* __INF_GTK_BROWSER_VIEW_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfgtk/PaxHeaders.26529/inf-gtk-chat.h0000644000000000000000000000013213034342512020176 xustar0030 mtime=1483851082.021718383 30 atime=1483851082.021718383 30 ctime=1488261589.304138401 libinfinity-0.7.1/libinfgtk/inf-gtk-chat.h0000644000175000017500000000501713034342512020733 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_GTK_CHAT_H__ #define __INF_GTK_CHAT_H__ #include #include #include #include G_BEGIN_DECLS #define INF_GTK_TYPE_CHAT (inf_gtk_chat_get_type()) #define INF_GTK_CHAT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_GTK_TYPE_CHAT, InfGtkChat)) #define INF_GTK_CHAT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INF_GTK_TYPE_CHAT, InfGtkChatClass)) #define INF_GTK_IS_CHAT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_GTK_TYPE_CHAT)) #define INF_GTK_IS_CHAT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INF_GTK_TYPE_CHAT)) #define INF_GTK_CHAT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INF_GTK_TYPE_CHAT, InfGtkChatClass)) typedef struct _InfGtkChat InfGtkChat; typedef struct _InfGtkChatClass InfGtkChatClass; /** * InfGtkChatClass: * * This structure does not contain any public fields. */ struct _InfGtkChatClass { /*< private >*/ GtkGridClass parent_class; }; /** * InfGtkChat: * * #InfGtkChat is an opaque data type. You should only access it via the * public API functions. */ struct _InfGtkChat { /*< private >*/ GtkGrid parent; }; GType inf_gtk_chat_get_type(void) G_GNUC_CONST; GtkWidget* inf_gtk_chat_new(void); void inf_gtk_chat_set_session(InfGtkChat* chat, InfChatSession* session); void inf_gtk_chat_set_active_user(InfGtkChat* chat, InfUser* user); InfUser* inf_gtk_chat_get_active_user(InfGtkChat* chat); GtkWidget* inf_gtk_chat_get_entry(InfGtkChat* chat); G_END_DECLS #endif /* __INF_GTK_CHAT_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfgtk/PaxHeaders.26529/inf-gtk-acl-sheet-view.h0000644000000000000000000000013213034342512022074 xustar0030 mtime=1483851082.017718362 30 atime=1483851082.017718362 30 ctime=1488261589.292138427 libinfinity-0.7.1/libinfgtk/inf-gtk-acl-sheet-view.h0000644000175000017500000000670413034342512022635 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_GTK_ACL_SHEET_VIEW_H__ #define __INF_GTK_ACL_SHEET_VIEW_H__ #include #include #include G_BEGIN_DECLS #define INF_GTK_TYPE_ACL_SHEET_VIEW (inf_gtk_acl_sheet_view_get_type()) #define INF_GTK_ACL_SHEET_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_GTK_TYPE_ACL_SHEET_VIEW, InfGtkAclSheetView)) #define INF_GTK_ACL_SHEET_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INF_GTK_TYPE_ACL_SHEET_VIEW, InfGtkAclSheetViewClass)) #define INF_GTK_IS_ACL_SHEET_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_GTK_TYPE_ACL_SHEET_VIEW)) #define INF_GTK_IS_ACL_SHEET_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INF_GTK_TYPE_ACL_SHEET_VIEW)) #define INF_GTK_ACL_SHEET_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INF_GTK_TYPE_ACL_SHEET_VIEW, InfGtkAclSheetViewClass)) typedef struct _InfGtkAclSheetView InfGtkAclSheetView; typedef struct _InfGtkAclSheetViewClass InfGtkAclSheetViewClass; /** * InfGtkAclSheetViewClass: * @sheet_changed: Default signal handler for the * #InfGtkAclSheetView::sheet-changed signal. * * This structure contains the default signal handlers for the * #InfGtkAclSheetView class. */ struct _InfGtkAclSheetViewClass { /*< private >*/ GtkGridClass parent_class; /*< public >*/ void (*sheet_changed)(InfGtkAclSheetView* view); }; /** * InfGtkAclSheetView: * * #InfGtkAclSheetView is an opaque data type. You should only access it via the * public API functions. */ struct _InfGtkAclSheetView { /*< private >*/ GtkGrid parent; }; GType inf_gtk_acl_sheet_view_get_type(void) G_GNUC_CONST; GtkWidget* inf_gtk_acl_sheet_view_new(void); void inf_gtk_acl_sheet_view_set_sheet(InfGtkAclSheetView* view, const InfAclSheet* sheet); const InfAclSheet* inf_gtk_acl_sheet_view_get_sheet(InfGtkAclSheetView* view); void inf_gtk_acl_sheet_view_set_editable(InfGtkAclSheetView* view, gboolean editable); gboolean inf_gtk_acl_sheet_view_get_editable(InfGtkAclSheetView* view); void inf_gtk_acl_sheet_view_set_show_default(InfGtkAclSheetView* view, gboolean show); gboolean inf_gtk_acl_sheet_view_get_show_default(InfGtkAclSheetView* view); void inf_gtk_acl_sheet_view_set_permission_mask(InfGtkAclSheetView* view, const InfAclMask* mask); const InfAclMask* inf_gtk_acl_sheet_view_get_permission_mask(InfGtkAclSheetView* view); G_END_DECLS #endif /* __INF_GTK_ACL_SHEET_VIEW_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfgtk/PaxHeaders.26529/inf-gtk-browser-model.c0000644000000000000000000000013213034342512022033 xustar0030 mtime=1483851082.017718362 30 atime=1483851082.017718362 30 ctime=1488261589.312138383 libinfinity-0.7.1/libinfgtk/inf-gtk-browser-model.c0000644000175000017500000001646013034342512022574 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-gtk-browser-model * @title: InfGtkBrowserModel * @short_description: Interface for tree models representing infinote * directories * @include: libinfgtk/inf-gtk-browser-model.h * @see_also: #InfGtkBrowserStore * @stability: Unstable * * #InfGtkBrowserModel provides an interface for tree models that are used to * show the contents of infinote directories. All implementations of * #InfGtkBrowserModel also need to implement #GtkTreeModel and can then by * displayed in a #GtkTreeView. * * #InfGtkBrowserStore is a reference implementation of this interface, * allowing to add discoveries and browsers to it which it then manages. * Other implementations include #InfGtkBrowserModelSort and * #InfGtkBrowserModelFilter which can be used to sort or filter the list. */ #include #include #include static const GEnumValue inf_gtk_browser_model_status_values[] = { { INF_GTK_BROWSER_MODEL_DISCOVERED, "INF_GTK_BROWSER_MODEL_DISCOVERED", "discovered" }, { INF_GTK_BROWSER_MODEL_RESOLVING, "INF_GTK_BROWSER_MODEL_RESOLVING", "resolving" }, { INF_GTK_BROWSER_MODEL_CONNECTING, "INF_GTK_BROWSER_MODEL_CONNECTING", "connecting" }, { INF_GTK_BROWSER_MODEL_CONNECTED, "INF_GTK_BROWSER_MODEL_CONNECTED", "connected" }, { INF_GTK_BROWSER_MODEL_ERROR, "INF_GTK_BROWSER_MODEL_ERROR", "error" }, { 0, NULL, NULL } }; INF_DEFINE_ENUM_TYPE(InfGtkBrowserModelStatus, inf_gtk_browser_model_status, inf_gtk_browser_model_status_values) G_DEFINE_INTERFACE(InfGtkBrowserModel, inf_gtk_browser_model, GTK_TYPE_TREE_MODEL) enum { SET_BROWSER, LAST_SIGNAL }; static guint browser_model_signals[LAST_SIGNAL]; static void inf_gtk_browser_model_default_init(InfGtkBrowserModelInterface* iface) { /** * InfGtkBrowserModel::set-browser: * @model: The #InfGtkBrowserModel emitting the signal. * @path: A #GtkTreePath pointing to the item with a new browesr. * @iter: A #GtkTreeIter pointing to the item with a new browser. * @old_browser: The previous #InfBrowser. * @new_browser: The new #InfBrowser. * * This signal is emitted every time the #InfBrowser for one of the * model's top-level entries change. This means either that a completely * new item was inserted, that an item providing only a discovery has * been resolved (see inf_gtk_browser_model_resolve()), or that a * top-level entry has been removed. * * During emission of the signal the actual value in the model might * either be the old or the new browser. */ browser_model_signals[SET_BROWSER] = g_signal_new( "set-browser", INF_GTK_TYPE_BROWSER_MODEL, G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfGtkBrowserModelInterface, set_browser), NULL, NULL, NULL, G_TYPE_NONE, 4, GTK_TYPE_TREE_PATH | G_SIGNAL_TYPE_STATIC_SCOPE, GTK_TYPE_TREE_ITER | G_SIGNAL_TYPE_STATIC_SCOPE, INF_TYPE_BROWSER, INF_TYPE_BROWSER ); } /** * inf_gtk_browser_model_set_browser: * @model: A #InfGtkBrowserModel. * @path: A #GtkTreePath to a top-level row. * @iter: A #GtkTreeIter pointing to the same row. * @old_browser: The browser which was set at this row before. * @new_browser: The new #InfBrowser to set for this row. * * Emits the #InfGtkBrowserModel::set-browser signal. This is supposed to only * be called by implementations of #InfGtkBrowserModel whenever they set or * unset a browser on a row. **/ void inf_gtk_browser_model_set_browser(InfGtkBrowserModel* model, GtkTreePath* path, GtkTreeIter* iter, InfBrowser* old_browser, InfBrowser* new_browser) { g_return_if_fail(INF_GTK_IS_BROWSER_MODEL(model)); g_return_if_fail(path != NULL); g_return_if_fail(iter != NULL); g_return_if_fail(old_browser == NULL || INF_IS_BROWSER(old_browser)); g_return_if_fail(new_browser == NULL || INF_IS_BROWSER(new_browser)); g_signal_emit( G_OBJECT(model), browser_model_signals[SET_BROWSER], 0, path, iter, old_browser, new_browser ); } /** * inf_gtk_browser_model_resolve: * @model: A #InfGtkBrowserModel. * @discovery: A #InfDiscovery added to @store. * @info: A #InfDiscoveryInfo discovered by @discovery. * * Resolves @info and adds the resulting connection to the model. If that * connection is already contained, the original (newly resolved) entry * is removed in favor of the existing entry whose browser might already * have explored (parts of) the server's directory. */ void inf_gtk_browser_model_resolve(InfGtkBrowserModel* model, InfDiscovery* discovery, InfDiscoveryInfo* info) { InfGtkBrowserModelInterface* iface; g_return_if_fail(INF_GTK_IS_BROWSER_MODEL(model)); g_return_if_fail(INF_IS_DISCOVERY(discovery)); g_return_if_fail(info != NULL); iface = INF_GTK_BROWSER_MODEL_GET_IFACE(model); g_return_if_fail(iface->resolve != NULL); iface->resolve(model, discovery, info); } /** * inf_gtk_browser_model_browser_iter_to_tree_iter: * @model: A #InfGtkBrowserModel. * @browser: A #InfBrowser. * @iter: A #InfBrowserIter pointing into @browser, or %NULL. * @tree_iter: (out): A #GtkTreeIter that will be set by this function. * * Sets @tree_iter to point to the same node @iter refers to * within the model. If @browser is not known to @model, i.e. its connection * was never added to @model, then the function returns %FALSE and * @tree_iter is left untouched. * * If @iter is %NULL, the function sets @tree_iter to point to the top * level entry representing @browser. * * Returns: Whether @tree_iter was set. **/ gboolean inf_gtk_browser_model_browser_iter_to_tree_iter(InfGtkBrowserModel* model, InfBrowser* browser, const InfBrowserIter* iter, GtkTreeIter* tree_iter) { InfGtkBrowserModelInterface* iface; g_return_val_if_fail(INF_GTK_IS_BROWSER_MODEL(model), FALSE); g_return_val_if_fail(INF_IS_BROWSER(browser), FALSE); g_return_val_if_fail(tree_iter != NULL, FALSE); iface = INF_GTK_BROWSER_MODEL_GET_IFACE(model); g_return_val_if_fail(iface->browser_iter_to_tree_iter != NULL, FALSE); return iface->browser_iter_to_tree_iter(model, browser, iter, tree_iter); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfgtk/PaxHeaders.26529/inf-gtk-certificate-dialog.c0000644000000000000000000000013213034342512022771 xustar0030 mtime=1483851082.021718383 30 atime=1483851082.021718383 30 ctime=1488261589.320138365 libinfinity-0.7.1/libinfgtk/inf-gtk-certificate-dialog.c0000644000175000017500000004352713034342512023536 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-gtk-certificate-dialog * @title: InfGtkCertificateDialog * @short_description: A dialog warning the user about a server's certificate * @include: libinfgtk/inf-gtk-certificate-dialog.h * @stability: Unstable * * #InfGtkCertificateDialog is a dialog that can be shown to a user if the * validation of the server's certificate cannot be performed automatically. * The dialog will present to the user the reason(s) of the validation * failure and might ask whether to fully establish the connection to the * server or not. **/ #include #include #include #include #include #include #include typedef struct _InfGtkCertificateDialogPrivate InfGtkCertificateDialogPrivate; struct _InfGtkCertificateDialogPrivate { InfCertificateChain* certificate_chain; gnutls_x509_crt_t pinned_certificate; InfCertificateVerifyFlags verify_flags; gchar* hostname; GtkTreeStore* certificate_store; GtkWidget* caption; GtkWidget* info; GtkWidget* certificate_expander; GtkWidget* certificate_tree_view; GtkWidget* certificate_info_view; GtkCellRenderer* text_renderer; }; enum { PROP_0, PROP_CERTIFICATE_CHAIN, PROP_PINNED_CERTIFICATE, PROP_VERIFY_FLAGS, PROP_HOSTNAME }; #define INF_GTK_CERTIFICATE_DIALOG_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INF_GTK_TYPE_CERTIFICATE_DIALOG, InfGtkCertificateDialogPrivate)) G_DEFINE_TYPE_WITH_CODE(InfGtkCertificateDialog, inf_gtk_certificate_dialog, GTK_TYPE_DIALOG, G_ADD_PRIVATE(InfGtkCertificateDialog)) /* When a host presents a certificate different from one that we have pinned, * usually we warn the user that something fishy is going on. However, if the * pinned certificate has expired or will expire soon, then we kind of expect * the certificate to change, and issue a less "flashy" warning message. This * value defines how long before the pinned certificate expires we show a * less dramatic warning message. */ static const unsigned int INF_GTK_CERTIFICATE_DIALOG_EXPIRATION_TOLERANCE = 30 * 24 * 3600; /* 30 days */ static void inf_gtk_certificate_dialog_renew_info(InfGtkCertificateDialog* dialog) { InfGtkCertificateDialogPrivate* priv; gnutls_x509_crt_t own_cert; time_t expiration_time; gint normal_width_chars; gint size; PangoFontDescription* font_desc; const gchar* ctext; gchar* text; gchar* markup; GString* info_text; GtkWidget* caption; GtkWidget* info; priv = INF_GTK_CERTIFICATE_DIALOG_PRIVATE(dialog); if(priv->verify_flags != 0 && priv->hostname != NULL) { own_cert = inf_certificate_chain_get_own_certificate(priv->certificate_chain); text = g_strdup_printf( _("The connection to host \"%s\" is not considered secure"), priv->hostname ); gtk_label_set_text(GTK_LABEL(priv->caption), text); g_free(text); info_text = g_string_sized_new(256); if(priv->verify_flags & INF_CERTIFICATE_VERIFY_NOT_PINNED) { /* TODO: Here it might also be interesting to show the pinned * certificate to the user... */ expiration_time = gnutls_x509_crt_get_expiration_time( priv->pinned_certificate ); if(expiration_time != (time_t)(-1) && time(NULL) > expiration_time - INF_GTK_CERTIFICATE_DIALOG_EXPIRATION_TOLERANCE) { ctext = _("The host has presented a new certificate."); markup = g_markup_printf_escaped("%s", ctext); g_string_append(info_text, markup); g_free(markup); g_string_append_c(info_text, ' '); g_string_append( info_text, _("Its previous certificate has expired or is closed to " "expiration. Please make sure that you trust the new " "certificate.") ); } else { ctext = _("The host has presented an unexpected certificate!"); markup = g_markup_printf_escaped("%s", ctext); g_string_append(info_text, markup); g_free(markup); g_string_append_c(info_text, ' '); g_string_append( info_text, _("This means someone might be eavesdropping on the connection. " "Please only continue if you expected this message, otherwise " "please contact the server administrator.") ); } } else { g_string_append( info_text, _("The server certificate cannot be verified automatically. Please " "make sure that you trust this host before proceeding.") ); if(priv->verify_flags & INF_CERTIFICATE_VERIFY_ISSUER_NOT_KNOWN) { if(info_text->len > 0) g_string_append(info_text, "\n\n"); g_string_append( info_text, _("The issuer of the certificate is not known.") ); } if(priv->verify_flags & INF_CERTIFICATE_VERIFY_HOSTNAME_MISMATCH) { if(info_text->len > 0) g_string_append(info_text, "\n\n"); text = inf_cert_util_get_hostname(own_cert); g_string_append_printf( info_text, _("The hostname of the server, \"%s\", does not match the hostname " "the certificate is issued to, \"%s\"."), priv->hostname, text ); g_free(text); } } gtk_label_set_markup(GTK_LABEL(priv->info), info_text->str); g_string_free(info_text, TRUE); } else { gtk_label_set_text(GTK_LABEL(priv->caption), NULL); gtk_label_set_text(GTK_LABEL(priv->info), NULL); } } static void inf_gtk_certificate_dialog_set_chain(InfGtkCertificateDialog* dialog, InfCertificateChain* chain) { InfGtkCertificateDialogPrivate* priv; guint i; gnutls_x509_crt_t crt; GtkTreeIter prev_row; GtkTreeIter new_row; GtkTreeIter* parent; GtkTreePath* path; priv = INF_GTK_CERTIFICATE_DIALOG_PRIVATE(dialog); if(priv->certificate_chain != NULL) inf_certificate_chain_unref(priv->certificate_chain); priv->certificate_chain = chain; gtk_tree_store_clear(priv->certificate_store); inf_gtk_certificate_view_set_certificate( INF_GTK_CERTIFICATE_VIEW(priv->certificate_info_view), NULL ); parent = NULL; if(chain != NULL) { inf_certificate_chain_ref(chain); for(i = inf_certificate_chain_get_n_certificates(chain); i > 0; -- i) { crt = inf_certificate_chain_get_nth_certificate(chain, i - 1); gtk_tree_store_append(priv->certificate_store, &new_row, parent); gtk_tree_store_set(priv->certificate_store, &new_row, 0, crt, -1); prev_row = new_row; parent = &prev_row; } path = gtk_tree_model_get_path( GTK_TREE_MODEL(priv->certificate_store), &new_row ); gtk_tree_view_expand_to_path( GTK_TREE_VIEW(priv->certificate_tree_view), path ); gtk_tree_selection_select_path( gtk_tree_view_get_selection(GTK_TREE_VIEW(priv->certificate_tree_view)), path ); gtk_tree_view_scroll_to_cell( GTK_TREE_VIEW(priv->certificate_tree_view), path, NULL, FALSE, 0.0, 0.0 ); gtk_tree_path_free(path); gtk_widget_show(priv->certificate_expander); } else { gtk_widget_hide(priv->certificate_expander); } g_object_notify(G_OBJECT(dialog), "certificate-chain"); } static void inf_gtk_certificate_dialog_selection_changed_cb(GtkTreeSelection* selection, gpointer user_data) { InfGtkCertificateDialog* dialog; InfGtkCertificateDialogPrivate* priv; GtkTreeIter iter; gnutls_x509_crt_t cert; dialog = INF_GTK_CERTIFICATE_DIALOG(user_data); priv = INF_GTK_CERTIFICATE_DIALOG_PRIVATE(dialog); if(gtk_tree_selection_get_selected(selection, NULL, &iter)) { gtk_tree_model_get( GTK_TREE_MODEL(priv->certificate_store), &iter, 0, &cert, -1 ); inf_gtk_certificate_view_set_certificate( INF_GTK_CERTIFICATE_VIEW(priv->certificate_info_view), cert ); } else { inf_gtk_certificate_view_set_certificate( INF_GTK_CERTIFICATE_VIEW(priv->certificate_info_view), NULL ); } } static void inf_gtk_certificate_dialog_chain_data_func(GtkTreeViewColumn* column, GtkCellRenderer* renderer, GtkTreeModel* tree_model, GtkTreeIter* iter, gpointer user_data) { gpointer crt_ptr; gnutls_x509_crt_t cert; GValue value = { 0 }; gchar* common_name; gtk_tree_model_get(tree_model, iter, 0, &crt_ptr, -1); cert = (gnutls_x509_crt_t)crt_ptr; common_name = inf_cert_util_get_dn_by_oid(cert, GNUTLS_OID_X520_COMMON_NAME, 0); g_value_init(&value, G_TYPE_STRING); if(common_name != NULL) g_value_take_string(&value, common_name); else g_value_set_static_string(&value, _("")); g_object_set_property(G_OBJECT(renderer), "text", &value); g_value_unset(&value); } static void inf_gtk_certificate_dialog_init(InfGtkCertificateDialog* dialog) { InfGtkCertificateDialogPrivate* priv; priv = INF_GTK_CERTIFICATE_DIALOG_PRIVATE(dialog); priv->certificate_chain = NULL; priv->pinned_certificate = NULL; priv->verify_flags = 0; priv->hostname = NULL; gtk_widget_init_template(GTK_WIDGET(dialog)); gtk_tree_selection_set_mode( gtk_tree_view_get_selection(GTK_TREE_VIEW(priv->certificate_tree_view)), GTK_SELECTION_BROWSE ); gtk_tree_view_column_set_cell_data_func( gtk_tree_view_get_column(GTK_TREE_VIEW(priv->certificate_tree_view), 0), priv->text_renderer, inf_gtk_certificate_dialog_chain_data_func, NULL, NULL ); } static void inf_gtk_certificate_dialog_finalize(GObject* object) { InfGtkCertificateDialog* dialog; InfGtkCertificateDialogPrivate* priv; dialog = INF_GTK_CERTIFICATE_DIALOG(object); priv = INF_GTK_CERTIFICATE_DIALOG_PRIVATE(dialog); inf_certificate_chain_unref(priv->certificate_chain); g_free(priv->hostname); G_OBJECT_CLASS(inf_gtk_certificate_dialog_parent_class)->finalize(object); } static void inf_gtk_certificate_dialog_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfGtkCertificateDialog* dialog; InfGtkCertificateDialogPrivate* priv; dialog = INF_GTK_CERTIFICATE_DIALOG(object); priv = INF_GTK_CERTIFICATE_DIALOG_PRIVATE(dialog); switch(prop_id) { case PROP_CERTIFICATE_CHAIN: inf_gtk_certificate_dialog_set_chain( dialog, (InfCertificateChain*)g_value_get_boxed(value) ); break; case PROP_PINNED_CERTIFICATE: priv->pinned_certificate = g_value_get_pointer(value); inf_gtk_certificate_dialog_renew_info(dialog); break; case PROP_VERIFY_FLAGS: priv->verify_flags = g_value_get_flags(value); if(priv->verify_flags != 0 && priv->hostname != NULL) inf_gtk_certificate_dialog_renew_info(dialog); break; case PROP_HOSTNAME: if(priv->hostname != NULL) g_free(priv->hostname); priv->hostname = g_value_dup_string(value); if(priv->verify_flags != 0 && priv->hostname != NULL) inf_gtk_certificate_dialog_renew_info(dialog); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void inf_gtk_certificate_dialog_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfGtkCertificateDialog* dialog; InfGtkCertificateDialogPrivate* priv; dialog = INF_GTK_CERTIFICATE_DIALOG(object); priv = INF_GTK_CERTIFICATE_DIALOG_PRIVATE(dialog); switch(prop_id) { case PROP_CERTIFICATE_CHAIN: g_value_set_boxed(value, priv->certificate_chain); break; case PROP_PINNED_CERTIFICATE: g_value_set_pointer(value, priv->pinned_certificate); break; case PROP_VERIFY_FLAGS: g_value_set_flags(value, priv->verify_flags); break; case PROP_HOSTNAME: g_value_set_string(value, priv->hostname); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } /* * GType registration */ static void inf_gtk_certificate_dialog_class_init( InfGtkCertificateDialogClass* certificate_dialog_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(certificate_dialog_class); object_class->finalize = inf_gtk_certificate_dialog_finalize; object_class->set_property = inf_gtk_certificate_dialog_set_property; object_class->get_property = inf_gtk_certificate_dialog_get_property; gtk_widget_class_set_template_from_resource( GTK_WIDGET_CLASS(object_class), "/de/0x539/libinfgtk/ui/infgtkcertificatedialog.ui" ); gtk_widget_class_bind_template_child_private( GTK_WIDGET_CLASS(object_class), InfGtkCertificateDialog, certificate_store ); gtk_widget_class_bind_template_child_private( GTK_WIDGET_CLASS(object_class), InfGtkCertificateDialog, caption ); gtk_widget_class_bind_template_child_private( GTK_WIDGET_CLASS(object_class), InfGtkCertificateDialog, info ); gtk_widget_class_bind_template_child_private( GTK_WIDGET_CLASS(object_class), InfGtkCertificateDialog, certificate_expander ); gtk_widget_class_bind_template_child_private( GTK_WIDGET_CLASS(object_class), InfGtkCertificateDialog, certificate_tree_view ); gtk_widget_class_bind_template_child_private( GTK_WIDGET_CLASS(object_class), InfGtkCertificateDialog, certificate_info_view ); gtk_widget_class_bind_template_child_private( GTK_WIDGET_CLASS(object_class), InfGtkCertificateDialog, text_renderer ); gtk_widget_class_bind_template_callback( GTK_WIDGET_CLASS(object_class), inf_gtk_certificate_dialog_selection_changed_cb ); g_object_class_install_property( object_class, PROP_CERTIFICATE_CHAIN, g_param_spec_boxed( "certificate-chain", "Certificate chain", "The certificate chain to show in the dialog", INF_TYPE_CERTIFICATE_CHAIN, G_PARAM_READWRITE ) ); g_object_class_install_property( object_class, PROP_PINNED_CERTIFICATE, g_param_spec_pointer( "pinned-certificate", "Pinned Certificate", "The certificate that we had pinned for this host", G_PARAM_READWRITE ) ); g_object_class_install_property( object_class, PROP_VERIFY_FLAGS, g_param_spec_flags( "verify-flags", "Verify flags", "What warnings about the certificate to display", INF_TYPE_CERTIFICATE_VERIFY_FLAGS, 0, G_PARAM_READWRITE ) ); g_object_class_install_property( object_class, PROP_HOSTNAME, g_param_spec_string( "hostname", "Host name", "Host name of the server from which the certificate is", NULL, G_PARAM_READWRITE ) ); } /* * Public API. */ /** * inf_gtk_certificate_dialog_new: (constructor) * @parent: Parent #GtkWindow of the dialog. * @dialog_flags: Flags for the dialog, see #GtkDialogFlags. * @verify_flags: What certificate warnings to show, see * #InfCertificateVerifyFlags. * @hostname: The host name of the server that provides the certificate. * @certificate_chain: (transfer none): The certificate chain provided by * the server. * @pinned_certificate: (transfer none): The certificate that we had pinned * for this host, or %NULL. * * Creates a new #InfGtkCertificateDialog. A #InfGtkCertificateDialog shows * a warning about a server's certificate to a user, for example when the * issuer is not trusted or the hostname does not match what the certificate * was issued to. * * Returns: (transfer full): A new #InfGtkCertificateDialog. */ InfGtkCertificateDialog* inf_gtk_certificate_dialog_new(GtkWindow* parent, GtkDialogFlags dialog_flags, InfCertificateVerifyFlags verify_flags, const gchar* hostname, InfCertificateChain* certificate_chain, gnutls_x509_crt_t pinned_certificate) { GObject* object; g_return_val_if_fail(parent == NULL || GTK_IS_WINDOW(parent), NULL); g_return_val_if_fail(verify_flags != 0, NULL); g_return_val_if_fail(hostname != NULL, NULL); g_return_val_if_fail(certificate_chain != NULL, NULL); object = g_object_new( INF_GTK_TYPE_CERTIFICATE_DIALOG, "certificate-chain", certificate_chain, "pinned-certificate", pinned_certificate, "verify-flags", verify_flags, "hostname", hostname, NULL ); if(dialog_flags & GTK_DIALOG_MODAL) gtk_window_set_modal(GTK_WINDOW(object), TRUE); if(dialog_flags & GTK_DIALOG_DESTROY_WITH_PARENT) gtk_window_set_destroy_with_parent(GTK_WINDOW(object), TRUE); gtk_window_set_transient_for(GTK_WINDOW(object), parent); return INF_GTK_CERTIFICATE_DIALOG(object); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfgtk/PaxHeaders.26529/inf-gtk-connection-view.c0000644000000000000000000000013213034342512022361 xustar0030 mtime=1483851082.021718383 30 atime=1483851082.021718383 30 ctime=1488261589.328138348 libinfinity-0.7.1/libinfgtk/inf-gtk-connection-view.c0000644000175000017500000004370013034342512023117 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-gtk-connection-view * @title: InfGtkConnectionView * @short_description: A widget showing connection parameters * @include: libinfgtk/inf-gtk-connection-view.h * @stability: Unstable * * #InfGtkConnectionView is a widget that shows parameters for a given * connection such as the name of the remote host, its IP address, and * encryption information. **/ #include #include #include #include #include #include typedef struct _InfGtkConnectionViewPrivate InfGtkConnectionViewPrivate; struct _InfGtkConnectionViewPrivate { InfXmppConnection* connection; GtkWidget* remote_hostname; GtkWidget* remote_ipaddress; GtkWidget* local_ipaddress; GtkWidget* tls_version; GtkWidget* cipher_suite; GtkWidget* dh_prime_bits; /* TODO: This box is duplicated with InfGtkCertificateDialog, we should * de-duplicate it. */ GtkTreeStore* certificate_store; GtkWidget* certificate_expander; GtkWidget* certificate_tree_view; GtkWidget* certificate_info_view; GtkCellRenderer* text_renderer; }; enum { PROP_0, PROP_CONNECTION }; #define INF_GTK_CONNECTION_VIEW_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INF_GTK_TYPE_CONNECTION_VIEW, InfGtkConnectionViewPrivate)) G_DEFINE_TYPE_WITH_CODE(InfGtkConnectionView, inf_gtk_connection_view, GTK_TYPE_GRID, G_ADD_PRIVATE(InfGtkConnectionView)) static gchar* inf_gtk_connection_view_format_ipaddress(InfIpAddress* address, guint port) { gchar* out; gchar* str; str = inf_ip_address_to_string(address); switch(inf_ip_address_get_family(address)) { case INF_IP_ADDRESS_IPV4: out = g_strdup_printf("%s:%u", str, port); break; case INF_IP_ADDRESS_IPV6: out = g_strdup_printf("[%s]:%u", str, port); break; default: g_assert_not_reached(); out = NULL; break; } g_free(str); return out; } static void inf_gtk_connection_view_set_chain(InfGtkConnectionView* view, InfCertificateChain* chain) { InfGtkConnectionViewPrivate* priv; guint i; gnutls_x509_crt_t crt; GtkTreeIter prev_row; GtkTreeIter new_row; GtkTreeIter* parent; GtkTreePath* path; priv = INF_GTK_CONNECTION_VIEW_PRIVATE(view); gtk_tree_store_clear(priv->certificate_store); inf_gtk_certificate_view_set_certificate( INF_GTK_CERTIFICATE_VIEW(priv->certificate_info_view), NULL ); parent = NULL; if(chain != NULL) { for(i = inf_certificate_chain_get_n_certificates(chain); i > 0; -- i) { crt = inf_certificate_chain_get_nth_certificate(chain, i - 1); gtk_tree_store_append(priv->certificate_store, &new_row, parent); gtk_tree_store_set(priv->certificate_store, &new_row, 0, crt, -1); prev_row = new_row; parent = &prev_row; } path = gtk_tree_model_get_path( GTK_TREE_MODEL(priv->certificate_store), &new_row ); gtk_tree_view_expand_to_path( GTK_TREE_VIEW(priv->certificate_tree_view), path ); gtk_tree_selection_select_path( gtk_tree_view_get_selection(GTK_TREE_VIEW(priv->certificate_tree_view)), path ); gtk_tree_view_scroll_to_cell( GTK_TREE_VIEW(priv->certificate_tree_view), path, NULL, FALSE, 0.0, 0.0 ); gtk_tree_path_free(path); gtk_widget_show(priv->certificate_expander); } else { gtk_widget_hide(priv->certificate_expander); } } static void inf_gtk_connection_view_selection_changed_cb(GtkTreeSelection* selection, gpointer user_data) { InfGtkConnectionView* view; InfGtkConnectionViewPrivate* priv; GtkTreeIter iter; gnutls_x509_crt_t cert; view = INF_GTK_CONNECTION_VIEW(user_data); priv = INF_GTK_CONNECTION_VIEW_PRIVATE(view); if(gtk_tree_selection_get_selected(selection, NULL, &iter)) { gtk_tree_model_get( GTK_TREE_MODEL(priv->certificate_store), &iter, 0, &cert, -1 ); inf_gtk_certificate_view_set_certificate( INF_GTK_CERTIFICATE_VIEW(priv->certificate_info_view), cert ); } else { inf_gtk_certificate_view_set_certificate( INF_GTK_CERTIFICATE_VIEW(priv->certificate_info_view), NULL ); } } static void inf_gtk_connection_view_chain_data_func(GtkTreeViewColumn* column, GtkCellRenderer* renderer, GtkTreeModel* tree_model, GtkTreeIter* iter, gpointer user_data) { gpointer crt_ptr; gnutls_x509_crt_t cert; GValue value = { 0 }; gchar* common_name; gtk_tree_model_get(tree_model, iter, 0, &crt_ptr, -1); cert = (gnutls_x509_crt_t)crt_ptr; common_name = inf_cert_util_get_dn_by_oid(cert, GNUTLS_OID_X520_COMMON_NAME, 0); g_value_init(&value, G_TYPE_STRING); if(common_name != NULL) g_value_take_string(&value, common_name); else g_value_set_static_string(&value, _("")); g_object_set_property(G_OBJECT(renderer), "text", &value); g_value_unset(&value); } static void inf_gtk_connection_view_update_connection_info(InfGtkConnectionView* view, InfXmppConnection* connection) { InfGtkConnectionViewPrivate* priv; InfTcpConnection* tcp; InfIpAddress* remote_address; guint remote_port; InfIpAddress* local_address; guint local_port; gchar* text; const gchar* cs; gnutls_kx_algorithm_t kx; gnutls_cipher_algorithm_t cipher; gnutls_mac_algorithm_t mac; gnutls_protocol_t ver; guint dh_prime_bits; priv = INF_GTK_CONNECTION_VIEW_PRIVATE(view); if(connection == NULL) { gtk_label_set_text(GTK_LABEL(priv->remote_hostname), NULL); gtk_label_set_text(GTK_LABEL(priv->remote_ipaddress), NULL); gtk_label_set_text(GTK_LABEL(priv->local_ipaddress), NULL); gtk_label_set_text(GTK_LABEL(priv->tls_version), NULL); gtk_label_set_text(GTK_LABEL(priv->cipher_suite), NULL); gtk_label_set_text(GTK_LABEL(priv->dh_prime_bits), NULL); inf_gtk_connection_view_set_chain(view, NULL); } else { g_object_get(G_OBJECT(connection), "remote-hostname", &text, NULL); if(text != NULL) { gtk_label_set_text(GTK_LABEL(priv->remote_hostname), text); } else { text = g_markup_printf_escaped("%s", _("Unknown")); gtk_label_set_markup(GTK_LABEL(priv->remote_hostname), text); } g_free(text); g_object_get(G_OBJECT(connection), "tcp-connection", &tcp, NULL); g_object_get( G_OBJECT(tcp), "remote-address", &remote_address, "remote-port", &remote_port, "local-address", &local_address, "local-port", &local_port, NULL ); g_object_unref(tcp); text = inf_gtk_connection_view_format_ipaddress( remote_address, remote_port ); gtk_label_set_text(GTK_LABEL(priv->remote_ipaddress), text); g_free(text); text = inf_gtk_connection_view_format_ipaddress( local_address, local_port ); gtk_label_set_text(GTK_LABEL(priv->local_ipaddress), text); g_free(text); inf_ip_address_free(remote_address); inf_ip_address_free(local_address); if(inf_xmpp_connection_get_tls_enabled(connection)) { kx = inf_xmpp_connection_get_kx_algorithm(connection); cipher = inf_xmpp_connection_get_cipher_algorithm(connection); mac = inf_xmpp_connection_get_mac_algorithm(connection); ver = inf_xmpp_connection_get_tls_protocol(connection); dh_prime_bits = inf_xmpp_connection_get_dh_prime_bits(connection); gtk_label_set_text( GTK_LABEL(priv->tls_version), gnutls_protocol_get_name(ver) ); cs = gnutls_cipher_suite_get_name(kx, cipher, mac); if(ver == GNUTLS_SSL3) text = g_strdup_printf("SSL_%s", cs); else text = g_strdup_printf("TLS_%s", cs); gtk_label_set_text(GTK_LABEL(priv->cipher_suite), text); g_free(text); if(dh_prime_bits > 0) { text = g_markup_printf_escaped("%u bit", dh_prime_bits); gtk_label_set_text(GTK_LABEL(priv->dh_prime_bits), text); } else { text = g_markup_printf_escaped("%s", _("N/A")); gtk_label_set_markup(GTK_LABEL(priv->dh_prime_bits), text); } g_free(text); inf_gtk_connection_view_set_chain( view, inf_xmpp_connection_get_peer_certificate(connection) ); } else { text = g_markup_printf_escaped("%s", _("No Encryption")); gtk_label_set_markup(GTK_LABEL(priv->tls_version), text); g_free(text); text = g_markup_printf_escaped("%s", _("N/A")); gtk_label_set_markup(GTK_LABEL(priv->cipher_suite), text); gtk_label_set_markup(GTK_LABEL(priv->dh_prime_bits), text); g_free(text); inf_gtk_connection_view_set_chain(view, NULL); } } } static void inf_gtk_connection_view_notify_tls_enabled_cb(GObject* object, GParamSpec* pspec, gpointer user_data) { InfGtkConnectionView* view; InfGtkConnectionViewPrivate* priv; view = INF_GTK_CONNECTION_VIEW(user_data); priv = INF_GTK_CONNECTION_VIEW_PRIVATE(view); g_assert(priv->connection != NULL); inf_gtk_connection_view_update_connection_info(view, priv->connection); } static void inf_gtk_connection_view_notify_credentials_cb(GObject* object, GParamSpec* pspec, gpointer user_data) { InfGtkConnectionView* view; InfGtkConnectionViewPrivate* priv; view = INF_GTK_CONNECTION_VIEW(user_data); priv = INF_GTK_CONNECTION_VIEW_PRIVATE(view); g_assert(priv->connection != NULL); inf_gtk_connection_view_update_connection_info(view, priv->connection); } static void inf_gtk_connection_view_init(InfGtkConnectionView* view) { InfGtkConnectionViewPrivate* priv; priv = INF_GTK_CONNECTION_VIEW_PRIVATE(view); priv->connection = NULL; gtk_widget_init_template(GTK_WIDGET(view)); gtk_tree_selection_set_mode( gtk_tree_view_get_selection(GTK_TREE_VIEW(priv->certificate_tree_view)), GTK_SELECTION_BROWSE ); gtk_tree_view_column_set_cell_data_func( gtk_tree_view_get_column(GTK_TREE_VIEW(priv->certificate_tree_view), 0), priv->text_renderer, inf_gtk_connection_view_chain_data_func, NULL, NULL ); } static void inf_gtk_connection_view_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfGtkConnectionView* view; InfGtkConnectionViewPrivate* priv; view = INF_GTK_CONNECTION_VIEW(object); priv = INF_GTK_CONNECTION_VIEW_PRIVATE(view); switch(prop_id) { case PROP_CONNECTION: inf_gtk_connection_view_set_connection(view, INF_XMPP_CONNECTION(value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void inf_gtk_connection_view_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfGtkConnectionView* view; InfGtkConnectionViewPrivate* priv; view = INF_GTK_CONNECTION_VIEW(object); priv = INF_GTK_CONNECTION_VIEW_PRIVATE(view); switch(prop_id) { case PROP_CONNECTION: g_value_set_object(value, priv->connection); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void inf_gtk_connection_view_dispose(GObject* object) { InfGtkConnectionView* view; InfGtkConnectionViewPrivate* priv; view = INF_GTK_CONNECTION_VIEW(object); priv = INF_GTK_CONNECTION_VIEW_PRIVATE(view); if(priv->connection != NULL) inf_gtk_connection_view_set_connection(view, NULL); G_OBJECT_CLASS(inf_gtk_connection_view_parent_class)->dispose(object); } /* * GType registration */ static void inf_gtk_connection_view_class_init( InfGtkConnectionViewClass* connection_view_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(connection_view_class); object_class->set_property = inf_gtk_connection_view_set_property; object_class->get_property = inf_gtk_connection_view_get_property; object_class->dispose = inf_gtk_connection_view_dispose; gtk_widget_class_set_template_from_resource( GTK_WIDGET_CLASS(connection_view_class), "/de/0x539/libinfgtk/ui/infgtkconnectionview.ui" ); gtk_widget_class_bind_template_child_private( GTK_WIDGET_CLASS(object_class), InfGtkConnectionView, certificate_store ); gtk_widget_class_bind_template_child_private( GTK_WIDGET_CLASS(connection_view_class), InfGtkConnectionView, remote_hostname ); gtk_widget_class_bind_template_child_private( GTK_WIDGET_CLASS(connection_view_class), InfGtkConnectionView, remote_ipaddress ); gtk_widget_class_bind_template_child_private( GTK_WIDGET_CLASS(connection_view_class), InfGtkConnectionView, local_ipaddress ); gtk_widget_class_bind_template_child_private( GTK_WIDGET_CLASS(connection_view_class), InfGtkConnectionView, tls_version ); gtk_widget_class_bind_template_child_private( GTK_WIDGET_CLASS(connection_view_class), InfGtkConnectionView, cipher_suite ); gtk_widget_class_bind_template_child_private( GTK_WIDGET_CLASS(connection_view_class), InfGtkConnectionView, dh_prime_bits ); gtk_widget_class_bind_template_child_private( GTK_WIDGET_CLASS(object_class), InfGtkConnectionView, certificate_expander ); gtk_widget_class_bind_template_child_private( GTK_WIDGET_CLASS(object_class), InfGtkConnectionView, certificate_tree_view ); gtk_widget_class_bind_template_child_private( GTK_WIDGET_CLASS(object_class), InfGtkConnectionView, certificate_info_view ); gtk_widget_class_bind_template_child_private( GTK_WIDGET_CLASS(object_class), InfGtkConnectionView, text_renderer ); gtk_widget_class_bind_template_callback( GTK_WIDGET_CLASS(object_class), inf_gtk_connection_view_selection_changed_cb ); g_object_class_install_property( object_class, PROP_CONNECTION, g_param_spec_object( "connection", "Connection", "Connection for which to show parameters", INF_TYPE_XMPP_CONNECTION, G_PARAM_READWRITE ) ); } /* * Public API. */ /** * inf_gtk_connection_view_new: (constructor) * * Creates a new #InfGtkConnectionView. To show a connection, use * inf_gtk_connection_view_set_connection() on the returned widget. * * Returns: (transfer floating): A new #InfGtkConnectionView. */ GtkWidget* inf_gtk_connection_view_new(void) { GObject* object; object = g_object_new(INF_GTK_TYPE_CONNECTION_VIEW, NULL); return GTK_WIDGET(object); } /** * inf_gtk_connection_view_new_with_connection: (constructor) * @connection: The connection to show. * * Creates a new #InfGtkConnectionView showing the given connection. This * is the same as creating a new connection view and calling * inf_gtk_connection_view_set_connection() afterwards. * * Returns: (transfer floating): A new #InfGtkConnectionView. */ GtkWidget* inf_gtk_connection_view_new_with_connection(InfXmppConnection* connection) { GObject* object; g_return_val_if_fail( connection == NULL || INF_IS_XMPP_CONNECTION(connection), NULL ); object = g_object_new( INF_GTK_TYPE_CONNECTION_VIEW, "connection", connection, NULL ); return GTK_WIDGET(object); } /** * inf_gtk_connection_view_set_connection: * @view: A #InfGtkConnectionView. * @connection: The connection to show. * * Shows the given connection in @view. */ void inf_gtk_connection_view_set_connection(InfGtkConnectionView* view, InfXmppConnection* connection) { InfGtkConnectionViewPrivate* priv; g_return_if_fail(INF_GTK_IS_CONNECTION_VIEW(view)); g_return_if_fail(connection == NULL || INF_IS_XMPP_CONNECTION(connection)); priv = INF_GTK_CONNECTION_VIEW_PRIVATE(view); if(priv->connection != NULL) { inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->connection), G_CALLBACK(inf_gtk_connection_view_notify_tls_enabled_cb), view ); inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->connection), G_CALLBACK(inf_gtk_connection_view_notify_credentials_cb), view ); g_object_unref(priv->connection); } priv->connection = connection; if(connection != NULL) { g_object_ref(connection); g_signal_connect( G_OBJECT(connection), "notify::tls-enabled", G_CALLBACK(inf_gtk_connection_view_notify_tls_enabled_cb), view ); g_signal_connect( G_OBJECT(connection), "notify::credentials", G_CALLBACK(inf_gtk_connection_view_notify_credentials_cb), view ); } inf_gtk_connection_view_update_connection_info(view, connection); g_object_notify(G_OBJECT(view), "connection"); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfgtk/PaxHeaders.26529/inf-gtk-permissions-dialog.h0000644000000000000000000000013213034342512023067 xustar0030 mtime=1483851082.021718383 30 atime=1483851082.021718383 30 ctime=1488261589.308138392 libinfinity-0.7.1/libinfgtk/inf-gtk-permissions-dialog.h0000644000175000017500000000570413034342512023627 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_GTK_PERMISSIONS_DIALOG_H__ #define __INF_GTK_PERMISSIONS_DIALOG_H__ #include #include #include G_BEGIN_DECLS #define INF_GTK_TYPE_PERMISSIONS_DIALOG (inf_gtk_permissions_dialog_get_type()) #define INF_GTK_PERMISSIONS_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_GTK_TYPE_PERMISSIONS_DIALOG, InfGtkPermissionsDialog)) #define INF_GTK_PERMISSIONS_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INF_GTK_TYPE_PERMISSIONS_DIALOG, InfGtkPermissionsDialogClass)) #define INF_GTK_IS_PERMISSIONS_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_GTK_TYPE_PERMISSIONS_DIALOG)) #define INF_GTK_IS_PERMISSIONS_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INF_GTK_TYPE_PERMISSIONS_DIALOG)) #define INF_GTK_PERMISSIONS_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INF_GTK_TYPE_PERMISSIONS_DIALOG, InfGtkPermissionsDialogClass)) typedef struct _InfGtkPermissionsDialog InfGtkPermissionsDialog; typedef struct _InfGtkPermissionsDialogClass InfGtkPermissionsDialogClass; /** * InfGtkPermissionsDialogClass: * * This structure does not contain any public fields. */ struct _InfGtkPermissionsDialogClass { /*< private >*/ GtkDialogClass parent_class; }; /** * InfGtkPermissionsDialog: * * #InfGtkPermissionsDialog is an opaque data type. You should only access * it via the public API functions. */ struct _InfGtkPermissionsDialog { /*< private >*/ GtkDialog parent; }; GType inf_gtk_permissions_dialog_get_type(void) G_GNUC_CONST; InfGtkPermissionsDialog* inf_gtk_permissions_dialog_new(GtkWindow* parent, GtkDialogFlags dialog_flags, InfBrowser* browser, const InfBrowserIter* iter); void inf_gtk_permissions_dialog_set_node(InfGtkPermissionsDialog* dialog, InfBrowser* browser, const InfBrowserIter* iter); G_END_DECLS #endif /* __INF_GTK_PERMISSIONS_DIALOG_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfgtk/PaxHeaders.26529/inf-gtk-io.h0000644000000000000000000000013213034342512017666 xustar0030 mtime=1483851082.021718383 30 atime=1483851082.021718383 30 ctime=1488261589.304138401 libinfinity-0.7.1/libinfgtk/inf-gtk-io.h0000644000175000017500000000347613034342512020432 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_GTK_IO_H__ #define __INF_GTK_IO_H__ #include G_BEGIN_DECLS #define INF_GTK_TYPE_IO (inf_gtk_io_get_type()) #define INF_GTK_IO(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_GTK_TYPE_IO, InfGtkIo)) #define INF_GTK_IO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INF_GTK_TYPE_IO, InfGtkIoClass)) #define INF_GTK_IS_IO(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_GTK_TYPE_IO)) #define INF_GTK_IS_IO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INF_GTK_TYPE_IO)) #define INF_GTK_IO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INF_GTK_TYPE_IO, InfGtkIoClass)) typedef struct _InfGtkIo InfGtkIo; typedef struct _InfGtkIoClass InfGtkIoClass; struct _InfGtkIoClass { GObjectClass parent_class; }; struct _InfGtkIo { GObject parent; }; GType inf_gtk_io_get_type(void) G_GNUC_CONST; InfGtkIo* inf_gtk_io_new(void); G_END_DECLS #endif /* __INF_GTK_IO_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfgtk/PaxHeaders.26529/inf-gtk-certificate-manager.c0000644000000000000000000000013213034342512023144 xustar0030 mtime=1483851082.021718383 30 atime=1483851082.021718383 30 ctime=1488261589.324138357 libinfinity-0.7.1/libinfgtk/inf-gtk-certificate-manager.c0000644000175000017500000002500413034342512023677 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-gtk-certificate-manager * @title: InfGtkCertificateManager * @short_description: Verify server certificates and warn the user * @include: libinfgtk/inf-gtk-certificate-manager.h * @stability: Unstable * * #InfGtkCertificateManager is derived from #InfCertificateVerify, and * as such it verifies server certificates. This class handles the * #InfCertificateVerify::check-certificate signal by showing a * #InfGtkCertificateDialog to the user to let them decide whether or not * to accept the server's certificate. **/ #include #include #include typedef struct _InfGtkCertificateManagerDialog InfGtkCertificateManagerDialog; struct _InfGtkCertificateManagerDialog { InfGtkCertificateManager* manager; InfXmppConnection* connection; InfGtkCertificateDialog* dialog; }; typedef struct _InfGtkCertificateManagerPrivate InfGtkCertificateManagerPrivate; struct _InfGtkCertificateManagerPrivate { GtkWindow* parent_window; GSList* dialogs; }; enum { PROP_0, PROP_PARENT_WINDOW }; #define INF_GTK_CERTIFICATE_MANAGER_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INF_GTK_TYPE_CERTIFICATE_MANAGER, InfGtkCertificateManagerPrivate)) G_DEFINE_TYPE_WITH_CODE(InfGtkCertificateManager, inf_gtk_certificate_manager, INF_TYPE_CERTIFICATE_VERIFY, G_ADD_PRIVATE(InfGtkCertificateManager)) static void inf_gtk_certificate_manager_dialog_free(InfGtkCertificateManagerDialog* item) { gtk_widget_destroy(GTK_WIDGET(item->dialog)); g_slice_free(InfGtkCertificateManagerDialog, item); } static void inf_gtk_certificate_manager_response_cb(GtkDialog* dialog, int response, gpointer user_data) { InfGtkCertificateManagerDialog* item; InfGtkCertificateManager* manager; InfGtkCertificateManagerPrivate* priv; InfXmppConnection* connection; item = (InfGtkCertificateManagerDialog*)user_data; manager = INF_GTK_CERTIFICATE_MANAGER(item->manager); priv = INF_GTK_CERTIFICATE_MANAGER_PRIVATE(manager); connection = item->connection; switch(response) { case GTK_RESPONSE_ACCEPT: inf_certificate_verify_checked( INF_CERTIFICATE_VERIFY(manager), connection, TRUE ); break; case GTK_RESPONSE_REJECT: case GTK_RESPONSE_DELETE_EVENT: inf_certificate_verify_checked( INF_CERTIFICATE_VERIFY(manager), connection, FALSE ); break; default: g_assert_not_reached(); break; } inf_gtk_certificate_manager_dialog_free(item); priv->dialogs = g_slist_remove(priv->dialogs, item); } static void inf_gtk_certificate_manager_init(InfGtkCertificateManager* manager) { InfGtkCertificateManagerPrivate* priv; priv = INF_GTK_CERTIFICATE_MANAGER_PRIVATE(manager); priv->parent_window = NULL; priv->dialogs = NULL; } static void inf_gtk_certificate_manager_dispose(GObject* object) { InfGtkCertificateManager* manager; InfGtkCertificateManagerPrivate* priv; manager = INF_GTK_CERTIFICATE_MANAGER(object); priv = INF_GTK_CERTIFICATE_MANAGER_PRIVATE(manager); if(priv->parent_window != NULL) { g_object_unref(priv->parent_window); priv->parent_window = NULL; } G_OBJECT_CLASS(inf_gtk_certificate_manager_parent_class)->dispose(object); g_assert(priv->dialogs == NULL); } static void inf_gtk_certificate_manager_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfGtkCertificateManager* manager; InfGtkCertificateManagerPrivate* priv; manager = INF_GTK_CERTIFICATE_MANAGER(object); priv = INF_GTK_CERTIFICATE_MANAGER_PRIVATE(manager); switch(prop_id) { case PROP_PARENT_WINDOW: g_assert(priv->parent_window == NULL); /* construct/only */ priv->parent_window = GTK_WINDOW(g_value_dup_object(value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void inf_gtk_certificate_manager_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfGtkCertificateManager* manager; InfGtkCertificateManagerPrivate* priv; manager = INF_GTK_CERTIFICATE_MANAGER(object); priv = INF_GTK_CERTIFICATE_MANAGER_PRIVATE(manager); switch(prop_id) { case PROP_PARENT_WINDOW: g_value_set_object(value, G_OBJECT(priv->parent_window)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void inf_gtk_certificate_manager_check_certificate( InfCertificateVerify* verify, InfXmppConnection* connection, InfCertificateChain* certificate_chain, gnutls_x509_crt_t pinned_certificate, InfCertificateVerifyFlags flags) { InfGtkCertificateManager* manager; InfGtkCertificateManagerPrivate* priv; InfGtkCertificateManagerDialog* item; InfGtkCertificateDialog* dialog; gchar* hostname; gchar* text; GtkWidget* label; GtkWidget* vbox; manager = INF_GTK_CERTIFICATE_MANAGER(verify); priv = INF_GTK_CERTIFICATE_MANAGER_PRIVATE(manager); g_object_get(G_OBJECT(connection), "remote-hostname", &hostname, NULL); dialog = inf_gtk_certificate_dialog_new( priv->parent_window, 0, flags, hostname, certificate_chain, pinned_certificate ); gtk_dialog_add_button( GTK_DIALOG(dialog), _("_Cancel connection"), GTK_RESPONSE_REJECT ); gtk_dialog_add_button( GTK_DIALOG(dialog), _("C_ontinue connection"), GTK_RESPONSE_ACCEPT ); text = g_strdup_printf( _("Do you want to continue the connection to host \"%s\"? If you " "choose to continue, this certificate will be trusted in the " "future when connecting to this host."), hostname ); g_free(hostname); label = gtk_label_new(text); gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); gtk_label_set_max_width_chars(GTK_LABEL(label), 75); gtk_widget_set_halign(GTK_WIDGET(label), GTK_ALIGN_START); gtk_widget_set_valign(GTK_WIDGET(label), GTK_ALIGN_START); #if GTK_CHECK_VERSION(3,16,0) gtk_label_set_xalign(GTK_LABEL(label), 0.0); #else gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0); #endif gtk_widget_show(label); g_free(text); vbox = gtk_dialog_get_content_area(GTK_DIALOG(dialog)); gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, TRUE, 6); item = g_slice_new(InfGtkCertificateManagerDialog); item->manager = manager; item->connection = connection; item->dialog = dialog; priv->dialogs = g_slist_prepend(priv->dialogs, item); g_signal_connect( G_OBJECT(dialog), "response", G_CALLBACK(inf_gtk_certificate_manager_response_cb), item ); gtk_window_present(GTK_WINDOW(dialog)); } static void inf_gtk_certificate_manager_check_cancelled(InfCertificateVerify* verify, InfXmppConnection* connection) { InfGtkCertificateManager* manager; InfGtkCertificateManagerPrivate* priv; InfGtkCertificateManagerDialog* item; GSList* iter; manager = INF_GTK_CERTIFICATE_MANAGER(verify); priv = INF_GTK_CERTIFICATE_MANAGER_PRIVATE(manager); for(iter = priv->dialogs; iter != NULL; iter = iter->next) { item = (InfGtkCertificateManagerDialog*)iter->data; if(item->connection == connection) break; } g_assert(iter != NULL); inf_gtk_certificate_manager_dialog_free(item); priv->dialogs = g_slist_remove(priv->dialogs, item); } /* * GType registration */ static void inf_gtk_certificate_manager_class_init( InfGtkCertificateManagerClass* certificate_manager_class) { GObjectClass* object_class; InfCertificateVerifyClass* certificate_verify_class; object_class = G_OBJECT_CLASS(certificate_manager_class); certificate_verify_class = INF_CERTIFICATE_VERIFY_CLASS(certificate_manager_class); object_class->dispose = inf_gtk_certificate_manager_dispose; object_class->set_property = inf_gtk_certificate_manager_set_property; object_class->get_property = inf_gtk_certificate_manager_get_property; certificate_verify_class->check_certificate = inf_gtk_certificate_manager_check_certificate; certificate_verify_class->check_cancelled = inf_gtk_certificate_manager_check_cancelled; g_object_class_install_property( object_class, PROP_PARENT_WINDOW, g_param_spec_object( "parent-window", "Parent window", "The parent window for certificate verification dialogs", GTK_TYPE_WINDOW, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); } /* * Public API. */ /** * inf_gtk_certificate_manager_new: (constructor) * @parent_window: The #GtkWindow to which to make certificate verification * dialogs transient to. * @xmpp_manager: The #InfXmppManager whose #InfXmppConnections to * manage the certificates for. * @known_hosts_file: (type filename) (allow-none): Path pointing to a file * that contains pinned certificates, or %NULL. * * Creates a new #InfGtkCertificateManager. See #InfCertificateVerify for * details about the certificate verification process. * * Returns: (transfer full): A new #InfGtkCertificateManager. **/ InfGtkCertificateManager* inf_gtk_certificate_manager_new(GtkWindow* parent_window, InfXmppManager* xmpp_manager, const gchar* known_hosts_file) { GObject* object; object = g_object_new( INF_GTK_TYPE_CERTIFICATE_MANAGER, "parent-window", parent_window, "xmpp-manager", xmpp_manager, "known-hosts-file", known_hosts_file, NULL ); return INF_GTK_CERTIFICATE_MANAGER(object); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfgtk/PaxHeaders.26529/inf-gtk-certificate-view.h0000644000000000000000000000013213034342512022511 xustar0030 mtime=1483851082.021718383 30 atime=1483851082.021718383 30 ctime=1488261589.300138409 libinfinity-0.7.1/libinfgtk/inf-gtk-certificate-view.h0000644000175000017500000000513413034342512023246 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_GTK_CERTIFICATE_VIEW_H__ #define __INF_GTK_CERTIFICATE_VIEW_H__ #include #include #include /* Get ssize_t on MSVC, required by gnutls.h */ #include G_BEGIN_DECLS #define INF_GTK_TYPE_CERTIFICATE_VIEW (inf_gtk_certificate_view_get_type()) #define INF_GTK_CERTIFICATE_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_GTK_TYPE_CERTIFICATE_VIEW, InfGtkCertificateView)) #define INF_GTK_CERTIFICATE_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INF_GTK_TYPE_CERTIFICATE_VIEW, InfGtkCertificateViewClass)) #define INF_GTK_IS_CERTIFICATE_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_GTK_TYPE_CERTIFICATE_VIEW)) #define INF_GTK_IS_CERTIFICATE_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INF_GTK_TYPE_CERTIFICATE_VIEW)) #define INF_GTK_CERTIFICATE_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INF_GTK_TYPE_CERTIFICATE_VIEW, InfGtkCertificateViewClass)) #define INF_GTK_TYPE_CERTIFICATE_VIEW_FLAGS (inf_gtk_certificate_view_flags_get_type()) typedef struct _InfGtkCertificateView InfGtkCertificateView; typedef struct _InfGtkCertificateViewClass InfGtkCertificateViewClass; struct _InfGtkCertificateViewClass { GtkGridClass parent_class; }; struct _InfGtkCertificateView { GtkGrid parent; }; GType inf_gtk_certificate_view_get_type(void) G_GNUC_CONST; GtkWidget* inf_gtk_certificate_view_new(void); GtkWidget* inf_gtk_certificate_view_new_with_certificate(gnutls_x509_crt_t cert); void inf_gtk_certificate_view_set_certificate(InfGtkCertificateView* view, gnutls_x509_crt_t cert); G_END_DECLS #endif /* __INF_GTK_CERTIFICATE_VIEW_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfgtk/PaxHeaders.26529/inf-gtk-resources.c0000644000000000000000000000013113045431556021274 xustar0030 mtime=1486238574.830690981 29 atime=1486238574.82269088 30 ctime=1488261589.332138339 libinfinity-0.7.1/libinfgtk/inf-gtk-resources.c0000644000175000017500000104040313045431556022031 0ustar00arminarmin00000000000000#include #if defined (__ELF__) && ( __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 6)) # define SECTION __attribute__ ((section (".gresource.inf_gtk"), aligned (8))) #else # define SECTION #endif static const SECTION union { const guint8 data[42884]; const double alignment; void * const ptr;} _inf_gtk_resource_data = { { 0x47, 0x56, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x70, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x24, 0xd8, 0xb5, 0x44, 0x04, 0x00, 0x00, 0x00, 0x70, 0x01, 0x00, 0x00, 0x06, 0x00, 0x4c, 0x00, 0x78, 0x01, 0x00, 0x00, 0x7c, 0x01, 0x00, 0x00, 0x3c, 0xb2, 0xca, 0xe2, 0x07, 0x00, 0x00, 0x00, 0x7c, 0x01, 0x00, 0x00, 0x1a, 0x00, 0x76, 0x00, 0x98, 0x01, 0x00, 0x00, 0x07, 0x19, 0x00, 0x00, 0x94, 0xc1, 0x56, 0x71, 0x07, 0x00, 0x00, 0x00, 0x07, 0x19, 0x00, 0x00, 0x17, 0x00, 0x76, 0x00, 0x20, 0x19, 0x00, 0x00, 0x2c, 0x37, 0x00, 0x00, 0xa9, 0x6b, 0x44, 0xc8, 0x07, 0x00, 0x00, 0x00, 0x2c, 0x37, 0x00, 0x00, 0x0d, 0x00, 0x76, 0x00, 0x40, 0x37, 0x00, 0x00, 0x47, 0x45, 0x00, 0x00, 0xec, 0x8b, 0x78, 0x7c, 0x09, 0x00, 0x00, 0x00, 0x47, 0x45, 0x00, 0x00, 0x03, 0x00, 0x4c, 0x00, 0x4c, 0x45, 0x00, 0x00, 0x50, 0x45, 0x00, 0x00, 0xed, 0x2e, 0xde, 0x28, 0x07, 0x00, 0x00, 0x00, 0x50, 0x45, 0x00, 0x00, 0x15, 0x00, 0x76, 0x00, 0x68, 0x45, 0x00, 0x00, 0x9a, 0x4f, 0x00, 0x00, 0xd5, 0xb6, 0xe6, 0x79, 0x07, 0x00, 0x00, 0x00, 0x9a, 0x4f, 0x00, 0x00, 0x1a, 0x00, 0x76, 0x00, 0xb8, 0x4f, 0x00, 0x00, 0xf7, 0x6b, 0x00, 0x00, 0x1a, 0x69, 0xdd, 0x8c, 0x0a, 0x00, 0x00, 0x00, 0xf7, 0x6b, 0x00, 0x00, 0x03, 0x00, 0x4c, 0x00, 0xfc, 0x6b, 0x00, 0x00, 0x18, 0x6c, 0x00, 0x00, 0x87, 0x78, 0x8c, 0x47, 0x07, 0x00, 0x00, 0x00, 0x18, 0x6c, 0x00, 0x00, 0x18, 0x00, 0x76, 0x00, 0x30, 0x6c, 0x00, 0x00, 0x3b, 0x95, 0x00, 0x00, 0xd4, 0xb5, 0x02, 0x00, 0xff, 0xff, 0xff, 0xff, 0x3b, 0x95, 0x00, 0x00, 0x01, 0x00, 0x4c, 0x00, 0x3c, 0x95, 0x00, 0x00, 0x40, 0x95, 0x00, 0x00, 0xcd, 0x00, 0x4b, 0xec, 0x00, 0x00, 0x00, 0x00, 0x40, 0x95, 0x00, 0x00, 0x0a, 0x00, 0x4c, 0x00, 0x4c, 0x95, 0x00, 0x00, 0x50, 0x95, 0x00, 0x00, 0xbb, 0x06, 0x32, 0x5c, 0x07, 0x00, 0x00, 0x00, 0x50, 0x95, 0x00, 0x00, 0x1e, 0x00, 0x76, 0x00, 0x70, 0x95, 0x00, 0x00, 0x84, 0xa7, 0x00, 0x00, 0x30, 0x78, 0x35, 0x33, 0x39, 0x2f, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x66, 0x67, 0x74, 0x6b, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x75, 0x69, 0x00, 0x00, 0x5f, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x3f, 0x78, 0x6d, 0x6c, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x22, 0x31, 0x2e, 0x30, 0x22, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x3d, 0x22, 0x55, 0x54, 0x46, 0x2d, 0x38, 0x22, 0x3f, 0x3e, 0x0a, 0x3c, 0x21, 0x2d, 0x2d, 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x67, 0x6c, 0x61, 0x64, 0x65, 0x20, 0x33, 0x2e, 0x31, 0x38, 0x2e, 0x33, 0x20, 0x2d, 0x2d, 0x3e, 0x0a, 0x3c, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x20, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x3d, 0x22, 0x6c, 0x69, 0x62, 0x69, 0x6e, 0x66, 0x67, 0x74, 0x6b, 0x30, 0x37, 0x22, 0x3e, 0x3c, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x73, 0x20, 0x6c, 0x69, 0x62, 0x3d, 0x22, 0x67, 0x74, 0x6b, 0x2b, 0x22, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x22, 0x33, 0x2e, 0x31, 0x30, 0x22, 0x2f, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x54, 0x72, 0x65, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x22, 0x3e, 0x3c, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73, 0x3e, 0x3c, 0x21, 0x2d, 0x2d, 0x20, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x2d, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x2d, 0x2d, 0x3e, 0x3c, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x22, 0x67, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x22, 0x2f, 0x3e, 0x3c, 0x2f, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x49, 0x6e, 0x66, 0x47, 0x74, 0x6b, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x44, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x22, 0x20, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x44, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x61, 0x6e, 0x5f, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x22, 0x3e, 0x46, 0x61, 0x6c, 0x73, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x5f, 0x77, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3e, 0x31, 0x32, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x22, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3d, 0x22, 0x79, 0x65, 0x73, 0x22, 0x3e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x4e, 0x6f, 0x74, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x72, 0x65, 0x73, 0x69, 0x7a, 0x61, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x46, 0x61, 0x6c, 0x73, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x69, 0x63, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x3e, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x2d, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x68, 0x69, 0x6e, 0x74, 0x22, 0x3e, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2d, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3d, 0x22, 0x76, 0x62, 0x6f, 0x78, 0x22, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x42, 0x6f, 0x78, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x2d, 0x76, 0x62, 0x6f, 0x78, 0x31, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x61, 0x6e, 0x5f, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x22, 0x3e, 0x46, 0x61, 0x6c, 0x73, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x22, 0x3e, 0x36, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2d, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3d, 0x22, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x72, 0x65, 0x61, 0x22, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x42, 0x6f, 0x78, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x2d, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x72, 0x65, 0x61, 0x31, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x61, 0x6e, 0x5f, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x22, 0x3e, 0x46, 0x61, 0x6c, 0x73, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x5f, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x22, 0x3e, 0x65, 0x6e, 0x64, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x2f, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x2f, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x22, 0x3e, 0x46, 0x61, 0x6c, 0x73, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x70, 0x61, 0x63, 0x6b, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3e, 0x65, 0x6e, 0x64, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x47, 0x72, 0x69, 0x64, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x67, 0x72, 0x69, 0x64, 0x31, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x61, 0x6e, 0x5f, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x22, 0x3e, 0x46, 0x61, 0x6c, 0x73, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3e, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x22, 0x3e, 0x31, 0x32, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x61, 0x6e, 0x5f, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x22, 0x3e, 0x46, 0x61, 0x6c, 0x73, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x47, 0x54, 0x4b, 0x5f, 0x41, 0x4c, 0x49, 0x47, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x52, 0x54, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x69, 0x63, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x3e, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x2d, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x69, 0x63, 0x6f, 0x6e, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x22, 0x3e, 0x36, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x47, 0x72, 0x69, 0x64, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x67, 0x72, 0x69, 0x64, 0x32, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x61, 0x6e, 0x5f, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x22, 0x3e, 0x46, 0x61, 0x6c, 0x73, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x72, 0x6f, 0x77, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x22, 0x3e, 0x36, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x63, 0x61, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x61, 0x6e, 0x5f, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x22, 0x3e, 0x46, 0x61, 0x6c, 0x73, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x5f, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x22, 0x3e, 0x31, 0x32, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x68, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x47, 0x54, 0x4b, 0x5f, 0x41, 0x4c, 0x49, 0x47, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x52, 0x54, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x47, 0x54, 0x4b, 0x5f, 0x41, 0x4c, 0x49, 0x47, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x52, 0x54, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x78, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x77, 0x72, 0x61, 0x70, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6d, 0x61, 0x78, 0x5f, 0x77, 0x69, 0x64, 0x74, 0x68, 0x5f, 0x63, 0x68, 0x61, 0x72, 0x73, 0x22, 0x3e, 0x36, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x3e, 0x3c, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3d, 0x22, 0x62, 0x6f, 0x6c, 0x64, 0x22, 0x2f, 0x3e, 0x3c, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x22, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3d, 0x22, 0x31, 0x2e, 0x32, 0x22, 0x2f, 0x3e, 0x3c, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x69, 0x6e, 0x66, 0x6f, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x61, 0x6e, 0x5f, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x22, 0x3e, 0x46, 0x61, 0x6c, 0x73, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x68, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x47, 0x54, 0x4b, 0x5f, 0x41, 0x4c, 0x49, 0x47, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x52, 0x54, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x47, 0x54, 0x4b, 0x5f, 0x41, 0x4c, 0x49, 0x47, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x52, 0x54, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x78, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x77, 0x72, 0x61, 0x70, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6d, 0x61, 0x78, 0x5f, 0x77, 0x69, 0x64, 0x74, 0x68, 0x5f, 0x63, 0x68, 0x61, 0x72, 0x73, 0x22, 0x3e, 0x37, 0x35, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x31, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x45, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x65, 0x72, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x65, 0x72, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x61, 0x6e, 0x5f, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x5f, 0x74, 0x6f, 0x70, 0x22, 0x3e, 0x36, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x22, 0x3e, 0x36, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x47, 0x72, 0x69, 0x64, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x67, 0x72, 0x69, 0x64, 0x33, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x61, 0x6e, 0x5f, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x22, 0x3e, 0x46, 0x61, 0x6c, 0x73, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x5f, 0x6c, 0x65, 0x66, 0x74, 0x22, 0x3e, 0x31, 0x32, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3e, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x22, 0x3e, 0x31, 0x32, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x53, 0x63, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x64, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x73, 0x63, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x64, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x31, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x61, 0x6e, 0x5f, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3e, 0x69, 0x6e, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6d, 0x69, 0x6e, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x5f, 0x77, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3e, 0x32, 0x30, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x54, 0x72, 0x65, 0x65, 0x56, 0x69, 0x65, 0x77, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x76, 0x69, 0x65, 0x77, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x61, 0x6e, 0x5f, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x22, 0x3e, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x73, 0x68, 0x6f, 0x77, 0x5f, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x65, 0x72, 0x73, 0x22, 0x3e, 0x46, 0x61, 0x6c, 0x73, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3e, 0x31, 0x32, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x2d, 0x73, 0x65, 0x74, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2d, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3d, 0x22, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x54, 0x72, 0x65, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x74, 0x72, 0x65, 0x65, 0x76, 0x69, 0x65, 0x77, 0x2d, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x22, 0x3e, 0x3c, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x22, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x3d, 0x22, 0x69, 0x6e, 0x66, 0x5f, 0x67, 0x74, 0x6b, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x5f, 0x63, 0x62, 0x22, 0x20, 0x73, 0x77, 0x61, 0x70, 0x70, 0x65, 0x64, 0x3d, 0x22, 0x6e, 0x6f, 0x22, 0x2f, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x54, 0x72, 0x65, 0x65, 0x56, 0x69, 0x65, 0x77, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x22, 0x3e, 0x36, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x22, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3d, 0x22, 0x79, 0x65, 0x73, 0x22, 0x3e, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x43, 0x65, 0x6c, 0x6c, 0x52, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x65, 0x72, 0x50, 0x69, 0x78, 0x62, 0x75, 0x66, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x69, 0x63, 0x6f, 0x6e, 0x5f, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x65, 0x72, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x69, 0x63, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x3e, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x43, 0x65, 0x6c, 0x6c, 0x52, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x65, 0x72, 0x54, 0x65, 0x78, 0x74, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x74, 0x65, 0x78, 0x74, 0x5f, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x65, 0x72, 0x22, 0x2f, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x49, 0x6e, 0x66, 0x47, 0x74, 0x6b, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x56, 0x69, 0x65, 0x77, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x5f, 0x76, 0x69, 0x65, 0x77, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x31, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x22, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x31, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x61, 0x6e, 0x5f, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x22, 0x3e, 0x46, 0x61, 0x6c, 0x73, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3d, 0x22, 0x79, 0x65, 0x73, 0x22, 0x3e, 0x5f, 0x56, 0x69, 0x65, 0x77, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x75, 0x73, 0x65, 0x5f, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x6c, 0x69, 0x6e, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x32, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x31, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3e, 0x31, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3e, 0x3c, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x3e, 0x0a, 0x00, 0x00, 0x28, 0x75, 0x75, 0x61, 0x79, 0x29, 0x69, 0x6e, 0x66, 0x67, 0x74, 0x6b, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x76, 0x69, 0x65, 0x77, 0x2e, 0x75, 0x69, 0x00, 0x00, 0xfc, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x3f, 0x78, 0x6d, 0x6c, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x22, 0x31, 0x2e, 0x30, 0x22, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x3d, 0x22, 0x55, 0x54, 0x46, 0x2d, 0x38, 0x22, 0x3f, 0x3e, 0x0a, 0x3c, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x20, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x3d, 0x22, 0x6c, 0x69, 0x62, 0x69, 0x6e, 0x66, 0x67, 0x74, 0x6b, 0x30, 0x37, 0x22, 0x3e, 0x3c, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x73, 0x20, 0x6c, 0x69, 0x62, 0x3d, 0x22, 0x67, 0x74, 0x6b, 0x2b, 0x22, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x22, 0x33, 0x2e, 0x31, 0x30, 0x22, 0x2f, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x54, 0x72, 0x65, 0x65, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x22, 0x3e, 0x3c, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73, 0x3e, 0x3c, 0x21, 0x2d, 0x2d, 0x20, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x2d, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x2d, 0x2d, 0x3e, 0x3c, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x22, 0x67, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x22, 0x2f, 0x3e, 0x3c, 0x2f, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x49, 0x6e, 0x66, 0x47, 0x74, 0x6b, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x69, 0x65, 0x77, 0x22, 0x20, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x47, 0x72, 0x69, 0x64, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x72, 0x6f, 0x77, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x22, 0x3e, 0x36, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x22, 0x3e, 0x31, 0x32, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x63, 0x61, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3d, 0x22, 0x79, 0x65, 0x73, 0x22, 0x3e, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x78, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x3e, 0x3c, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3d, 0x22, 0x62, 0x6f, 0x6c, 0x64, 0x22, 0x2f, 0x3e, 0x3c, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x77, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3e, 0x32, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3d, 0x22, 0x79, 0x65, 0x73, 0x22, 0x3e, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x20, 0x48, 0x6f, 0x73, 0x74, 0x20, 0x4e, 0x61, 0x6d, 0x65, 0x3a, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x6c, 0x65, 0x66, 0x74, 0x22, 0x3e, 0x31, 0x32, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x78, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x31, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x78, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x68, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x31, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x31, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x5f, 0x69, 0x70, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3d, 0x22, 0x79, 0x65, 0x73, 0x22, 0x3e, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x20, 0x49, 0x50, 0x20, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x3a, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x6c, 0x65, 0x66, 0x74, 0x22, 0x3e, 0x31, 0x32, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x78, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x32, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x5f, 0x69, 0x70, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x78, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x68, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x31, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x32, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x69, 0x70, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3d, 0x22, 0x79, 0x65, 0x73, 0x22, 0x3e, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x49, 0x50, 0x20, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x3a, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x6c, 0x65, 0x66, 0x74, 0x22, 0x3e, 0x31, 0x32, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x78, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x33, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x69, 0x70, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x78, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x68, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x31, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x33, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x63, 0x61, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3d, 0x22, 0x79, 0x65, 0x73, 0x22, 0x3e, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x78, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x3e, 0x3c, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3d, 0x22, 0x62, 0x6f, 0x6c, 0x64, 0x22, 0x2f, 0x3e, 0x3c, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x34, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x77, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3e, 0x32, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x5f, 0x74, 0x6c, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3d, 0x22, 0x79, 0x65, 0x73, 0x22, 0x3e, 0x54, 0x4c, 0x53, 0x20, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x6c, 0x65, 0x66, 0x74, 0x22, 0x3e, 0x31, 0x32, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x78, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x35, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x74, 0x6c, 0x73, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x78, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x68, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x31, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x35, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x5f, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, 0x73, 0x75, 0x69, 0x74, 0x65, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3d, 0x22, 0x79, 0x65, 0x73, 0x22, 0x3e, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x20, 0x53, 0x75, 0x69, 0x74, 0x65, 0x3a, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x6c, 0x65, 0x66, 0x74, 0x22, 0x3e, 0x31, 0x32, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x78, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x36, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x5f, 0x73, 0x75, 0x69, 0x74, 0x65, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x78, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x68, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x31, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x36, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x5f, 0x64, 0x68, 0x5f, 0x70, 0x72, 0x69, 0x6d, 0x65, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3d, 0x22, 0x79, 0x65, 0x73, 0x22, 0x3e, 0x44, 0x48, 0x20, 0x50, 0x72, 0x69, 0x6d, 0x65, 0x20, 0x42, 0x69, 0x74, 0x73, 0x3a, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x6c, 0x65, 0x66, 0x74, 0x22, 0x3e, 0x31, 0x32, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x78, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x37, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x64, 0x68, 0x5f, 0x70, 0x72, 0x69, 0x6d, 0x65, 0x5f, 0x62, 0x69, 0x74, 0x73, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x78, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x68, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x31, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x37, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x45, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x65, 0x72, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x65, 0x72, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x61, 0x6e, 0x5f, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x5f, 0x74, 0x6f, 0x70, 0x22, 0x3e, 0x36, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x22, 0x3e, 0x36, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x47, 0x72, 0x69, 0x64, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x67, 0x72, 0x69, 0x64, 0x33, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x61, 0x6e, 0x5f, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x22, 0x3e, 0x46, 0x61, 0x6c, 0x73, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x5f, 0x6c, 0x65, 0x66, 0x74, 0x22, 0x3e, 0x31, 0x32, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3e, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x22, 0x3e, 0x31, 0x32, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x53, 0x63, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x64, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x73, 0x63, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x64, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x31, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x61, 0x6e, 0x5f, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3e, 0x69, 0x6e, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6d, 0x69, 0x6e, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x5f, 0x77, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3e, 0x32, 0x30, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x54, 0x72, 0x65, 0x65, 0x56, 0x69, 0x65, 0x77, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x76, 0x69, 0x65, 0x77, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x61, 0x6e, 0x5f, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x22, 0x3e, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x73, 0x68, 0x6f, 0x77, 0x5f, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x65, 0x72, 0x73, 0x22, 0x3e, 0x46, 0x61, 0x6c, 0x73, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3e, 0x31, 0x32, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x2d, 0x73, 0x65, 0x74, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2d, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3d, 0x22, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x54, 0x72, 0x65, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x74, 0x72, 0x65, 0x65, 0x76, 0x69, 0x65, 0x77, 0x2d, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x22, 0x3e, 0x3c, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x22, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x3d, 0x22, 0x69, 0x6e, 0x66, 0x5f, 0x67, 0x74, 0x6b, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x76, 0x69, 0x65, 0x77, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x5f, 0x63, 0x62, 0x22, 0x20, 0x73, 0x77, 0x61, 0x70, 0x70, 0x65, 0x64, 0x3d, 0x22, 0x6e, 0x6f, 0x22, 0x2f, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x54, 0x72, 0x65, 0x65, 0x56, 0x69, 0x65, 0x77, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x22, 0x3e, 0x36, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x22, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3d, 0x22, 0x79, 0x65, 0x73, 0x22, 0x3e, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x43, 0x65, 0x6c, 0x6c, 0x52, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x65, 0x72, 0x50, 0x69, 0x78, 0x62, 0x75, 0x66, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x69, 0x63, 0x6f, 0x6e, 0x5f, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x65, 0x72, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x69, 0x63, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x3e, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x43, 0x65, 0x6c, 0x6c, 0x52, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x65, 0x72, 0x54, 0x65, 0x78, 0x74, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x74, 0x65, 0x78, 0x74, 0x5f, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x65, 0x72, 0x22, 0x2f, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x49, 0x6e, 0x66, 0x47, 0x74, 0x6b, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x56, 0x69, 0x65, 0x77, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x5f, 0x76, 0x69, 0x65, 0x77, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x31, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x22, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x31, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x61, 0x6e, 0x5f, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x22, 0x3e, 0x46, 0x61, 0x6c, 0x73, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3d, 0x22, 0x79, 0x65, 0x73, 0x22, 0x3e, 0x5f, 0x56, 0x69, 0x65, 0x77, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x75, 0x73, 0x65, 0x5f, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x6c, 0x69, 0x6e, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x38, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x77, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3e, 0x32, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3e, 0x3c, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x3e, 0x0a, 0x00, 0x00, 0x28, 0x75, 0x75, 0x61, 0x79, 0x29, 0x69, 0x6e, 0x66, 0x67, 0x74, 0x6b, 0x63, 0x68, 0x61, 0x74, 0x2e, 0x75, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf7, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x3f, 0x78, 0x6d, 0x6c, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x22, 0x31, 0x2e, 0x30, 0x22, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x3d, 0x22, 0x55, 0x54, 0x46, 0x2d, 0x38, 0x22, 0x3f, 0x3e, 0x0a, 0x3c, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x20, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x3d, 0x22, 0x6c, 0x69, 0x62, 0x69, 0x6e, 0x66, 0x67, 0x74, 0x6b, 0x30, 0x37, 0x22, 0x3e, 0x3c, 0x21, 0x2d, 0x2d, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x2d, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x73, 0x20, 0x67, 0x74, 0x6b, 0x2b, 0x20, 0x33, 0x2e, 0x30, 0x20, 0x2d, 0x2d, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x41, 0x64, 0x6a, 0x75, 0x73, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x73, 0x63, 0x72, 0x6f, 0x6c, 0x6c, 0x5f, 0x76, 0x61, 0x64, 0x6a, 0x22, 0x3e, 0x3c, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x22, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x3d, 0x22, 0x69, 0x6e, 0x66, 0x5f, 0x67, 0x74, 0x6b, 0x5f, 0x63, 0x68, 0x61, 0x74, 0x5f, 0x61, 0x64, 0x6a, 0x75, 0x73, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x5f, 0x63, 0x62, 0x22, 0x20, 0x73, 0x77, 0x61, 0x70, 0x70, 0x65, 0x64, 0x3d, 0x22, 0x6e, 0x6f, 0x22, 0x2f, 0x3e, 0x3c, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x2d, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x22, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x3d, 0x22, 0x69, 0x6e, 0x66, 0x5f, 0x67, 0x74, 0x6b, 0x5f, 0x63, 0x68, 0x61, 0x74, 0x5f, 0x61, 0x64, 0x6a, 0x75, 0x73, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x5f, 0x63, 0x62, 0x22, 0x20, 0x73, 0x77, 0x61, 0x70, 0x70, 0x65, 0x64, 0x3d, 0x22, 0x6e, 0x6f, 0x22, 0x2f, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x54, 0x65, 0x78, 0x74, 0x54, 0x61, 0x67, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x63, 0x68, 0x61, 0x74, 0x5f, 0x74, 0x61, 0x67, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x22, 0x74, 0x61, 0x67, 0x22, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x54, 0x65, 0x78, 0x74, 0x54, 0x61, 0x67, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x74, 0x61, 0x67, 0x5f, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x3e, 0x6e, 0x6f, 0x72, 0x6d, 0x61, 0x6c, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x22, 0x74, 0x61, 0x67, 0x22, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x54, 0x65, 0x78, 0x74, 0x54, 0x61, 0x67, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x74, 0x61, 0x67, 0x5f, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x3e, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x66, 0x6f, 0x72, 0x65, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x22, 0x3e, 0x23, 0x30, 0x30, 0x30, 0x30, 0x66, 0x66, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x22, 0x74, 0x61, 0x67, 0x22, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x54, 0x65, 0x78, 0x74, 0x54, 0x61, 0x67, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x74, 0x61, 0x67, 0x5f, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x3e, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x66, 0x6f, 0x72, 0x65, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x22, 0x3e, 0x23, 0x31, 0x31, 0x33, 0x33, 0x32, 0x32, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x22, 0x74, 0x61, 0x67, 0x22, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x54, 0x65, 0x78, 0x74, 0x54, 0x61, 0x67, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x74, 0x61, 0x67, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x6c, 0x6f, 0x67, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x3e, 0x62, 0x61, 0x63, 0x6b, 0x6c, 0x6f, 0x67, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x66, 0x6f, 0x72, 0x65, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x22, 0x3e, 0x23, 0x36, 0x30, 0x36, 0x30, 0x36, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x54, 0x65, 0x78, 0x74, 0x42, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x63, 0x68, 0x61, 0x74, 0x5f, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x61, 0x67, 0x2d, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x63, 0x68, 0x61, 0x74, 0x5f, 0x74, 0x61, 0x67, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x49, 0x6e, 0x66, 0x47, 0x74, 0x6b, 0x43, 0x68, 0x61, 0x74, 0x22, 0x20, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x47, 0x72, 0x69, 0x64, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x72, 0x6f, 0x77, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x22, 0x3e, 0x36, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x53, 0x63, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x64, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x73, 0x63, 0x72, 0x6f, 0x6c, 0x6c, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x61, 0x64, 0x6a, 0x75, 0x73, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0x3e, 0x73, 0x63, 0x72, 0x6f, 0x6c, 0x6c, 0x5f, 0x76, 0x61, 0x64, 0x6a, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3e, 0x69, 0x6e, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x2d, 0x73, 0x65, 0x74, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x68, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x68, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x2d, 0x73, 0x65, 0x74, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x54, 0x65, 0x78, 0x74, 0x56, 0x69, 0x65, 0x77, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x63, 0x68, 0x61, 0x74, 0x5f, 0x76, 0x69, 0x65, 0x77, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x65, 0x64, 0x69, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x46, 0x61, 0x6c, 0x73, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x61, 0x6e, 0x2d, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x3e, 0x47, 0x44, 0x4b, 0x5f, 0x46, 0x4f, 0x43, 0x55, 0x53, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x4d, 0x41, 0x53, 0x4b, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x77, 0x72, 0x61, 0x70, 0x2d, 0x6d, 0x6f, 0x64, 0x65, 0x22, 0x3e, 0x77, 0x6f, 0x72, 0x64, 0x2d, 0x63, 0x68, 0x61, 0x72, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x69, 0x6e, 0x64, 0x65, 0x6e, 0x74, 0x22, 0x3e, 0x2d, 0x31, 0x32, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x22, 0x3e, 0x63, 0x68, 0x61, 0x74, 0x5f, 0x62, 0x75, 0x66, 0x66, 0x65, 0x72, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x68, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x68, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x2d, 0x73, 0x65, 0x74, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x2d, 0x73, 0x65, 0x74, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x47, 0x72, 0x69, 0x64, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x67, 0x72, 0x69, 0x64, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3e, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x22, 0x3e, 0x31, 0x32, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x63, 0x68, 0x61, 0x74, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x73, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x22, 0x3e, 0x46, 0x61, 0x6c, 0x73, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x72, 0x75, 0x6e, 0x63, 0x61, 0x74, 0x65, 0x2d, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x6c, 0x69, 0x6e, 0x65, 0x22, 0x3e, 0x46, 0x61, 0x6c, 0x73, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x68, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x68, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x2d, 0x73, 0x65, 0x74, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x22, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x3d, 0x22, 0x69, 0x6e, 0x66, 0x5f, 0x67, 0x74, 0x6b, 0x5f, 0x63, 0x68, 0x61, 0x74, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x63, 0x62, 0x22, 0x20, 0x73, 0x77, 0x61, 0x70, 0x70, 0x65, 0x64, 0x3d, 0x22, 0x6e, 0x6f, 0x22, 0x2f, 0x3e, 0x3c, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x22, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x3d, 0x22, 0x69, 0x6e, 0x66, 0x5f, 0x67, 0x74, 0x6b, 0x5f, 0x63, 0x68, 0x61, 0x74, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x5f, 0x63, 0x62, 0x22, 0x20, 0x73, 0x77, 0x61, 0x70, 0x70, 0x65, 0x64, 0x3d, 0x22, 0x6e, 0x6f, 0x22, 0x2f, 0x3e, 0x3c, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6b, 0x65, 0x79, 0x2d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x2d, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x22, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x3d, 0x22, 0x69, 0x6e, 0x66, 0x5f, 0x67, 0x74, 0x6b, 0x5f, 0x63, 0x68, 0x61, 0x74, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x70, 0x72, 0x65, 0x73, 0x73, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x62, 0x22, 0x20, 0x73, 0x77, 0x61, 0x70, 0x70, 0x65, 0x64, 0x3d, 0x22, 0x6e, 0x6f, 0x22, 0x2f, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x73, 0x65, 0x6e, 0x64, 0x5f, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x46, 0x61, 0x6c, 0x73, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3d, 0x22, 0x79, 0x65, 0x73, 0x22, 0x3e, 0x53, 0x65, 0x6e, 0x64, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x65, 0x64, 0x22, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x3d, 0x22, 0x69, 0x6e, 0x66, 0x5f, 0x67, 0x74, 0x6b, 0x5f, 0x63, 0x68, 0x61, 0x74, 0x5f, 0x73, 0x65, 0x6e, 0x64, 0x5f, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x5f, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x65, 0x64, 0x5f, 0x63, 0x62, 0x22, 0x20, 0x73, 0x77, 0x61, 0x70, 0x70, 0x65, 0x64, 0x3d, 0x22, 0x6e, 0x6f, 0x22, 0x2f, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x31, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x31, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3e, 0x3c, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x3e, 0x0a, 0x00, 0x00, 0x28, 0x75, 0x75, 0x61, 0x79, 0x29, 0x64, 0x65, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x66, 0x67, 0x74, 0x6b, 0x61, 0x63, 0x6c, 0x73, 0x68, 0x65, 0x65, 0x74, 0x76, 0x69, 0x65, 0x77, 0x2e, 0x75, 0x69, 0x00, 0x00, 0x00, 0x22, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x3f, 0x78, 0x6d, 0x6c, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x22, 0x31, 0x2e, 0x30, 0x22, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x3d, 0x22, 0x55, 0x54, 0x46, 0x2d, 0x38, 0x22, 0x3f, 0x3e, 0x0a, 0x3c, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x20, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x3d, 0x22, 0x6c, 0x69, 0x62, 0x69, 0x6e, 0x66, 0x67, 0x74, 0x6b, 0x30, 0x37, 0x22, 0x3e, 0x3c, 0x21, 0x2d, 0x2d, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x2d, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x73, 0x20, 0x67, 0x74, 0x6b, 0x2b, 0x20, 0x33, 0x2e, 0x30, 0x20, 0x2d, 0x2d, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x73, 0x68, 0x65, 0x65, 0x74, 0x5f, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x22, 0x3e, 0x3c, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73, 0x3e, 0x3c, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x22, 0x67, 0x63, 0x68, 0x61, 0x72, 0x61, 0x72, 0x72, 0x61, 0x79, 0x22, 0x2f, 0x3e, 0x3c, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x22, 0x49, 0x6e, 0x66, 0x41, 0x63, 0x6c, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x22, 0x2f, 0x3e, 0x3c, 0x2f, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x49, 0x6e, 0x66, 0x47, 0x74, 0x6b, 0x41, 0x63, 0x6c, 0x53, 0x68, 0x65, 0x65, 0x74, 0x56, 0x69, 0x65, 0x77, 0x22, 0x20, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x47, 0x72, 0x69, 0x64, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x72, 0x6f, 0x77, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x22, 0x3e, 0x36, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x53, 0x63, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x64, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x73, 0x63, 0x72, 0x6f, 0x6c, 0x6c, 0x5f, 0x6d, 0x61, 0x69, 0x6e, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3e, 0x69, 0x6e, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6d, 0x69, 0x6e, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x5f, 0x77, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3e, 0x32, 0x35, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x54, 0x72, 0x65, 0x65, 0x56, 0x69, 0x65, 0x77, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x76, 0x69, 0x65, 0x77, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x22, 0x3e, 0x73, 0x68, 0x65, 0x65, 0x74, 0x5f, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x68, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x68, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x2d, 0x73, 0x65, 0x74, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x2d, 0x73, 0x65, 0x74, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2d, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3d, 0x22, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x54, 0x72, 0x65, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x74, 0x72, 0x65, 0x65, 0x76, 0x69, 0x65, 0x77, 0x2d, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x22, 0x2f, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x54, 0x72, 0x65, 0x65, 0x56, 0x69, 0x65, 0x77, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x22, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3d, 0x22, 0x79, 0x65, 0x73, 0x22, 0x3e, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x43, 0x65, 0x6c, 0x6c, 0x52, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x65, 0x72, 0x54, 0x65, 0x78, 0x74, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x65, 0x72, 0x22, 0x2f, 0x3e, 0x3c, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x3e, 0x3c, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x65, 0x78, 0x74, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x3e, 0x3c, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x54, 0x72, 0x65, 0x65, 0x56, 0x69, 0x65, 0x77, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x22, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3d, 0x22, 0x79, 0x65, 0x73, 0x22, 0x3e, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x43, 0x65, 0x6c, 0x6c, 0x52, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x65, 0x72, 0x54, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x65, 0x72, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x46, 0x61, 0x6c, 0x73, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x72, 0x61, 0x64, 0x69, 0x6f, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x64, 0x22, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x3d, 0x22, 0x69, 0x6e, 0x66, 0x5f, 0x67, 0x74, 0x6b, 0x5f, 0x61, 0x63, 0x6c, 0x5f, 0x73, 0x68, 0x65, 0x65, 0x74, 0x5f, 0x76, 0x69, 0x65, 0x77, 0x5f, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x74, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x64, 0x5f, 0x63, 0x62, 0x22, 0x20, 0x73, 0x77, 0x61, 0x70, 0x70, 0x65, 0x64, 0x3d, 0x22, 0x6e, 0x6f, 0x22, 0x2f, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x54, 0x72, 0x65, 0x65, 0x56, 0x69, 0x65, 0x77, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x79, 0x65, 0x73, 0x5f, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x22, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3d, 0x22, 0x79, 0x65, 0x73, 0x22, 0x3e, 0x59, 0x65, 0x73, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x43, 0x65, 0x6c, 0x6c, 0x52, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x65, 0x72, 0x54, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x79, 0x65, 0x73, 0x5f, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x65, 0x72, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x46, 0x61, 0x6c, 0x73, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x72, 0x61, 0x64, 0x69, 0x6f, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x64, 0x22, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x3d, 0x22, 0x69, 0x6e, 0x66, 0x5f, 0x67, 0x74, 0x6b, 0x5f, 0x61, 0x63, 0x6c, 0x5f, 0x73, 0x68, 0x65, 0x65, 0x74, 0x5f, 0x76, 0x69, 0x65, 0x77, 0x5f, 0x79, 0x65, 0x73, 0x5f, 0x74, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x64, 0x5f, 0x63, 0x62, 0x22, 0x20, 0x73, 0x77, 0x61, 0x70, 0x70, 0x65, 0x64, 0x3d, 0x22, 0x6e, 0x6f, 0x22, 0x2f, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x54, 0x72, 0x65, 0x65, 0x56, 0x69, 0x65, 0x77, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x6e, 0x6f, 0x5f, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x22, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3d, 0x22, 0x79, 0x65, 0x73, 0x22, 0x3e, 0x4e, 0x6f, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x43, 0x65, 0x6c, 0x6c, 0x52, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x65, 0x72, 0x54, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x6e, 0x6f, 0x5f, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x65, 0x72, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x46, 0x61, 0x6c, 0x73, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x72, 0x61, 0x64, 0x69, 0x6f, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x64, 0x22, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x3d, 0x22, 0x69, 0x6e, 0x66, 0x5f, 0x67, 0x74, 0x6b, 0x5f, 0x61, 0x63, 0x6c, 0x5f, 0x73, 0x68, 0x65, 0x65, 0x74, 0x5f, 0x76, 0x69, 0x65, 0x77, 0x5f, 0x6e, 0x6f, 0x5f, 0x74, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x64, 0x5f, 0x63, 0x62, 0x22, 0x20, 0x73, 0x77, 0x61, 0x70, 0x70, 0x65, 0x64, 0x3d, 0x22, 0x6e, 0x6f, 0x22, 0x2f, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3e, 0x3c, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x3e, 0x0a, 0x00, 0x00, 0x28, 0x75, 0x75, 0x61, 0x79, 0x29, 0x69, 0x6e, 0x66, 0x67, 0x74, 0x6b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x75, 0x69, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x3f, 0x78, 0x6d, 0x6c, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x22, 0x31, 0x2e, 0x30, 0x22, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x3d, 0x22, 0x55, 0x54, 0x46, 0x2d, 0x38, 0x22, 0x3f, 0x3e, 0x0a, 0x3c, 0x21, 0x2d, 0x2d, 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x67, 0x6c, 0x61, 0x64, 0x65, 0x20, 0x33, 0x2e, 0x31, 0x38, 0x2e, 0x33, 0x20, 0x2d, 0x2d, 0x3e, 0x0a, 0x3c, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x20, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x3d, 0x22, 0x6c, 0x69, 0x62, 0x69, 0x6e, 0x66, 0x67, 0x74, 0x6b, 0x30, 0x37, 0x22, 0x3e, 0x3c, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x73, 0x20, 0x6c, 0x69, 0x62, 0x3d, 0x22, 0x67, 0x74, 0x6b, 0x2b, 0x22, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x22, 0x33, 0x2e, 0x31, 0x30, 0x22, 0x2f, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x22, 0x3e, 0x3c, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73, 0x3e, 0x3c, 0x21, 0x2d, 0x2d, 0x20, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x2d, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2d, 0x69, 0x64, 0x20, 0x2d, 0x2d, 0x3e, 0x3c, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x22, 0x67, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x22, 0x2f, 0x3e, 0x3c, 0x21, 0x2d, 0x2d, 0x20, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x2d, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2d, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x2d, 0x2d, 0x3e, 0x3c, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3d, 0x22, 0x67, 0x63, 0x68, 0x61, 0x72, 0x61, 0x72, 0x72, 0x61, 0x79, 0x22, 0x2f, 0x3e, 0x3c, 0x2f, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x49, 0x6e, 0x66, 0x47, 0x74, 0x6b, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x44, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x22, 0x20, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x44, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x61, 0x6e, 0x5f, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x22, 0x3e, 0x46, 0x61, 0x6c, 0x73, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x5f, 0x77, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3e, 0x31, 0x32, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x77, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3e, 0x36, 0x34, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x3e, 0x34, 0x38, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x72, 0x65, 0x73, 0x69, 0x7a, 0x61, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x69, 0x63, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x3e, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x2d, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x68, 0x69, 0x6e, 0x74, 0x22, 0x3e, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2d, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3d, 0x22, 0x76, 0x62, 0x6f, 0x78, 0x22, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x42, 0x6f, 0x78, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x2d, 0x76, 0x62, 0x6f, 0x78, 0x31, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x61, 0x6e, 0x5f, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x22, 0x3e, 0x46, 0x61, 0x6c, 0x73, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x22, 0x3e, 0x36, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2d, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3d, 0x22, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x72, 0x65, 0x61, 0x22, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x42, 0x6f, 0x78, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x2d, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x72, 0x65, 0x61, 0x31, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x61, 0x6e, 0x5f, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x22, 0x3e, 0x46, 0x61, 0x6c, 0x73, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x5f, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x22, 0x3e, 0x65, 0x6e, 0x64, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x2f, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x2f, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x22, 0x3e, 0x46, 0x61, 0x6c, 0x73, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x70, 0x61, 0x63, 0x6b, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3e, 0x65, 0x6e, 0x64, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x47, 0x72, 0x69, 0x64, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x67, 0x72, 0x69, 0x64, 0x31, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3e, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x61, 0x6e, 0x5f, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x22, 0x3e, 0x46, 0x61, 0x6c, 0x73, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x22, 0x3e, 0x31, 0x32, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x61, 0x6e, 0x5f, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x22, 0x3e, 0x46, 0x61, 0x6c, 0x73, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x47, 0x54, 0x4b, 0x5f, 0x41, 0x4c, 0x49, 0x47, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x52, 0x54, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x69, 0x63, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x3e, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x2d, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x69, 0x63, 0x6f, 0x6e, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x22, 0x3e, 0x36, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x47, 0x72, 0x69, 0x64, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x67, 0x72, 0x69, 0x64, 0x32, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x61, 0x6e, 0x5f, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x22, 0x3e, 0x46, 0x61, 0x6c, 0x73, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x72, 0x6f, 0x77, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x22, 0x3e, 0x36, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x5f, 0x74, 0x65, 0x78, 0x74, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x61, 0x6e, 0x5f, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x22, 0x3e, 0x46, 0x61, 0x6c, 0x73, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x5f, 0x62, 0x6f, 0x74, 0x74, 0x6f, 0x6d, 0x22, 0x3e, 0x31, 0x32, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x47, 0x54, 0x4b, 0x5f, 0x41, 0x4c, 0x49, 0x47, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x52, 0x54, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x68, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x47, 0x54, 0x4b, 0x5f, 0x41, 0x4c, 0x49, 0x47, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x52, 0x54, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x78, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x77, 0x72, 0x61, 0x70, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x77, 0x69, 0x64, 0x74, 0x68, 0x5f, 0x63, 0x68, 0x61, 0x72, 0x73, 0x22, 0x3e, 0x34, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x47, 0x72, 0x69, 0x64, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x67, 0x72, 0x69, 0x64, 0x33, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x61, 0x6e, 0x5f, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x22, 0x3e, 0x46, 0x61, 0x6c, 0x73, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x22, 0x3e, 0x36, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3e, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x47, 0x72, 0x69, 0x64, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x67, 0x72, 0x69, 0x64, 0x34, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x61, 0x6e, 0x5f, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x22, 0x3e, 0x46, 0x61, 0x6c, 0x73, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x72, 0x6f, 0x77, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x22, 0x3e, 0x36, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x53, 0x63, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x64, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x73, 0x63, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x64, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x31, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x61, 0x6e, 0x5f, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x73, 0x68, 0x61, 0x64, 0x6f, 0x77, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3e, 0x69, 0x6e, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6d, 0x69, 0x6e, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x5f, 0x77, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3e, 0x32, 0x30, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6d, 0x69, 0x6e, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x5f, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x3e, 0x33, 0x35, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x54, 0x72, 0x65, 0x65, 0x56, 0x69, 0x65, 0x77, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x74, 0x72, 0x65, 0x65, 0x5f, 0x76, 0x69, 0x65, 0x77, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x61, 0x6e, 0x5f, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x22, 0x3e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x2d, 0x73, 0x65, 0x74, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6b, 0x65, 0x79, 0x2d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x2d, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x22, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x3d, 0x22, 0x69, 0x6e, 0x66, 0x5f, 0x67, 0x74, 0x6b, 0x5f, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x5f, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x70, 0x72, 0x65, 0x73, 0x73, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x62, 0x22, 0x20, 0x73, 0x77, 0x61, 0x70, 0x70, 0x65, 0x64, 0x3d, 0x22, 0x6e, 0x6f, 0x22, 0x2f, 0x3e, 0x3c, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x2d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x2d, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x22, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x3d, 0x22, 0x69, 0x6e, 0x66, 0x5f, 0x67, 0x74, 0x6b, 0x5f, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x5f, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x5f, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x5f, 0x70, 0x72, 0x65, 0x73, 0x73, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x62, 0x22, 0x20, 0x73, 0x77, 0x61, 0x70, 0x70, 0x65, 0x64, 0x3d, 0x22, 0x6e, 0x6f, 0x22, 0x2f, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2d, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3d, 0x22, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x54, 0x72, 0x65, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x74, 0x72, 0x65, 0x65, 0x76, 0x69, 0x65, 0x77, 0x2d, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x22, 0x3e, 0x3c, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x22, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x3d, 0x22, 0x69, 0x6e, 0x66, 0x5f, 0x67, 0x74, 0x6b, 0x5f, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x5f, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x5f, 0x63, 0x62, 0x22, 0x20, 0x73, 0x77, 0x61, 0x70, 0x70, 0x65, 0x64, 0x3d, 0x22, 0x6e, 0x6f, 0x22, 0x2f, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x54, 0x72, 0x65, 0x65, 0x56, 0x69, 0x65, 0x77, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x22, 0x3e, 0x36, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x22, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3d, 0x22, 0x79, 0x65, 0x73, 0x22, 0x3e, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x43, 0x65, 0x6c, 0x6c, 0x52, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x65, 0x72, 0x43, 0x6f, 0x6d, 0x62, 0x6f, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x65, 0x72, 0x22, 0x3e, 0x3c, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x65, 0x64, 0x69, 0x74, 0x69, 0x6e, 0x67, 0x2d, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x22, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x3d, 0x22, 0x69, 0x6e, 0x66, 0x5f, 0x67, 0x74, 0x6b, 0x5f, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x5f, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x5f, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x65, 0x72, 0x5f, 0x65, 0x64, 0x69, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x63, 0x62, 0x22, 0x20, 0x73, 0x77, 0x61, 0x70, 0x70, 0x65, 0x64, 0x3d, 0x22, 0x6e, 0x6f, 0x22, 0x2f, 0x3e, 0x3c, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x65, 0x64, 0x69, 0x74, 0x69, 0x6e, 0x67, 0x2d, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x65, 0x64, 0x22, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x3d, 0x22, 0x69, 0x6e, 0x66, 0x5f, 0x67, 0x74, 0x6b, 0x5f, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x5f, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x5f, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x65, 0x72, 0x5f, 0x65, 0x64, 0x69, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x65, 0x64, 0x5f, 0x63, 0x62, 0x22, 0x20, 0x73, 0x77, 0x61, 0x70, 0x70, 0x65, 0x64, 0x3d, 0x22, 0x6e, 0x6f, 0x22, 0x2f, 0x3e, 0x3c, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x65, 0x64, 0x69, 0x74, 0x65, 0x64, 0x22, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x3d, 0x22, 0x69, 0x6e, 0x66, 0x5f, 0x67, 0x74, 0x6b, 0x5f, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x5f, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x5f, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x65, 0x72, 0x5f, 0x65, 0x64, 0x69, 0x74, 0x65, 0x64, 0x5f, 0x63, 0x62, 0x22, 0x20, 0x73, 0x77, 0x61, 0x70, 0x70, 0x65, 0x64, 0x3d, 0x22, 0x6e, 0x6f, 0x22, 0x2f, 0x3e, 0x3c, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x22, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x3d, 0x22, 0x69, 0x6e, 0x66, 0x5f, 0x67, 0x74, 0x6b, 0x5f, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x5f, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x5f, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x65, 0x72, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x5f, 0x63, 0x62, 0x22, 0x20, 0x73, 0x77, 0x61, 0x70, 0x70, 0x65, 0x64, 0x3d, 0x22, 0x6e, 0x6f, 0x22, 0x2f, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x47, 0x72, 0x69, 0x64, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x67, 0x72, 0x69, 0x64, 0x36, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x61, 0x6e, 0x5f, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x22, 0x3e, 0x46, 0x61, 0x6c, 0x73, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x22, 0x3e, 0x31, 0x32, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3e, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x61, 0x64, 0x64, 0x5f, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x61, 0x6e, 0x5f, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x73, 0x5f, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x65, 0x64, 0x22, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x3d, 0x22, 0x69, 0x6e, 0x66, 0x5f, 0x67, 0x74, 0x6b, 0x5f, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x5f, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x5f, 0x61, 0x64, 0x64, 0x5f, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x65, 0x64, 0x5f, 0x63, 0x62, 0x22, 0x20, 0x73, 0x77, 0x61, 0x70, 0x70, 0x65, 0x64, 0x3d, 0x22, 0x6e, 0x6f, 0x22, 0x2f, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x31, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x61, 0x6e, 0x5f, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x22, 0x3e, 0x46, 0x61, 0x6c, 0x73, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x69, 0x63, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x3e, 0x6c, 0x69, 0x73, 0x74, 0x2d, 0x61, 0x64, 0x64, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x61, 0x6e, 0x5f, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x73, 0x5f, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x65, 0x64, 0x22, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x3d, 0x22, 0x69, 0x6e, 0x66, 0x5f, 0x67, 0x74, 0x6b, 0x5f, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x5f, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x5f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x5f, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x65, 0x64, 0x5f, 0x63, 0x62, 0x22, 0x20, 0x73, 0x77, 0x61, 0x70, 0x70, 0x65, 0x64, 0x3d, 0x22, 0x6e, 0x6f, 0x22, 0x2f, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x32, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x61, 0x6e, 0x5f, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x22, 0x3e, 0x46, 0x61, 0x6c, 0x73, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x69, 0x63, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x3e, 0x6c, 0x69, 0x73, 0x74, 0x2d, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x31, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x31, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x49, 0x6e, 0x66, 0x47, 0x74, 0x6b, 0x41, 0x63, 0x6c, 0x53, 0x68, 0x65, 0x65, 0x74, 0x56, 0x69, 0x65, 0x77, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x73, 0x68, 0x65, 0x65, 0x74, 0x5f, 0x76, 0x69, 0x65, 0x77, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x73, 0x68, 0x65, 0x65, 0x74, 0x2d, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x22, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x3d, 0x22, 0x69, 0x6e, 0x66, 0x5f, 0x67, 0x74, 0x6b, 0x5f, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x5f, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x5f, 0x73, 0x68, 0x65, 0x65, 0x74, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x5f, 0x63, 0x62, 0x22, 0x20, 0x73, 0x77, 0x61, 0x70, 0x70, 0x65, 0x64, 0x3d, 0x22, 0x6e, 0x6f, 0x22, 0x2f, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x31, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x31, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x31, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3e, 0x31, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3e, 0x3c, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x3e, 0x0a, 0x00, 0x00, 0x28, 0x75, 0x75, 0x61, 0x79, 0x29, 0x75, 0x69, 0x2f, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x66, 0x67, 0x74, 0x6b, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x76, 0x69, 0x65, 0x77, 0x2e, 0x75, 0x69, 0xfb, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x3f, 0x78, 0x6d, 0x6c, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x22, 0x31, 0x2e, 0x30, 0x22, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x3d, 0x22, 0x55, 0x54, 0x46, 0x2d, 0x38, 0x22, 0x3f, 0x3e, 0x0a, 0x3c, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x20, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x3d, 0x22, 0x6c, 0x69, 0x62, 0x69, 0x6e, 0x66, 0x67, 0x74, 0x6b, 0x30, 0x37, 0x22, 0x3e, 0x3c, 0x21, 0x2d, 0x2d, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x2d, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x73, 0x20, 0x67, 0x74, 0x6b, 0x2b, 0x20, 0x33, 0x2e, 0x31, 0x30, 0x20, 0x2d, 0x2d, 0x3e, 0x3c, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x49, 0x6e, 0x66, 0x47, 0x74, 0x6b, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x56, 0x69, 0x65, 0x77, 0x22, 0x20, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x47, 0x72, 0x69, 0x64, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x72, 0x6f, 0x77, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x22, 0x3e, 0x36, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x22, 0x3e, 0x31, 0x32, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x63, 0x61, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3d, 0x22, 0x79, 0x65, 0x73, 0x22, 0x3e, 0x49, 0x73, 0x73, 0x75, 0x65, 0x64, 0x20, 0x54, 0x6f, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x78, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x3e, 0x3c, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3d, 0x22, 0x62, 0x6f, 0x6c, 0x64, 0x22, 0x2f, 0x3e, 0x3c, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x77, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3e, 0x32, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x5f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3d, 0x22, 0x79, 0x65, 0x73, 0x22, 0x3e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x20, 0x4e, 0x61, 0x6d, 0x65, 0x3a, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x6c, 0x65, 0x66, 0x74, 0x22, 0x3e, 0x31, 0x32, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x78, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x31, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x78, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x31, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x31, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x5f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3d, 0x22, 0x79, 0x65, 0x73, 0x22, 0x3e, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x6c, 0x65, 0x66, 0x74, 0x22, 0x3e, 0x31, 0x32, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x78, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x32, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x78, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x31, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x32, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x5f, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x75, 0x6e, 0x69, 0x74, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3d, 0x22, 0x79, 0x65, 0x73, 0x22, 0x3e, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x55, 0x6e, 0x69, 0x74, 0x3a, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x6c, 0x65, 0x66, 0x74, 0x22, 0x3e, 0x31, 0x32, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x78, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x33, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x75, 0x6e, 0x69, 0x74, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x78, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x31, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x33, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x5f, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3d, 0x22, 0x79, 0x65, 0x73, 0x22, 0x3e, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x20, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x3a, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x6c, 0x65, 0x66, 0x74, 0x22, 0x3e, 0x31, 0x32, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x78, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x34, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x78, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x3e, 0x3c, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x64, 0x65, 0x73, 0x63, 0x22, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3d, 0x22, 0x4d, 0x6f, 0x6e, 0x6f, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x2f, 0x3e, 0x3c, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x22, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3d, 0x22, 0x30, 0x2e, 0x38, 0x33, 0x33, 0x33, 0x33, 0x33, 0x22, 0x2f, 0x3e, 0x3c, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x31, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x34, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x63, 0x61, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x73, 0x73, 0x75, 0x65, 0x72, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3d, 0x22, 0x79, 0x65, 0x73, 0x22, 0x3e, 0x49, 0x73, 0x73, 0x75, 0x65, 0x64, 0x20, 0x42, 0x79, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x78, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x3e, 0x3c, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3d, 0x22, 0x62, 0x6f, 0x6c, 0x64, 0x22, 0x2f, 0x3e, 0x3c, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x35, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x77, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3e, 0x32, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x5f, 0x69, 0x73, 0x73, 0x75, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3d, 0x22, 0x79, 0x65, 0x73, 0x22, 0x3e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x20, 0x4e, 0x61, 0x6d, 0x65, 0x3a, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x6c, 0x65, 0x66, 0x74, 0x22, 0x3e, 0x31, 0x32, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x78, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x36, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x69, 0x73, 0x73, 0x75, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x78, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x31, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x36, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x5f, 0x69, 0x73, 0x73, 0x75, 0x65, 0x72, 0x5f, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3d, 0x22, 0x79, 0x65, 0x73, 0x22, 0x3e, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x6c, 0x65, 0x66, 0x74, 0x22, 0x3e, 0x31, 0x32, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x78, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x37, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x69, 0x73, 0x73, 0x75, 0x65, 0x72, 0x5f, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x78, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x31, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x37, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x5f, 0x69, 0x73, 0x73, 0x75, 0x65, 0x72, 0x5f, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x75, 0x6e, 0x69, 0x74, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3d, 0x22, 0x79, 0x65, 0x73, 0x22, 0x3e, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x55, 0x6e, 0x69, 0x74, 0x3a, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x6c, 0x65, 0x66, 0x74, 0x22, 0x3e, 0x31, 0x32, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x78, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x38, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x69, 0x73, 0x73, 0x75, 0x65, 0x72, 0x5f, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x5f, 0x75, 0x6e, 0x69, 0x74, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x78, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x31, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x38, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x63, 0x61, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x69, 0x74, 0x79, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3d, 0x22, 0x79, 0x65, 0x73, 0x22, 0x3e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x69, 0x74, 0x79, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x78, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x3e, 0x3c, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3d, 0x22, 0x62, 0x6f, 0x6c, 0x64, 0x22, 0x2f, 0x3e, 0x3c, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x39, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x77, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3e, 0x32, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3d, 0x22, 0x79, 0x65, 0x73, 0x22, 0x3e, 0x49, 0x73, 0x73, 0x75, 0x65, 0x64, 0x20, 0x4f, 0x6e, 0x3a, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x6c, 0x65, 0x66, 0x74, 0x22, 0x3e, 0x31, 0x32, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x78, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x31, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x78, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x31, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x31, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x5f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3d, 0x22, 0x79, 0x65, 0x73, 0x22, 0x3e, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x20, 0x4f, 0x6e, 0x3a, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x6c, 0x65, 0x66, 0x74, 0x22, 0x3e, 0x31, 0x32, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x78, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x31, 0x31, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x78, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x31, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x31, 0x31, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x63, 0x61, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x73, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3d, 0x22, 0x79, 0x65, 0x73, 0x22, 0x3e, 0x46, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x73, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x78, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x3e, 0x3c, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3d, 0x22, 0x62, 0x6f, 0x6c, 0x64, 0x22, 0x2f, 0x3e, 0x3c, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x31, 0x32, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x77, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3e, 0x32, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x5f, 0x73, 0x68, 0x61, 0x31, 0x5f, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3d, 0x22, 0x79, 0x65, 0x73, 0x22, 0x3e, 0x53, 0x48, 0x41, 0x2d, 0x31, 0x20, 0x46, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x3a, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x6c, 0x65, 0x66, 0x74, 0x22, 0x3e, 0x31, 0x32, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x78, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x31, 0x33, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x73, 0x68, 0x61, 0x31, 0x5f, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x78, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x3e, 0x3c, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x64, 0x65, 0x73, 0x63, 0x22, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3d, 0x22, 0x4d, 0x6f, 0x6e, 0x6f, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x2f, 0x3e, 0x3c, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x22, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3d, 0x22, 0x30, 0x2e, 0x38, 0x33, 0x33, 0x33, 0x33, 0x33, 0x22, 0x2f, 0x3e, 0x3c, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x31, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x31, 0x33, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x5f, 0x73, 0x68, 0x61, 0x32, 0x35, 0x36, 0x5f, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3d, 0x22, 0x79, 0x65, 0x73, 0x22, 0x3e, 0x53, 0x48, 0x41, 0x2d, 0x32, 0x35, 0x36, 0x20, 0x46, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x3a, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x6c, 0x65, 0x66, 0x74, 0x22, 0x3e, 0x31, 0x32, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x78, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x79, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x31, 0x34, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x73, 0x68, 0x61, 0x32, 0x35, 0x36, 0x5f, 0x66, 0x69, 0x6e, 0x67, 0x65, 0x72, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x78, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6d, 0x61, 0x78, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x2d, 0x63, 0x68, 0x61, 0x72, 0x73, 0x22, 0x3e, 0x34, 0x37, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x77, 0x72, 0x61, 0x70, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x77, 0x72, 0x61, 0x70, 0x2d, 0x6d, 0x6f, 0x64, 0x65, 0x22, 0x3e, 0x63, 0x68, 0x61, 0x72, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x68, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x3e, 0x3c, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x66, 0x6f, 0x6e, 0x74, 0x2d, 0x64, 0x65, 0x73, 0x63, 0x22, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3d, 0x22, 0x4d, 0x6f, 0x6e, 0x6f, 0x73, 0x70, 0x61, 0x63, 0x65, 0x22, 0x2f, 0x3e, 0x3c, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x73, 0x63, 0x61, 0x6c, 0x65, 0x22, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3d, 0x22, 0x30, 0x2e, 0x38, 0x33, 0x33, 0x33, 0x33, 0x33, 0x22, 0x2f, 0x3e, 0x3c, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x31, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x31, 0x34, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x63, 0x61, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3d, 0x22, 0x79, 0x65, 0x73, 0x22, 0x3e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x78, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x3e, 0x3c, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x77, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3d, 0x22, 0x62, 0x6f, 0x6c, 0x64, 0x22, 0x2f, 0x3e, 0x3c, 0x2f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x31, 0x35, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x77, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3e, 0x32, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x5f, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3d, 0x22, 0x79, 0x65, 0x73, 0x22, 0x3e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x20, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x3a, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6d, 0x61, 0x72, 0x67, 0x69, 0x6e, 0x2d, 0x6c, 0x65, 0x66, 0x74, 0x22, 0x3e, 0x31, 0x32, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x78, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x31, 0x36, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x78, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x31, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x5f, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x31, 0x36, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3e, 0x3c, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x3e, 0x0a, 0x00, 0x00, 0x28, 0x75, 0x75, 0x61, 0x79, 0x29, 0x2f, 0x04, 0x00, 0x00, 0x00, 0x6c, 0x69, 0x62, 0x69, 0x6e, 0x66, 0x67, 0x74, 0x6b, 0x2f, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x69, 0x6e, 0x66, 0x67, 0x74, 0x6b, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x63, 0x72, 0x65, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x2e, 0x75, 0x69, 0x00, 0x00, 0x04, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x3f, 0x78, 0x6d, 0x6c, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x22, 0x31, 0x2e, 0x30, 0x22, 0x20, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x3d, 0x22, 0x55, 0x54, 0x46, 0x2d, 0x38, 0x22, 0x3f, 0x3e, 0x0a, 0x3c, 0x21, 0x2d, 0x2d, 0x20, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x67, 0x6c, 0x61, 0x64, 0x65, 0x20, 0x33, 0x2e, 0x31, 0x38, 0x2e, 0x33, 0x20, 0x2d, 0x2d, 0x3e, 0x0a, 0x3c, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x20, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x3d, 0x22, 0x6c, 0x69, 0x62, 0x69, 0x6e, 0x66, 0x67, 0x74, 0x6b, 0x30, 0x37, 0x22, 0x3e, 0x3c, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x73, 0x20, 0x6c, 0x69, 0x62, 0x3d, 0x22, 0x67, 0x74, 0x6b, 0x2b, 0x22, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x22, 0x33, 0x2e, 0x30, 0x22, 0x2f, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x61, 0x6e, 0x5f, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x22, 0x3e, 0x46, 0x61, 0x6c, 0x73, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x69, 0x63, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x3e, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2d, 0x72, 0x75, 0x6e, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x49, 0x6e, 0x66, 0x47, 0x74, 0x6b, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x43, 0x72, 0x65, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x22, 0x20, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x44, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x61, 0x6e, 0x5f, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x22, 0x3e, 0x46, 0x61, 0x6c, 0x73, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x22, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3d, 0x22, 0x79, 0x65, 0x73, 0x22, 0x3e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x20, 0x4e, 0x65, 0x77, 0x20, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x72, 0x65, 0x73, 0x69, 0x7a, 0x61, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x46, 0x61, 0x6c, 0x73, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x69, 0x63, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x3e, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x68, 0x69, 0x6e, 0x74, 0x22, 0x3e, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x62, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2d, 0x77, 0x69, 0x64, 0x74, 0x68, 0x22, 0x3e, 0x31, 0x32, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2d, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3d, 0x22, 0x76, 0x62, 0x6f, 0x78, 0x22, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x42, 0x6f, 0x78, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x2d, 0x76, 0x62, 0x6f, 0x78, 0x31, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x61, 0x6e, 0x5f, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x22, 0x3e, 0x46, 0x61, 0x6c, 0x73, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x22, 0x3e, 0x36, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2d, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3d, 0x22, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x72, 0x65, 0x61, 0x22, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x42, 0x6f, 0x78, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x2d, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x72, 0x65, 0x61, 0x31, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x61, 0x6e, 0x5f, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x22, 0x3e, 0x46, 0x61, 0x6c, 0x73, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x5f, 0x73, 0x74, 0x79, 0x6c, 0x65, 0x22, 0x3e, 0x65, 0x6e, 0x64, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x2f, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x68, 0x6f, 0x6c, 0x64, 0x65, 0x72, 0x2f, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x22, 0x3e, 0x46, 0x61, 0x6c, 0x73, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x70, 0x61, 0x63, 0x6b, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x22, 0x3e, 0x65, 0x6e, 0x64, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x47, 0x72, 0x69, 0x64, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x67, 0x72, 0x69, 0x64, 0x31, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x61, 0x6e, 0x5f, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x22, 0x3e, 0x46, 0x61, 0x6c, 0x73, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3e, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x22, 0x3e, 0x31, 0x32, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x61, 0x6e, 0x5f, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x22, 0x3e, 0x46, 0x61, 0x6c, 0x73, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x47, 0x54, 0x4b, 0x5f, 0x41, 0x4c, 0x49, 0x47, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x52, 0x54, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x69, 0x63, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x3e, 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2d, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x69, 0x63, 0x6f, 0x6e, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x22, 0x3e, 0x36, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x47, 0x72, 0x69, 0x64, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x67, 0x72, 0x69, 0x64, 0x32, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x61, 0x6e, 0x5f, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x22, 0x3e, 0x46, 0x61, 0x6c, 0x73, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x72, 0x6f, 0x77, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x22, 0x3e, 0x36, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x47, 0x72, 0x69, 0x64, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x67, 0x72, 0x69, 0x64, 0x33, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x61, 0x6e, 0x5f, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x22, 0x3e, 0x46, 0x61, 0x6c, 0x73, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3e, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x74, 0x61, 0x6c, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x2d, 0x73, 0x70, 0x61, 0x63, 0x69, 0x6e, 0x67, 0x22, 0x3e, 0x31, 0x32, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x61, 0x6e, 0x5f, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x22, 0x3e, 0x46, 0x61, 0x6c, 0x73, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3d, 0x22, 0x79, 0x65, 0x73, 0x22, 0x3e, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x4e, 0x61, 0x6d, 0x65, 0x3a, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x68, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x47, 0x54, 0x4b, 0x5f, 0x41, 0x4c, 0x49, 0x47, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x52, 0x54, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x61, 0x6e, 0x5f, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x61, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x65, 0x73, 0x5f, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x72, 0x75, 0x6e, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x6c, 0x69, 0x6e, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x22, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x3d, 0x22, 0x69, 0x6e, 0x66, 0x5f, 0x67, 0x74, 0x6b, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x5f, 0x63, 0x62, 0x22, 0x20, 0x73, 0x77, 0x61, 0x70, 0x70, 0x65, 0x64, 0x3d, 0x22, 0x6e, 0x6f, 0x22, 0x2f, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x31, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x6c, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3d, 0x22, 0x79, 0x65, 0x73, 0x22, 0x3e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x20, 0x5f, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x61, 0x6e, 0x5f, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x61, 0x6e, 0x5f, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x73, 0x5f, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x22, 0x3e, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x62, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x75, 0x73, 0x65, 0x5f, 0x75, 0x6e, 0x64, 0x65, 0x72, 0x6c, 0x69, 0x6e, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x79, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x30, 0x2e, 0x35, 0x36, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x32, 0x33, 0x38, 0x34, 0x31, 0x38, 0x35, 0x37, 0x39, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x65, 0x64, 0x22, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x3d, 0x22, 0x69, 0x6e, 0x66, 0x5f, 0x67, 0x74, 0x6b, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x64, 0x69, 0x61, 0x6c, 0x6f, 0x67, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x65, 0x64, 0x5f, 0x63, 0x62, 0x22, 0x20, 0x73, 0x77, 0x61, 0x70, 0x70, 0x65, 0x64, 0x3d, 0x22, 0x6e, 0x6f, 0x22, 0x2f, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x32, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x47, 0x74, 0x6b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x22, 0x20, 0x69, 0x64, 0x3d, 0x22, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x5f, 0x74, 0x65, 0x78, 0x74, 0x22, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x76, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x63, 0x61, 0x6e, 0x5f, 0x66, 0x6f, 0x63, 0x75, 0x73, 0x22, 0x3e, 0x46, 0x61, 0x6c, 0x73, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x68, 0x61, 0x6c, 0x69, 0x67, 0x6e, 0x22, 0x3e, 0x47, 0x54, 0x4b, 0x5f, 0x41, 0x4c, 0x49, 0x47, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x52, 0x54, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x31, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x6c, 0x65, 0x66, 0x74, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x31, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x74, 0x6f, 0x70, 0x2d, 0x61, 0x74, 0x74, 0x61, 0x63, 0x68, 0x22, 0x3e, 0x30, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x65, 0x78, 0x70, 0x61, 0x6e, 0x64, 0x22, 0x3e, 0x46, 0x61, 0x6c, 0x73, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x66, 0x69, 0x6c, 0x6c, 0x22, 0x3e, 0x54, 0x72, 0x75, 0x65, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x22, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3e, 0x31, 0x3c, 0x2f, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x79, 0x3e, 0x3c, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x3e, 0x3c, 0x2f, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x3e, 0x3c, 0x2f, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x3e, 0x3c, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x3e, 0x0a, 0x00, 0x00, 0x28, 0x75, 0x75, 0x61, 0x79, 0x29 } }; static GStaticResource static_resource = { _inf_gtk_resource_data.data, sizeof (_inf_gtk_resource_data.data), NULL, NULL, NULL }; G_GNUC_INTERNAL GResource *_inf_gtk_get_resource (void); GResource *_inf_gtk_get_resource (void) { return g_static_resource_get_resource (&static_resource); } /* If G_HAS_CONSTRUCTORS is true then the compiler support *both* constructors and destructors, in a sane way, including e.g. on library unload. If not you're on your own. Some compilers need #pragma to handle this, which does not work with macros, so the way you need to use this is (for constructors): #ifdef G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA #pragma G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(my_constructor) #endif G_DEFINE_CONSTRUCTOR(my_constructor) static void my_constructor(void) { ... } */ #ifndef __GTK_DOC_IGNORE__ #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7) #define G_HAS_CONSTRUCTORS 1 #define G_DEFINE_CONSTRUCTOR(_func) static void __attribute__((constructor)) _func (void); #define G_DEFINE_DESTRUCTOR(_func) static void __attribute__((destructor)) _func (void); #elif defined (_MSC_VER) && (_MSC_VER >= 1500) /* Visual studio 2008 and later has _Pragma */ #define G_HAS_CONSTRUCTORS 1 /* We do some weird things to avoid the constructors being optimized * away on VS2015 if WholeProgramOptimization is enabled. First we * make a reference to the array from the wrapper to make sure its * references. Then we use a pragma to make sure the wrapper function * symbol is always included at the link stage. Also, the symbols * need to be extern (but not dllexport), even though they are not * really used from another object file. */ /* We need to account for differences between the mangling of symbols * for Win32 (x86) and x64 programs, as symbols on Win32 are prefixed * with an underscore but symbols on x64 are not. */ #ifdef _WIN64 #define G_MSVC_SYMBOL_PREFIX "" #else #define G_MSVC_SYMBOL_PREFIX "_" #endif #define G_DEFINE_CONSTRUCTOR(_func) G_MSVC_CTOR (_func, G_MSVC_SYMBOL_PREFIX) #define G_DEFINE_DESTRUCTOR(_func) G_MSVC_DTOR (_func, G_MSVC_SYMBOL_PREFIX) #define G_MSVC_CTOR(_func,_sym_prefix) \ static void _func(void); \ extern int (* _array ## _func)(void); \ int _func ## _wrapper(void) { _func(); g_slist_find (NULL, _array ## _func); return 0; } \ __pragma(comment(linker,"/include:" _sym_prefix # _func "_wrapper")) \ __pragma(section(".CRT$XCU",read)) \ __declspec(allocate(".CRT$XCU")) int (* _array ## _func)(void) = _func ## _wrapper; #define G_MSVC_DTOR(_func,_sym_prefix) \ static void _func(void); \ extern int (* _array ## _func)(void); \ int _func ## _constructor(void) { atexit (_func); g_slist_find (NULL, _array ## _func); return 0; } \ __pragma(comment(linker,"/include:" _sym_prefix # _func "_constructor")) \ __pragma(section(".CRT$XCU",read)) \ __declspec(allocate(".CRT$XCU")) int (* _array ## _func)(void) = _func ## _constructor; #elif defined (_MSC_VER) #define G_HAS_CONSTRUCTORS 1 /* Pre Visual studio 2008 must use #pragma section */ #define G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA 1 #define G_DEFINE_DESTRUCTOR_NEEDS_PRAGMA 1 #define G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(_func) \ section(".CRT$XCU",read) #define G_DEFINE_CONSTRUCTOR(_func) \ static void _func(void); \ static int _func ## _wrapper(void) { _func(); return 0; } \ __declspec(allocate(".CRT$XCU")) static int (*p)(void) = _func ## _wrapper; #define G_DEFINE_DESTRUCTOR_PRAGMA_ARGS(_func) \ section(".CRT$XCU",read) #define G_DEFINE_DESTRUCTOR(_func) \ static void _func(void); \ static int _func ## _constructor(void) { atexit (_func); return 0; } \ __declspec(allocate(".CRT$XCU")) static int (* _array ## _func)(void) = _func ## _constructor; #elif defined(__SUNPRO_C) /* This is not tested, but i believe it should work, based on: * http://opensource.apple.com/source/OpenSSL098/OpenSSL098-35/src/fips/fips_premain.c */ #define G_HAS_CONSTRUCTORS 1 #define G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA 1 #define G_DEFINE_DESTRUCTOR_NEEDS_PRAGMA 1 #define G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(_func) \ init(_func) #define G_DEFINE_CONSTRUCTOR(_func) \ static void _func(void); #define G_DEFINE_DESTRUCTOR_PRAGMA_ARGS(_func) \ fini(_func) #define G_DEFINE_DESTRUCTOR(_func) \ static void _func(void); #else /* constructors not supported for this compiler */ #endif #endif /* __GTK_DOC_IGNORE__ */ #ifdef G_HAS_CONSTRUCTORS #ifdef G_DEFINE_CONSTRUCTOR_NEEDS_PRAGMA #pragma G_DEFINE_CONSTRUCTOR_PRAGMA_ARGS(resource_constructor) #endif G_DEFINE_CONSTRUCTOR(resource_constructor) #ifdef G_DEFINE_DESTRUCTOR_NEEDS_PRAGMA #pragma G_DEFINE_DESTRUCTOR_PRAGMA_ARGS(resource_destructor) #endif G_DEFINE_DESTRUCTOR(resource_destructor) #else #warning "Constructor not supported on this compiler, linking in resources will not work" #endif static void resource_constructor (void) { g_static_resource_init (&static_resource); } static void resource_destructor (void) { g_static_resource_fini (&static_resource); } libinfinity-0.7.1/libinfgtk/PaxHeaders.26529/inf-gtk-browser-model-sort.h0000644000000000000000000000013213034342512023025 xustar0030 mtime=1483851082.017718362 30 atime=1483851082.017718362 30 ctime=1488261589.296138418 libinfinity-0.7.1/libinfgtk/inf-gtk-browser-model-sort.h0000644000175000017500000000451213034342512023561 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_GTK_BROWSER_MODEL_SORT_H__ #define __INF_GTK_BROWSER_MODEL_SORT_H__ #include #include #include G_BEGIN_DECLS #define INF_GTK_TYPE_BROWSER_MODEL_SORT (inf_gtk_browser_model_sort_get_type()) #define INF_GTK_BROWSER_MODEL_SORT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_GTK_TYPE_BROWSER_MODEL_SORT, InfGtkBrowserModelSort)) #define INF_GTK_BROWSER_MODEL_SORT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INF_GTK_TYPE_BROWSER_MODEL_SORT, InfGtkBrowserModelSortClass)) #define INF_GTK_IS_BROWSER_MODEL_SORT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_GTK_TYPE_BROWSER_MODEL_SORT)) #define INF_GTK_IS_BROWSER_MODEL_SORT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INF_GTK_TYPE_BROWSER_MODEL_SORT)) #define INF_GTK_BROWSER_MODEL_SORT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INF_GTK_TYPE_BROWSER_MODEL_SORT, InfGtkBrowserModelSortClass)) typedef struct _InfGtkBrowserModelSort InfGtkBrowserModelSort; typedef struct _InfGtkBrowserModelSortClass InfGtkBrowserModelSortClass; struct _InfGtkBrowserModelSortClass { GtkTreeModelSortClass parent_class; }; struct _InfGtkBrowserModelSort { GtkTreeModelSort parent; }; GType inf_gtk_browser_model_sort_get_type(void) G_GNUC_CONST; InfGtkBrowserModelSort* inf_gtk_browser_model_sort_new(InfGtkBrowserModel* child_model); G_END_DECLS #endif /* __INF_GTK_BROWSER_MODEL_SORT_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/PaxHeaders.26529/COPYING0000644000000000000000000000013212400102201014614 xustar0030 mtime=1409320065.083133199 30 atime=1409320065.083133199 30 ctime=1488261588.768139572 libinfinity-0.7.1/COPYING0000644000175000017500000006364212400102201015361 0ustar00arminarmin00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! libinfinity-0.7.1/PaxHeaders.26529/libinfinity0000644000000000000000000000013113055210725016045 xustar0030 mtime=1488261589.140138759 29 atime=1488261588.79213952 30 ctime=1488261589.140138759 libinfinity-0.7.1/libinfinity/0000755000175000017500000000000013055210725016655 5ustar00arminarmin00000000000000libinfinity-0.7.1/libinfinity/PaxHeaders.26529/inf-i18n.h0000644000000000000000000000013213034342512017622 xustar0030 mtime=1483851082.041718492 30 atime=1483851082.041718492 30 ctime=1488261588.996139074 libinfinity-0.7.1/libinfinity/inf-i18n.h0000644000175000017500000000227213034342512020357 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_I18N_H__ #define __INF_I18N_H__ #include #define _(String) _inf_gettext(String) #ifdef gettext_noop # define N_(String) gettext_noop(String) #else # define N_(String) (String) #endif void _inf_gettext_init(void); const char* _inf_gettext(const char* msgid); #endif /* __INF_I18N_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/PaxHeaders.26529/adopted0000644000000000000000000000013213055210725017466 xustar0030 mtime=1488261589.036138987 30 atime=1488261588.900139284 30 ctime=1488261589.036138987 libinfinity-0.7.1/libinfinity/adopted/0000755000175000017500000000000013055210725020275 5ustar00arminarmin00000000000000libinfinity-0.7.1/libinfinity/adopted/PaxHeaders.26529/inf-adopted-request-log.c0000644000000000000000000000013213034342512024343 xustar0030 mtime=1483851082.025718404 30 atime=1483851082.025718404 30 ctime=1488261589.024139013 libinfinity-0.7.1/libinfinity/adopted/inf-adopted-request-log.c0000644000175000017500000011740613034342512025106 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-adopted-request-log * @title: InfAdoptedRequestLog * @short_description: History of requests * @include: libinfinity/adopted/inf-adopted-request-log.h * @see_also: #InfAdoptedRequest, #InfAdoptedAlgorithm * @stability: Unstable * * #InfAdoptedRequestLog stores all requests by a particular user. These need * to be looked up by #InfAdoptedAlgorithm to perform transformations of * older requests to the current state. It also adds relations between the * requests so that is easy to find the request that an Undo request undoes, * or the Undo request undoing a given request, if available. * * When requests are no longer needed, then they can also be removed again * from the log, however requests can only be removed so that remaining Undo * or Redo requests do not refer to some request that is about to be removed. */ #include #include /* For (g_)memmove */ typedef struct _InfAdoptedRequestLogCleanupCacheData InfAdoptedRequestLogCleanupCacheData; struct _InfAdoptedRequestLogCleanupCacheData { guint user_id; guint up_to; GSList* requests_to_remove; }; typedef struct _InfAdoptedRequestLogEntry InfAdoptedRequestLogEntry; struct _InfAdoptedRequestLogEntry { InfAdoptedRequest* request; InfAdoptedRequestLogEntry* original; InfAdoptedRequestLogEntry* next_associated; InfAdoptedRequestLogEntry* prev_associated; InfAdoptedRequestLogEntry* lower_related; InfAdoptedRequestLogEntry* upper_related; }; typedef struct _InfAdoptedRequestLogPrivate InfAdoptedRequestLogPrivate; struct _InfAdoptedRequestLogPrivate { guint user_id; InfAdoptedRequestLogEntry* entries; GTree* cache; InfAdoptedRequestLogEntry* next_undo; InfAdoptedRequestLogEntry* next_redo; gsize offset; guint begin; guint end; gsize alloc; }; enum { PROP_0, /* construct only */ PROP_USER_ID, PROP_BEGIN, PROP_END, PROP_NEXT_UNDO, PROP_NEXT_REDO }; enum { ADD_REQUEST, LAST_SIGNAL }; #define INF_ADOPTED_REQUEST_LOG_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INF_ADOPTED_TYPE_REQUEST_LOG, InfAdoptedRequestLogPrivate)) #define INF_ADOPTED_REQUEST_LOG_PRIVATE(obj) ((InfAdoptedRequestLogPrivate*)(obj)->priv) static const guint INF_ADOPTED_REQUEST_LOG_INC = 0x80; static guint request_log_signals[LAST_SIGNAL]; G_DEFINE_TYPE_WITH_CODE(InfAdoptedRequestLog, inf_adopted_request_log, G_TYPE_OBJECT, G_ADD_PRIVATE(InfAdoptedRequestLog)) #ifdef INF_ADOPTED_REQUEST_LOG_CHECK_RELATED static void inf_adopted_request_log_verify_related(InfAdoptedRequestLog* log) { InfAdoptedRequestLogPrivate* priv; InfAdoptedRequestLogEntry* begin; InfAdoptedRequestLogEntry* end; InfAdoptedRequestLogEntry* current; InfAdoptedRequestLogEntry* lower_related; InfAdoptedRequestLogEntry* upper_related; priv = INF_ADOPTED_REQUEST_LOG_PRIVATE(log); begin = priv->entries + priv->offset; end = begin + (priv->end - priv->begin); lower_related = NULL; upper_related = NULL; for(current = begin; current != end; ++current) { g_assert( (lower_related == NULL && upper_related == NULL) || (lower_related != NULL && upper_related != NULL)); if(lower_related == NULL) { g_assert(current->lower_related == current); g_assert(current->upper_related >= current); if(current->upper_related > current) { lower_related = current->lower_related; upper_related = current->upper_related; } } else { g_assert(current->lower_related == lower_related); g_assert(current->upper_related == upper_related); if(current == upper_related) { lower_related = NULL; upper_related = NULL; } } } } #else # define inf_adopted_request_log_verify_related(log) #endif /* * Transformation cache */ static int inf_adopted_request_log_cache_key_cmp(gconstpointer a, gconstpointer b, gpointer user_data) { InfAdoptedRequestLog* log; InfAdoptedRequestLogPrivate* priv; const InfAdoptedStateVector* key_a; const InfAdoptedStateVector* key_b; guint n_a, n_b; key_a = (const InfAdoptedStateVector*)a; key_b = (const InfAdoptedStateVector*)b; log = (InfAdoptedRequestLog*)user_data; priv = INF_ADOPTED_REQUEST_LOG_PRIVATE(log); /* Primary, order by component of user ID -- this makes cleanup very * efficient. */ n_a = inf_adopted_state_vector_get(key_a, priv->user_id); n_b = inf_adopted_state_vector_get(key_b, priv->user_id); if(n_a < n_b) return -1; if(n_a > n_b) return 1; /* If user ID component is equal, go by other components. */ return inf_adopted_state_vector_compare(key_a, key_b); } static gboolean inf_adopted_request_log_remove_requests_cache_foreach_func(gpointer key, gpointer value, gpointer user_data) { InfAdoptedStateVector* vector; InfAdoptedRequestLogCleanupCacheData* data; vector = (InfAdoptedStateVector*)key; data = (InfAdoptedRequestLogCleanupCacheData*)user_data; /* Remove all requests which are a cached translation of one of the requests * that have been removed, i.e. have a user component smaller than up_to. */ if(inf_adopted_state_vector_get(vector, data->user_id) < data->up_to) { data->requests_to_remove = g_slist_prepend(data->requests_to_remove, vector); return FALSE; } else { /* Stop traversal. The tree is traversed in sorted order, and the primary * sort criteria of the tree is the vector component of the user. So if * we have reached this point, all other elements in the tree will have * a higher user component and are not scheduled for removal. */ return TRUE; } } /* * Associated and Related requests */ /* Find the request that is undone if the next request was an undo request * (to be cached in priv->next_undo). Similar if type is REDO. */ static InfAdoptedRequestLogEntry* inf_adopted_request_log_find_associated(InfAdoptedRequestLog* log, InfAdoptedRequestType type) { InfAdoptedRequestLogPrivate* priv; InfAdoptedRequestLogEntry* entry; g_assert(type != INF_ADOPTED_REQUEST_DO); priv = INF_ADOPTED_REQUEST_LOG_PRIVATE(log); entry = priv->entries + priv->offset + (priv->end - priv->begin) - 1; while(entry >= priv->entries + priv->offset) { switch(inf_adopted_request_get_request_type(entry->request)) { case INF_ADOPTED_REQUEST_DO: /* There is no Undo to Redo */ if(type == INF_ADOPTED_REQUEST_REDO) return NULL; return entry; case INF_ADOPTED_REQUEST_UNDO: if(type == INF_ADOPTED_REQUEST_UNDO) { g_assert(entry->prev_associated != NULL); entry = entry->prev_associated - 1; } else { return entry; } break; case INF_ADOPTED_REQUEST_REDO: if(type == INF_ADOPTED_REQUEST_REDO) { g_assert(entry->prev_associated != NULL); entry = entry->prev_associated - 1; } else { return entry; } break; default: g_assert_not_reached(); break; } } return NULL; } /* * GObject overrides */ static void inf_adopted_request_log_init(InfAdoptedRequestLog* log) { InfAdoptedRequestLogPrivate* priv; log->priv = INF_ADOPTED_REQUEST_LOG_GET_PRIVATE(log); priv = INF_ADOPTED_REQUEST_LOG_PRIVATE(log); priv->user_id = 0; priv->alloc = INF_ADOPTED_REQUEST_LOG_INC; priv->entries = g_malloc(priv->alloc * sizeof(InfAdoptedRequestLogEntry)); priv->cache = NULL; priv->begin = 0; priv->end = 0; priv->offset = 0; priv->next_undo = NULL; priv->next_redo = NULL; } static void inf_adopted_request_log_dispose(GObject* object) { InfAdoptedRequestLog* log; InfAdoptedRequestLogPrivate* priv; guint i; log = INF_ADOPTED_REQUEST_LOG(object); priv = INF_ADOPTED_REQUEST_LOG_PRIVATE(log); if(priv->cache != NULL) { g_tree_destroy(priv->cache); priv->cache = NULL; } for(i = priv->offset; i < priv->offset + (priv->end - priv->begin); ++ i) g_object_unref(G_OBJECT(priv->entries[i].request)); priv->begin = 0; priv->end = 0; priv->offset = 0; G_OBJECT_CLASS(inf_adopted_request_log_parent_class)->dispose(object); } static void inf_adopted_request_log_finalize(GObject* object) { InfAdoptedRequestLog* log; InfAdoptedRequestLogPrivate* priv; log = INF_ADOPTED_REQUEST_LOG(object); priv = INF_ADOPTED_REQUEST_LOG_PRIVATE(log); g_free(priv->entries); G_OBJECT_CLASS(inf_adopted_request_log_parent_class)->finalize(object); } static void inf_adopted_request_log_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfAdoptedRequestLog* log; InfAdoptedRequestLogPrivate* priv; log = INF_ADOPTED_REQUEST_LOG(object); priv = INF_ADOPTED_REQUEST_LOG_PRIVATE(log); switch(prop_id) { case PROP_USER_ID: g_assert(priv->user_id == 0); /* construct only */ g_assert(g_value_get_uint(value) != 0); /* 0 is invalid user ID */ priv->user_id = g_value_get_uint(value); break; case PROP_BEGIN: g_assert(priv->begin == 0); /* construct only */ priv->begin = g_value_get_uint(value); priv->end = priv->begin; break; case PROP_END: case PROP_NEXT_UNDO: case PROP_NEXT_REDO: /* These are read only; fallthrough */ default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void inf_adopted_request_log_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfAdoptedRequestLog* log; InfAdoptedRequestLogPrivate* priv; log = INF_ADOPTED_REQUEST_LOG(object); priv = INF_ADOPTED_REQUEST_LOG_PRIVATE(log); switch(prop_id) { case PROP_USER_ID: g_value_set_uint(value, priv->user_id); break; case PROP_BEGIN: g_value_set_uint(value, priv->begin); break; case PROP_END: g_value_set_uint(value, priv->end); break; case PROP_NEXT_UNDO: if(priv->next_undo != NULL) g_value_set_object(value, G_OBJECT(priv->next_undo->request)); else g_value_set_object(value, NULL); break; case PROP_NEXT_REDO: if(priv->next_redo != NULL) g_value_set_object(value, G_OBJECT(priv->next_redo->request)); else g_value_set_object(value, NULL); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void inf_adopted_request_log_add_request_handler(InfAdoptedRequestLog* log, InfAdoptedRequest* request) { InfAdoptedRequestLogPrivate* priv; InfAdoptedRequestLogEntry* entry; InfAdoptedRequestLogEntry* old_entries; InfAdoptedRequestLogEntry* current; guint i; priv = INF_ADOPTED_REQUEST_LOG_PRIVATE(log); g_assert(inf_adopted_request_get_user_id(request) == priv->user_id); g_assert( priv->begin == priv->end || inf_adopted_state_vector_get( inf_adopted_request_get_vector(request), priv->user_id ) == priv->end ); if(priv->offset + (priv->end - priv->begin) == priv->alloc) { if(priv->offset > 0) { g_memmove( priv->entries, priv->entries + priv->offset, (priv->end - priv->begin) * sizeof(InfAdoptedRequestLogEntry) ); /* We now corrupted several pointers in our entries because of * moving memory around. */ for(i = 0; i < priv->end - priv->begin; ++ i) { g_assert(priv->entries[i].original != NULL); priv->entries[i].original -= priv->offset; if(priv->entries[i].next_associated != NULL) priv->entries[i].next_associated -= priv->offset; if(priv->entries[i].prev_associated != NULL) priv->entries[i].prev_associated -= priv->offset; priv->entries[i].lower_related -= priv->offset; priv->entries[i].upper_related -= priv->offset; } if(priv->next_undo != NULL) priv->next_undo -= priv->offset; if(priv->next_redo != NULL) priv->next_redo -= priv->offset; priv->offset = 0; } else { old_entries = priv->entries; priv->alloc += INF_ADOPTED_REQUEST_LOG_INC; priv->entries = g_realloc( priv->entries, priv->alloc * sizeof(InfAdoptedRequestLogEntry) ); if(priv->entries != old_entries) { /* The realloc above could have invalidated several pointers */ for(i = 0; i < priv->end - priv->begin; ++ i) { g_assert(priv->entries[i].original != NULL); priv->entries[i].original = priv->entries + (priv->entries[i].original - old_entries); if(priv->entries[i].next_associated != NULL) { priv->entries[i].next_associated = priv->entries + (priv->entries[i].next_associated - old_entries); } if(priv->entries[i].prev_associated != NULL) { priv->entries[i].prev_associated = priv->entries + (priv->entries[i].prev_associated - old_entries); } priv->entries[i].lower_related = priv->entries + (priv->entries[i].lower_related - old_entries); priv->entries[i].upper_related = priv->entries + (priv->entries[i].upper_related - old_entries); } if(priv->next_undo != NULL) priv->next_undo = priv->entries + (priv->next_undo - old_entries); if(priv->next_redo != NULL) priv->next_redo = priv->entries + (priv->next_redo - old_entries); } } } g_object_freeze_notify(G_OBJECT(log)); if(priv->begin == priv->end) { priv->begin = inf_adopted_state_vector_get( inf_adopted_request_get_vector(request), priv->user_id ); priv->end = priv->begin; } entry = &priv->entries[priv->offset + (priv->end - priv->begin)]; ++ priv->end; g_object_notify(G_OBJECT(log), "end"); entry->request = request; g_object_ref(G_OBJECT(request)); switch(inf_adopted_request_get_request_type(request)) { case INF_ADOPTED_REQUEST_DO: entry->original = entry; entry->next_associated = NULL; entry->prev_associated = NULL; entry->lower_related = entry; entry->upper_related = entry; priv->next_undo = entry; g_object_notify(G_OBJECT(log), "next-undo"); if(priv->next_redo != NULL) { priv->next_redo = NULL; g_object_notify(G_OBJECT(log), "next-redo"); } break; case INF_ADOPTED_REQUEST_UNDO: g_assert(priv->next_undo != NULL); entry->next_associated = NULL; entry->prev_associated = priv->next_undo; entry->prev_associated->next_associated = entry; entry->original = entry->prev_associated->original; entry->lower_related = entry->original->lower_related; entry->upper_related = entry; for(current = entry->lower_related; current != entry; ++current) { current->lower_related = entry->lower_related; current->upper_related = entry; } priv->next_undo = inf_adopted_request_log_find_associated(log, INF_ADOPTED_REQUEST_UNDO); g_object_notify(G_OBJECT(log), "next-undo"); priv->next_redo = entry; g_object_notify(G_OBJECT(log), "next-redo"); g_assert(priv->next_undo == NULL || inf_adopted_request_get_request_type(priv->next_undo->request) == INF_ADOPTED_REQUEST_DO || inf_adopted_request_get_request_type(priv->next_undo->request) == INF_ADOPTED_REQUEST_REDO); break; case INF_ADOPTED_REQUEST_REDO: g_assert(priv->next_redo != NULL); entry->next_associated = NULL; entry->prev_associated = priv->next_redo; entry->prev_associated->next_associated = entry; entry->original = entry->prev_associated->original; entry->lower_related = entry->original->lower_related; entry->upper_related = entry; for(current = entry->lower_related; current != entry; ++current) { current->lower_related = entry->lower_related; current->upper_related = entry; } priv->next_undo = entry; g_object_notify(G_OBJECT(log), "next-undo"); priv->next_redo = inf_adopted_request_log_find_associated(log, INF_ADOPTED_REQUEST_REDO); g_object_notify(G_OBJECT(log), "next-redo"); g_assert(priv->next_redo == NULL || inf_adopted_request_get_request_type(priv->next_redo->request) == INF_ADOPTED_REQUEST_UNDO); break; default: g_assert_not_reached(); break; } inf_adopted_request_log_verify_related(log); g_object_thaw_notify(G_OBJECT(log)); } static void inf_adopted_request_log_class_init( InfAdoptedRequestLogClass* request_log_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(request_log_class); object_class->dispose = inf_adopted_request_log_dispose; object_class->finalize = inf_adopted_request_log_finalize; object_class->set_property = inf_adopted_request_log_set_property; object_class->get_property = inf_adopted_request_log_get_property; request_log_class->add_request = inf_adopted_request_log_add_request_handler; g_object_class_install_property( object_class, PROP_USER_ID, g_param_spec_uint( "user-id", "User ID", "The ID of the user whose requests the log contains", 0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_BEGIN, g_param_spec_uint( "begin", "Begin", "The first index contained in the log", 0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_END, g_param_spec_uint( "end", "End", "The index of the next request that is inserted into the log", 0, G_MAXUINT, 0, G_PARAM_READABLE ) ); g_object_class_install_property( object_class, PROP_NEXT_UNDO, g_param_spec_object( "next-undo", "Next undo", "The request that is undone when the user issues an undo request now", INF_ADOPTED_TYPE_REQUEST, G_PARAM_READABLE ) ); g_object_class_install_property( object_class, PROP_NEXT_REDO, g_param_spec_object( "next-redo", "Next redo", "The request that is redone when the user issues a redo request new", INF_ADOPTED_TYPE_REQUEST, G_PARAM_READABLE ) ); /** * InfAdoptedRequestLog::add-request: * @log: The #InfAdoptedRequestLog to which a new request is added. * @request: The new request being added. * * This signal is emitted whenever a new request is added to the request log * via inf_adopted_request_log_add_request(). */ request_log_signals[ADD_REQUEST] = g_signal_new( "add-request", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfAdoptedRequestLogClass, add_request), NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, INF_ADOPTED_TYPE_REQUEST ); } /* * Public API */ /** * inf_adopted_request_log_new: (constructor) * @user_id: The ID of the #InfAdoptedUser to create a request log for. The * request log only contains requests of that particular user. * * Creates a new #InfAdoptedRequestLog for the user with the given ID. * * Returns: (transfer full): A new #InfAdoptedRequestLog. **/ InfAdoptedRequestLog* inf_adopted_request_log_new(guint user_id) { GObject* object; g_return_val_if_fail(user_id != 0, NULL); object = g_object_new( INF_ADOPTED_TYPE_REQUEST_LOG, "user-id", user_id, NULL ); return INF_ADOPTED_REQUEST_LOG(object); } /** * inf_adopted_request_log_get_user_id: * @log: A #InfAdoptedRequestLog. * * Returns the ID of the user whose requests @log contains. * * Returns: The log's user ID. **/ guint inf_adopted_request_log_get_user_id(InfAdoptedRequestLog* log) { g_return_val_if_fail(INF_ADOPTED_IS_REQUEST_LOG(log), 0); return INF_ADOPTED_REQUEST_LOG_PRIVATE(log)->user_id; } /** * inf_adopted_request_log_get_begin: * @log: A #InfAdoptedRequestLog. * * Returns the first index (i.e. the index of the oldest request) in the log. * * Returns: The first index in the log. **/ guint inf_adopted_request_log_get_begin(InfAdoptedRequestLog* log) { g_return_val_if_fail(INF_ADOPTED_IS_REQUEST_LOG(log), 0); return INF_ADOPTED_REQUEST_LOG_PRIVATE(log)->begin; } /** * inf_adopted_request_log_get_end: * @log: A #InfAdoptedRequestLog. * * Returns the index a newly inserted request would have (i.e. one past the * index of the newest request in the log). This ensures that * inf_adopted_request_log_get_end() - inf_adopted_request_log_get_begin() * reveals the number of requests in the log. * * Returns: The index of the next request in the log. **/ guint inf_adopted_request_log_get_end(InfAdoptedRequestLog* log) { g_return_val_if_fail(INF_ADOPTED_IS_REQUEST_LOG(log), 0); return INF_ADOPTED_REQUEST_LOG_PRIVATE(log)->end; } /** * inf_adopted_request_log_is_empty: * @log: A #InfAdoptedRequestLog. * * Returns whether @log is empty. A log is empty if it does not contain any * requsets. * * Returns: Whether @log is empty. */ gboolean inf_adopted_request_log_is_empty(InfAdoptedRequestLog* log) { InfAdoptedRequestLogPrivate* priv; g_return_val_if_fail(INF_ADOPTED_IS_REQUEST_LOG(log), TRUE); priv = INF_ADOPTED_REQUEST_LOG_PRIVATE(log); if(priv->begin == priv->end) return TRUE; return FALSE; } /** * inf_adopted_request_log_set_begin: * @log: A #InfAdoptedRequestLog. * @n: The index of the first request to be added to the log. * * This function sets the index of the first log that will be added to @log. * For a new request log, this is set to 0. If you intend to insert a request * sequence into @log that does not start with 0, then you can call this * function with the desired start index, so that * inf_adopted_request_log_get_begin() and inf_adopted_request_log_get_end() * return the correct value. * * If you don't need inf_adopted_request_log_get_begin() or * inf_adopted_request_log_get_end() before adding the first request to the * log, then you don't need to call this function, since * inf_adopted_request_log_add_request() will do it implicitely based on the * request's vector time component for the request log's user. * * This function can only be called if the request log is empty, see * inf_adopted_request_log_is_empty(). */ void inf_adopted_request_log_set_begin(InfAdoptedRequestLog* log, guint n) { InfAdoptedRequestLogPrivate* priv; g_return_if_fail(INF_ADOPTED_IS_REQUEST_LOG(log)); priv = INF_ADOPTED_REQUEST_LOG_PRIVATE(log); g_return_if_fail(priv->begin == priv->end); if(priv->begin != n) { priv->begin = n; priv->end = n; g_object_notify(G_OBJECT(log), "begin"); g_object_notify(G_OBJECT(log), "end"); } } /** * inf_adopted_request_log_get_request: * @log: A #InfAdoptedRequestLog. * @n: The index of a request contained in @log. * * Returns the request with the given index. Such a request must exist in * @log. * * Returns: (transfer none): A #InfAdoptedRequest. The request is owned by * the request log, you do not need to free it. **/ InfAdoptedRequest* inf_adopted_request_log_get_request(InfAdoptedRequestLog* log, guint n) { InfAdoptedRequestLogPrivate* priv; g_return_val_if_fail(INF_ADOPTED_IS_REQUEST_LOG(log), NULL); priv = INF_ADOPTED_REQUEST_LOG_PRIVATE(log); g_return_val_if_fail(n >= priv->begin && n < priv->end, NULL); return priv->entries[priv->offset + n - priv->begin].request; } /** * inf_adopted_request_log_add_request: * @log: A #InfAdoptedRequestLog. * @request: A #InfAdoptedRequest. * * Inserts @request into @log. The component represented by the log's user * of the request's state vector must match the end index of @log if @log * is not empty. Also, the user that issued @request must be the same user as * the one this request log belongs to. **/ void inf_adopted_request_log_add_request(InfAdoptedRequestLog* log, InfAdoptedRequest* request) { InfAdoptedRequestLogPrivate* priv; g_return_if_fail(INF_ADOPTED_IS_REQUEST_LOG(log)); g_return_if_fail(INF_ADOPTED_IS_REQUEST(request)); priv = INF_ADOPTED_REQUEST_LOG_PRIVATE(log); g_return_if_fail(inf_adopted_request_get_user_id(request) == priv->user_id); g_return_if_fail( priv->begin == priv->end || inf_adopted_state_vector_get( inf_adopted_request_get_vector(request), priv->user_id ) == priv->end ); g_signal_emit(G_OBJECT(log), request_log_signals[ADD_REQUEST], 0, request); } /** * inf_adopted_request_log_remove_requests: * @log: A #InfAdoptedRequestLog. * @up_to: The index of the first request not to remove. * * Removes all requests with index lower than @up_to. This function only works * if the request before @up_to is an "upper related" request. * See inf_adopted_request_log_upper_related(). This condition guarantees * that remaining requests do not refer to removed ones. **/ void inf_adopted_request_log_remove_requests(InfAdoptedRequestLog* log, guint up_to) { InfAdoptedRequestLogPrivate* priv; InfAdoptedRequestLogCleanupCacheData data; guint i; GSList* item; g_return_if_fail(INF_ADOPTED_IS_REQUEST_LOG(log)); priv = INF_ADOPTED_REQUEST_LOG_PRIVATE(log); g_return_if_fail(up_to >= priv->begin && up_to <= priv->end); g_return_if_fail( up_to == priv->begin || priv->entries[priv->offset + up_to - priv->begin - 1].upper_related == &priv->entries[priv->offset + up_to - priv->begin - 1] ); for(i = priv->offset; i < priv->offset + (up_to - priv->begin); ++i) g_object_unref(G_OBJECT(priv->entries[i].request)); g_object_freeze_notify(G_OBJECT(log)); /* If the next undo/redo request has been removed, there cannot be * a new next undo/redo request, because the next undo is already the * newest one in the log */ if(priv->next_undo != NULL) { if(priv->next_undo < priv->entries + priv->offset + (up_to - priv->begin)) { priv->next_undo = NULL; g_object_notify(G_OBJECT(log), "next-undo"); } } if(priv->next_redo != NULL) { if(priv->next_redo < priv->entries + priv->offset + (up_to - priv->begin)) { priv->next_redo = NULL; g_object_notify(G_OBJECT(log), "next-redo"); } } priv->offset += (up_to - priv->begin); priv->begin = up_to; g_object_notify(G_OBJECT(log), "begin"); if(priv->cache != NULL) { data.user_id = priv->user_id; data.up_to = up_to; data.requests_to_remove = NULL; g_tree_foreach( priv->cache, inf_adopted_request_log_remove_requests_cache_foreach_func, &data ); for(item = data.requests_to_remove; item != NULL; item = item->next) g_tree_remove(priv->cache, (InfAdoptedStateVector*)item->data); g_slist_free(data.requests_to_remove); } inf_adopted_request_log_verify_related(log); g_object_thaw_notify(G_OBJECT(log)); } /** * inf_adopted_request_log_next_associated: * @log: A #InfAdoptedRequestLog. * @request: A #InfAdoptedRequest contained in @log. * * If @request is of type %INF_ADOPTED_REQUEST_DO or * %INF_ADOPTED_REQUEST_REDO, this returns UNDO request that undoes this * request, if any. If @request is a %INF_ADOPTED_REQUEST UNDO request, this * returns a request that redoes @request, if any. * * Returns: (transfer none) (allow-none): The next associated request of * @request, or %NULL. **/ InfAdoptedRequest* inf_adopted_request_log_next_associated(InfAdoptedRequestLog* log, InfAdoptedRequest* request) { InfAdoptedRequestLogPrivate* priv; InfAdoptedStateVector* vector; guint user_id; guint n; InfAdoptedRequestLogEntry* entry; g_return_val_if_fail(INF_ADOPTED_IS_REQUEST_LOG(log), NULL); g_return_val_if_fail(INF_ADOPTED_IS_REQUEST(request), NULL); priv = INF_ADOPTED_REQUEST_LOG_PRIVATE(log); vector = inf_adopted_request_get_vector(request); user_id = inf_adopted_request_get_user_id(request); n = inf_adopted_state_vector_get(vector, user_id); g_return_val_if_fail(priv->user_id == user_id, NULL); g_return_val_if_fail(n >= priv->begin && n < priv->end, NULL); entry = priv->entries + priv->offset + n - priv->begin; if(entry->next_associated == NULL) return NULL; return entry->next_associated->request; } /** * inf_adopted_request_log_prev_associated: * @log: A #InfAdoptedRequestLog. * @request: A #InfAdoptedRequest. * * If @request is of type %INF_ADOPTED_REQUEST_REDO or, this returns the UNDO * request that is redone by @request, if @request is a * %INF_ADOPTED_REQUEST_UNDO request, this returns the request that is undone * by @request. * * @request must either be contained in @log or the vector time component * of its own user must be equivalent to inf_adopted_request_log_get_end(), * in which case @request is treated as it if was the newest request in @log. * * Returns: (transfer none) (allow-none): The previous associated request of * @request, or %NULL. **/ InfAdoptedRequest* inf_adopted_request_log_prev_associated(InfAdoptedRequestLog* log, InfAdoptedRequest* request) { InfAdoptedRequestLogPrivate* priv; InfAdoptedStateVector* vector; guint user_id; guint n; InfAdoptedRequestLogEntry* entry; g_return_val_if_fail(INF_ADOPTED_IS_REQUEST_LOG(log), NULL); g_return_val_if_fail(INF_ADOPTED_IS_REQUEST(request), NULL); priv = INF_ADOPTED_REQUEST_LOG_PRIVATE(log); vector = inf_adopted_request_get_vector(request); user_id = inf_adopted_request_get_user_id(request); n = inf_adopted_state_vector_get(vector, user_id); g_return_val_if_fail(priv->user_id == user_id, NULL); g_return_val_if_fail(n >= priv->begin && n <= priv->end, NULL); if(n == priv->end) { switch(inf_adopted_request_get_request_type(request)) { case INF_ADOPTED_REQUEST_DO: entry = NULL; break; case INF_ADOPTED_REQUEST_UNDO: entry = priv->next_undo; break; case INF_ADOPTED_REQUEST_REDO: entry = priv->next_redo; break; default: g_assert_not_reached(); break; } if(entry != NULL) return entry->request; else return NULL; } else { entry = priv->entries + priv->offset + n - priv->begin; if(entry->prev_associated == NULL) return NULL; return entry->prev_associated->request; } } /** * inf_adopted_request_log_original_request: * @log: A #InfAdoptedRequestLog. * @request: A #InfAdoptedRequest. * * Returns the most previous associated request for @request, that is, * the %INF_ADOPTED_REQUEST_DO request that @request undoes or redoes, * respectively. If @request itself is a %INF_ADOPTED_REQUEST_DO request, * @request itself is returned. * * @request must either be contained in @log or the vector time component * of its own user must be equivalent to inf_adopted_request_log_get_end(), * in which case @request is treated as it if was the newest request in @log. * * Returns: (transfer none): The original request of @request. * This function never returns %NULL. **/ InfAdoptedRequest* inf_adopted_request_log_original_request(InfAdoptedRequestLog* log, InfAdoptedRequest* request) { InfAdoptedRequestLogPrivate* priv; InfAdoptedStateVector* vector; guint user_id; guint n; InfAdoptedRequestLogEntry* entry; g_return_val_if_fail(INF_ADOPTED_IS_REQUEST_LOG(log), NULL); g_return_val_if_fail(INF_ADOPTED_IS_REQUEST(request), NULL); priv = INF_ADOPTED_REQUEST_LOG_PRIVATE(log); vector = inf_adopted_request_get_vector(request); user_id = inf_adopted_request_get_user_id(request); n = inf_adopted_state_vector_get(vector, user_id); g_return_val_if_fail(priv->user_id == user_id, NULL); g_return_val_if_fail(n >= priv->begin && n <= priv->end, NULL); if(n == priv->end) { switch(inf_adopted_request_get_request_type(request)) { case INF_ADOPTED_REQUEST_DO: entry = NULL; break; case INF_ADOPTED_REQUEST_UNDO: entry = priv->next_undo; break; case INF_ADOPTED_REQUEST_REDO: entry = priv->next_redo; break; default: g_assert_not_reached(); break; } if(entry != NULL) return entry->original->request; else return request; } else { /* Note that this check would in principle not be needed, if request were * always contained in request log. However, it can happen that it is a * different request (for example, a helper request that does not affect * the buffer -- InfTextUndoGrouping uses such a request). In this case we * do not want to exchange the given request by the one which is in the * request log. */ if(inf_adopted_request_get_request_type(request) == INF_ADOPTED_REQUEST_DO) return request; entry = priv->entries + priv->offset + n - priv->begin; g_assert(entry->original != NULL); return entry->original->request; } } /** * inf_adopted_request_log_next_undo: * @log: A #InfAdoptedRequestLog. * * Returns the request that would be undone if a undo request was added to * the request log. * * Returns: (transfer none) (allow-none): The next request to be undone, or * %NULL. **/ InfAdoptedRequest* inf_adopted_request_log_next_undo(InfAdoptedRequestLog* log) { InfAdoptedRequestLogPrivate* priv; g_return_val_if_fail(INF_ADOPTED_IS_REQUEST_LOG(log), NULL); priv = INF_ADOPTED_REQUEST_LOG_PRIVATE(log); if(priv->next_undo == NULL) return NULL; return priv->next_undo->request; } /** * inf_adopted_request_log_next_redo: * @log: A #InfAdoptedRequestLog. * * Returns the request that would be redone if a redo request was added to * the request log. * * Returns: (transfer none) (allow-none): The next request to be redone, or * %NULL. **/ InfAdoptedRequest* inf_adopted_request_log_next_redo(InfAdoptedRequestLog* log) { InfAdoptedRequestLogPrivate* priv; g_return_val_if_fail(INF_ADOPTED_IS_REQUEST_LOG(log), NULL); priv = INF_ADOPTED_REQUEST_LOG_PRIVATE(log); if(priv->next_redo == NULL) return NULL; return priv->next_redo->request; } /** * inf_adopted_request_log_upper_related: * @log: A #InfAdoptedRequestLog. * @n: Index of a request in @log. * * Returns the newest request in @log that is related to @nth request * in log. Requests are considered related when they are enclosed by a * do/undo, an undo/redo or a redo/undo pair. * * Note that the sets of related requests within a request log are * disjoint. * * Returns: (transfer none): The newest request in @log being related to the * @nth request. **/ InfAdoptedRequest* inf_adopted_request_log_upper_related(InfAdoptedRequestLog* log, guint n) { InfAdoptedRequestLogPrivate* priv; InfAdoptedRequestLogEntry* current; g_return_val_if_fail(INF_ADOPTED_IS_REQUEST_LOG(log), NULL); priv = INF_ADOPTED_REQUEST_LOG_PRIVATE(log); g_return_val_if_fail(n >= priv->begin && n < priv->end, NULL); inf_adopted_request_log_verify_related(log); current = priv->entries + priv->offset + n - priv->begin; return current->upper_related->request; } /** * inf_adopted_request_log_lower_related: * @log: A #InfAdoptedRequestLog. * @n: Index of a request in @log. * * Returns the oldest request in @log that is related to @nth request * in log. Requests are considered related when they are enclosed by a * do/undo, an undo/redo or a redo/undo pair. * * Note that the sets of related requests within a request log are * disjoint. * * Returns: (transfer none): The oldest request in @log being related to the * @nth request. **/ InfAdoptedRequest* inf_adopted_request_log_lower_related(InfAdoptedRequestLog* log, guint n) { InfAdoptedRequestLogPrivate* priv; InfAdoptedRequestLogEntry* current; g_return_val_if_fail(INF_ADOPTED_IS_REQUEST_LOG(log), NULL); priv = INF_ADOPTED_REQUEST_LOG_PRIVATE(log); g_return_val_if_fail(n >= priv->begin && n < priv->end, NULL); inf_adopted_request_log_verify_related(log); current = priv->entries + priv->offset + n - priv->begin; return current->lower_related->request; } /** * inf_adopted_request_log_add_cached_request: * @log: A #InfAdoptedRequestLog. * @request: The #InfAdoptedRequest to add to the cache. * * #InfAdoptedRequestLog has a cache for translated requests built in. This * can be used to store requests that have been translated to another point * in the state space, and to efficiently look them up later. The advantage * of having this functionality within #InfAdoptedRequestLog is that when * requests are removed from the log the cache is automatically updated * accordingly. * * The data structure of the cache is optimized for quick lookup of entries * by the state vector and cleaning up entries in an efficient manner also * when the cache has grown very big. * * The request cache is mainly used by #InfAdoptedAlgorithm to efficiently * handle big transformations. * * This function adds a request to the cache of the request log. * @request must be a translated version of a request existing in @log. */ void inf_adopted_request_log_add_cached_request(InfAdoptedRequestLog* log, InfAdoptedRequest* request) { InfAdoptedRequestLogPrivate* priv; InfAdoptedStateVector* vector; g_return_if_fail(INF_ADOPTED_IS_REQUEST_LOG(log)); g_return_if_fail(INF_ADOPTED_IS_REQUEST(request)); priv = INF_ADOPTED_REQUEST_LOG_PRIVATE(log); g_return_if_fail(inf_adopted_request_get_user_id(request) == priv->user_id); vector = inf_adopted_request_get_vector(request); if(priv->cache == NULL) { priv->cache = g_tree_new_full( inf_adopted_request_log_cache_key_cmp, log, NULL, g_object_unref ); } g_return_if_fail(g_tree_lookup(priv->cache, vector) == NULL); g_tree_insert(priv->cache, vector, request); g_object_ref(request); /* Implement lookup_cached_request */ /* Use this implementation in InfAdoptedAlgorithm */ /* Make the performance tests */ } /** * inf_adopted_request_log_lookup_cached_request: * @log: A #InfAdoptedRequestLog. * @vec: The state vector at which to look up the request. * * Looks up the request at @vec from the cache of the request log. If the * queried request does not exist in the cache, the function returns %NULL. * * See inf_adopted_request_log_add_cached_request() for an explanation of * the request cache. * * Returns: (transfer none) (allow-none): The cached #InfAdoptedRequest * according to @vec, or %NULL. */ InfAdoptedRequest* inf_adopted_request_log_lookup_cached_request(InfAdoptedRequestLog* log, InfAdoptedStateVector* vec) { InfAdoptedRequestLogPrivate* priv; g_return_val_if_fail(INF_ADOPTED_IS_REQUEST_LOG(log), NULL); g_return_val_if_fail(vec != NULL, NULL); priv = INF_ADOPTED_REQUEST_LOG_PRIVATE(log); if(priv->cache == NULL) return NULL; return INF_ADOPTED_REQUEST(g_tree_lookup(priv->cache, vec)); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/adopted/PaxHeaders.26529/inf-adopted-no-operation.h0000644000000000000000000000013213034342512024513 xustar0030 mtime=1483851082.021718383 30 atime=1483851082.021718383 30 ctime=1488261588.908139266 libinfinity-0.7.1/libinfinity/adopted/inf-adopted-no-operation.h0000644000175000017500000000470413034342512025252 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_ADOPTED_NO_OPERATION_H__ #define __INF_ADOPTED_NO_OPERATION_H__ #include G_BEGIN_DECLS #define INF_ADOPTED_TYPE_NO_OPERATION (inf_adopted_no_operation_get_type()) #define INF_ADOPTED_NO_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_ADOPTED_TYPE_NO_OPERATION, InfAdoptedNoOperation)) #define INF_ADOPTED_NO_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INF_ADOPTED_TYPE_NO_OPERATION, InfAdoptedNoOperationClass)) #define INF_ADOPTED_IS_NO_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_ADOPTED_TYPE_NO_OPERATION)) #define INF_ADOPTED_IS_NO_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INF_ADOPTED_TYPE_NO_OPERATION)) #define INF_ADOPTED_NO_OPERATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INF_ADOPTED_TYPE_NO_OPERATION, InfAdoptedNoOperationClass)) typedef struct _InfAdoptedNoOperation InfAdoptedNoOperation; typedef struct _InfAdoptedNoOperationClass InfAdoptedNoOperationClass; /** * InfAdoptedNoOperationClass: * * This structure does not contain any public fields. */ struct _InfAdoptedNoOperationClass { /*< private >*/ GObjectClass parent_class; }; /** * InfAdoptedNoOperation: * * #InfAdoptedNoOperation is an opaque data type. You should only access it * via the public API functions. */ struct _InfAdoptedNoOperation { /*< private >*/ GObject parent; }; GType inf_adopted_no_operation_get_type(void) G_GNUC_CONST; InfAdoptedNoOperation* inf_adopted_no_operation_new(void); G_END_DECLS #endif /* __INF_ADOPTED_NO_OPERATION_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/adopted/PaxHeaders.26529/inf-adopted-undo-grouping.c0000644000000000000000000000013213034342512024671 xustar0030 mtime=1483851082.025718404 30 atime=1483851082.025718404 30 ctime=1488261589.032138995 libinfinity-0.7.1/libinfinity/adopted/inf-adopted-undo-grouping.c0000644000175000017500000006501313034342512025430 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include /** * SECTION:inf-adopted-undo-grouping * @title: InfAdoptedUndoGrouping * @short_description: Grouping of requests to be undone simultaneously * @include: libinfinity/adopted/inf-adopted-undo-grouping.h * @see_also: #InfAdoptedAlgorithm * @stability: Unstable * * #InfAdoptedUndoGrouping groups related requests together so that they can * be undone at the same time. For example, Undo in a text editor is normally * expected to operate on written words, not characters. Therefore, multiple * requests need to be undone at once. * * The undo grouping helps with this. Everytime it needs to decide whether two * requests should be grouped it emits * #InfAdoptedUndoGrouping::group-requests. If the signal handler returns * %TRUE then the two requests will be undone at the same time, otherwise not. * * It is also possible to explicitely group a bunch of requests that would * not be grouped otherwise, by calling inf_adopted_undo_grouping_start_group() * and inf_adopted_undo_grouping_end_group() before and after issuing the * requests, respectively. * * The default signal handler always returns %FALSE. However, this behaviour * can be changed in derived classes. */ typedef struct _InfAdoptedUndoGroupingItem InfAdoptedUndoGroupingItem; struct _InfAdoptedUndoGroupingItem { InfAdoptedRequest* request; gboolean in_group; }; typedef enum __InfAdoptedUndoGroupingFlags { /* allow grouping with items before explicit group */ INF_ADOPTED_UNDO_GROUPING_ALLOW_WITH_PREV = 1 << 0, /* allow grouping with items after explicit group */ INF_ADOPTED_UNDO_GROUPING_ALLOW_WITH_NEXT = 1 << 1, /* whether the next item is the first item inside an explicit group */ INF_ADOPTED_UNDO_GROUPING_FIRST_IN_GROUP = 1 << 2, /* whether the next item is the first item after an explicit group */ INF_ADOPTED_UNDO_GROUPING_FIRST_AFTER_GROUP = 1 << 3 } InfAdoptedUndoGroupingFlags; typedef struct _InfAdoptedUndoGroupingPrivate InfAdoptedUndoGroupingPrivate; struct _InfAdoptedUndoGroupingPrivate { InfAdoptedAlgorithm* algorithm; InfAdoptedUser* user; InfAdoptedUndoGroupingItem* items; guint n_items; guint n_alloc; guint first_item; guint item_pos; /* relative to first_item */ guint group_ref; guint group_flags; }; enum { PROP_0, /* construct only */ PROP_ALGORITHM, PROP_USER }; enum { GROUP_REQUESTS, LAST_SIGNAL }; #define INF_ADOPTED_UNDO_GROUPING_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INF_ADOPTED_TYPE_UNDO_GROUPING, InfAdoptedUndoGroupingPrivate)) static guint undo_grouping_signals[LAST_SIGNAL]; G_DEFINE_TYPE_WITH_CODE(InfAdoptedUndoGrouping, inf_adopted_undo_grouping, G_TYPE_OBJECT, G_ADD_PRIVATE(InfAdoptedUndoGrouping)) static void inf_adopted_undo_grouping_add_request(InfAdoptedUndoGrouping* grouping, InfAdoptedRequest* request) { InfAdoptedUndoGroupingPrivate* priv; guint max; InfAdoptedUndoGroupingItem* item; InfAdoptedUndoGroupingItem* prev_item; InfAdoptedUndoGroupingFlags flags; gboolean first_after_group; gboolean first_in_group; gboolean allow_with_next; gboolean allow_with_prev; priv = INF_ADOPTED_UNDO_GROUPING_PRIVATE(grouping); switch(inf_adopted_request_get_request_type(request)) { case INF_ADOPTED_REQUEST_DO: if(priv->first_item + priv->item_pos == priv->n_alloc) { /* The maximum number of requests that we ever need to hold is half of * the algorithm's max total log size, since undoing one of the requests * in the log takes another request. We add +1 because we add the new * request before removing the old one. */ g_object_get( G_OBJECT(priv->algorithm), "max-total-log-size", &max, NULL ); if(max != G_MAXUINT) { max = (max/2) + 1; /* Don't start to wrap around as long as we have not reached the max * buffer size. */ if(priv->n_alloc < max) { priv->n_alloc = MIN(priv->n_alloc * 2, max); priv->n_alloc = MAX(priv->n_alloc, MIN(16, max)); priv->items = g_realloc( priv->items, priv->n_alloc * sizeof(InfAdoptedUndoGroupingItem) ); } } else { priv->n_alloc = MAX(priv->n_alloc * 2, 16); priv->items = g_realloc( priv->items, priv->n_alloc * sizeof(InfAdoptedUndoGroupingItem) ); } } /* Cut redo possibilities */ priv->n_items = priv->item_pos; g_assert(priv->n_items < priv->n_alloc); item = &priv->items[(priv->first_item + priv->item_pos) % priv->n_alloc]; item->request = request; g_object_ref(request); if(priv->item_pos > 0) { flags = priv->group_flags; first_after_group = (flags & INF_ADOPTED_UNDO_GROUPING_FIRST_AFTER_GROUP) != 0; first_in_group = (flags & INF_ADOPTED_UNDO_GROUPING_FIRST_IN_GROUP) != 0; allow_with_next = (flags & INF_ADOPTED_UNDO_GROUPING_ALLOW_WITH_NEXT) != 0; allow_with_prev = (flags & INF_ADOPTED_UNDO_GROUPING_ALLOW_WITH_PREV) != 0; if(first_after_group && !allow_with_next) { item->in_group = FALSE; } else if(priv->group_ref > 0 && first_in_group && !allow_with_prev) { item->in_group = FALSE; } else if(priv->group_ref > 0 && !first_in_group) { item->in_group = TRUE; } else { prev_item = &priv->items[ (priv->first_item + priv->item_pos - 1) % priv->n_alloc ]; g_signal_emit( G_OBJECT(grouping), undo_grouping_signals[GROUP_REQUESTS], 0, prev_item->request, request, &item->in_group ); } } else { /* No previous request, so start group */ item->in_group = FALSE; } priv->group_flags &= ~(INF_ADOPTED_UNDO_GROUPING_FIRST_IN_GROUP | INF_ADOPTED_UNDO_GROUPING_FIRST_AFTER_GROUP); ++priv->n_items; ++priv->item_pos; break; case INF_ADOPTED_REQUEST_UNDO: g_assert(priv->item_pos > 0); --priv->item_pos; break; case INF_ADOPTED_REQUEST_REDO: g_assert(priv->item_pos < priv->n_items); ++priv->item_pos; break; } } /* Remove requests that can no longer be undone from buffer */ static void inf_adopted_undo_grouping_cleanup(InfAdoptedUndoGrouping* grouping) { InfAdoptedUndoGroupingPrivate* priv; InfAdoptedUndoGroupingItem* item; guint max_total_log_size; guint vdiff; guint i; priv = INF_ADOPTED_UNDO_GROUPING_PRIVATE(grouping); g_assert(priv->user != NULL); g_object_get( priv->algorithm, "max-total-log-size", &max_total_log_size, NULL ); if(max_total_log_size != G_MAXUINT) { while(priv->n_items > 0) { item = &priv->items[priv->first_item]; vdiff = inf_adopted_state_vector_vdiff( inf_adopted_request_get_vector(item->request), inf_adopted_user_get_vector(priv->user) ); if(vdiff + priv->item_pos > max_total_log_size) { /* Request is too old to be undone, remove from buffer */ if(priv->item_pos == 0) { /* Remove all items since we cannot redo the following anymore at * this point since the first one to redo is too old. */ for(i = 0; i < priv->n_items; ++i) g_object_unref(priv->items[(priv->first_item + i) % priv->n_alloc].request); priv->first_item = 0; priv->n_items = 0; break; } else { g_object_unref(item->request); /* Remove the request being too old */ priv->first_item = (priv->first_item + 1) % priv->n_alloc; --priv->n_items; --priv->item_pos; /* Reuse buffer if we drop to zero */ if(priv->n_items == 0) priv->first_item = 0; else priv->items[priv->first_item].in_group = FALSE; } } else { /* All OK */ break; } } } } static void inf_adopted_undo_grouping_add_request_cb(InfAdoptedRequestLog* log, InfAdoptedRequest* request, gpointer user_data) { InfAdoptedUndoGrouping* grouping; grouping = INF_ADOPTED_UNDO_GROUPING(user_data); inf_adopted_undo_grouping_add_request(grouping, request); } static void inf_adopted_undo_grouping_end_execute_request_cb(InfAdoptedAlgorithm* algo, InfAdoptedUser* user, InfAdoptedRequest* request, InfAdoptedRequest* trans, const GError* error, gpointer user_data) { InfAdoptedUndoGrouping* grouping; InfAdoptedUndoGroupingPrivate* priv; guint user_id; /* Note that this signal handler is called _after_ the request has been * executed and the buffer and local user vector times updated. If the * execution causes requests in the request log to be removed due to * algorithm cleanup, then this will still happen after the signal emission * though, so all requests in our buffers are still valid at this point. */ grouping = INF_ADOPTED_UNDO_GROUPING(user_data); priv = INF_ADOPTED_UNDO_GROUPING_PRIVATE(grouping); /* If the request does not affect the buffer then it did not increase the * state vector, in which case we don't need to check again here. */ if(priv->user != NULL) { user_id = inf_user_get_id(INF_USER(priv->user)); /* We need to do cleanup if our user issued this request, even if the * request does not affect the buffer, since it raises that user's * vector time, and thus might cause requests in its request log to be * dropped. */ if(inf_adopted_request_affects_buffer(request) || inf_adopted_request_get_user_id(request) == user_id) { inf_adopted_undo_grouping_cleanup(grouping); } } } static void inf_adopted_undo_grouping_init_user(InfAdoptedUndoGrouping* grouping) { InfAdoptedUndoGroupingPrivate* priv; InfAdoptedRequestLog* log; InfAdoptedRequest* request; guint max_total_log_size; guint end; guint i; priv = INF_ADOPTED_UNDO_GROUPING_PRIVATE(grouping); g_assert(priv->user != NULL); g_signal_connect( G_OBJECT(inf_adopted_user_get_request_log(priv->user)), "add-request", G_CALLBACK(inf_adopted_undo_grouping_add_request_cb), grouping ); g_object_get( priv->algorithm, "max-total-log-size", &max_total_log_size, NULL ); /* Add initial requests from request log */ log = inf_adopted_user_get_request_log(priv->user); end = inf_adopted_request_log_get_end(log); for(i = inf_adopted_request_log_get_begin(log); i < end; ++i) { request = inf_adopted_request_log_get_request(log, i); inf_adopted_undo_grouping_add_request(grouping, request); /* TODO: Instead of cleaning up requests that we have added just before, * we may find out which ones will not end up in the buffer anyway because * they cannot be undone anymore. This would require * inf_adopted_algorithm_can_undo_redo() to work for requests that are * anywhere in the log and to be public. */ inf_adopted_undo_grouping_cleanup(grouping); } } static void inf_adopted_undo_grouping_deinit_user(InfAdoptedUndoGrouping* grouping) { InfAdoptedUndoGroupingPrivate* priv; InfAdoptedRequest* request; guint i; priv = INF_ADOPTED_UNDO_GROUPING_PRIVATE(grouping); g_assert(priv->user != NULL); inf_signal_handlers_disconnect_by_func( G_OBJECT(inf_adopted_user_get_request_log(priv->user)), G_CALLBACK(inf_adopted_undo_grouping_add_request_cb), grouping ); g_object_unref(priv->user); priv->user = NULL; for(i = 0; i < priv->n_items; ++i) { request = priv->items[(priv->first_item + i) % priv->n_alloc].request; g_object_unref(request); } g_free(priv->items); priv->items = NULL; priv->n_items = 0; priv->n_alloc = 0; priv->first_item = 0; priv->item_pos = 0; g_object_notify(G_OBJECT(grouping), "user"); } static void inf_adopted_undo_grouping_init(InfAdoptedUndoGrouping* grouping) { InfAdoptedUndoGroupingPrivate* priv; priv = INF_ADOPTED_UNDO_GROUPING_PRIVATE(grouping); priv->algorithm = NULL; priv->user = NULL; priv->items = NULL; priv->n_items = 0; priv->n_alloc = 0; priv->first_item = 0; priv->item_pos = 0; priv->group_ref = 0; priv->group_flags = 0; } static void inf_adopted_undo_grouping_dispose(GObject* object) { InfAdoptedUndoGrouping* grouping; InfAdoptedUndoGroupingPrivate* priv; grouping = INF_ADOPTED_UNDO_GROUPING(object); priv = INF_ADOPTED_UNDO_GROUPING_PRIVATE(grouping); inf_adopted_undo_grouping_set_algorithm(grouping, NULL, NULL); G_OBJECT_CLASS(inf_adopted_undo_grouping_parent_class)->dispose(object); } static void inf_adopted_undo_grouping_finalize(GObject* object) { InfAdoptedUndoGrouping* grouping; InfAdoptedUndoGroupingPrivate* priv; grouping = INF_ADOPTED_UNDO_GROUPING(object); priv = INF_ADOPTED_UNDO_GROUPING_PRIVATE(grouping); G_OBJECT_CLASS(inf_adopted_undo_grouping_parent_class)->finalize(object); } static void inf_adopted_undo_grouping_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfAdoptedUndoGrouping* grouping; InfAdoptedUndoGroupingPrivate* priv; grouping = INF_ADOPTED_UNDO_GROUPING(object); priv = INF_ADOPTED_UNDO_GROUPING_PRIVATE(grouping); switch(prop_id) { case PROP_ALGORITHM: inf_adopted_undo_grouping_set_algorithm( grouping, INF_ADOPTED_ALGORITHM(g_value_get_object(value)), NULL ); break; case PROP_USER: inf_adopted_undo_grouping_set_algorithm( grouping, priv->algorithm, INF_ADOPTED_USER(g_value_get_object(value)) ); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void inf_adopted_undo_grouping_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfAdoptedUndoGrouping* grouping; InfAdoptedUndoGroupingPrivate* priv; grouping = INF_ADOPTED_UNDO_GROUPING(object); priv = INF_ADOPTED_UNDO_GROUPING_PRIVATE(grouping); switch(prop_id) { case PROP_ALGORITHM: g_value_set_object(value, priv->algorithm); break; case PROP_USER: g_value_set_object(value, priv->user); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static gboolean inf_adopted_undo_grouping_group_requests(InfAdoptedUndoGrouping* grouping, InfAdoptedRequest* first, InfAdoptedRequest* second) { return FALSE; } static void inf_adopted_undo_grouping_class_init( InfAdoptedUndoGroupingClass* undo_grouping_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(undo_grouping_class); object_class->dispose = inf_adopted_undo_grouping_dispose; object_class->finalize = inf_adopted_undo_grouping_finalize; object_class->set_property = inf_adopted_undo_grouping_set_property; object_class->get_property = inf_adopted_undo_grouping_get_property; undo_grouping_class->group_requests = inf_adopted_undo_grouping_group_requests; g_object_class_install_property( object_class, PROP_ALGORITHM, g_param_spec_object( "algorithm", "Algorithm", "The algorithm for which to group requests", INF_ADOPTED_TYPE_ALGORITHM, G_PARAM_READWRITE ) ); g_object_class_install_property( object_class, PROP_USER, g_param_spec_object( "user", "User", "The user for which to group requests", INF_ADOPTED_TYPE_USER, G_PARAM_READWRITE ) ); /** * InfAdoptedUndoGrouping::group-requests: * @grouping: The #InfAdoptedUndoGrouping which is about to group a request. * @first: The previous request. * @second: The current request. * * This signal is emitted whenever the #InfAdoptedUndoGrouping needs to * decide whether to put two requests into the same undo group or not. * A signal handler should return %TRUE if they belong into the same group * or %FALSE otherwise. Note however that the two requests may not * immediately follow each other because other users may have issued * requests inbetween. Check the vector times of the requests to find out, * using inf_adopted_request_get_vector(). */ undo_grouping_signals[GROUP_REQUESTS] = g_signal_new( "group-requests", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfAdoptedUndoGroupingClass, group_requests), g_signal_accumulator_true_handled, NULL, NULL, G_TYPE_BOOLEAN, 2, INF_ADOPTED_TYPE_REQUEST, INF_ADOPTED_TYPE_REQUEST ); } /** * inf_adopted_undo_grouping_new: (constructor) * * Creates a new #InfAdoptedUndoGrouping. To start grouping requests, set a * user whose requests to group via inf_adopted_undo_grouping_set_algorithm(). * Before doing so you might want to connect to * #InfAdoptedUndoGrouping::group-requests, so the user's initial requests can * be grouped correctly. * * Returns: (transfer full): A new #InfAdoptedUndoGrouping, to be freed * via g_object_unref(). */ InfAdoptedUndoGrouping* inf_adopted_undo_grouping_new(void) { GObject* object; object = g_object_new(INF_ADOPTED_TYPE_UNDO_GROUPING, NULL); return INF_ADOPTED_UNDO_GROUPING(object); } /** * inf_adopted_undo_grouping_get_algorithm: * @grouping: A #InfAdoptedUndoGrouping. * * Returns the #InfAdoptedAlgorithm for @grouping. * * Returns: (transfer none): @grouping's algorithm. */ InfAdoptedAlgorithm* inf_adopted_undo_grouping_get_algorithm(InfAdoptedUndoGrouping* grouping) { g_return_val_if_fail(INF_ADOPTED_IS_UNDO_GROUPING(grouping), NULL); return INF_ADOPTED_UNDO_GROUPING_PRIVATE(grouping)->algorithm; } /** * inf_adopted_undo_grouping_set_algorithm: * @grouping: A #InfAdoptedUndoGrouping. * @algorithm: The #InfAdoptedAlgorithm for the document to group requests, * or %NULL. * @user: The user for which to group requests, or %NULL. Ignored if * @algorithm is %NULL. * * Sets the algorithm and user to group requests for. This function will group * all requests in user's request log, and also each new request that is * added to it's log. Requests that cannot be undone anymore (because * they are too old), will be correctly taken care off. */ void inf_adopted_undo_grouping_set_algorithm(InfAdoptedUndoGrouping* grouping, InfAdoptedAlgorithm* algorithm, InfAdoptedUser* user) { InfAdoptedUndoGroupingPrivate* priv; g_return_if_fail(INF_ADOPTED_IS_UNDO_GROUPING(grouping)); g_return_if_fail(algorithm == NULL || INF_ADOPTED_IS_ALGORITHM(algorithm)); g_return_if_fail(user == NULL || INF_ADOPTED_IS_USER(user)); priv = INF_ADOPTED_UNDO_GROUPING_PRIVATE(grouping); g_object_freeze_notify(G_OBJECT(grouping)); if(priv->algorithm != algorithm) { if(priv->algorithm != NULL) { inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->algorithm), G_CALLBACK(inf_adopted_undo_grouping_end_execute_request_cb), grouping ); /* The user belonged to the old algorithm */ if(priv->user != NULL) inf_adopted_undo_grouping_deinit_user(grouping); g_object_unref(priv->algorithm); priv->algorithm = NULL; } priv->algorithm = algorithm; if(algorithm != NULL) { g_object_ref(algorithm); g_signal_connect( G_OBJECT(priv->algorithm), "end-execute-request", G_CALLBACK(inf_adopted_undo_grouping_end_execute_request_cb), grouping ); } g_object_notify(G_OBJECT(grouping), "algorithm"); } if(priv->user != user) { if(priv->user != NULL) inf_adopted_undo_grouping_deinit_user(grouping); priv->user = user; if(user != NULL) { g_object_ref(user); inf_adopted_undo_grouping_init_user(grouping); } g_object_notify(G_OBJECT(grouping), "user"); } g_object_thaw_notify(G_OBJECT(grouping)); } /** * inf_adopted_undo_grouping_start_group: * @grouping: A #InfAdoptedUndoGrouping. * @allow_group_with_prev: Whether the new group can be part of the previous * group if #InfAdoptedUndoGrouping::group-requests allows. * * Makes all requests issued after this call belong into the same group, * i.e. they will be undone at once. This can make sense for example when the * user copy+pastes something into the document which causes multiple requests * to be generated. A call to inf_adopted_undo_grouping_end_group() restores * the normal behavior. */ void inf_adopted_undo_grouping_start_group(InfAdoptedUndoGrouping* grouping, gboolean allow_group_with_prev) { InfAdoptedUndoGroupingPrivate* priv; g_return_if_fail(INF_ADOPTED_IS_UNDO_GROUPING(grouping)); priv = INF_ADOPTED_UNDO_GROUPING_PRIVATE(grouping); g_return_if_fail(priv->algorithm != NULL); g_return_if_fail(priv->user != NULL); if(priv->group_ref++ == 0) { priv->group_flags = INF_ADOPTED_UNDO_GROUPING_FIRST_IN_GROUP; if(allow_group_with_prev) priv->group_flags |= INF_ADOPTED_UNDO_GROUPING_ALLOW_WITH_PREV; } } /** * inf_adopted_undo_grouping_end_group: * @grouping: A #InfAdoptedUndoGrouping. * @allow_group_with_next: Whether subsequent requests are allow to be part of * this group if #InfAdoptedUndoGrouping::group-requests allows. * * When inf_adopted_undo_grouping_start_group() was called before, then this * function restores the normal behaviour of grouping requests. */ void inf_adopted_undo_grouping_end_group(InfAdoptedUndoGrouping* grouping, gboolean allow_group_with_next) { InfAdoptedUndoGroupingPrivate* priv; g_return_if_fail(INF_ADOPTED_IS_UNDO_GROUPING(grouping)); priv = INF_ADOPTED_UNDO_GROUPING_PRIVATE(grouping); g_return_if_fail(priv->algorithm != NULL); g_return_if_fail(priv->user != NULL); g_return_if_fail(priv->group_ref > 0); if(--priv->group_ref == 0) { priv->group_flags = INF_ADOPTED_UNDO_GROUPING_FIRST_AFTER_GROUP; if(allow_group_with_next) priv->group_flags |= INF_ADOPTED_UNDO_GROUPING_ALLOW_WITH_NEXT; } } /** * inf_adopted_undo_grouping_get_undo_size: * @grouping: A #InfAdoptedUndoGrouping. * * Returns the number of requests to undo so that a whole group is being * undone. This takes into account that possibly not the whole group cannot * be undone due to the #InfAdoptedAlgorithm:max-total-log-size constraint. * * Returns: The number of requests in the current undo group. */ guint inf_adopted_undo_grouping_get_undo_size(InfAdoptedUndoGrouping* grouping) { InfAdoptedUndoGroupingPrivate* priv; guint max_total_log_size; InfAdoptedRequestLog* log; InfAdoptedStateVector* current; guint pos; guint index; InfAdoptedRequest* lower_related; InfAdoptedStateVector* vector; guint vdiff; g_return_val_if_fail(INF_ADOPTED_IS_UNDO_GROUPING(grouping), 0); priv = INF_ADOPTED_UNDO_GROUPING_PRIVATE(grouping); if(priv->item_pos == 0) return 0; g_object_get( G_OBJECT(priv->algorithm), "max-total-log-size", &max_total_log_size, NULL ); log = inf_adopted_user_get_request_log(priv->user); current = inf_adopted_user_get_vector(priv->user); pos = priv->item_pos; do { g_assert(pos > 0); index = inf_adopted_request_get_index(priv->items[pos-1].request); lower_related = inf_adopted_request_log_lower_related(log, index); vector = inf_adopted_request_get_vector(lower_related); vdiff = inf_adopted_state_vector_vdiff(vector, current); if(vdiff + priv->item_pos - pos >= max_total_log_size) return priv->item_pos - pos; --pos; } while(priv->items[(priv->first_item + pos) % priv->n_alloc].in_group); return priv->item_pos - pos; } /** * inf_adopted_undo_grouping_get_redo_size: * @grouping: A #InfAdoptedUndoGrouping. * * Returns the number of requests to redo so that a whole group is being * redone. This takes into account that possibly not the whole group cannot * be undone due to the #InfAdoptedAlgorithm:max-total-log-size constraint. * * Returns: The number of requests in the current redo group. */ guint inf_adopted_undo_grouping_get_redo_size(InfAdoptedUndoGrouping* grouping) { InfAdoptedUndoGroupingPrivate* priv; guint max_total_log_size; InfAdoptedRequestLog* log; InfAdoptedStateVector* current; guint pos; guint index; InfAdoptedRequest* lower_related; InfAdoptedStateVector* vector; guint vdiff; g_return_val_if_fail(INF_ADOPTED_IS_UNDO_GROUPING(grouping), 0); priv = INF_ADOPTED_UNDO_GROUPING_PRIVATE(grouping); if(priv->item_pos == priv->n_items) return 0; g_object_get( G_OBJECT(priv->algorithm), "max-total-log-size", &max_total_log_size, NULL ); log = inf_adopted_user_get_request_log(priv->user); current = inf_adopted_user_get_vector(priv->user); pos = priv->item_pos; do { g_assert(pos < priv->n_items); index = inf_adopted_request_get_index(priv->items[pos].request); lower_related = inf_adopted_request_log_lower_related(log, index); vector = inf_adopted_request_get_vector(lower_related); vdiff = inf_adopted_state_vector_vdiff(vector, current); if(vdiff + pos - priv->item_pos >= max_total_log_size) return pos - priv->item_pos; ++pos; } while(pos < priv->n_items && priv->items[(priv->first_item + pos) % priv->n_alloc].in_group); return pos - priv->item_pos; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/adopted/PaxHeaders.26529/inf-adopted-state-vector.h0000644000000000000000000000013113034342512024520 xustar0030 mtime=1483851082.025718404 30 atime=1483851082.025718404 29 ctime=1488261588.92013924 libinfinity-0.7.1/libinfinity/adopted/inf-adopted-state-vector.h0000644000175000017500000001063713034342512025262 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_ADOPTED_STATE_VECTOR_H__ #define __INF_ADOPTED_STATE_VECTOR_H__ #include G_BEGIN_DECLS #define INF_ADOPTED_TYPE_STATE_VECTOR (inf_adopted_state_vector_get_type()) /** * InfAdoptedStateVector: * * #InfAdoptedStateVector is an opaque data type. You should only access it * via the public API functions. */ typedef struct _InfAdoptedStateVector InfAdoptedStateVector; /** * InfAdoptedStateVectorError: * @INF_ADOPTED_STATE_VECTOR_BAD_FORMAT: A string representation of an * #InfAdoptedStateVector as required by * inf_adopted_state_vector_from_string() or * inf_adopted_state_vector_from_string_diff() is invalid. * @INF_ADOPTED_STATE_VECTOR_FAILED: No further specified error code. * * Error codes for #InfAdoptedStateVector. */ typedef enum _InfAdoptedStateVectorError { INF_ADOPTED_STATE_VECTOR_BAD_FORMAT, INF_ADOPTED_STATE_VECTOR_FAILED } InfAdoptedStateVectorError; /** * InfAdoptedStateVectorForeachFunc: * @id: The ID of the entry. * @value: The value of the entry. * @user_data: The user data passed to inf_adopted_state_vector_foreach(). * * This function is called for every component in the state vector during * the invocation of inf_adopted_state_vector_foreach(). */ typedef void(*InfAdoptedStateVectorForeachFunc)(guint id, guint value, gpointer user_data); GType inf_adopted_state_vector_get_type(void) G_GNUC_CONST; GQuark inf_adopted_state_vector_error_quark(void); InfAdoptedStateVector* inf_adopted_state_vector_new(void); InfAdoptedStateVector* inf_adopted_state_vector_copy(InfAdoptedStateVector* vec); void inf_adopted_state_vector_free(InfAdoptedStateVector* vec); guint inf_adopted_state_vector_get(const InfAdoptedStateVector* vec, guint id); void inf_adopted_state_vector_set(InfAdoptedStateVector* vec, guint id, guint value); void inf_adopted_state_vector_add(InfAdoptedStateVector* vec, guint id, gint value); void inf_adopted_state_vector_foreach(const InfAdoptedStateVector* vec, InfAdoptedStateVectorForeachFunc func, gpointer user_data); int inf_adopted_state_vector_compare(const InfAdoptedStateVector* first, const InfAdoptedStateVector* second); gboolean inf_adopted_state_vector_causally_before(const InfAdoptedStateVector* first, const InfAdoptedStateVector* second); gboolean inf_adopted_state_vector_causally_before_inc( const InfAdoptedStateVector* first, const InfAdoptedStateVector* second, guint inc_component); guint inf_adopted_state_vector_vdiff(const InfAdoptedStateVector* first, const InfAdoptedStateVector* second); gchar* inf_adopted_state_vector_to_string(const InfAdoptedStateVector* vec); InfAdoptedStateVector* inf_adopted_state_vector_from_string(const gchar* str, GError** error); gchar* inf_adopted_state_vector_to_string_diff(const InfAdoptedStateVector* vec, const InfAdoptedStateVector* orig); InfAdoptedStateVector* inf_adopted_state_vector_from_string_diff(const gchar* str, const InfAdoptedStateVector* orig, GError** error); G_END_DECLS #endif /* __INF_ADOPTED_STATE_VECTOR_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/adopted/PaxHeaders.26529/inf-adopted-session-record.h0000644000000000000000000000013213034342512025040 xustar0030 mtime=1483851082.025718404 30 atime=1483851082.025718404 30 ctime=1488261588.912139258 libinfinity-0.7.1/libinfinity/adopted/inf-adopted-session-record.h0000644000175000017500000000600513034342512025573 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_ADOPTED_SESSION_RECORD_RECORD_H__ #define __INF_ADOPTED_SESSION_RECORD_RECORD_H__ #include #include G_BEGIN_DECLS #define INF_ADOPTED_TYPE_SESSION_RECORD (inf_adopted_session_record_get_type()) #define INF_ADOPTED_SESSION_RECORD(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_ADOPTED_TYPE_SESSION_RECORD, InfAdoptedSessionRecord)) #define INF_ADOPTED_SESSION_RECORD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INF_ADOPTED_TYPE_SESSION_RECORD, InfAdoptedSessionRecordClass)) #define INF_ADOPTED_IS_SESSION_RECORD(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_ADOPTED_TYPE_SESSION_RECORD)) #define INF_ADOPTED_IS_SESSION_RECORD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INF_ADOPTED_TYPE_SESSION_RECORD)) #define INF_ADOPTED_SESSION_RECORD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INF_ADOPTED_TYPE_SESSION_RECORD, InfAdoptedSessionRecordClass)) typedef struct _InfAdoptedSessionRecord InfAdoptedSessionRecord; typedef struct _InfAdoptedSessionRecordClass InfAdoptedSessionRecordClass; /** * InfAdoptedSessionRecordClass: * * This structure does not contain any public fields. */ struct _InfAdoptedSessionRecordClass { /*< private >*/ GObjectClass parent_class; }; /** * InfAdoptedSessionRecord: * * #InfAdoptedSessionRecord is an opaque data type. You should only access it * via the public API functions. */ struct _InfAdoptedSessionRecord { /*< private >*/ GObject parent; }; GType inf_adopted_session_record_get_type(void); InfAdoptedSessionRecord* inf_adopted_session_record_new(InfAdoptedSession* session); gboolean inf_adopted_session_record_start_recording(InfAdoptedSessionRecord* record, const gchar* filename, GError** error); gboolean inf_adopted_session_record_stop_recording(InfAdoptedSessionRecord* record, GError** error); gboolean inf_adopted_session_record_is_recording(InfAdoptedSessionRecord* record); G_END_DECLS #endif /* __INF_ADOPTED_SESSION_RECORD_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/adopted/PaxHeaders.26529/inf-adopted-session-replay.h0000644000000000000000000000013213034342512025056 xustar0030 mtime=1483851082.025718404 30 atime=1483851082.025718404 30 ctime=1488261588.916139249 libinfinity-0.7.1/libinfinity/adopted/inf-adopted-session-replay.h0000644000175000017500000001102413034342512025606 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_ADOPTED_SESSION_REPLAY_H__ #define __INF_ADOPTED_SESSION_REPLAY_H__ #include #include #include G_BEGIN_DECLS #define INF_ADOPTED_TYPE_SESSION_REPLAY (inf_adopted_session_replay_get_type()) #define INF_ADOPTED_SESSION_REPLAY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_ADOPTED_TYPE_SESSION_REPLAY, InfAdoptedSessionReplay)) #define INF_ADOPTED_SESSION_REPLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INF_ADOPTED_TYPE_SESSION_REPLAY, InfAdoptedSessionReplayClass)) #define INF_ADOPTED_IS_SESSION_REPLAY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_ADOPTED_TYPE_SESSION_REPLAY)) #define INF_ADOPTED_IS_SESSION_REPLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INF_ADOPTED_TYPE_SESSION_REPLAY)) #define INF_ADOPTED_SESSION_REPLAY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INF_ADOPTED_TYPE_SESSION_REPLAY, InfAdoptedSessionReplayClass)) typedef struct _InfAdoptedSessionReplay InfAdoptedSessionReplay; typedef struct _InfAdoptedSessionReplayClass InfAdoptedSessionReplayClass; /** * InfAdoptedSessionReplayError: * @INF_ADOPTED_SESSION_REPLAY_ERROR_BAD_FILE: The record file could not be * opened for reading. * @INF_ADOPTED_SESSION_REPLAY_ERROR_BAD_XML: The record file contains * invalid XML. * @INF_ADOPTED_SESSION_REPLAY_ERROR_BAD_DOCUMENT: The record file is not a * session recording. * @INF_ADOPTED_SESSION_REPLAY_ERROR_BAD_SESSION_TYPE: The record file is a * session recording for a different type of session than the one provided. * @INF_ADOPTED_SESSION_REPLAY_ERROR_BAD_FORMAT: The record file is invalid. * @INF_ADOPTED_SESSION_REPLAY_ERROR_UNEXPECTED_EOF: More data was expected * to be read from the record file, but the end of file was reached. * * Error codes for the INF_ADOPTED_SESSION_REPLAY_ERROR * error domain. These can occur while loading or replaying a session * with #InfAdoptedSessionReplay. */ typedef enum _InfAdoptedSessionReplayError { INF_ADOPTED_SESSION_REPLAY_ERROR_BAD_FILE, INF_ADOPTED_SESSION_REPLAY_ERROR_BAD_XML, INF_ADOPTED_SESSION_REPLAY_ERROR_BAD_DOCUMENT, INF_ADOPTED_SESSION_REPLAY_ERROR_BAD_SESSION_TYPE, INF_ADOPTED_SESSION_REPLAY_ERROR_BAD_FORMAT, INF_ADOPTED_SESSION_REPLAY_ERROR_UNEXPECTED_EOF } InfAdoptedSessionReplayError; /** * InfAdoptedSessionReplayClass: * * This structure does not contain any public fields. */ struct _InfAdoptedSessionReplayClass { /*< private >*/ GObjectClass parent_class; }; /** * InfAdoptedSessionReplay: * * #InfAdoptedSessionReplay is an opaque data type. You should only access it * via the public API functions. */ struct _InfAdoptedSessionReplay { /*< private >*/ GObject parent; }; GType inf_adopted_session_replay_get_type(void); InfAdoptedSessionReplay* inf_adopted_session_replay_new(void); /* TODO: Move InfcNotePlugin to common, as InfNotePlugin, and "derive" * InfdNotePlugin from it. */ gboolean inf_adopted_session_replay_set_record(InfAdoptedSessionReplay* replay, const gchar* filename, const InfcNotePlugin* plugin, GError** error); InfAdoptedSession* inf_adopted_session_replay_get_session(InfAdoptedSessionReplay* replay); gboolean inf_adopted_session_replay_play_next(InfAdoptedSessionReplay* replay, GError** error); gboolean inf_adopted_session_replay_play_to_end(InfAdoptedSessionReplay* replay, GError** error); G_END_DECLS #endif /* __INF_ADOPTED_SESSION_REPLAY_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/adopted/PaxHeaders.26529/inf-adopted-user.h0000644000000000000000000000013113034342512023056 xustar0030 mtime=1483851082.025718404 30 atime=1483851082.025718404 29 ctime=1488261588.92013924 libinfinity-0.7.1/libinfinity/adopted/inf-adopted-user.h0000644000175000017500000000545313034342512023620 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_ADOPTED_USER_H__ #define __INF_ADOPTED_USER_H__ #include #include #include #include G_BEGIN_DECLS #define INF_ADOPTED_TYPE_USER (inf_adopted_user_get_type()) #define INF_ADOPTED_USER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_ADOPTED_TYPE_USER, InfAdoptedUser)) #define INF_ADOPTED_USER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INF_ADOPTED_TYPE_USER, InfAdoptedUserClass)) #define INF_ADOPTED_IS_USER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_ADOPTED_TYPE_USER)) #define INF_ADOPTED_IS_USER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INF_ADOPTED_TYPE_USER)) #define INF_ADOPTED_USER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INF_ADOPTED_TYPE_USER, InfAdoptedUserClass)) /* Already declared in inf-adopted-operation.h to avoid * cyclic include chains */ /*typedef struct _InfAdoptedUser InfAdoptedUser;*/ typedef struct _InfAdoptedUserClass InfAdoptedUserClass; /** * InfAdoptedUserClass: * * This structure does not contain any public fields. */ struct _InfAdoptedUserClass { /*< private >*/ InfUserClass parent_class; }; /** * InfAdoptedUser: * * #InfAdoptedUser is an opaque data type. You should only access it * via the public API functions. */ struct _InfAdoptedUser { /*< private >*/ InfUser parent; gpointer priv; }; GType inf_adopted_user_get_type(void) G_GNUC_CONST; guint inf_adopted_user_get_component(InfAdoptedUser* user, guint id); InfAdoptedStateVector* inf_adopted_user_get_vector(InfAdoptedUser* user); void inf_adopted_user_set_vector(InfAdoptedUser* user, InfAdoptedStateVector* vec); InfAdoptedRequestLog* inf_adopted_user_get_request_log(InfAdoptedUser* user); G_END_DECLS #endif /* __INF_ADOPTED_USER_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/adopted/PaxHeaders.26529/inf-adopted-split-operation.h0000644000000000000000000000013213034342512025232 xustar0030 mtime=1483851082.025718404 30 atime=1483851082.025718404 30 ctime=1488261588.916139249 libinfinity-0.7.1/libinfinity/adopted/inf-adopted-split-operation.h0000644000175000017500000000617313034342512025773 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_ADOPTED_SPLIT_OPERATION_H__ #define __INF_ADOPTED_SPLIT_OPERATION_H__ #include #include G_BEGIN_DECLS #define INF_ADOPTED_TYPE_SPLIT_OPERATION (inf_adopted_split_operation_get_type()) #define INF_ADOPTED_SPLIT_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_ADOPTED_TYPE_SPLIT_OPERATION, InfAdoptedSplitOperation)) #define INF_ADOPTED_SPLIT_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INF_ADOPTED_TYPE_SPLIT_OPERATION, InfAdoptedSplitOperationClass)) #define INF_ADOPTED_IS_SPLIT_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_ADOPTED_TYPE_SPLIT_OPERATION)) #define INF_ADOPTED_IS_SPLIT_OPERATION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INF_ADOPTED_TYPE_SPLIT_OPERATION)) #define INF_ADOPTED_SPLIT_OPERATION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INF_ADOPTED_TYPE_SPLIT_OPERATION, InfAdoptedSplitOperationClass)) typedef struct _InfAdoptedSplitOperation InfAdoptedSplitOperation; typedef struct _InfAdoptedSplitOperationClass InfAdoptedSplitOperationClass; /** * InfAdoptedSplitOperationClass: * * This structure does not contain any public fields. */ struct _InfAdoptedSplitOperationClass { /*< private >*/ GObjectClass parent_class; }; /** * InfAdoptedSplitOperation: * * #InfAdoptedSplitOperation is an opaque data type. You should only access it * via the public API functions. */ struct _InfAdoptedSplitOperation { /*< private >*/ GObject parent; }; GType inf_adopted_split_operation_get_type(void) G_GNUC_CONST; InfAdoptedSplitOperation* inf_adopted_split_operation_new(InfAdoptedOperation* first, InfAdoptedOperation* second); GSList* inf_adopted_split_operation_unsplit(InfAdoptedSplitOperation* operation); InfAdoptedOperation* inf_adopted_split_operation_transform_other(InfAdoptedSplitOperation* op, InfAdoptedOperation* other, InfAdoptedOperation* op_lcs, InfAdoptedOperation* other_lcs, gint concurrency_id); G_END_DECLS #endif /* __INF_ADOPTED_SPLIT_OPERATION_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/adopted/PaxHeaders.26529/inf-adopted-no-operation.c0000644000000000000000000000013213034342512024506 xustar0030 mtime=1483851082.021718383 30 atime=1483851082.021718383 30 ctime=1488261589.020139022 libinfinity-0.7.1/libinfinity/adopted/inf-adopted-no-operation.c0000644000175000017500000001070713034342512025245 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include /** * SECTION:inf-adopted-no-operation * @title: InfAdoptedNoOperation * @short_description: An operation not doing anything. * @include: libinfinity/adopted/inf-adopted-no-operation.h * @stability: Unstable * @see_also: #InfAdoptedOperation * * #InfAdoptedNoOperation is an operation that does nothing when applied to * the buffer. This might be the result of an operation transformation, for * example if a request is received that is supposed to delete text that was * already deleted by the local site. It is also used by #InfAdoptedSession to * send the current state to other users in case the user being idle, so that * others keep knowing the current state of that user (this is especially * required for cleanup of request logs and caches). **/ static GObjectClass* parent_class; static void inf_adopted_no_operation_operation_iface_init(InfAdoptedOperationInterface* iface); G_DEFINE_TYPE_WITH_CODE(InfAdoptedNoOperation, inf_adopted_no_operation, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE(INF_ADOPTED_TYPE_OPERATION, inf_adopted_no_operation_operation_iface_init)) static void inf_adopted_no_operation_init(InfAdoptedNoOperation* operation) { } static void inf_adopted_no_operation_class_init( InfAdoptedNoOperationClass* operation_class) { } static gboolean inf_adopted_no_operation_need_concurrency_id(InfAdoptedOperation* operation, InfAdoptedOperation* against) { return FALSE; } static InfAdoptedOperation* inf_adopted_no_operation_transform(InfAdoptedOperation* operation, InfAdoptedOperation* against, InfAdoptedOperation* operation_lcs, InfAdoptedOperation* against_lcs, gint concurrency_id) { return INF_ADOPTED_OPERATION(inf_adopted_no_operation_new()); } static InfAdoptedOperation* inf_adopted_no_operation_copy(InfAdoptedOperation* operation) { return INF_ADOPTED_OPERATION(inf_adopted_no_operation_new()); } static InfAdoptedOperationFlags inf_adopted_no_operation_get_flags(InfAdoptedOperation* operation) { return INF_ADOPTED_OPERATION_REVERSIBLE; } static gboolean inf_adopted_no_operation_apply(InfAdoptedOperation* operation, InfAdoptedUser* by, InfBuffer* buffer, GError** error) { /* Does nothing */ return TRUE; } static InfAdoptedOperation* inf_adopted_no_operation_revert(InfAdoptedOperation* operation) { return INF_ADOPTED_OPERATION(inf_adopted_no_operation_new()); } static void inf_adopted_no_operation_operation_iface_init( InfAdoptedOperationInterface* iface) { iface->need_concurrency_id = inf_adopted_no_operation_need_concurrency_id; iface->transform = inf_adopted_no_operation_transform; iface->copy = inf_adopted_no_operation_copy; iface->get_flags = inf_adopted_no_operation_get_flags; iface->apply = inf_adopted_no_operation_apply; iface->apply_transformed = NULL; iface->revert = inf_adopted_no_operation_revert; } /** * inf_adopted_no_operation_new: (constructor) * * Creates a new #InfAdoptedNoOperation. A no operation is an operation * that does nothing, but might be the result of a transformation. * * Returns: (transfer full): A new #InfAdoptedNoOperation. **/ InfAdoptedNoOperation* inf_adopted_no_operation_new(void) { GObject* object; object = g_object_new(INF_ADOPTED_TYPE_NO_OPERATION, NULL); return INF_ADOPTED_NO_OPERATION(object); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/adopted/PaxHeaders.26529/inf-adopted-operation.h0000644000000000000000000000013213034342512024101 xustar0030 mtime=1483851082.025718404 30 atime=1483851082.025718404 30 ctime=1488261588.908139266 libinfinity-0.7.1/libinfinity/adopted/inf-adopted-operation.h0000644000175000017500000001724713034342512024646 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_ADOPTED_OPERATION_H__ #define __INF_ADOPTED_OPERATION_H__ /* We cannot include inf-adopted-user.h because inf-adopted-user.h includes * us via inf-adopted-request-log.h via inf-adopted-request.h */ /*#include */ typedef struct _InfAdoptedUser InfAdoptedUser; #include #include G_BEGIN_DECLS #define INF_ADOPTED_TYPE_OPERATION (inf_adopted_operation_get_type()) #define INF_ADOPTED_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_ADOPTED_TYPE_OPERATION, InfAdoptedOperation)) #define INF_ADOPTED_IS_OPERATION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_ADOPTED_TYPE_OPERATION)) #define INF_ADOPTED_OPERATION_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), INF_ADOPTED_TYPE_OPERATION, InfAdoptedOperationInterface)) #define INF_ADOPTED_TYPE_OPERATION_FLAGS (inf_adopted_operation_flags_get_type()) typedef struct _InfAdoptedOperation InfAdoptedOperation; typedef struct _InfAdoptedOperationInterface InfAdoptedOperationInterface; /** * InfAdoptedConcurrencyId: * @INF_ADOPTED_CONCURRENCY_SELF: Transform the operation itself. * @INF_ADOPTED_CONCURRENCY_NONE: Unspecified which operation to transform. * @INF_ADOPTED_CONCURRENCY_OTHER: Transform the other operation. * * A concurrency ID is used to determine which operation to transform in case * two similar operations are transformed against each other. */ typedef enum _InfAdoptedConcurrencyId { INF_ADOPTED_CONCURRENCY_SELF = 1, INF_ADOPTED_CONCURRENCY_NONE = 0, INF_ADOPTED_CONCURRENCY_OTHER = -1 } InfAdoptedConcurrencyId; /** * InfAdoptedOperationFlags: * @INF_ADOPTED_OPERATION_AFFECTS_BUFFER: The operation changes the content of * the buffer. * @INF_ADOPTED_OPERATION_REVERSIBLE: The operation is reversible, which means * that inf_adopted_operation_revert() can be called to generate an operation * that undoes the effect of the operation. * * Various flags for #InfAdoptedOperation. */ typedef enum _InfAdoptedOperationFlags { INF_ADOPTED_OPERATION_AFFECTS_BUFFER = 1 << 0, INF_ADOPTED_OPERATION_REVERSIBLE = 1 << 1 } InfAdoptedOperationFlags; /** * InfAdoptedOperationInterface: * @need_concurrency_id: Virtual function to determine whether a concurrency * ID is required to transform @operation against @against. * @transform: Virtual function that transform @operation against @against and * returns a new #InfAdoptedOperation as the result of the transformation. * @concurrency_id is either 1 or -1 and can be used to make a decision in * case there is no other criteria to decide how to do the transformation, for * example when both @operation and @against are inserting text at the same * position in the buffer. * @copy: Virtual function that returns a copy of the operation. * @get_flags: Virtual function that returns the flags of the operation, * see #InfAdoptedOperationFlags. * @apply: Virtual function that applies the operation to the buffer. @by is * the user that applies the operation. * @apply_transformed: Virtual function that applies a transformed version * of the operation to the buffer. It attempts to use information from the * buffer to make the original operation reversible, if it is not already. * The implementation of this function is optional, and only needs to be * implemented if the operation is not reversible but can be made reversible * with additional information from the buffer or the transformed operation. * @revert: Virtual function that creates a new operation that undoes the * effect of the operation. If @get_flags does never return the * %INF_ADOPTED_OPERATION_REVERSIBLE flag set, then this is allowed to be * %NULL. * * The virtual methods that need to be implemented by an operation to be used * with #InfAdoptedAlgorithm. */ struct _InfAdoptedOperationInterface { /*< private >*/ GTypeInterface parent; /*< public >*/ gboolean (*need_concurrency_id)(InfAdoptedOperation* operation, InfAdoptedOperation* against); InfAdoptedOperation* (*transform)(InfAdoptedOperation* operation, InfAdoptedOperation* against, InfAdoptedOperation* operation_lcs, InfAdoptedOperation* against_lcs, InfAdoptedConcurrencyId concurrency_id); InfAdoptedOperation* (*copy)(InfAdoptedOperation* operation); InfAdoptedOperationFlags (*get_flags)(InfAdoptedOperation* operation); gboolean (*apply)(InfAdoptedOperation* operation, InfAdoptedUser* by, InfBuffer* buffer, GError** error); InfAdoptedOperation* (*apply_transformed)(InfAdoptedOperation* operation, InfAdoptedOperation* transformed, InfAdoptedUser* by, InfBuffer* buffer, GError** error); InfAdoptedOperation* (*revert)(InfAdoptedOperation* operation); }; /** * InfAdoptedOperation: * * #InfAdoptedOperation is an opaque data type. You should only access it * via the public API functions. */ GType inf_adopted_concurrency_id_get_type(void) G_GNUC_CONST; GType inf_adopted_operation_flags_get_type(void) G_GNUC_CONST; GType inf_adopted_operation_get_type(void) G_GNUC_CONST; gboolean inf_adopted_operation_need_concurrency_id(InfAdoptedOperation* operation, InfAdoptedOperation* against); InfAdoptedOperation* inf_adopted_operation_transform(InfAdoptedOperation* operation, InfAdoptedOperation* against, InfAdoptedOperation* operation_lcs, InfAdoptedOperation* against_lcs, gint concurrency_id); InfAdoptedOperation* inf_adopted_operation_copy(InfAdoptedOperation* operation); InfAdoptedOperationFlags inf_adopted_operation_get_flags(InfAdoptedOperation* operation); gboolean inf_adopted_operation_apply(InfAdoptedOperation* operation, InfAdoptedUser* by, InfBuffer* buffer, GError** error); InfAdoptedOperation* inf_adopted_operation_apply_transformed(InfAdoptedOperation* operation, InfAdoptedOperation* transformed, InfAdoptedUser* by, InfBuffer* buffer, GError** error); gboolean inf_adopted_operation_is_reversible(InfAdoptedOperation* operation); InfAdoptedOperation* inf_adopted_operation_revert(InfAdoptedOperation* operation); G_END_DECLS #endif /* __INF_ADOPTED_OPERATION_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/adopted/PaxHeaders.26529/inf-adopted-session-record.c0000644000000000000000000000013213034342512025033 xustar0030 mtime=1483851082.025718404 30 atime=1483851082.025718404 30 ctime=1488261589.028139004 libinfinity-0.7.1/libinfinity/adopted/inf-adopted-session-record.c0000644000175000017500000005236413034342512025577 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /* TODO: Better error handling; we should have a proper InfErrnoError * (or InfSystemError or something), and we should check the fflush error * codes. */ /* TODO: Or just use GIOChannel here... */ /** * SECTION:inf-adopted-session-record * @title: InfAdoptedSessionRecord * @short_description: Create a record of a session * @include: libinfinity/adopted/inf-adopted-session-record.h * @see_also: #InfAdoptedSession, #InfAdoptedSessionReplay * @stability: Unstable * * #InfAdoptedSessionRecord creates a record of a #InfAdoptedSession. It * records every modification made to the session from the beginning of its * own lifetime to the end of its lifetime. * * It does not record user status changes and thus the recorded session * cannot reliably be replayed with all user information. It's main purpose is * to make it easy to reproduce bugs in libinfinity. However, it might be * extended in the future. * * To replay a record, use #InfAdoptedSessionReplay or the tool * inf-test-text-replay in the infinote test suite. */ #include #include #include #include #include #include #include /* TODO: Record user join/leave events, and update last send vectors on * rejoin. */ typedef struct _InfAdoptedSessionRecordPrivate InfAdoptedSessionRecordPrivate; struct _InfAdoptedSessionRecordPrivate { InfAdoptedSession* session; xmlTextWriterPtr writer; FILE* file; gchar* filename; GHashTable* last_send_table; }; enum { PROP_0, /* construct only */ PROP_SESSION, PROP_FILENAME }; #define INF_ADOPTED_SESSION_RECORD_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INF_ADOPTED_TYPE_SESSION_RECORD, InfAdoptedSessionRecordPrivate)) static GQuark libxml2_writer_error_quark; G_DEFINE_TYPE_WITH_CODE(InfAdoptedSessionRecord, inf_adopted_session_record, G_TYPE_OBJECT, G_ADD_PRIVATE(InfAdoptedSessionRecord)) static void inf_adopted_session_record_handle_xml_error(InfAdoptedSessionRecord* record) { InfAdoptedSessionRecordPrivate* priv; xmlErrorPtr xmlerror; priv = INF_ADOPTED_SESSION_RECORD_PRIVATE(record); xmlerror = xmlGetLastError(); g_warning( /* Error writing record `': */ _("Error writing record \"%s\": %s"), priv->filename, xmlerror->message ); } static void inf_adopted_session_record_write_node(InfAdoptedSessionRecord* record, xmlNodePtr xml) { InfAdoptedSessionRecordPrivate* priv; xmlAttrPtr attr; xmlChar* value; xmlNodePtr child; int result; priv = INF_ADOPTED_SESSION_RECORD_PRIVATE(record); result = xmlTextWriterStartElement(priv->writer, xml->name); if(result < 0) inf_adopted_session_record_handle_xml_error(record); for(attr = xml->properties; attr != NULL; attr = attr->next) { value = xmlGetProp(xml, attr->name); result = xmlTextWriterWriteAttribute(priv->writer, attr->name, value); if(result < 0) inf_adopted_session_record_handle_xml_error(record); xmlFree(value); } for(child = xml->children; child != NULL; child = child->next) { if(child->type == XML_ELEMENT_NODE) { inf_adopted_session_record_write_node(record, child); } else if(child->type == XML_TEXT_NODE) { value = xmlNodeGetContent(child); result = xmlTextWriterWriteString(priv->writer, value); if(result < 0) inf_adopted_session_record_handle_xml_error(record); xmlFree(value); } } result = xmlTextWriterEndElement(priv->writer); if(result < 0) inf_adopted_session_record_handle_xml_error(record); } static void inf_adopted_session_record_user_joined(InfAdoptedSessionRecord* record, InfAdoptedUser* user) { InfAdoptedSessionRecordPrivate* priv; priv = INF_ADOPTED_SESSION_RECORD_PRIVATE(record); g_hash_table_insert( priv->last_send_table, user, inf_adopted_state_vector_copy(inf_adopted_user_get_vector(user)) ); } static void inf_adopted_session_record_begin_execute_request_cb(InfAdoptedAlgorithm* algo, InfAdoptedUser* user, InfAdoptedRequest* req, gpointer user_data) { InfAdoptedSessionRecord* record; InfAdoptedSessionRecordPrivate* priv; InfAdoptedSessionClass* session_class; InfAdoptedStateVector* previous; xmlNodePtr xml; int result; record = INF_ADOPTED_SESSION_RECORD(user_data); priv = INF_ADOPTED_SESSION_RECORD_PRIVATE(record); session_class = INF_ADOPTED_SESSION_GET_CLASS(priv->session); xml = xmlNewNode(NULL, (const xmlChar*)"request"); previous = g_hash_table_lookup(priv->last_send_table, user); g_assert(previous != NULL); session_class->request_to_xml(priv->session, xml, req, previous, FALSE); inf_xml_util_set_attribute_double( xml, "received", inf_adopted_request_get_receive_time(req) / 1000000. ); inf_xml_util_set_attribute_double( xml, "executed", inf_adopted_request_get_execute_time(req) / 1000000. ); inf_adopted_session_record_write_node(record, xml); xmlFreeNode(xml); result = xmlTextWriterFlush(priv->writer); if(result < 0) inf_adopted_session_record_handle_xml_error(record); fflush(priv->file); /* Update last send entry */ previous = inf_adopted_state_vector_copy(inf_adopted_request_get_vector(req)); if(inf_adopted_request_affects_buffer(req)) inf_adopted_state_vector_add(previous, inf_user_get_id(INF_USER(user)), 1); g_hash_table_insert(priv->last_send_table, user, previous); } static void inf_adopted_session_record_add_user_cb(InfUserTable* user_table, InfUser* user, gpointer user_data) { InfAdoptedSessionRecord* record; InfAdoptedSessionRecordPrivate* priv; xmlNodePtr xml; int result; record = INF_ADOPTED_SESSION_RECORD(user_data); priv = INF_ADOPTED_SESSION_RECORD_PRIVATE(record); inf_adopted_session_record_user_joined(record, INF_ADOPTED_USER(user)); result = xmlTextWriterWriteString(priv->writer, (const xmlChar*)"\n "); if(result < 0) inf_adopted_session_record_handle_xml_error(record); xml = xmlNewNode(NULL, (const xmlChar*)"user"); inf_session_user_to_xml(INF_SESSION(priv->session), user, xml); inf_xml_util_set_attribute_double( xml, "executed", g_get_real_time() / 1000000. ); inf_adopted_session_record_write_node(record, xml); xmlFreeNode(xml); result = xmlTextWriterFlush(priv->writer); if(result < 0) inf_adopted_session_record_handle_xml_error(record); fflush(priv->file); } static void inf_adopted_session_record_start_foreach_user_func(InfUser* user, gpointer user_data) { inf_adopted_session_record_user_joined( INF_ADOPTED_SESSION_RECORD(user_data), INF_ADOPTED_USER(user) ); } static void inf_adopted_session_record_real_start(InfAdoptedSessionRecord* record) { InfAdoptedSessionRecordPrivate* priv; InfAdoptedAlgorithm* algorithm; InfUserTable* user_table; xmlNodePtr xml; xmlNodePtr child; xmlNodePtr cur; int result; guint total; InfSessionClass* session_class; priv = INF_ADOPTED_SESSION_RECORD_PRIVATE(record); algorithm = inf_adopted_session_get_algorithm(priv->session); user_table = inf_session_get_user_table(INF_SESSION(priv->session)); session_class = INF_SESSION_GET_CLASS(priv->session); g_signal_connect( G_OBJECT(algorithm), "begin-execute-request", G_CALLBACK(inf_adopted_session_record_begin_execute_request_cb), record ); g_signal_connect( G_OBJECT(user_table), "add-user", G_CALLBACK(inf_adopted_session_record_add_user_cb), record ); priv->last_send_table = g_hash_table_new_full( NULL, NULL, NULL, (GDestroyNotify)inf_adopted_state_vector_free ); inf_user_table_foreach_user( inf_session_get_user_table(INF_SESSION(priv->session)), inf_adopted_session_record_start_foreach_user_func, record ); result = xmlTextWriterStartDocument(priv->writer, NULL, "UTF-8", NULL); if(result < 0) inf_adopted_session_record_handle_xml_error(record); result = xmlTextWriterStartElement( priv->writer, (const xmlChar*)"infinote-adopted-session-record" ); if(result < 0) inf_adopted_session_record_handle_xml_error(record); /* TODO: Have someone else inserting sync-begin and sync-end... that's quite * hacky here. */ xml = xmlNewNode(NULL, (const xmlChar*)"initial"); child = xmlNewChild(xml, NULL, (const xmlChar*)"sync-begin", NULL); session_class->to_xml_sync(INF_SESSION(priv->session), xml); xmlNewChild(xml, NULL, (const xmlChar*)"sync-end", NULL); total = 0; for(cur = child; cur != NULL; cur = cur->next) ++ total; inf_xml_util_set_attribute_uint(child, "num-messages", total - 2); inf_adopted_session_record_write_node(record, xml); xmlFreeNode(xml); result = xmlTextWriterFlush(priv->writer); if(result < 0) inf_adopted_session_record_handle_xml_error(record); fflush(priv->file); } static void inf_adopted_session_record_synchronization_complete_cb(InfSession* session, InfXmlConnection* conn, gpointer user_data) { InfAdoptedSessionRecord* record; record = INF_ADOPTED_SESSION_RECORD(user_data); inf_signal_handlers_disconnect_by_func( G_OBJECT(session), G_CALLBACK(inf_adopted_session_record_synchronization_complete_cb), record ); inf_adopted_session_record_real_start(record); } /* * GObject overrides. */ static void inf_adopted_session_record_init(InfAdoptedSessionRecord* record) { InfAdoptedSessionRecordPrivate* priv; priv = INF_ADOPTED_SESSION_RECORD_PRIVATE(record); priv->session = NULL; priv->writer = NULL; priv->file = NULL; priv->filename = NULL; priv->last_send_table = NULL; } static void inf_adopted_session_record_dispose(GObject* object) { InfAdoptedSessionRecord* record; InfAdoptedSessionRecordPrivate* priv; GError* error; record = INF_ADOPTED_SESSION_RECORD(object); priv = INF_ADOPTED_SESSION_RECORD_PRIVATE(record); if(priv->writer != NULL) { error = NULL; inf_adopted_session_record_stop_recording(record, &error); if(error != NULL) { g_assert(priv->filename != NULL); g_warning( /* Error while finishing record `': */ "Error while finishing record `%s': %s", priv->filename, error->message ); g_error_free(error); } } if(priv->session != NULL) { g_object_unref(priv->session); priv->session = NULL; } G_OBJECT_CLASS(inf_adopted_session_record_parent_class)->dispose(object); } static void inf_adopted_session_record_finalize(GObject* object) { InfAdoptedSessionRecord* record; InfAdoptedSessionRecordPrivate* priv; record = INF_ADOPTED_SESSION_RECORD(object); priv = INF_ADOPTED_SESSION_RECORD_PRIVATE(record); g_assert(priv->filename == NULL); G_OBJECT_CLASS(inf_adopted_session_record_parent_class)->finalize(object); } static void inf_adopted_session_record_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfAdoptedSessionRecord* record; InfAdoptedSessionRecordPrivate* priv; record = INF_ADOPTED_SESSION_RECORD(object); priv = INF_ADOPTED_SESSION_RECORD_PRIVATE(record); switch(prop_id) { case PROP_SESSION: g_assert(priv->session == NULL); /* construct only */ priv->session = INF_ADOPTED_SESSION(g_value_dup_object(value)); break; case PROP_FILENAME: /* read only */ default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void inf_adopted_session_record_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfAdoptedSessionRecord* record; InfAdoptedSessionRecordPrivate* priv; record = INF_ADOPTED_SESSION_RECORD(object); priv = INF_ADOPTED_SESSION_RECORD_PRIVATE(record); switch(prop_id) { case PROP_SESSION: g_value_set_object(value, G_OBJECT(priv->session)); break; case PROP_FILENAME: g_value_set_string(value, priv->filename); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } /* * Gype registration. */ static void inf_adopted_session_record_class_init( InfAdoptedSessionRecordClass* record_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(record_class); object_class->dispose = inf_adopted_session_record_dispose; object_class->finalize = inf_adopted_session_record_finalize; object_class->set_property = inf_adopted_session_record_set_property; object_class->get_property = inf_adopted_session_record_get_property; libxml2_writer_error_quark = g_quark_from_static_string("LIBXML2_WRITER_ERROR"); g_object_class_install_property( object_class, PROP_SESSION, g_param_spec_object( "session", "Session", "The session to record", INF_ADOPTED_TYPE_SESSION, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_FILENAME, g_param_spec_string( "filename", "Filename", "The filename of the record file", NULL, G_PARAM_READABLE ) ); } /* * Public API. */ /** * inf_adopted_session_record_new: (constructor) * @session: A #InfAdoptedSession. * * Creates a new #InfAdoptedSessionRecord, recording @session. To start * recording, call inf_adopted_session_record_start_recording(). * * Return Value: (transfer full): A new #InfAdoptedSessionRecord. **/ InfAdoptedSessionRecord* inf_adopted_session_record_new(InfAdoptedSession* session) { GObject* object; g_return_val_if_fail(INF_ADOPTED_IS_SESSION(session), NULL); object = g_object_new( INF_ADOPTED_TYPE_SESSION_RECORD, "session", session, NULL ); return INF_ADOPTED_SESSION_RECORD(object); } /** * inf_adopted_session_record_start_recording: * @record: A #InfAdoptedSessionRecord. * @filename: (type filename): The file in which to store the record. * @error: Location to store error information, if any. * * Starts to record the session. Make sure the session is not already closed * before calling this function. If an error occurs, such as if @filename * could not be opened, then the function returns %FALSE and @error is set. * * Return Value: %TRUE if the session is started to be recorded, %FALSE on * error. **/ gboolean inf_adopted_session_record_start_recording(InfAdoptedSessionRecord* record, const gchar* filename, GError** error) { InfAdoptedSessionRecordPrivate* priv; InfSessionStatus status; xmlOutputBufferPtr buffer; xmlErrorPtr xmlerror; int errcode; g_return_val_if_fail(INF_ADOPTED_IS_SESSION_RECORD(record), FALSE); g_return_val_if_fail(filename != NULL, FALSE); g_return_val_if_fail(error == NULL || *error == NULL, FALSE); priv = INF_ADOPTED_SESSION_RECORD_PRIVATE(record); status = inf_session_get_status(INF_SESSION(priv->session)); g_return_val_if_fail(priv->writer == NULL, FALSE); g_return_val_if_fail(status != INF_SESSION_CLOSED, FALSE); priv->file = fopen(filename, "w"); if(priv->file == NULL) { errcode = errno; g_set_error_literal( error, g_quark_from_static_string("ERRNO_ERROR"), errcode, strerror(errcode) ); return FALSE; } buffer = xmlOutputBufferCreateFile(priv->file, NULL); if(buffer == NULL) { fclose(priv->file); priv->file = NULL; xmlerror = xmlGetLastError(); g_set_error_literal( error, libxml2_writer_error_quark, xmlerror->code, xmlerror->message ); return FALSE; } priv->writer = xmlNewTextWriter(buffer); if(priv->writer == NULL) { /* TODO: Does this also fclose our file? */ xmlOutputBufferClose(buffer); priv->file = NULL; xmlerror = xmlGetLastError(); g_set_error_literal( error, libxml2_writer_error_quark, xmlerror->code, xmlerror->message ); return FALSE; } xmlTextWriterSetIndent(priv->writer, 1); switch(status) { case INF_SESSION_SYNCHRONIZING: g_signal_connect_after( G_OBJECT(priv->session), "synchronization-complete", G_CALLBACK(inf_adopted_session_record_synchronization_complete_cb), record ); break; case INF_SESSION_RUNNING: inf_adopted_session_record_real_start(record); break; default: g_assert_not_reached(); break; } g_assert(priv->filename == NULL); priv->filename = g_strdup(filename); g_object_notify(G_OBJECT(record), "filename"); return TRUE; } /** * inf_adopted_session_record_stop_recording: * @record: A #InfAdoptedSessionRecord. * @error: Location to store error information, if any. * * Stops the recording of the current session, which must have been started * previously via inf_adopted_session_record_start_recording(). If an error * occurs, then the function returns %FALSE and @error is set. Note that even * if an error occurs, then the recording is stopped as well. However, the * file might not have been completely written to disk, so you should still * show any errors during this function to the user. * * Return Value: %TRUE if the recording has been stored successfully, %FALSE * otherwise. */ gboolean inf_adopted_session_record_stop_recording(InfAdoptedSessionRecord* record, GError** error) { InfAdoptedSessionRecordPrivate* priv; InfSessionStatus status; InfAdoptedAlgorithm* algorithm; InfUserTable* user_table; xmlErrorPtr xmlerror; int result; g_return_val_if_fail(INF_ADOPTED_IS_SESSION_RECORD(record), FALSE); g_return_val_if_fail(error == NULL || *error == NULL, FALSE); priv = INF_ADOPTED_SESSION_RECORD_PRIVATE(record); g_return_val_if_fail(priv->writer != NULL, FALSE); inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->session), G_CALLBACK(inf_adopted_session_record_synchronization_complete_cb), record ); /* In synchronizing state we did not yet connect to these signals, and * the algorithm doesn't even exist. */ status = inf_session_get_status(INF_SESSION(priv->session)); if(status != INF_SESSION_SYNCHRONIZING) { user_table = inf_session_get_user_table(INF_SESSION(priv->session)); /* The algorithm has been destroyed when the session has been closed. */ if(status != INF_SESSION_CLOSED) { algorithm = inf_adopted_session_get_algorithm(priv->session); g_assert(algorithm != NULL); inf_signal_handlers_disconnect_by_func( G_OBJECT(algorithm), G_CALLBACK(inf_adopted_session_record_begin_execute_request_cb), record ); } inf_signal_handlers_disconnect_by_func( G_OBJECT(user_table), G_CALLBACK(inf_adopted_session_record_add_user_cb), record ); } result = xmlTextWriterWriteString(priv->writer, (const xmlChar*)"\n"); if(result < 0) inf_adopted_session_record_handle_xml_error(record); result = xmlTextWriterEndDocument(priv->writer); if(result < 0) { xmlerror = xmlGetLastError(); g_set_error_literal( error, libxml2_writer_error_quark, xmlerror->code, xmlerror->message ); return FALSE; } /* TODO: Does this fclose our file? */ xmlFreeTextWriter(priv->writer); priv->writer = NULL; priv->file = NULL; g_free(priv->filename); priv->filename = NULL; /* This has only been created if the session has entered running state * already. */ if(priv->last_send_table != NULL) { g_hash_table_unref(priv->last_send_table); priv->last_send_table = NULL; } g_object_notify(G_OBJECT(record), "filename"); return result >= 0; } /** * inf_adopted_session_record_is_recording: * @record: A #InfAdoptedSessionRecord. * * Returns whether @record is currently recording a session. * * Returns: Whether @record currently records the session. */ gboolean inf_adopted_session_record_is_recording(InfAdoptedSessionRecord* record) { g_return_val_if_fail(INF_ADOPTED_IS_SESSION_RECORD(record), FALSE); return INF_ADOPTED_SESSION_RECORD_PRIVATE(record)->writer != NULL; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/adopted/PaxHeaders.26529/inf-adopted-session.h0000644000000000000000000000013213034342512023564 xustar0030 mtime=1483851082.025718404 30 atime=1483851082.025718404 30 ctime=1488261588.912139258 libinfinity-0.7.1/libinfinity/adopted/inf-adopted-session.h0000644000175000017500000001425713034342512024327 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_ADOPTED_SESSION_H__ #define __INF_ADOPTED_SESSION_H__ #include #include #include #include #include G_BEGIN_DECLS #define INF_ADOPTED_TYPE_SESSION (inf_adopted_session_get_type()) #define INF_ADOPTED_SESSION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_ADOPTED_TYPE_SESSION, InfAdoptedSession)) #define INF_ADOPTED_SESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INF_ADOPTED_TYPE_SESSION, InfAdoptedSessionClass)) #define INF_ADOPTED_IS_SESSION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_ADOPTED_TYPE_SESSION)) #define INF_ADOPTED_IS_SESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INF_ADOPTED_TYPE_SESSION)) #define INF_ADOPTED_SESSION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INF_ADOPTED_TYPE_SESSION, InfAdoptedSessionClass)) typedef struct _InfAdoptedSession InfAdoptedSession; typedef struct _InfAdoptedSessionClass InfAdoptedSessionClass; /** * InfAdoptedSessionError: * @INF_ADOPTED_SESSION_ERROR_NO_SUCH_USER: The "user" field in a request * message does not contain a valid user ID. * @INF_ADOPTED_SESSION_ERROR_MISSING_OPERATION: A request message does not * contain an operation. * @INF_ADOPTED_SESSION_ERROR_INVALID_REQUEST: A request in a synchronized * request log is invalid. Invalid means that it is not the request that * was issued after the previous request in the log, or that it is an Undo * or Redo request without a request to Undo or Redo, respectively. * @INF_ADOPTED_SESSION_ERROR_MISSING_STATE_VECTOR: A synchronized user does * not contain that the state that user currently is in. * @INF_ADOPTED_SESSION_ERROR_FAILED: No further specified error code. * * Error codes for #InfAdoptedSession. These only occur when invalid requests * are received from the network. */ typedef enum _InfAdoptedSessionError { INF_ADOPTED_SESSION_ERROR_NO_SUCH_USER, INF_ADOPTED_SESSION_ERROR_MISSING_OPERATION, INF_ADOPTED_SESSION_ERROR_INVALID_REQUEST, INF_ADOPTED_SESSION_ERROR_MISSING_STATE_VECTOR, INF_ADOPTED_SESSION_ERROR_FAILED } InfAdoptedSessionError; /** * InfAdoptedSessionClass: * @xml_to_request: Virtual function to deserialize an #InfAdoptedRequest * from XML. The implementation of this function can use * inf_adopted_session_read_request_info() to read the common info. * @request_to_xml: Virtual function to serialize an #InfAdoptedRequest * to XML. This function should add properties and children to the given XML * node. At might use inf_adopted_session_write_request_info() to write the * common info. * @check_request: Default signal handler of the * InfAdoptedSession::check-request signal. * * Virtual functions and default signal handlers for #InfAdoptedSession. */ struct _InfAdoptedSessionClass { /*< private >*/ InfSessionClass parent_class; /* Virtual table */ /*< public >*/ InfAdoptedRequest*(*xml_to_request)(InfAdoptedSession* session, xmlNodePtr xml, InfAdoptedStateVector* diff_vec, gboolean for_sync, GError** error); void(*request_to_xml)(InfAdoptedSession* session, xmlNodePtr xml, InfAdoptedRequest* request, InfAdoptedStateVector* diff_vec, gboolean for_sync); /* Signals */ gboolean(*check_request)(InfAdoptedSession* session, InfAdoptedRequest* request, InfAdoptedUser* user); }; /** * InfAdoptedSession: * * #InfAdoptedSession is an opaque data type. You should only access it via * the public API functions. */ struct _InfAdoptedSession { /*< private >*/ InfSession parent; }; GType inf_adopted_session_get_type(void); InfIo* inf_adopted_session_get_io(InfAdoptedSession* session); InfAdoptedAlgorithm* inf_adopted_session_get_algorithm(InfAdoptedSession* session); void inf_adopted_session_broadcast_request(InfAdoptedSession* session, InfAdoptedRequest* request); void inf_adopted_session_undo(InfAdoptedSession* session, InfAdoptedUser* user, guint n); void inf_adopted_session_redo(InfAdoptedSession* session, InfAdoptedUser* user, guint n); gboolean inf_adopted_session_read_request_info(InfAdoptedSession* session, xmlNodePtr xml, InfAdoptedStateVector* diff_vec, InfAdoptedUser** user, InfAdoptedStateVector** time, xmlNodePtr* operation, GError** error); void inf_adopted_session_write_request_info(InfAdoptedSession* session, InfAdoptedRequest* request, InfAdoptedStateVector* diff_vec, xmlNodePtr xml, xmlNodePtr operation); G_END_DECLS #endif /* __INF_ADOPTED_SESSION_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/adopted/PaxHeaders.26529/inf-adopted-session.c0000644000000000000000000000013213034342512023557 xustar0030 mtime=1483851082.025718404 30 atime=1483851082.025718404 30 ctime=1488261589.024139013 libinfinity-0.7.1/libinfinity/adopted/inf-adopted-session.c0000644000175000017500000015421513034342512024321 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-adopted-session * @title: InfAdoptedSession * @short_description: Session handling concurrency control via the adOPTed * algorithm. * @include: libinfinity/adopted/inf-adopted-session.h * @see_also: #InfSession, #InfAdoptedAlgorithm * @stability: Unstable * * #InfAdoptedSession handles concurrency control with an #InfAdoptedAlgorithm * on top of a #InfSession. It takes care of sending all necessary information * to joining users, receives requests from the network (passing them to * #InfAdoptedAlgorithm) and transfers local requests to the other users. It * also makes sure to periodically send the state the local host is in to * other uses even if the local users are idle (which is required for others * to cleanup their request logs and request caches). */ /* TODO: warning if no update from a particular non-local user for some time */ #include #include #include #include #include #include #include #include typedef struct _InfAdoptedSessionToXmlSyncForeachData InfAdoptedSessionToXmlSyncForeachData; struct _InfAdoptedSessionToXmlSyncForeachData { InfAdoptedSession* session; xmlNodePtr parent_xml; }; typedef struct _InfAdoptedSessionLocalUser InfAdoptedSessionLocalUser; struct _InfAdoptedSessionLocalUser { InfAdoptedUser* user; InfAdoptedStateVector* last_send_vector; time_t noop_time; /* TODO: should be monotonic time */ }; typedef struct _InfAdoptedSessionPrivate InfAdoptedSessionPrivate; struct _InfAdoptedSessionPrivate { InfIo* io; guint max_total_log_size; InfAdoptedAlgorithm* algorithm; GSList* local_users; /* having zero or one item in 99.9% of all cases */ /* Timeout for sending noop with our current vector time */ InfIoTimeout* noop_timeout; /* User to send the time for */ InfAdoptedSessionLocalUser* next_noop_user; /* Buffer for requests that are not ready to be executed yet */ GPtrArray* request_buffer; }; enum { PROP_0, /* construct only */ PROP_IO, PROP_MAX_TOTAL_LOG_SIZE, /* read only */ PROP_ALGORITHM }; enum { CHECK_REQUEST, LAST_SIGNAL }; #define INF_ADOPTED_SESSION_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INF_ADOPTED_TYPE_SESSION, InfAdoptedSessionPrivate)) static guint session_signals[LAST_SIGNAL]; static GQuark inf_adopted_session_error_quark; /* TODO: This should perhaps be a property: */ static const int INF_ADOPTED_SESSION_NOOP_INTERVAL = 30; G_DEFINE_TYPE_WITH_CODE(InfAdoptedSession, inf_adopted_session, INF_TYPE_SESSION, G_ADD_PRIVATE(InfAdoptedSession)) /* * Utility functions. */ static InfAdoptedSessionLocalUser* inf_adopted_session_lookup_local_user(InfAdoptedSession* session, InfAdoptedUser* user) { InfAdoptedSessionPrivate* priv; InfAdoptedSessionLocalUser* local; GSList* item; priv = INF_ADOPTED_SESSION_PRIVATE(session); for(item = priv->local_users; item != NULL; item = g_slist_next(item)) { local = (InfAdoptedSessionLocalUser*)item->data; if(local->user == user) return local; } return NULL; } /* Checks whether request can be inserted into log */ /* TODO: Move into request log class? */ static gboolean inf_adopted_session_validate_request(InfAdoptedRequestLog* log, InfAdoptedRequest* request, GError** error) { InfAdoptedStateVector* vector; guint user_id; guint n; guint begin; guint end; vector = inf_adopted_request_get_vector(request); user_id = inf_adopted_request_get_user_id(request); n = inf_adopted_state_vector_get(vector, user_id); begin = inf_adopted_request_log_get_begin(log); end = inf_adopted_request_log_get_end(log); /* TODO: Actually, begin != end is only relevant for the first request * in request log. */ if(end != n && begin != end) { g_set_error( error, inf_adopted_session_error_quark, INF_ADOPTED_SESSION_ERROR_INVALID_REQUEST, _("Request has index '%u', but index '%u' was expected"), n, inf_adopted_request_log_get_end(log) ); return FALSE; } else { switch(inf_adopted_request_get_request_type(request)) { case INF_ADOPTED_REQUEST_DO: /* Nothing to check for */ return TRUE; case INF_ADOPTED_REQUEST_UNDO: if(inf_adopted_request_log_next_undo(log) == NULL) { g_set_error_literal( error, inf_adopted_session_error_quark, INF_ADOPTED_SESSION_ERROR_INVALID_REQUEST, _("Undo received, but no previous request found") ); return FALSE; } else { return TRUE; } case INF_ADOPTED_REQUEST_REDO: if(inf_adopted_request_log_next_redo(log) == NULL) { g_set_error_literal( error, inf_adopted_session_error_quark, INF_ADOPTED_SESSION_ERROR_INVALID_REQUEST, _("Redo received, but no previous request found") ); return FALSE; } else { return TRUE; } default: g_assert_not_reached(); return FALSE; } } } static InfAdoptedUser* inf_adopted_session_user_from_request_xml(InfAdoptedSession* session, xmlNodePtr xml, GError** error) { InfUserTable* user_table; InfUser* user; guint user_id; user_table = inf_session_get_user_table(INF_SESSION(session)); if(!inf_xml_util_get_attribute_uint_required(xml, "user", &user_id, error)) return FALSE; /* User ID 0 means no user */ if(user_id == 0) return NULL; user = inf_user_table_lookup_user_by_id(user_table, user_id); if(user == NULL) { g_set_error( error, inf_adopted_session_error_quark, INF_ADOPTED_SESSION_ERROR_NO_SUCH_USER, _("No such user with user ID '%u'"), user_id ); return NULL; } g_assert(INF_ADOPTED_IS_USER(user)); return INF_ADOPTED_USER(user); } /* * Noop timer */ static void inf_adopted_session_noop_timeout_func(gpointer user_data) { InfAdoptedSession* session; InfAdoptedSessionPrivate* priv; InfAdoptedOperation* op; InfAdoptedRequest* request; session = INF_ADOPTED_SESSION(user_data); priv = INF_ADOPTED_SESSION_PRIVATE(session); priv->noop_timeout = NULL; g_assert(priv->next_noop_user != NULL); op = INF_ADOPTED_OPERATION(inf_adopted_no_operation_new()); request = inf_adopted_algorithm_generate_request( priv->algorithm, INF_ADOPTED_REQUEST_DO, priv->next_noop_user->user, op ); g_object_unref(op); /* There is no need to actually execute the request, since it does not * do anything anyway. */ /* This resets noop_time for this user, determines the next user for * which to generate a noop request and schedules the new timeout. */ inf_adopted_session_broadcast_request(session, request); g_object_unref(request); } static InfAdoptedSessionLocalUser* inf_adopted_session_find_next_noop_user(InfAdoptedSession* session) { InfAdoptedSessionPrivate* priv; GSList* item; InfAdoptedSessionLocalUser* local; InfAdoptedSessionLocalUser* next_user; priv = INF_ADOPTED_SESSION_PRIVATE(session); next_user = NULL; for(item = priv->local_users; item != NULL; item = g_slist_next(item)) { local = (InfAdoptedSessionLocalUser*)item->data; if(local->noop_time != 0) if(next_user == NULL || local->noop_time < next_user->noop_time) next_user = local; } return next_user; } static void inf_adopted_session_schedule_noop_timer(InfAdoptedSession* session) { InfAdoptedSessionPrivate* priv; time_t current; time_t sched; priv = INF_ADOPTED_SESSION_PRIVATE(session); if(priv->noop_timeout != NULL) { inf_io_remove_timeout(priv->io, priv->noop_timeout); priv->noop_timeout = NULL; } if(priv->next_noop_user != NULL) { current = time(NULL); sched = priv->next_noop_user->noop_time + INF_ADOPTED_SESSION_NOOP_INTERVAL; if(sched >= current) sched -= current; else sched = 0; priv->noop_timeout = inf_io_add_timeout( priv->io, sched * 1000, inf_adopted_session_noop_timeout_func, session, NULL ); } } static void inf_adopted_session_start_noop_timer(InfAdoptedSession* session, InfAdoptedSessionLocalUser* local) { InfAdoptedSessionPrivate* priv; priv = INF_ADOPTED_SESSION_PRIVATE(session); g_assert(local->noop_time == 0); local->noop_time = time(NULL); if(priv->noop_timeout == NULL) { priv->next_noop_user = inf_adopted_session_find_next_noop_user(session); g_assert(priv->next_noop_user != NULL); inf_adopted_session_schedule_noop_timer(session); } } static void inf_adopted_session_stop_noop_timer(InfAdoptedSession* session, InfAdoptedSessionLocalUser* local) { InfAdoptedSessionPrivate* priv; InfAdoptedSessionLocalUser* next_noop_user; priv = INF_ADOPTED_SESSION_PRIVATE(session); if(local->noop_time > 0) { local->noop_time = 0; next_noop_user = inf_adopted_session_find_next_noop_user(session); if(next_noop_user != priv->next_noop_user) { priv->next_noop_user = next_noop_user; inf_adopted_session_schedule_noop_timer(session); } } } /* Breadcasts a request N times - makes only sense for undo and redo requests, * so that's the only thing we offer API for. */ static void inf_adopted_session_broadcast_n_requests(InfAdoptedSession* session, InfAdoptedRequest* request, guint n) { InfAdoptedSessionPrivate* priv; InfAdoptedSessionClass* session_class; InfUserTable* user_table; guint user_id; InfUser* user; InfAdoptedSessionLocalUser* local; xmlNodePtr xml; priv = INF_ADOPTED_SESSION_PRIVATE(session); session_class = INF_ADOPTED_SESSION_GET_CLASS(session); g_assert(session_class->request_to_xml != NULL); user_table = inf_session_get_user_table(INF_SESSION(session)); user_id = inf_adopted_request_get_user_id(request); user = inf_user_table_lookup_user_by_id(user_table, user_id); g_assert(user != NULL); local = inf_adopted_session_lookup_local_user( session, INF_ADOPTED_USER(user) ); g_assert(local != NULL); xml = xmlNewNode(NULL, (const xmlChar*)"request"); session_class->request_to_xml( session, xml, request, local->last_send_vector, FALSE ); if(n > 1) inf_xml_util_set_attribute_uint(xml, "num", n); inf_session_send_to_subscriptions(INF_SESSION(session), xml); inf_adopted_state_vector_free(local->last_send_vector); local->last_send_vector = inf_adopted_state_vector_copy( inf_adopted_request_get_vector(request) ); /* Add this request to last send vector if it increases vector time * (-> affects buffer). */ if(inf_adopted_request_affects_buffer(request) == TRUE) inf_adopted_state_vector_add(local->last_send_vector, user_id, n); inf_adopted_session_stop_noop_timer(session, local); } static gboolean inf_adopted_session_process_request(InfAdoptedSession* session, InfAdoptedRequest* request, InfAdoptedUser* user, GError** error) { InfAdoptedSessionPrivate* priv; InfAdoptedStateVector* request_vector; InfAdoptedStateVector* current_vector; gboolean reject_request; GError* local_error; gboolean execute_result; xmlNodePtr reply_xml; gchar* request_str; gchar* current_str; priv = INF_ADOPTED_SESSION_PRIVATE(session); request_vector = inf_adopted_request_get_vector(request); current_vector = inf_adopted_algorithm_get_current(priv->algorithm); if(inf_adopted_state_vector_causally_before(request_vector, current_vector)) { g_signal_emit( G_OBJECT(session), session_signals[CHECK_REQUEST], 0, request, user, &reject_request ); local_error = NULL; if(reject_request) { g_set_error_literal( &local_error, inf_adopted_session_error_quark, INF_ADOPTED_SESSION_ERROR_INVALID_REQUEST, _("The request was rejected via the API") ); execute_result = FALSE; } else { execute_result = inf_adopted_algorithm_execute_request( priv->algorithm, request, TRUE, &local_error ); } if(local_error != NULL) { /* Send a message back to where the request came from, to let them * know we couldn't handle this. Note that at the moment this is not * explicitly handled, but it can aid in debugging. */ if(inf_user_get_connection(INF_USER(user)) != NULL) { /* Send a message back to where we got this request from, to inform * them that the request cannot be handled. */ request_str = inf_adopted_state_vector_to_string(request_vector); current_str = inf_adopted_state_vector_to_string(current_vector); reply_xml = xmlNewNode(NULL, (const xmlChar*)"invalid-request"); inf_xml_util_set_attribute( reply_xml, "request", request_str ); inf_xml_util_set_attribute( reply_xml, "state", current_str ); inf_xml_util_set_attribute_uint( reply_xml, "user", inf_user_get_id(INF_USER(user)) ); xmlNewChild( reply_xml, NULL, (const xmlChar*)"reason", (const xmlChar*)local_error->message ); g_free(request_str); g_free(current_str); inf_communication_group_send_message( inf_session_get_subscription_group(INF_SESSION(session)), inf_user_get_connection(INF_USER(user)), reply_xml ); } g_propagate_error(error, local_error); } return execute_result; } else { if(priv->request_buffer == NULL) priv->request_buffer = g_ptr_array_new(); g_ptr_array_add(priv->request_buffer, request); g_object_ref(request); return TRUE; } } static void inf_adopted_session_process_buffered_requests(InfAdoptedSession* session) { InfAdoptedSessionPrivate* priv; InfUserTable* user_table; InfAdoptedStateVector* current; guint i; InfAdoptedRequest* request; InfAdoptedStateVector* vector; guint user_id; InfUser* user; priv = INF_ADOPTED_SESSION_PRIVATE(session); if(priv->request_buffer != NULL) { user_table = inf_session_get_user_table(INF_SESSION(session)); current = inf_adopted_algorithm_get_current(priv->algorithm); for(i = 0; i < priv->request_buffer->len; ++i) { request = INF_ADOPTED_REQUEST(g_ptr_array_index(priv->request_buffer, i)); vector = inf_adopted_request_get_vector(request); if(inf_adopted_state_vector_causally_before(vector, current)) { g_ptr_array_remove_index_fast(priv->request_buffer, i); user_id = inf_adopted_request_get_user_id(request); user = inf_user_table_lookup_user_by_id(user_table, user_id); g_assert(INF_ADOPTED_IS_USER(user)); /* Note that there is no error handling here, since the buffered * requests are not related to the request which has currently been * received. In order to handle a failure here, the * InfAdoptedAlgorithm::end-execute-request signal should be used. */ inf_adopted_session_process_request( session, request, INF_ADOPTED_USER(user), NULL ); g_object_unref(request); return inf_adopted_session_process_buffered_requests(session); } } } } /* * Signal handlers */ static void inf_adopted_session_local_user_added(InfAdoptedSession* session, InfAdoptedUser* user) { InfAdoptedSessionPrivate* priv; InfSessionStatus status; InfAdoptedSessionLocalUser* local; InfAdoptedStateVector* current_state; priv = INF_ADOPTED_SESSION_PRIVATE(session); status = inf_session_get_status(INF_SESSION(session)); /* Cannot be local while synchronizing */ g_assert(status == INF_SESSION_RUNNING); local = g_slice_new(InfAdoptedSessionLocalUser); local->user = user; local->last_send_vector = inf_adopted_state_vector_copy( inf_adopted_user_get_vector(user) ); /* Set current vector for local user, this is kept up-to-date by * InfAdoptedAlgorithm. TODO: Also do this in InfAdoptedAlgorithm? */ inf_adopted_user_set_vector( user, inf_adopted_state_vector_copy( inf_adopted_algorithm_get_current(priv->algorithm) ) ); local->noop_time = 0; priv->local_users = g_slist_prepend(priv->local_users, local); /* Start noop timer if user is not up to date */ current_state = inf_adopted_algorithm_get_current(priv->algorithm); if(inf_adopted_state_vector_compare(current_state, local->last_send_vector)) inf_adopted_session_start_noop_timer(session, local); } static void inf_adopted_session_remove_local_user_cb(InfUserTable* user_table, InfUser* user, gpointer user_data) { InfAdoptedSession* session; InfAdoptedSessionPrivate* priv; InfAdoptedSessionLocalUser* local; session = INF_ADOPTED_SESSION(user_data); priv = INF_ADOPTED_SESSION_PRIVATE(session); local = inf_adopted_session_lookup_local_user( session, INF_ADOPTED_USER(user) ); g_assert(local != NULL); inf_adopted_session_stop_noop_timer(session, local); inf_adopted_state_vector_free(local->last_send_vector); priv->local_users = g_slist_remove(priv->local_users, local); g_slice_free(InfAdoptedSessionLocalUser, local); } static void inf_adopted_session_add_local_user_cb(InfUserTable* user_table, InfUser* user, gpointer user_data) { g_assert(INF_ADOPTED_IS_USER(user)); inf_adopted_session_local_user_added( INF_ADOPTED_SESSION(user_data), INF_ADOPTED_USER(user) ); } static void inf_adopted_session_constructed_foreach_local_user_func(InfUser* user, gpointer user_data) { g_assert(INF_ADOPTED_IS_USER(user)); inf_adopted_session_local_user_added( INF_ADOPTED_SESSION(user_data), INF_ADOPTED_USER(user) ); } static void inf_adopted_session_end_execute_request_cb(InfAdoptedAlgorithm* algorithm, InfAdoptedUser* user, InfAdoptedRequest* request, InfAdoptedRequest* translated, const GError* error, gpointer user_data) { InfAdoptedSession* session; InfAdoptedSessionPrivate* priv; GSList* item; InfAdoptedSessionLocalUser* local; guint id; InfAdoptedOperation* operation; session = INF_ADOPTED_SESSION(user_data); priv = INF_ADOPTED_SESSION_PRIVATE(session); if(translated != NULL) { if(inf_adopted_request_affects_buffer(translated)) { id = inf_adopted_request_get_user_id(translated); /* A request has been executed, meaning we are no longer up to date. Send * a noop in some time, so that others know what we already processed. */ for(item = priv->local_users; item != NULL; item = g_slist_next(item)) { local = (InfAdoptedSessionLocalUser*)item->data; if(local->noop_time == 0) /* Except we issued the request ourselves, of course. */ if(inf_user_get_id(INF_USER(local->user)) != id) inf_adopted_session_start_noop_timer(session, local); } } /* Mark inactive users active if they do something */ /* Note: This behaviour is implicitly performed by both client and server, * and requires no further network traffic. However, users explictely have * to be set inactive. */ operation = inf_adopted_request_get_operation(translated); if(!INF_ADOPTED_IS_NO_OPERATION(operation)) { /* TODO: We should offer a virtual function to flush all requests for * local users, either here or even in InfSession via a vfunc, so that * we don't accidentally make local users active by a delayed request. */ if(inf_user_get_status(INF_USER(user)) == INF_USER_INACTIVE) g_object_set(G_OBJECT(user), "status", INF_USER_ACTIVE, NULL); } } } /* * Helper functions */ static void inf_adopted_session_create_algorithm(InfAdoptedSession* session) { InfAdoptedSessionPrivate* priv; priv = INF_ADOPTED_SESSION_PRIVATE(session); g_assert(priv->algorithm == NULL); g_assert( inf_session_get_status(INF_SESSION(session)) == INF_SESSION_RUNNING ); priv->algorithm = inf_adopted_algorithm_new_full( inf_session_get_user_table(INF_SESSION(session)), inf_session_get_buffer(INF_SESSION(session)), priv->max_total_log_size ); g_signal_connect( G_OBJECT(priv->algorithm), "end-execute-request", G_CALLBACK(inf_adopted_session_end_execute_request_cb), session ); g_object_notify(G_OBJECT(session), "algorithm"); } /* * GObject overrides. */ static void inf_adopted_session_init(InfAdoptedSession* session) { InfAdoptedSessionPrivate* priv; priv = INF_ADOPTED_SESSION_PRIVATE(session); priv->io = NULL; priv->max_total_log_size = 2048; priv->algorithm = NULL; priv->local_users = NULL; priv->noop_timeout = NULL; priv->next_noop_user = NULL; priv->request_buffer = NULL; } static void inf_adopted_session_constructed(GObject* object) { InfAdoptedSession* session; InfAdoptedSessionPrivate* priv; InfSessionStatus status; InfUserTable* user_table; G_OBJECT_CLASS(inf_adopted_session_parent_class)->constructed(object); session = INF_ADOPTED_SESSION(object); priv = INF_ADOPTED_SESSION_PRIVATE(session); g_assert(priv->io != NULL); g_object_get(G_OBJECT(session), "status", &status, NULL); user_table = inf_session_get_user_table(INF_SESSION(session)); g_signal_connect( G_OBJECT(user_table), "add-local-user", G_CALLBACK(inf_adopted_session_add_local_user_cb), session ); g_signal_connect( G_OBJECT(user_table), "remove-local-user", G_CALLBACK(inf_adopted_session_remove_local_user_cb), session ); switch(status) { case INF_SESSION_PRESYNC: case INF_SESSION_SYNCHRONIZING: /* algorithm is created during initial synchronization when parameters * like initial vector time, max total log size etc. are known. */ break; case INF_SESSION_RUNNING: g_assert(inf_session_get_buffer(INF_SESSION(session)) != NULL); inf_adopted_session_create_algorithm(session); break; case INF_SESSION_CLOSED: /* Session should not be initially closed */ default: g_assert_not_reached(); break; } /* Add initial local users. Note that this requires the algorithm to exist, * though in synchronizing state no local users can exist. */ inf_user_table_foreach_local_user( user_table, inf_adopted_session_constructed_foreach_local_user_func, session ); } static void inf_adopted_session_dispose(GObject* object) { InfAdoptedSession* session; InfAdoptedSessionPrivate* priv; InfUserTable* user_table; guint i; session = INF_ADOPTED_SESSION(object); priv = INF_ADOPTED_SESSION_PRIVATE(session); user_table = inf_session_get_user_table(INF_SESSION(session)); inf_signal_handlers_disconnect_by_func( G_OBJECT(user_table), G_CALLBACK(inf_adopted_session_add_local_user_cb), session ); inf_signal_handlers_disconnect_by_func( G_OBJECT(user_table), G_CALLBACK(inf_adopted_session_remove_local_user_cb), session ); if(priv->noop_timeout != NULL) { inf_io_remove_timeout(priv->io, priv->noop_timeout); priv->noop_timeout = NULL; } /* This calls the close vfunc if the session is running, in which we * free the local users. */ G_OBJECT_CLASS(inf_adopted_session_parent_class)->dispose(object); g_assert(priv->local_users == NULL); if(priv->request_buffer != NULL) { for(i = 0; i < priv->request_buffer->len; ++i) g_object_unref(g_ptr_array_index(priv->request_buffer, i)); g_ptr_array_free(priv->request_buffer, TRUE); priv->request_buffer = NULL; } if(priv->algorithm != NULL) { inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->algorithm), G_CALLBACK(inf_adopted_session_end_execute_request_cb), session ); g_object_unref(G_OBJECT(priv->algorithm)); priv->algorithm = NULL; } if(priv->io != NULL) { g_object_unref(G_OBJECT(priv->io)); priv->io = NULL; } } static void inf_adopted_session_finalize(GObject* object) { InfAdoptedSession* session; InfAdoptedSessionPrivate* priv; session = INF_ADOPTED_SESSION(object); priv = INF_ADOPTED_SESSION_PRIVATE(session); /* Should have been freed in close, called by dispose */ g_assert(priv->local_users == NULL); G_OBJECT_CLASS(inf_adopted_session_parent_class)->finalize(object); } static void inf_adopted_session_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfAdoptedSession* session; InfAdoptedSessionPrivate* priv; session = INF_ADOPTED_SESSION(object); priv = INF_ADOPTED_SESSION_PRIVATE(session); switch(prop_id) { case PROP_IO: g_assert(priv->io == NULL); /* construct only */ priv->io = INF_IO(g_value_dup_object(value)); break; case PROP_MAX_TOTAL_LOG_SIZE: priv->max_total_log_size = g_value_get_uint(value); break; case PROP_ALGORITHM: /* read only */ default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void inf_adopted_session_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfAdoptedSession* session; InfAdoptedSessionPrivate* priv; session = INF_ADOPTED_SESSION(object); priv = INF_ADOPTED_SESSION_PRIVATE(session); switch(prop_id) { case PROP_IO: g_value_set_object(value, G_OBJECT(priv->io)); break; case PROP_MAX_TOTAL_LOG_SIZE: g_value_set_uint(value, priv->max_total_log_size); break; case PROP_ALGORITHM: g_value_set_object(value, G_OBJECT(priv->algorithm)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } /* * VFunc implementations. */ static void inf_adopted_session_to_xml_sync_foreach_user_func(InfUser* user, gpointer user_data) { InfAdoptedRequestLog* log; InfAdoptedSessionToXmlSyncForeachData* data; InfAdoptedSessionClass* session_class; guint i; guint end; xmlNodePtr xml; InfAdoptedRequest* request; g_assert(INF_ADOPTED_IS_USER(user)); data = (InfAdoptedSessionToXmlSyncForeachData*)user_data; log = inf_adopted_user_get_request_log(INF_ADOPTED_USER(user)); end = inf_adopted_request_log_get_end(log); session_class = INF_ADOPTED_SESSION_GET_CLASS(data->session); g_assert(session_class->request_to_xml != NULL); for(i = inf_adopted_request_log_get_begin(log); i < end; ++ i) { request = inf_adopted_request_log_get_request(log, i); xml = xmlNewChild( data->parent_xml, NULL, (const xmlChar*)"sync-request", NULL ); /* TODO: Diff to previous request? */ session_class->request_to_xml(data->session, xml, request, NULL, TRUE); xmlAddChild(data->parent_xml, xml); } } static void inf_adopted_session_to_xml_sync(InfSession* session, xmlNodePtr parent) { InfAdoptedSessionPrivate* priv; InfAdoptedSessionToXmlSyncForeachData foreach_data; priv = INF_ADOPTED_SESSION_PRIVATE(session); g_assert(priv->algorithm != NULL); INF_SESSION_CLASS(inf_adopted_session_parent_class)->to_xml_sync( session, parent ); foreach_data.session = INF_ADOPTED_SESSION(session); foreach_data.parent_xml = parent; inf_user_table_foreach_user( inf_session_get_user_table(session), inf_adopted_session_to_xml_sync_foreach_user_func, &foreach_data ); } static gboolean inf_adopted_session_process_xml_sync(InfSession* session, InfXmlConnection* connection, const xmlNodePtr xml, GError** error) { InfAdoptedSessionClass* session_class; InfAdoptedRequest* request; InfAdoptedUser* user; InfAdoptedRequestLog* log; InfSessionClass* parent_class; if(strcmp((const char*)xml->name, "sync-request") == 0) { session_class = INF_ADOPTED_SESSION_GET_CLASS(session); g_assert(session_class->xml_to_request != NULL); request = session_class->xml_to_request( INF_ADOPTED_SESSION(session), xml, NULL, /* TODO: Diff to previous request, if any. */ TRUE, error ); if(request == NULL) return FALSE; user = INF_ADOPTED_USER( inf_user_table_lookup_user_by_id( inf_session_get_user_table(session), inf_adopted_request_get_user_id(request) ) ); log = inf_adopted_user_get_request_log(user); if(inf_adopted_session_validate_request(log, request, error) == FALSE) { g_object_unref(request); return FALSE; } inf_adopted_request_log_add_request(log, request); g_object_unref(request); return TRUE; } parent_class = INF_SESSION_CLASS(inf_adopted_session_parent_class); return parent_class->process_xml_sync(session, connection, xml, error); } static InfCommunicationScope inf_adopted_session_process_xml_run(InfSession* session, InfXmlConnection* connection, const xmlNodePtr xml, GError** error) { InfAdoptedSessionPrivate* priv; InfAdoptedSessionClass* session_class; InfAdoptedRequest* request; InfAdoptedUser* user; guint user_id; InfAdoptedStateVector* user_vector; InfAdoptedStateVector* request_vector; gboolean has_num; gboolean process_request; guint num; GError* local_error; InfAdoptedRequest* copy_req; guint i; gchar* request_str; gchar* user_str; InfSessionClass* parent_class; priv = INF_ADOPTED_SESSION_PRIVATE(session); if(strcmp((const char*)xml->name, "request") == 0) { session_class = INF_ADOPTED_SESSION_GET_CLASS(session); g_assert(session_class->xml_to_request != NULL); user = inf_adopted_session_user_from_request_xml( INF_ADOPTED_SESSION(session), xml, error ); if(user == NULL) return INF_COMMUNICATION_SCOPE_PTP; if(inf_user_get_status(INF_USER(user)) == INF_USER_UNAVAILABLE || inf_user_get_connection(INF_USER(user)) != connection) { g_set_error_literal( error, inf_user_error_quark(), INF_USER_ERROR_NOT_JOINED, _("User did not join from this connection") ); return INF_COMMUNICATION_SCOPE_PTP; } local_error = NULL; has_num = inf_xml_util_get_attribute_uint(xml, "num", &num, &local_error); if(local_error != NULL) { g_propagate_error(error, local_error); return INF_COMMUNICATION_SCOPE_PTP; } if(has_num == FALSE) num = 1; user_id = inf_user_get_id(INF_USER(user)); user_vector = inf_adopted_user_get_vector(user); request = session_class->xml_to_request( INF_ADOPTED_SESSION(session), xml, user_vector, FALSE, error ); if(request == NULL) return INF_COMMUNICATION_SCOPE_PTP; request_vector = inf_adopted_request_get_vector(request); if(!inf_adopted_state_vector_causally_before(user_vector, request_vector)) { /* Note that this can actually not happen, since the request time is * transferred as a diff to the previous user time. If the absolute * time were transmitted this would need to be handled as an error. */ g_assert_not_reached(); } else if(inf_adopted_request_get_index(request) != inf_adopted_state_vector_get(user_vector, user_id)) { request_str = inf_adopted_state_vector_to_string(request_vector); user_str = inf_adopted_state_vector_to_string(user_vector); g_set_error( error, inf_adopted_session_error_quark, INF_ADOPTED_SESSION_ERROR_INVALID_REQUEST, _("Request \"%s\" by user \"%s\" is not consecutive with respect to " "previously received request \"%s\""), request_str, inf_user_get_name(INF_USER(user)), user_str ); g_free(request_str); g_free(user_str); g_object_unref(request); return INF_COMMUNICATION_SCOPE_PTP; } /* Update the user vector to the state of the request. */ user_vector = inf_adopted_state_vector_copy(request_vector); /* Note that this function takes ownership of user_vector */ inf_adopted_user_set_vector(INF_ADOPTED_USER(user), user_vector); /* Apply the request more than once if num >= 2 is given. This is mostly * used for multiple undos and redos, but is in general allowed for any * request. */ for(i = 0; i < num; ++i) { if(i == 0) { copy_req = request; g_object_ref(copy_req); } else { copy_req = inf_adopted_request_copy(request); /* TODO: This is a bit of a hack since requests are normally * immutable. It avoids an additional vector copy here though. */ inf_adopted_state_vector_add( inf_adopted_request_get_vector(copy_req), inf_user_get_id(INF_USER(user)), i ); } process_request = inf_adopted_session_process_request( INF_ADOPTED_SESSION(session), copy_req, user, error ); g_object_unref(copy_req); /* Update the user vector again, including the component of the processed request. */ if(inf_adopted_request_affects_buffer(request)) { user_vector = inf_adopted_state_vector_copy( inf_adopted_request_get_vector(copy_req) ); inf_adopted_state_vector_add(user_vector, user_id, 1); /* Note that this function takes ownership of user_vector */ inf_adopted_user_set_vector(INF_ADOPTED_USER(user), user_vector); } /* If an error occured then break here, and do not process the * subsequent requests -- they will likely fail as well. */ if(process_request == FALSE) break; } g_object_unref(request); /* The processed request(s) might have caused some of the buffered * requests to become ready. */ if(i > 0) { inf_adopted_session_process_buffered_requests( INF_ADOPTED_SESSION(session) ); } /* Cleanup requests that are no longer used after * having processed everything */ inf_adopted_algorithm_cleanup( inf_adopted_session_get_algorithm(INF_ADOPTED_SESSION(session)) ); /* Requests can always be forwarded since user is given. Explicitly allow * forwarding if the request could not be applied... maybe others are more * lucky? In the worst case it will just fail for them as well. */ return INF_COMMUNICATION_SCOPE_GROUP; } parent_class = INF_SESSION_CLASS(inf_adopted_session_parent_class); return parent_class->process_xml_run(session, connection, xml, error); } static GArray* inf_adopted_session_get_xml_user_props(InfSession* session, InfXmlConnection* conn, const xmlNodePtr xml) { InfSessionClass* parent_class; GArray* array; GParameter* parameter; InfAdoptedStateVector* vector; xmlChar* time; parent_class = INF_SESSION_CLASS(inf_adopted_session_parent_class); array = parent_class->get_xml_user_props(session, conn, xml); /* Vector time */ time = inf_xml_util_get_attribute(xml, "time"); if(time != NULL) { vector = inf_adopted_state_vector_from_string((const gchar*)time, NULL); xmlFree(time); /* TODO: Error reporting for get_xml_user_props */ if(vector != NULL) { parameter = inf_session_get_user_property(array, "vector"); g_value_init(¶meter->value, INF_ADOPTED_TYPE_STATE_VECTOR); g_value_take_boxed(¶meter->value, vector); } } return array; } static void inf_adopted_session_set_xml_user_props(InfSession* session, const GParameter* params, guint n_params, xmlNodePtr xml) { InfSessionClass* parent_class; InfAdoptedSessionPrivate* priv; const GParameter* time; InfAdoptedStateVector* vector; gchar* time_string; const GParameter* id_param; guint id; GSList* item; InfAdoptedSessionLocalUser* local_user; parent_class = INF_SESSION_CLASS(inf_adopted_session_parent_class); parent_class->set_xml_user_props(session, params, n_params, xml); priv = INF_ADOPTED_SESSION_PRIVATE(INF_ADOPTED_SESSION(session)); time = inf_session_lookup_user_property(params, n_params, "vector"); if(time != NULL) { /* If this is a local user, use last_send_vector instead of the user's * vector, so that subsequent differential updates are consistent. */ vector = NULL; id_param = inf_session_lookup_user_property(params, n_params, "id"); if(id_param != NULL) { id = g_value_get_uint(&id_param->value); for(item = priv->local_users; item != NULL; item = item->next) { local_user = (InfAdoptedSessionLocalUser*)item->data; if(inf_user_get_id(INF_USER(local_user->user)) == id) { vector = local_user->last_send_vector; break; } } } if(vector == NULL) { /* remote user, or a user join request */ vector = (InfAdoptedStateVector*)g_value_get_boxed(&time->value); } time_string = inf_adopted_state_vector_to_string(vector); inf_xml_util_set_attribute(xml, "time", time_string); g_free(time_string); } } static gboolean inf_adopted_session_validate_user_props(InfSession* session, const GParameter* params, guint n_params, InfUser* exclude, GError** error) { InfSessionClass* parent_class; const GParameter* time; gboolean result; parent_class = INF_SESSION_CLASS(inf_adopted_session_parent_class); result = parent_class->validate_user_props( session, params, n_params, exclude, error ); if(result == FALSE) return FALSE; time = inf_session_lookup_user_property(params, n_params, "vector"); if(time == NULL) { g_set_error_literal( error, inf_adopted_session_error_quark, INF_ADOPTED_SESSION_ERROR_MISSING_STATE_VECTOR, _("\"time\" attribute in user message is missing") ); return FALSE; } return TRUE; } static void inf_adopted_session_close(InfSession* session) { InfAdoptedSessionPrivate* priv; InfAdoptedSessionLocalUser* local; GSList* item; priv = INF_ADOPTED_SESSION_PRIVATE(session); /* Local user info is no longer required */ for(item = priv->local_users; item != NULL; item = g_slist_next(item)) { local = (InfAdoptedSessionLocalUser*)item->data; inf_adopted_state_vector_free(local->last_send_vector); g_slice_free(InfAdoptedSessionLocalUser, local); } g_slist_free(priv->local_users); priv->local_users = NULL; INF_SESSION_CLASS(inf_adopted_session_parent_class)->close(session); } static void inf_adopted_session_synchronization_complete_foreach_user_func(InfUser* user, gpointer data) { InfAdoptedRequestLog* log; log = inf_adopted_user_get_request_log(INF_ADOPTED_USER(user)); /* Set begin index of empty request logs. Algorithm relies on * inf_adopted_request_log_get_begin() to return the index of the request * that will first be added to the request log. */ if(inf_adopted_request_log_is_empty(log)) { inf_adopted_request_log_set_begin( log, inf_adopted_state_vector_get( inf_adopted_user_get_vector(INF_ADOPTED_USER(user)), inf_user_get_id(user) ) ); } } static void inf_adopted_session_synchronization_complete(InfSession* session, InfXmlConnection* connection) { InfSessionClass* parent_class; InfAdoptedSessionPrivate* priv; InfSessionStatus status; priv = INF_ADOPTED_SESSION_PRIVATE(session); status = inf_session_get_status(session); g_object_freeze_notify(G_OBJECT(session)); parent_class = INF_SESSION_CLASS(inf_adopted_session_parent_class); parent_class->synchronization_complete(session, connection); if(status == INF_SESSION_SYNCHRONIZING) { inf_user_table_foreach_user( inf_session_get_user_table(session), inf_adopted_session_synchronization_complete_foreach_user_func, NULL ); /* Create adOPTed algorithm upon successful synchronization */ g_assert(priv->algorithm == NULL); inf_adopted_session_create_algorithm(INF_ADOPTED_SESSION(session)); } g_object_thaw_notify(G_OBJECT(session)); } static gboolean inf_adopted_session_check_request(InfAdoptedSession* session, InfAdoptedRequest* request, InfAdoptedUser* user) { /* Accept all requests by default */ return FALSE; } /* * Gype registration. */ static void inf_adopted_session_class_init(InfAdoptedSessionClass* adopted_session_class) { GObjectClass* object_class; InfSessionClass* session_class; object_class = G_OBJECT_CLASS(adopted_session_class); session_class = INF_SESSION_CLASS(adopted_session_class); object_class->constructed = inf_adopted_session_constructed; object_class->dispose = inf_adopted_session_dispose; object_class->finalize = inf_adopted_session_finalize; object_class->set_property = inf_adopted_session_set_property; object_class->get_property = inf_adopted_session_get_property; session_class->to_xml_sync = inf_adopted_session_to_xml_sync; session_class->process_xml_sync = inf_adopted_session_process_xml_sync; session_class->process_xml_run = inf_adopted_session_process_xml_run; session_class->get_xml_user_props = inf_adopted_session_get_xml_user_props; session_class->set_xml_user_props = inf_adopted_session_set_xml_user_props; session_class->validate_user_props = inf_adopted_session_validate_user_props; session_class->close = inf_adopted_session_close; session_class->synchronization_complete = inf_adopted_session_synchronization_complete; adopted_session_class->xml_to_request = NULL; adopted_session_class->request_to_xml = NULL; adopted_session_class->check_request = inf_adopted_session_check_request; inf_adopted_session_error_quark = g_quark_from_static_string( "INF_ADOPTED_SESSION_ERROR" ); /** * InfAdoptedSession::check-request: * @session: The #InfAdoptedSession which is about to process a request. * @request: The request to be processed. * @user: The user who issued the request. * * This signal is emitted whenever the session received a request from a * non-local user. It is used to decide whether the request should be * processed or not. Note that generally not processing a request results is * loss of synchronization, since other hosts might process the request. * Only if the same condition can be applied on all sites a request should * be rejected. Another possibility is to reject a request at a central host * before it gets distributed to all other clients. If there is one signal * handler returning %TRUE the request is rejected, i.e. only if all signal * handlers return %FALSE it is accepted. */ session_signals[CHECK_REQUEST] = g_signal_new( "check-request", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfAdoptedSessionClass, check_request), g_signal_accumulator_true_handled, NULL, NULL, G_TYPE_BOOLEAN, 2, INF_ADOPTED_TYPE_REQUEST, INF_ADOPTED_TYPE_USER ); g_object_class_install_property( object_class, PROP_IO, g_param_spec_object( "io", "IO", "The IO object used for timeouts", INF_TYPE_IO, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_MAX_TOTAL_LOG_SIZE, g_param_spec_uint( "max-total-log-size", "Maxmimum total log size", "The maximum number of requests to keep in all user's logs", 0, G_MAXUINT, 2048, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_ALGORITHM, g_param_spec_object( "algorithm", "Algorithm", "The adOPTed algorithm used for translating incoming requests", INF_ADOPTED_TYPE_ALGORITHM, G_PARAM_READABLE ) ); } /* * Public API. */ /** * inf_adopted_session_get_io: * @session: A #InfAdoptedSession. * * Returns the #InfIo object of @session. * * Returns: (transfer none): A #InfIo. **/ InfIo* inf_adopted_session_get_io(InfAdoptedSession* session) { g_return_val_if_fail(INF_ADOPTED_IS_SESSION(session), NULL); return INF_ADOPTED_SESSION_PRIVATE(session)->io; } /** * inf_adopted_session_get_algorithm: * @session: A #InfAdoptedSession. * * Returns the #InfAdoptedAlgorithm object of @session. Returns %NULL if * @session has status %INF_SESSION_PRESYNC or %INF_SESSION_SYNCHRONIZING * because there the algorithm object is not yet created before successful * synchronization. * * Returns: (transfer none): A #InfAdoptedAlgorithm, or %NULL. **/ InfAdoptedAlgorithm* inf_adopted_session_get_algorithm(InfAdoptedSession* session) { g_return_val_if_fail(INF_ADOPTED_IS_SESSION(session), NULL); return INF_ADOPTED_SESSION_PRIVATE(session)->algorithm; } /** * inf_adopted_session_broadcast_request: * @session: A #InfAdoptedSession. * @request: A #InfAdoptedRequest obtained from @session's algorithm. * * Sends a request to all subscribed connections. The request should originate * from a call to inf_adopted_algorithm_generate_request(), with * @session's #InfAdoptedAlgorithm. **/ void inf_adopted_session_broadcast_request(InfAdoptedSession* session, InfAdoptedRequest* request) { g_return_if_fail(INF_ADOPTED_IS_SESSION(session)); g_return_if_fail(INF_ADOPTED_IS_REQUEST(request)); inf_adopted_session_broadcast_n_requests(session, request, 1); } /** * inf_adopted_session_undo: * @session: A #InfAdoptedSession. * @user: A local #InfAdoptedUser. * @n: The number of undo requests to issue. * * This is a shortcut for creating @n undo requests and broadcasting them. * If @n > 1 then this is also more efficient. **/ void inf_adopted_session_undo(InfAdoptedSession* session, InfAdoptedUser* user, guint n) { InfAdoptedSessionPrivate* priv; InfAdoptedRequest* first_request; InfAdoptedRequest* request; guint i; gboolean result; g_return_if_fail(INF_ADOPTED_IS_SESSION(session)); g_return_if_fail(INF_ADOPTED_IS_USER(user)); g_return_if_fail(n >= 1); /* TODO: Check whether we can issue n undo requests before doing anything */ priv = INF_ADOPTED_SESSION_PRIVATE(session); first_request = NULL; for(i = 0; i < n; ++i) { request = inf_adopted_algorithm_generate_request( priv->algorithm, INF_ADOPTED_REQUEST_UNDO, user, NULL ); result = inf_adopted_algorithm_execute_request( priv->algorithm, request, TRUE, NULL ); /* This cannot fail if the input parameters have been checked before. */ g_assert(result == TRUE); if(first_request == NULL) first_request = request; else g_object_unref(request); } inf_adopted_session_broadcast_n_requests(session, first_request, n); g_object_unref(first_request); } /** * inf_adopted_session_redo: * @session: A #InfAdoptedSession. * @user: A local #InfAdoptedUser. * @n: The number of redo requests to issue. * * This is a shortcut for creating @n redo requests and broadcasting them. * If @n > 1 then this is also more efficient. **/ void inf_adopted_session_redo(InfAdoptedSession* session, InfAdoptedUser* user, guint n) { InfAdoptedSessionPrivate* priv; InfAdoptedRequest* first_request; InfAdoptedRequest* request; guint i; gboolean result; /* TODO: Check whether we can issue n redo requests before doing anything */ g_return_if_fail(INF_ADOPTED_IS_SESSION(session)); g_return_if_fail(INF_ADOPTED_IS_USER(user)); g_return_if_fail(n >= 1); priv = INF_ADOPTED_SESSION_PRIVATE(session); first_request = NULL; for(i = 0; i < n; ++i) { request = inf_adopted_algorithm_generate_request( priv->algorithm, INF_ADOPTED_REQUEST_REDO, user, NULL ); result = inf_adopted_algorithm_execute_request( priv->algorithm, request, TRUE, NULL ); /* This cannot fail if the input parameters have been checked before. */ g_assert(result == TRUE); if(first_request == NULL) first_request = request; else g_object_unref(request); } inf_adopted_session_broadcast_n_requests(session, first_request, n); g_object_unref(first_request); } /** * inf_adopted_session_read_request_info: * @session: A #InfAdoptedSession. * @xml: The XML to read the data from. * @diff_vec: The reference vector of the time vector of the request, or %NULL. * @user: (out) (transfer none) (allow-none): Location to store the user of * the request, or %NULL. * @time: (out) (transfer full) (allow-none): Location to store the state the * request was made, or %NULL. * @operation: (out) (transfer none) (allow-none): Location to store the * operation of the request, or %NULL. * @error: Location to place an error, if any. * * This function reads common information such as the state vector the request * was made and the user that made the request from XML. It is most likely to * be used by implementations of the xml_to_request virtual function. * * Returns: %TRUE if the data could be read successfully, %FALSE if the XML * request does not contain valid request data, in which case @error is set. */ gboolean inf_adopted_session_read_request_info(InfAdoptedSession* session, xmlNodePtr xml, InfAdoptedStateVector* diff_vec, InfAdoptedUser** user, InfAdoptedStateVector** time, xmlNodePtr* operation, GError** error) { xmlChar* attr; xmlNodePtr child; if(user != NULL) { *user = inf_adopted_session_user_from_request_xml(session, xml, error); if(*user == NULL) return FALSE; } if(time != NULL) { attr = inf_xml_util_get_attribute_required(xml, "time", error); if(attr == NULL) return FALSE; if(diff_vec == NULL) { *time = inf_adopted_state_vector_from_string((const gchar*)attr, error); } else { *time = inf_adopted_state_vector_from_string_diff( (const gchar*)attr, diff_vec, error ); } xmlFree(attr); if(*time == NULL) return FALSE; } if(operation != NULL) { /* Get first child element */ child = xml->children; while(child != NULL && child->type != XML_ELEMENT_NODE) child = child->next; if(child == NULL) { g_set_error_literal( error, inf_adopted_session_error_quark, INF_ADOPTED_SESSION_ERROR_MISSING_OPERATION, _("Operation for request missing") ); if(time) inf_adopted_state_vector_free(*time); return FALSE; } *operation = child; } return TRUE; } /** * inf_adopted_session_write_request_info: * @session: A #InfAdoptedSession. * @diff_vec: A reference state vector, or %NULL. * @request: The #InfAdoptedRequest whose info to write. * @xml: The XML node to write the data into. * @operation: An XML node representing the operation of the request, or * %NULL. * * This function writes common data from @request, such as the user that * issued the request and the state in which the request was made into @xml. * If @diff_vec is given, then the state is written as a diff to this vector, * see inf_adopted_state_vector_to_string_diff(). Deserializing this data * again (via inf_adopted_session_read_request_info()) requires the same * @diff_vec then. * * This function is most likely to be used by implementations of the * request_to_xml virtual function. */ void inf_adopted_session_write_request_info(InfAdoptedSession* session, InfAdoptedRequest* request, InfAdoptedStateVector* diff_vec, xmlNodePtr xml, xmlNodePtr operation) { InfAdoptedStateVector* vector; guint user_id; gchar* vec_str; vector = inf_adopted_request_get_vector(request); user_id = inf_adopted_request_get_user_id(request); inf_xml_util_set_attribute_uint(xml, "user", user_id); if(diff_vec == NULL) vec_str = inf_adopted_state_vector_to_string(vector); else vec_str = inf_adopted_state_vector_to_string_diff(vector, diff_vec); inf_xml_util_set_attribute(xml, "time", vec_str); g_free(vec_str); if(operation != NULL) xmlAddChild(xml, operation); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/adopted/PaxHeaders.26529/inf-adopted-algorithm.c0000644000000000000000000000013213034342512024062 xustar0030 mtime=1483851082.021718383 30 atime=1483851082.021718383 30 ctime=1488261589.020139022 libinfinity-0.7.1/libinfinity/adopted/inf-adopted-algorithm.c0000644000175000017500000020765513034342512024633 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-adopted-algorithm * @title: InfAdoptedAlgorithm * @short_description: adOPTed implementation * @include: libinfinity/adopted/inf-adopted-algorithm.h * @stability: Unstable * @see_also: #InfAdoptedSession * * #InfAdoptedAlgorithm implements the adOPTed algorithm for concurrency * control as described in the paper "An integrating, transformation-oriented * approach to concurrency control and undo in group editors" by Matthias * Ressel, Doris Nitsche-Ruhland and Rul Gunzenhäuser * (http://portal.acm.org/citation.cfm?id=240305). * * It is based on requests, represented by the #InfAdoptedRequest class. If * there is at least one local #InfUser in the algorithm's user table, then * you can create own requests with the * inf_adopted_algorithm_generate_request() function. * Remote requests can be applied via * inf_adopted_algorithm_execute_request(). This class does not take care of * transfering the generated requests to other users which is the scope of * #InfAdoptedSession. * * The implementation is not tied to text editing. It can handle any * operations implementing #InfAdoptedOperation as long as they define * sufficient transformation functions. The libinftext library provides * operations for text editing, see #InfTextInsertOperation and * #InfTextDeleteOperation. **/ /* This class implements the adOPTed algorithm as described in the paper * "An integrating, transformation-oriented approach to concurrency control * and undo in group editors" by Matthias Ressel, Doris Nitsche-Ruhland * and Rul Gunzenhäuser (http://portal.acm.org/citation.cfm?id=240305). * * "Reducing the Problems of Group Undo" by Matthias Ressel and Rul * Gunzenhäuser (http://portal.acm.org/citation.cfm?doid=320297.320312) * might also be worth a read to (better) understand how local group undo * is achieved. */ /* TODO: Do only cleanup if too much entries in cache? */ /* TODO: If users are not issuing any requests for some time, and we can be * sure that we do not need to transform any requests, then remove them from * the users array (users_begin, users_end). Readd users as soon as they * issue buffer-altering requests. This way we keep the asymptotic complexity * dynamically as O(active users^2). */ #include #include #include typedef struct _InfAdoptedAlgorithmLocalUser InfAdoptedAlgorithmLocalUser; struct _InfAdoptedAlgorithmLocalUser { InfAdoptedUser* user; gboolean can_undo; gboolean can_redo; }; typedef struct _InfAdoptedAlgorithmPrivate InfAdoptedAlgorithmPrivate; struct _InfAdoptedAlgorithmPrivate { /* request log policy */ guint max_total_log_size; InfAdoptedStateVector* current; InfAdoptedStateVector* buffer_modified_time; InfAdoptedRequest* execute_request; InfUserTable* user_table; InfBuffer* buffer; /* Users in user table. We need to iterate over them very often, so we * keep them as array here. */ InfAdoptedUser** users_begin; InfAdoptedUser** users_end; GSList* local_users; }; enum { PROP_0, /* construct only */ PROP_USER_TABLE, PROP_BUFFER, PROP_MAX_TOTAL_LOG_SIZE, /* read/only */ PROP_CURRENT_STATE, PROP_BUFFER_MODIFIED_STATE }; enum { CAN_UNDO_CHANGED, CAN_REDO_CHANGED, BEGIN_EXECUTE_REQUEST, END_EXECUTE_REQUEST, LAST_SIGNAL }; #define INF_ADOPTED_ALGORITHM_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INF_ADOPTED_TYPE_ALGORITHM, InfAdoptedAlgorithmPrivate)) #define INF_ADOPTED_ALGORITHM_PRIVATE(obj) ((InfAdoptedAlgorithmPrivate*)(obj)->priv) static guint algorithm_signals[LAST_SIGNAL]; G_DEFINE_TYPE_WITH_CODE(InfAdoptedAlgorithm, inf_adopted_algorithm, G_TYPE_OBJECT, G_ADD_PRIVATE(InfAdoptedAlgorithm)) /* Returns a new state vector v so that both first and second are causally * before v and so that there is no other state vector with the same property * that is causally before v. */ /* TODO: Move this to state vector, possibly with a faster O(n) * implementation (This is O(n log n), at best) */ static InfAdoptedStateVector* inf_adopted_algorithm_least_common_successor(InfAdoptedAlgorithm* algorithm, InfAdoptedStateVector* first, InfAdoptedStateVector* second) { InfAdoptedAlgorithmPrivate* priv; InfAdoptedUser** user; InfAdoptedStateVector* result; guint id; priv = INF_ADOPTED_ALGORITHM_PRIVATE(algorithm); result = inf_adopted_state_vector_new(); for(user = priv->users_begin; user != priv->users_end; ++ user) { id = inf_user_get_id(INF_USER(*user)); inf_adopted_state_vector_set( result, id, MAX( inf_adopted_state_vector_get(first, id), inf_adopted_state_vector_get(second, id) ) ); } g_assert(inf_adopted_state_vector_causally_before(first, result)); g_assert(inf_adopted_state_vector_causally_before(second, result)); return result; } /* Returns a new state vector v so that v is both causally before first and * second and so that there is no other state vector with the same property * so that v is causally before that vector. */ /* TODO: Move this to state vector, possibly with a faster O(n) * implementation (This is O(n log n), at best) */ /* TODO: A version modifying first instead of returning a new result, * use in inf_adopted_algorithm_cleanup(). */ static InfAdoptedStateVector* inf_adopted_algorithm_least_common_predecessor(InfAdoptedAlgorithm* algorithm, InfAdoptedStateVector* first, InfAdoptedStateVector* second) { InfAdoptedAlgorithmPrivate* priv; InfAdoptedUser** user; InfAdoptedStateVector* result; guint id; priv = INF_ADOPTED_ALGORITHM_PRIVATE(algorithm); result = inf_adopted_state_vector_new(); for(user = priv->users_begin; user != priv->users_end; ++ user) { id = inf_user_get_id(INF_USER(*user)); inf_adopted_state_vector_set( result, id, MIN( inf_adopted_state_vector_get(first, id), inf_adopted_state_vector_get(second, id) ) ); } return result; } /* Checks whether the given request can be undone (or redone if it is an * undo request). In general, a user can perform an undo when * there is a request to undo in the request log. However, if there are too * much requests between it and the latest request (as determined by * max_total_log_size) we cannot issue an undo because others might already * have dropped that request from their request log (and therefore no longer * compute the Undo operation). */ static gboolean inf_adopted_algorithm_can_undo_redo(InfAdoptedAlgorithm* algorithm, InfAdoptedUser* user, InfAdoptedRequest* request) { InfAdoptedAlgorithmPrivate* priv; InfAdoptedRequestLog* log; guint diff; priv = INF_ADOPTED_ALGORITHM_PRIVATE(algorithm); if(request != NULL) { if(priv->max_total_log_size != G_MAXUINT) { log = inf_adopted_user_get_request_log(user); request = inf_adopted_request_log_original_request(log, request); /* TODO: If other requests need to be undone or redone before request * can be undone or redone, then we need to include these in the * vdiff. */ diff = inf_adopted_state_vector_vdiff( inf_adopted_request_get_vector(request), inf_adopted_user_get_vector(user) ); if(diff >= priv->max_total_log_size) return FALSE; else return TRUE; } else { /* unlimited */ return TRUE; } } else { /* no request to undo */ return FALSE; } } /* Updates the can_undo and can_redo fields of the * InfAdoptedAlgorithmLocalUsers. */ static void inf_adopted_algorithm_update_undo_redo(InfAdoptedAlgorithm* algorithm) { InfAdoptedAlgorithmPrivate* priv; InfAdoptedAlgorithmLocalUser* local; InfAdoptedRequestLog* log; GSList* item; gboolean can_undo; gboolean can_redo; priv = INF_ADOPTED_ALGORITHM_PRIVATE(algorithm); for(item = priv->local_users; item != NULL; item = g_slist_next(item)) { local = item->data; log = inf_adopted_user_get_request_log(local->user); can_undo = inf_adopted_algorithm_can_undo_redo( algorithm, local->user, inf_adopted_request_log_next_undo(log) ); can_redo = inf_adopted_algorithm_can_undo_redo( algorithm, local->user, inf_adopted_request_log_next_redo(log) ); if(local->can_undo != can_undo) { g_signal_emit( G_OBJECT(algorithm), algorithm_signals[CAN_UNDO_CHANGED], 0, local->user, can_undo ); } if(local->can_redo != can_redo) { g_signal_emit( G_OBJECT(algorithm), algorithm_signals[CAN_REDO_CHANGED], 0, local->user, can_redo ); } } } static InfAdoptedAlgorithmLocalUser* inf_adopted_algorithm_find_local_user(InfAdoptedAlgorithm* algorithm, InfAdoptedUser* user) { InfAdoptedAlgorithmPrivate* priv; GSList* item; InfAdoptedAlgorithmLocalUser* local; priv = INF_ADOPTED_ALGORITHM_PRIVATE(algorithm); for(item = priv->local_users; item != NULL; item = g_slist_next(item)) { local = (InfAdoptedAlgorithmLocalUser*)item->data; if(local->user == user) return local; } return NULL; } static void inf_adopted_algorithm_local_user_free(InfAdoptedAlgorithm* algorithm, InfAdoptedAlgorithmLocalUser* local) { InfAdoptedAlgorithmPrivate* priv; priv = INF_ADOPTED_ALGORITHM_PRIVATE(algorithm); priv->local_users = g_slist_remove(priv->local_users, local); g_slice_free(InfAdoptedAlgorithmLocalUser, local); } static void inf_adopted_algorithm_add_user(InfAdoptedAlgorithm* algorithm, InfAdoptedUser* user) { InfAdoptedAlgorithmPrivate* priv; InfAdoptedRequestLog* log; InfAdoptedStateVector* time; guint user_count; priv = INF_ADOPTED_ALGORITHM_PRIVATE(algorithm); log = inf_adopted_user_get_request_log(user); time = inf_adopted_user_get_vector(user); inf_adopted_state_vector_set( priv->current, inf_user_get_id(INF_USER(user)), inf_adopted_state_vector_get(time, inf_user_get_id(INF_USER(user))) ); user_count = (priv->users_end - priv->users_begin) + 1; priv->users_begin = g_realloc(priv->users_begin, sizeof(InfAdoptedUser*) * user_count); priv->users_end = priv->users_begin + user_count; priv->users_begin[user_count - 1] = user; } static void inf_adopted_algorithm_add_local_user(InfAdoptedAlgorithm* algorithm, InfAdoptedUser* user) { InfAdoptedAlgorithmPrivate* priv; InfAdoptedAlgorithmLocalUser* local; InfAdoptedRequestLog* log; priv = INF_ADOPTED_ALGORITHM_PRIVATE(algorithm); local = g_slice_new(InfAdoptedAlgorithmLocalUser); local->user = user; log = inf_adopted_user_get_request_log(user); local->can_undo = inf_adopted_algorithm_can_undo_redo( algorithm, user, inf_adopted_request_log_next_undo(log) ); local->can_redo = inf_adopted_algorithm_can_undo_redo( algorithm, user, inf_adopted_request_log_next_redo(log) ); priv->local_users = g_slist_prepend(priv->local_users, local); } static void inf_adopted_algorithm_add_user_cb(InfUserTable* user_table, InfUser* user, gpointer user_data) { InfAdoptedAlgorithm* algorithm; algorithm = INF_ADOPTED_ALGORITHM(user_data); g_assert(INF_ADOPTED_IS_USER(user)); inf_adopted_algorithm_add_user(algorithm, INF_ADOPTED_USER(user)); } static void inf_adopted_algorithm_add_local_user_cb(InfUserTable* user_table, InfUser* user, gpointer user_data) { InfAdoptedAlgorithm* algorithm; algorithm = INF_ADOPTED_ALGORITHM(user_data); g_assert(INF_ADOPTED_IS_USER(user)); inf_adopted_algorithm_add_local_user(algorithm, INF_ADOPTED_USER(user)); } static void inf_adopted_algorithm_remove_local_user_cb(InfUserTable* user_table, InfUser* user, gpointer user_data) { InfAdoptedAlgorithm* algorithm; InfAdoptedAlgorithmPrivate* priv; InfAdoptedAlgorithmLocalUser* local; algorithm = INF_ADOPTED_ALGORITHM(user_data); priv = INF_ADOPTED_ALGORITHM_PRIVATE(algorithm); local = inf_adopted_algorithm_find_local_user(algorithm, INF_ADOPTED_USER(user)); g_assert(local != NULL); inf_adopted_algorithm_local_user_free(algorithm, local); } /* Checks whether two states are equivalent, meaning one can be reached from * the other just by folding. */ static gboolean inf_adopted_algorithm_buffer_states_equivalent(InfAdoptedAlgorithm* algorithm, InfAdoptedStateVector* first, InfAdoptedStateVector* second) { InfAdoptedAlgorithmPrivate* priv; InfAdoptedUser** user_it; InfAdoptedUser* user; InfAdoptedRequest* request; InfAdoptedRequestLog* log; guint user_id; guint first_n; guint second_n; g_assert(inf_adopted_state_vector_causally_before(first, second)); priv = INF_ADOPTED_ALGORITHM_PRIVATE(algorithm); for(user_it = priv->users_begin; user_it != priv->users_end; ++ user_it) { user = *user_it; user_id = inf_user_get_id(INF_USER(user)); log = inf_adopted_user_get_request_log(user); first_n = inf_adopted_state_vector_get(first, user_id); second_n = inf_adopted_state_vector_get(second, user_id); /* TODO: This algorithm can probably be optimized by moving it into * request log. */ while(second_n > first_n) { /* If we dropped too much state, then we can't say whether the two * states are equivalent. Assume they aren't. */ if(second_n <= inf_adopted_request_log_get_begin(log)) return FALSE; request = inf_adopted_request_log_get_request(log, second_n - 1); if(inf_adopted_request_get_request_type(request) == INF_ADOPTED_REQUEST_DO) { return FALSE; } else { request = inf_adopted_request_log_prev_associated(log, request); second_n = inf_adopted_state_vector_get( inf_adopted_request_get_vector(request), user_id ); } } if(second_n < first_n) return FALSE; } return TRUE; } static void inf_adopted_algorithm_buffer_notify_modified_cb(GObject* object, GParamSpec* pspec, gpointer user_data) { InfAdoptedAlgorithm* algorithm; InfAdoptedAlgorithmPrivate* priv; gboolean equivalent; algorithm = INF_ADOPTED_ALGORITHM(user_data); priv = INF_ADOPTED_ALGORITHM_PRIVATE(algorithm); if(inf_buffer_get_modified(INF_BUFFER(object))) { if(priv->buffer_modified_time != NULL) { /* If the current state is equivalent to the one the buffer has changed * the modified flag the last time, then the modified flag actually * changed. Otherwise, we got notified without the flag actually * changing. This should not happen normally, but we would lose * information about when the buffer has been non-modified the last * time otherwise. */ equivalent = inf_adopted_algorithm_buffer_states_equivalent( algorithm, priv->buffer_modified_time, priv->current ); if(equivalent == TRUE) { inf_adopted_state_vector_free(priv->buffer_modified_time); priv->buffer_modified_time = NULL; } } } else { if(priv->buffer_modified_time != NULL) inf_adopted_state_vector_free(priv->buffer_modified_time); /* Buffer is not modified anymore */ priv->buffer_modified_time = inf_adopted_state_vector_copy(priv->current); } } static void inf_adopted_algorithm_update_local_user_times(InfAdoptedAlgorithm* algorithm) { /* TODO: I don't think we even need this because we could treat local * users implicitely as in-sync with priv->current. It would make some loops * a bit more complex, perhaps. * * Alternative: Let the local users just point to priv->current. */ InfAdoptedAlgorithmPrivate* priv; InfAdoptedAlgorithmLocalUser* local; GSList* item; priv = INF_ADOPTED_ALGORITHM_PRIVATE(algorithm); for(item = priv->local_users; item != NULL; item = g_slist_next(item)) { local = item->data; inf_adopted_user_set_vector( local->user, inf_adopted_state_vector_copy(priv->current) ); } } /* We can cache requests if: * a) they are reversible. If they are not, they will be made reversible * later (see inf_adopted_algorithm_execute_request), but the algorithm relies * on cached requests being reversible. * b) they affect the buffer. If they do not, then they will not be used for * later transformations anyway. */ static gboolean inf_adopted_algorithm_can_cache(InfAdoptedRequest* request) { InfAdoptedOperation* operation; InfAdoptedOperationFlags flags; #define INF_ADOPTED_OPERATION_CACHABLE \ (INF_ADOPTED_OPERATION_AFFECTS_BUFFER | INF_ADOPTED_OPERATION_REVERSIBLE) if(inf_adopted_request_get_request_type(request) != INF_ADOPTED_REQUEST_DO) return TRUE; operation = inf_adopted_request_get_operation(request); flags = inf_adopted_operation_get_flags(operation) & INF_ADOPTED_OPERATION_CACHABLE; return flags == INF_ADOPTED_OPERATION_CACHABLE; } /* Translates two requests to state at and then transforms them against each * other. The result needs to be unref()ed. */ static InfAdoptedRequest* inf_adopted_algorithm_transform_request(InfAdoptedAlgorithm* algorithm, InfAdoptedRequest* request, InfAdoptedRequest* against, InfAdoptedStateVector* at) { InfAdoptedRequest* request_at; InfAdoptedRequest* against_at; InfAdoptedConcurrencyId concurrency_id; InfAdoptedStateVector* lcs; InfAdoptedRequest* lcs_against; InfAdoptedRequest* lcs_request; InfAdoptedRequest* result; g_assert( inf_adopted_state_vector_causally_before( inf_adopted_request_get_vector(request), at ) ); g_assert( inf_adopted_state_vector_causally_before( inf_adopted_request_get_vector(against), at ) ); against_at = inf_adopted_algorithm_translate_request( algorithm, against, at ); request_at = inf_adopted_algorithm_translate_request( algorithm, request, at ); concurrency_id = INF_ADOPTED_CONCURRENCY_NONE; if(inf_adopted_request_need_concurrency_id(request_at, against_at) == TRUE) { lcs = inf_adopted_algorithm_least_common_successor( algorithm, inf_adopted_request_get_vector(request), inf_adopted_request_get_vector(against) ); g_assert(inf_adopted_state_vector_causally_before(lcs, at)); if(inf_adopted_state_vector_compare(lcs, at) != 0) { lcs_against = inf_adopted_algorithm_translate_request( algorithm, against, lcs ); lcs_request = inf_adopted_algorithm_translate_request( algorithm, request, lcs ); } else { lcs_against = against_at; lcs_request = request_at; g_object_ref(lcs_against); g_object_ref(lcs_request); } inf_adopted_state_vector_free(lcs); } else { lcs_against = NULL; lcs_request = NULL; } result = inf_adopted_request_transform( request_at, against_at, lcs_request, lcs_against ); if(lcs_request != NULL) g_object_unref(lcs_request); if(lcs_against != NULL) g_object_unref(lcs_against); g_object_unref(request_at); g_object_unref(against_at); return result; } static InfAdoptedRequest* inf_adopted_algorithm_translate_request_forward(InfAdoptedAlgorithm* algorithm, InfAdoptedRequest* request, InfAdoptedStateVector* to) { InfAdoptedAlgorithmPrivate* priv; InfAdoptedUser** user_it; InfAdoptedUser* user; InfAdoptedRequestLog* log; guint user_id; InfAdoptedRequest* cur_req; InfAdoptedRequest* next_req; InfAdoptedStateVector* vector; InfAdoptedRequest* index; InfAdoptedRequest* associated; InfAdoptedRequest* translated; InfAdoptedStateVector* associated_vector; guint from_n; guint to_n; guint associated_index; priv = INF_ADOPTED_ALGORITHM_PRIVATE(algorithm); cur_req = request; vector = inf_adopted_request_get_vector(cur_req); g_object_ref(cur_req); while(inf_adopted_state_vector_compare(vector, to) != 0) { next_req = NULL; g_assert(inf_adopted_state_vector_causally_before(vector, to) == TRUE); for(user_it = priv->users_begin; user_it != priv->users_end; ++user_it) { user = *user_it; user_id = inf_user_get_id(INF_USER(user)); if(user_id == inf_adopted_request_get_user_id(cur_req)) continue; from_n = inf_adopted_state_vector_get(vector, user_id); to_n = inf_adopted_state_vector_get(to, user_id); g_assert(from_n <= to_n); if(from_n == to_n) continue; log = inf_adopted_user_get_request_log(user); g_assert(from_n >= inf_adopted_request_log_get_begin(log)); g_assert(to_n <= inf_adopted_request_log_get_end(log)); index = inf_adopted_request_log_get_request(log, from_n); associated = inf_adopted_request_log_next_associated(log, index); if(associated != NULL && inf_adopted_request_get_index(associated) < to_n) { next_req = inf_adopted_request_fold( cur_req, user_id, inf_adopted_request_get_index(associated) - from_n + 1 ); break; } else { /* Cannot fold, so transform, if possible. */ associated = inf_adopted_request_log_original_request(log, index); associated_vector = inf_adopted_request_get_vector(associated); if(inf_adopted_state_vector_causally_before(associated_vector, vector)) { translated = inf_adopted_algorithm_translate_request( algorithm, associated, vector ); next_req = inf_adopted_algorithm_transform_request( algorithm, cur_req, translated, vector ); g_object_unref(translated); break; } } } /* Late Mirror, only if no transformations or folds possible */ if(next_req == NULL) { user_id = inf_adopted_request_get_user_id(cur_req); user = INF_ADOPTED_USER( inf_user_table_lookup_user_by_id(priv->user_table, user_id) ); log = inf_adopted_user_get_request_log(user); from_n = inf_adopted_request_get_index(cur_req); to_n = inf_adopted_state_vector_get(to, user_id); index = inf_adopted_request_log_get_request(log, from_n); associated = inf_adopted_request_log_next_associated(log, index); /* The last request might not be in the request log yet, so fetch * the index from the log endpoint. */ if(associated == NULL) { if(inf_adopted_request_get_request_type(index) == INF_ADOPTED_REQUEST_UNDO) { if(inf_adopted_request_log_next_redo(log) == index) associated_index = to_n; else associated_index = G_MAXUINT; } else { if(inf_adopted_request_log_next_undo(log) == index) associated_index = to_n; else associated_index = G_MAXUINT; } } else { associated_index = inf_adopted_request_get_index(associated); } if(associated_index != G_MAXUINT && associated_index <= to_n) { next_req = inf_adopted_request_mirror( cur_req, associated_index - from_n ); } } /* If next_req == NULL, to is not reachable in state space */ g_assert(next_req != NULL); g_object_unref(cur_req); cur_req = next_req; vector = inf_adopted_request_get_vector(cur_req); } return cur_req; } static void inf_adopted_algorithm_log_request(InfAdoptedAlgorithm* algorithm, InfAdoptedUser* user, InfAdoptedRequest* request) { InfAdoptedAlgorithmPrivate* priv; InfAdoptedRequestLog* log; /* InfAdoptedStateVector* user_vector; InfAdoptedStateVector* request_vector;*/ guint user_id; gboolean equivalent; priv = INF_ADOPTED_ALGORITHM_PRIVATE(algorithm); log = inf_adopted_user_get_request_log(user); /* user_vector = inf_adopted_user_get_vector(user); request_vector = inf_adopted_request_get_vector(request);*/ user_id = inf_user_get_id(INF_USER(user)); g_assert(inf_adopted_request_get_user_id(request) == user_id); /* Now update our local state. There are only updates required if the * request is buffer-altering. */ if(inf_adopted_request_affects_buffer(request)) { /* First, add to request log */ inf_adopted_request_log_add_request(log, request); /* Update current document state */ inf_adopted_state_vector_add(priv->current, user_id, 1); /* Update local user times */ inf_adopted_algorithm_update_local_user_times(algorithm); /* Unset the modified flag of the buffer if the state is equivalent * (reachable only by folding, i.e. skipping undo/redo pairs) to the * known state when the buffer was not considered modified. */ if(priv->buffer_modified_time != NULL) { equivalent = inf_adopted_algorithm_buffer_states_equivalent( algorithm, priv->buffer_modified_time, priv->current ); if(equivalent == TRUE) { inf_buffer_set_modified(priv->buffer, FALSE); inf_adopted_state_vector_free(priv->buffer_modified_time); priv->buffer_modified_time = inf_adopted_state_vector_copy(priv->current); } else { /* The buffer does this automatically when applying an operation: */ /*inf_buffer_set_modified(priv->buffer, TRUE);*/ } } else { /* When the modified flag is set to false, then we create the * buffer_modified_time, so when it is unset, the flag needs to be set. * Otherwise, we didn't get notified correctly. */ g_assert(inf_buffer_get_modified(priv->buffer) == TRUE); } } } static InfAdoptedRequest* inf_adopted_algorithm_apply_request(InfAdoptedAlgorithm* algorithm, InfAdoptedUser* user, InfAdoptedRequest* request, InfAdoptedRequest* translated, GError** error) { InfAdoptedAlgorithmPrivate* priv; InfAdoptedOperation* reversible_operation; InfAdoptedRequest* log_request; GError* local_error; gchar* request_str; gchar* translated_str; priv = INF_ADOPTED_ALGORITHM_PRIVATE(algorithm); /* TODO: Assert that the user ID * for request and translated are the same and that translated can be * applied in the current state, and that translated is a DO request. */ local_error = NULL; log_request = NULL; /* Apply the operation to the buffer. If this originated from a DO request, * make the operation reversible before adding it to the request log. */ if(inf_adopted_request_get_request_type(request) == INF_ADOPTED_REQUEST_DO) { /* Make the operation reversible */ reversible_operation = inf_adopted_operation_apply_transformed( inf_adopted_request_get_operation(request), inf_adopted_request_get_operation(translated), user, priv->buffer, &local_error ); if(local_error == NULL) { g_assert(reversible_operation != NULL); /* It can happen that we could not make the operation reversible, or * that it was reversible already in the first place, in which case we * get the same as the original operation from apply_transformed. */ if(reversible_operation == inf_adopted_request_get_operation(request)) { log_request = request; g_object_ref(log_request); g_object_unref(reversible_operation); } else { /* Create the log request from the reversible operation */ log_request = inf_adopted_request_new_do( inf_adopted_request_get_vector(request), inf_adopted_request_get_user_id(request), reversible_operation, inf_adopted_request_get_receive_time(request) ); inf_adopted_request_set_execute_time( log_request, inf_adopted_request_get_execute_time(request) ); g_object_unref(reversible_operation); } } } else { inf_adopted_operation_apply( inf_adopted_request_get_operation(translated), user, priv->buffer, &local_error ); if(local_error == NULL) { log_request = request; g_object_ref(log_request); } } if(local_error != NULL) { g_assert(log_request == NULL); request_str = inf_adopted_state_vector_to_string( inf_adopted_request_get_vector(request) ); translated_str = inf_adopted_state_vector_to_string( inf_adopted_request_get_vector(translated) ); g_propagate_prefixed_error( error, local_error, _("Failed to apply request \"%s\" from user \"%s\" at state \"%s\": "), request_str, inf_user_get_name(INF_USER(user)), translated_str ); g_free(request_str); g_free(translated_str); return NULL; } g_assert(log_request != NULL); return log_request; } static void inf_adopted_algorithm_init(InfAdoptedAlgorithm* algorithm) { InfAdoptedAlgorithmPrivate* priv; algorithm->priv = INF_ADOPTED_ALGORITHM_GET_PRIVATE(algorithm); priv = INF_ADOPTED_ALGORITHM_PRIVATE(algorithm); priv->max_total_log_size = 2048; priv->execute_request = NULL; priv->current = inf_adopted_state_vector_new(); priv->buffer_modified_time = NULL; priv->user_table = NULL; priv->buffer = NULL; /* Lookup by user, user is not refed because the request log holds a * reference anyway. */ priv->users_begin = NULL; priv->users_end = NULL; priv->local_users = NULL; } static void inf_adopted_algorithm_constructed_foreach_user_func(InfUser* user, gpointer user_data) { InfAdoptedAlgorithm* algorithm; algorithm = INF_ADOPTED_ALGORITHM(user_data); g_assert(INF_ADOPTED_IS_USER(user)); inf_adopted_algorithm_add_user(algorithm, INF_ADOPTED_USER(user)); } static void inf_adopted_algorithm_constructed_foreach_local_user_func(InfUser* user, gpointer user_data) { InfAdoptedAlgorithm* algorithm; algorithm = INF_ADOPTED_ALGORITHM(user_data); g_assert(INF_ADOPTED_IS_USER(user)); inf_adopted_algorithm_add_local_user(algorithm, INF_ADOPTED_USER(user)); } static void inf_adopted_algorithm_constructed(GObject* object) { InfAdoptedAlgorithm* algorithm; InfAdoptedAlgorithmPrivate* priv; gboolean modified; G_OBJECT_CLASS(inf_adopted_algorithm_parent_class)->constructed(object); algorithm = INF_ADOPTED_ALGORITHM(object); priv = INF_ADOPTED_ALGORITHM_PRIVATE(algorithm); /* Add initial users */ inf_user_table_foreach_user( priv->user_table, inf_adopted_algorithm_constructed_foreach_user_func, algorithm ); inf_user_table_foreach_local_user( priv->user_table, inf_adopted_algorithm_constructed_foreach_local_user_func, algorithm ); g_object_get(G_OBJECT(priv->buffer), "modified", &modified, NULL); if(modified == FALSE) priv->buffer_modified_time = inf_adopted_state_vector_copy(priv->current); } static void inf_adopted_algorithm_dispose(GObject* object) { InfAdoptedAlgorithm* algorithm; InfAdoptedAlgorithmPrivate* priv; GList* item; algorithm = INF_ADOPTED_ALGORITHM(object); priv = INF_ADOPTED_ALGORITHM_PRIVATE(algorithm); while(priv->local_users != NULL) inf_adopted_algorithm_local_user_free(algorithm, priv->local_users->data); g_free(priv->users_begin); if(priv->buffer != NULL) { inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->buffer), G_CALLBACK(inf_adopted_algorithm_buffer_notify_modified_cb), algorithm ); g_object_unref(priv->buffer); priv->buffer = NULL; } if(priv->buffer_modified_time != NULL) inf_adopted_state_vector_free(priv->buffer_modified_time); if(priv->user_table != NULL) { inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->user_table), G_CALLBACK(inf_adopted_algorithm_add_user_cb), algorithm ); inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->user_table), G_CALLBACK(inf_adopted_algorithm_add_local_user_cb), algorithm ); inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->user_table), G_CALLBACK(inf_adopted_algorithm_remove_local_user_cb), algorithm ); g_object_unref(priv->user_table); priv->user_table = NULL; } G_OBJECT_CLASS(inf_adopted_algorithm_parent_class)->dispose(object); } static void inf_adopted_algorithm_finalize(GObject* object) { InfAdoptedAlgorithm* algorithm; InfAdoptedAlgorithmPrivate* priv; algorithm = INF_ADOPTED_ALGORITHM(object); priv = INF_ADOPTED_ALGORITHM_PRIVATE(algorithm); inf_adopted_state_vector_free(priv->current); G_OBJECT_CLASS(inf_adopted_algorithm_parent_class)->finalize(object); } static void inf_adopted_algorithm_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfAdoptedAlgorithm* algorithm; InfAdoptedAlgorithmPrivate* priv; algorithm = INF_ADOPTED_ALGORITHM(object); priv = INF_ADOPTED_ALGORITHM_PRIVATE(algorithm); switch(prop_id) { case PROP_USER_TABLE: g_assert(priv->user_table == NULL); /* construct/only */ priv->user_table = INF_USER_TABLE(g_value_dup_object(value)); g_signal_connect( G_OBJECT(priv->user_table), "add-user", G_CALLBACK(inf_adopted_algorithm_add_user_cb), algorithm ); g_signal_connect( G_OBJECT(priv->user_table), "add-local-user", G_CALLBACK(inf_adopted_algorithm_add_local_user_cb), algorithm ); g_signal_connect( G_OBJECT(priv->user_table), "remove-local-user", G_CALLBACK(inf_adopted_algorithm_remove_local_user_cb), algorithm ); break; case PROP_BUFFER: g_assert(priv->buffer == NULL); /* construct only */ g_assert(priv->buffer_modified_time == NULL); priv->buffer = INF_BUFFER(g_value_dup_object(value)); g_signal_connect( G_OBJECT(priv->buffer), "notify::modified", G_CALLBACK(inf_adopted_algorithm_buffer_notify_modified_cb), algorithm ); break; case PROP_MAX_TOTAL_LOG_SIZE: priv->max_total_log_size = g_value_get_uint(value); break; case PROP_CURRENT_STATE: case PROP_BUFFER_MODIFIED_STATE: /* read/only */ default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void inf_adopted_algorithm_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfAdoptedAlgorithm* log; InfAdoptedAlgorithmPrivate* priv; log = INF_ADOPTED_ALGORITHM(object); priv = INF_ADOPTED_ALGORITHM_PRIVATE(log); switch(prop_id) { case PROP_USER_TABLE: g_value_set_object(value, G_OBJECT(priv->user_table)); break; case PROP_BUFFER: g_value_set_object(value, G_OBJECT(priv->buffer)); break; case PROP_MAX_TOTAL_LOG_SIZE: g_value_set_uint(value, priv->max_total_log_size); break; case PROP_CURRENT_STATE: g_value_set_boxed(value, priv->current); break; case PROP_BUFFER_MODIFIED_STATE: g_value_set_boxed(value, priv->buffer_modified_time); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void inf_adopted_algorithm_can_undo_changed(InfAdoptedAlgorithm* algorithm, InfAdoptedUser* user, gboolean can_undo) { InfAdoptedAlgorithmPrivate* priv; GSList* item; priv = INF_ADOPTED_ALGORITHM_PRIVATE(algorithm); for(item = priv->local_users; item != NULL; item = g_slist_next(item)) if( ((InfAdoptedAlgorithmLocalUser*)item->data)->user == user) ((InfAdoptedAlgorithmLocalUser*)item->data)->can_undo = can_undo; } static void inf_adopted_algorithm_can_redo_changed(InfAdoptedAlgorithm* algorithm, InfAdoptedUser* user, gboolean can_redo) { InfAdoptedAlgorithmPrivate* priv; GSList* item; priv = INF_ADOPTED_ALGORITHM_PRIVATE(algorithm); for(item = priv->local_users; item != NULL; item = g_slist_next(item)) if( ((InfAdoptedAlgorithmLocalUser*)item->data)->user == user) ((InfAdoptedAlgorithmLocalUser*)item->data)->can_redo = can_redo; } static void inf_adopted_algorithm_class_init(InfAdoptedAlgorithmClass* algorithm_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(algorithm_class); object_class->constructed = inf_adopted_algorithm_constructed; object_class->dispose = inf_adopted_algorithm_dispose; object_class->finalize = inf_adopted_algorithm_finalize; object_class->set_property = inf_adopted_algorithm_set_property; object_class->get_property = inf_adopted_algorithm_get_property; algorithm_class->can_undo_changed = inf_adopted_algorithm_can_undo_changed; algorithm_class->can_redo_changed = inf_adopted_algorithm_can_redo_changed; algorithm_class->begin_execute_request = NULL; algorithm_class->end_execute_request = NULL; g_object_class_install_property( object_class, PROP_USER_TABLE, g_param_spec_object( "user-table", "User table", "The user table", INF_TYPE_USER_TABLE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_BUFFER, g_param_spec_object( "buffer", "Buffer", "The buffer to apply operations to", INF_TYPE_BUFFER, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_MAX_TOTAL_LOG_SIZE, g_param_spec_uint( "max-total-log-size", "Maxmimum total log size", "The maximum number of requests to keep in all user's logs", 0, G_MAXUINT, 2048, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_CURRENT_STATE, g_param_spec_boxed( "current-state", "Current state", "The state vector describing the current document state", INF_ADOPTED_TYPE_STATE_VECTOR, G_PARAM_READABLE ) ); g_object_class_install_property( object_class, PROP_BUFFER_MODIFIED_STATE, g_param_spec_boxed( "buffer-modified-state", "Buffer modified state", "The state in which the buffer is considered not being modified", INF_ADOPTED_TYPE_STATE_VECTOR, G_PARAM_READABLE ) ); /** * InfAdoptedAlgorithm::can-undo-changed: * @algorithm: The #InfAdoptedAlgorithm for which a user's * can-undo state changed. * @user: The #InfAdoptedUser whose can-undo state has changed. * @can_undo: Whether @user can issue an undo request in the current * state or not. * * This signal is emitted every time the can-undo state of a local user * in @algorithm's user table changed. The can-undo state defines whether * @user can generate an undo request * (via inf_adopted_algorithm_generate_request()) in the current situation, see * also inf_adopted_algorithm_can_undo(). */ algorithm_signals[CAN_UNDO_CHANGED] = g_signal_new( "can-undo-changed", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfAdoptedAlgorithmClass, can_undo_changed), NULL, NULL, NULL, G_TYPE_NONE, 2, INF_ADOPTED_TYPE_USER, G_TYPE_BOOLEAN ); /** * InfAdoptedAlgorithm::can-redo-changed: * @algorithm: The #InfAdoptedAlgorithm for which a user's * can-redo state changed. * @user: The #InfAdoptedUser whose can-redo state has changed. * @can_undo: Whether @user can issue a redo request in the current * state or not. * * This signal is emitted every time the can-redo state of a local user * in @algorithm's user table changed. The can-redo state defines whether * @user can generate a redo request * (via inf_adopted_algorithm_generate_request()) in the current situation, see * also inf_adopted_algorithm_can_redo(). */ algorithm_signals[CAN_REDO_CHANGED] = g_signal_new( "can-redo-changed", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfAdoptedAlgorithmClass, can_redo_changed), NULL, NULL, NULL, G_TYPE_NONE, 2, INF_ADOPTED_TYPE_USER, G_TYPE_BOOLEAN ); /** * InfAdoptedAlgorithm::begin-execute-request: * @algorithm: The #InfAdoptedAlgorithm executing a request. * @user: The #InfAdoptedUser executing the request. * @request: The #InfAdoptedRequest being executed. * * This signal is emitted every time the algorithm executes a request, i.e. * transforms it such that it can be applied to the current state, resolves * undo/redo operations and applies the resulting operation to the buffer. */ algorithm_signals[BEGIN_EXECUTE_REQUEST] = g_signal_new( "begin-execute-request", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfAdoptedAlgorithmClass, begin_execute_request), NULL, NULL, NULL, G_TYPE_NONE, 2, INF_ADOPTED_TYPE_USER, INF_ADOPTED_TYPE_REQUEST ); /** * InfAdoptedAlgorithm::end-execute-request: * @algorithm: The #InfAdoptedAlgorithm executing a request. * @user: The #InfAdoptedUser executing the request. * @request: The #InfAdoptedRequest that was executed. * @translated: The result of the request transformation, or %NULL. * @error: The error that occurred during execution, or %NULL. * * This signal is emitted after a request has been executed. The @request * parameter is not necessarily the same as the one in the corresponding * emission of #InfAdoptedAlgorithm::begin-execute-request, however its * effect on the buffer is the same. The difference is that the request in * this signal might be reversible while the request in the * #InfAdoptedAlgorithm::begin-execute-request emission might not be * reversible. The algorithm can make some requests reversible during * their execution. * * The @translated request is the result of the transformation, i.e. it is * always a %INF_ADOPTED_REQUEST_DO type request and its state vector * corresponds to the current state. It has already been applied on the * buffer by the algorithm. If @request is of type %INF_ADOPTED_REQUEST_UNDO * or %INF_ADOPTED_REQUEST_REDO then @translated represents the operation * that actually was performed on the buffer to undo or redo the effect of * a previous request. * * It can happen that an error occurs during execution. Usually this is due * to invalid input, such as a request that cannot be transformed to the * current state, a %INF_ADOPTED_REQUEST_UNDO request which has no * corresponding %INF_ADOPTED_REQUEST_DO or %INF_ADOPTED_REQUEST_REDO * request, or a request that ends up in an invalid operation (e.g. * inserting text behind the end of the document). If such an error occurs * then @request is the same as the one in the * %InfAdoptedAlgorithm::begin-execute-request emission, @translated may or * may not be %NULL and @error contains information on the error occured. */ algorithm_signals[END_EXECUTE_REQUEST] = g_signal_new( "end-execute-request", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfAdoptedAlgorithmClass, end_execute_request), NULL, NULL, NULL, G_TYPE_NONE, 4, INF_ADOPTED_TYPE_USER, INF_ADOPTED_TYPE_REQUEST, INF_ADOPTED_TYPE_REQUEST, G_TYPE_ERROR ); } /** * inf_adopted_algorithm_new: (constructor) * @user_table: The table of participating users. * @buffer: The buffer to apply operations to. * * Creates a #InfAdoptedAlgorithm. * * Returns: (transfer full): A new #InfAdoptedAlgorithm. **/ InfAdoptedAlgorithm* inf_adopted_algorithm_new(InfUserTable* user_table, InfBuffer* buffer) { GObject* object; g_return_val_if_fail(INF_IS_BUFFER(buffer), NULL); object = g_object_new( INF_ADOPTED_TYPE_ALGORITHM, "user-table", user_table, "buffer", buffer, NULL ); return INF_ADOPTED_ALGORITHM(object); } /** * inf_adopted_algorithm_new_full: (constructor) * @user_table: The table of participating users. * @buffer: The buffer to apply operations to. * @max_total_log_size: The maxmimum number of operations to keep in all * user's request logs. * * Note that it is possible that request logs need to grow a bit larger than * @max_total_log_size in high-latency situations or when a user does not send * status updates frequently. However, when all requests have been * processed by all users, the sum of all requests in the logs is guaranteed * to be lower or equal to this value. * * Set to %G_MAXUINT to disable limitation. In theory, this would allow * everyone to undo every operation up to the first one ever made. In practise, * this issues a huge amount of data that needs to be synchronized on user * join and is too expensive to compute anyway. * * The default value is 2048. * * Returns: (transfer full): A new #InfAdoptedAlgorithm. **/ InfAdoptedAlgorithm* inf_adopted_algorithm_new_full(InfUserTable* user_table, InfBuffer* buffer, guint max_total_log_size) { GObject* object; g_return_val_if_fail(INF_IS_BUFFER(buffer), NULL); object = g_object_new( INF_ADOPTED_TYPE_ALGORITHM, "user-table", user_table, "buffer", buffer, "max-total-log-size", max_total_log_size, NULL ); return INF_ADOPTED_ALGORITHM(object); } /** * inf_adopted_algorithm_get_current: * @algorithm: A #InfAdoptedAlgorithm. * * Returns the current vector time of @algorithm. * * Returns: (transfer none): A #InfAdoptedStateVector owned by @algorithm. **/ InfAdoptedStateVector* inf_adopted_algorithm_get_current(InfAdoptedAlgorithm* algorithm) { g_return_val_if_fail(INF_ADOPTED_IS_ALGORITHM(algorithm), NULL); return INF_ADOPTED_ALGORITHM_PRIVATE(algorithm)->current; } /** * inf_adopted_algorithm_get_execute_request: * @algorithm: A #InfAdoptedAlgorithm. * * Returns whether the algorithm is currently transforming a request to the * current state and appling its state to the buffer. If it is the function * is returning the request that was received and is currently being * executed, other wise the function returns %NULL. Note that the request * execution is not re-entrant, i.e. two requests cannot be executed * concurrently at the same time, or recursively. * * Returns: (transfer none) (allow-none): The request that @algorithm is * currently processing, or %NULL. The return value must not be freed by * the caller. */ InfAdoptedRequest* inf_adopted_algorithm_get_execute_request(InfAdoptedAlgorithm* algorithm) { g_return_val_if_fail(INF_ADOPTED_IS_ALGORITHM(algorithm), NULL); return INF_ADOPTED_ALGORITHM_PRIVATE(algorithm)->execute_request; } /** * inf_adopted_algorithm_generate_request: * @algorithm: A #InfAdoptedAlgorithm. * @type: The type of request to create. * @user: The user for which to create the request. * @operation: The operation to perform, or %NULL. * * Creates a new request that can be applied to the current document state. * The request is made by the given user. If operation is of type * %INF_ADOPTED_REQUEST_DO, then @operation specifies the operation to be * performed. Otherwise, @operation must be %NULL. * * To apply the effect of the request to the document, run * inf_adopted_algorithm_execute_request(). Note that even if the effect * is already applied to the document, the function must still be called * with the @apply parameter set to %FALSE, so that the algorithm knows that * the request has been applied. * * Returns: (transfer full): A new #InfAdoptedRequest. Free with * g_object_unref() when no longer needed. */ InfAdoptedRequest* inf_adopted_algorithm_generate_request(InfAdoptedAlgorithm* algorithm, InfAdoptedRequestType type, InfAdoptedUser* user, InfAdoptedOperation* operation) { InfAdoptedAlgorithmPrivate* priv; g_return_val_if_fail(INF_ADOPTED_IS_ALGORITHM(algorithm), NULL); g_return_val_if_fail(INF_ADOPTED_IS_USER(user), NULL); g_return_val_if_fail( type != INF_ADOPTED_REQUEST_DO || INF_ADOPTED_IS_OPERATION(operation), NULL ); priv = INF_ADOPTED_ALGORITHM_PRIVATE(algorithm); switch(type) { case INF_ADOPTED_REQUEST_DO: return inf_adopted_request_new_do( priv->current, inf_user_get_id(INF_USER(user)), operation, g_get_real_time() ); case INF_ADOPTED_REQUEST_UNDO: return inf_adopted_request_new_undo( priv->current, inf_user_get_id(INF_USER(user)), g_get_real_time() ); case INF_ADOPTED_REQUEST_REDO: return inf_adopted_request_new_redo( priv->current, inf_user_get_id(INF_USER(user)), g_get_real_time() ); default: g_return_val_if_reached(NULL); return NULL; } } /** * inf_adopted_algorithm_translate_request: * @algorithm: A #InfAdoptedAlgorithm. * @request: A #InfAdoptedRequest. * @to: (transfer none): The state vector to translate @request to. * * Translates @request so that it can be applied to the document at state @to. * @request will not be modified but a new, translated request is returned * instead. * * There are several preconditions for this function to be called. @to must * be a reachable point in the state space. Also, requests can only be * translated in forward direction, so @request's vector time must be * causally before (see inf_adopted_state_vector_causally_before()) @to. * * Returns: (transfer full): A new or cached #InfAdoptedRequest. Free with * g_object_unref() when no longer needed. */ InfAdoptedRequest* inf_adopted_algorithm_translate_request(InfAdoptedAlgorithm* algorithm, InfAdoptedRequest* request, InfAdoptedStateVector* to) { InfAdoptedAlgorithmPrivate* priv; guint user_id; InfUser* plain_user; InfAdoptedUser* user; InfAdoptedRequestLog* log; InfAdoptedRequest* result; g_return_val_if_fail(INF_ADOPTED_IS_ALGORITHM(algorithm), NULL); g_return_val_if_fail(INF_ADOPTED_IS_REQUEST(request), NULL); g_return_val_if_fail(to != NULL, NULL); priv = INF_ADOPTED_ALGORITHM_PRIVATE(algorithm); user_id = inf_adopted_request_get_user_id(request); plain_user = inf_user_table_lookup_user_by_id(priv->user_table, user_id); /* Validity checks */ g_return_val_if_fail(INF_ADOPTED_IS_USER(plain_user), NULL); user = INF_ADOPTED_USER(plain_user); log = inf_adopted_user_get_request_log(user); g_return_val_if_fail( inf_adopted_state_vector_causally_before(to, priv->current), NULL ); g_return_val_if_fail( inf_adopted_state_vector_causally_before( inf_adopted_request_get_vector( inf_adopted_request_log_original_request(log, request) ), to ), NULL ); /* If the request affects the buffer, then it might have been cached * earlier. */ if(inf_adopted_request_affects_buffer(request)) { result = inf_adopted_request_log_lookup_cached_request(log, to); if(result != NULL) { g_object_ref(result); return result; } } /* New algorithm */ result = inf_adopted_algorithm_translate_request_forward( algorithm, request, to ); g_assert( inf_adopted_state_vector_compare( inf_adopted_request_get_vector(result), to ) == 0 ); if(inf_adopted_algorithm_can_cache(result)) inf_adopted_request_log_add_cached_request(log, result); return result; } /** * inf_adopted_algorithm_execute_request: * @algorithm: A #InfAdoptedAlgorithm. * @request: The request to execute. * @apply: Whether to apply the request to the buffer. * @error: Location to store error information, if any. * * This function transforms the given request such that it can be applied to * the current document state and then applies it the buffer and adds it to * the request log of the algorithm, so that it is used for future * transformations of other requests. * * If @apply is %FALSE then the request is not applied to the buffer. In this * case, it is assumed that the buffer is already modified, and that the * request is made as a result from the buffer modification. This also means * that the request must be applicable to the current document state, without * requiring transformation. * * In addition, the function emits the * #InfAdoptedAlgorithm::begin-execute-request and * #InfAdoptedAlgorithm::end-execute-request signals, and makes * inf_adopted_algorithm_get_execute_request() return @request during that * period. * * This allows other code to hook in before and after request processing. This * does not cause any loss of generality because this function is not * re-entrant anyway: it cannot work when used concurrently by multiple * threads nor in a recursive manner, because only when one request has been * added to the log the next request can be translated, since it might need * the previous request for the translation path and it needs to be translated * to a state where the effect of the previous request is included so that it * can consistently applied to the buffer. * * There are also runtime errors that can occur if @request execution fails. * In this case the function returns %FALSE and @error is set. Possible * reasons for this include @request being an %INF_ADOPTED_REQUEST_UNDO or * %INF_ADOPTED_REQUEST_REDO request without there being an operation to * undo or redo, or if the translated operation cannot be applied to the * buffer. This usually means that the input @request was invalid. However, * this is not considered a programmer error because typically requests are * received from untrusted input sources such as network connections. * Note that there cannot be any runtime errors if @apply is set to %FALSE. * In that case it is safe to call the function with %NULL error. * * Returns: %TRUE on success or %FALSE on error. */ gboolean inf_adopted_algorithm_execute_request(InfAdoptedAlgorithm* algorithm, InfAdoptedRequest* request, gboolean apply, GError** error) { InfAdoptedAlgorithmPrivate* priv; InfAdoptedUser* user; InfAdoptedRequestLog* log; InfAdoptedRequest* original; InfAdoptedRequest* translated; InfAdoptedRequest* log_request; GError* local_error; gchar* request_str; g_return_val_if_fail(INF_ADOPTED_IS_ALGORITHM(algorithm), FALSE); g_return_val_if_fail(INF_ADOPTED_IS_REQUEST(request), FALSE); priv = INF_ADOPTED_ALGORITHM_PRIVATE(algorithm); g_return_val_if_fail( inf_adopted_state_vector_causally_before( inf_adopted_request_get_vector(request), priv->current ), FALSE ); g_return_val_if_fail( apply == TRUE || ( inf_adopted_state_vector_compare( inf_adopted_request_get_vector(request), priv->current ) == 0 && inf_adopted_request_get_request_type(request) == INF_ADOPTED_REQUEST_DO ), FALSE ); user = INF_ADOPTED_USER( inf_user_table_lookup_user_by_id( priv->user_table, inf_adopted_request_get_user_id(request) ) ); g_return_val_if_fail(user != NULL, FALSE); /* not re-entrant */ g_return_val_if_fail(priv->execute_request == NULL, FALSE); priv->execute_request = request; inf_adopted_request_set_execute_time(request, g_get_real_time()); g_signal_emit( G_OBJECT(algorithm), algorithm_signals[BEGIN_EXECUTE_REQUEST], 0, user, request ); local_error = NULL; switch(inf_adopted_request_get_request_type(request)) { case INF_ADOPTED_REQUEST_DO: /* nothing to check, DO requests can always be made */ break; case INF_ADOPTED_REQUEST_UNDO: if(!inf_adopted_algorithm_can_undo(algorithm, user)) { request_str = inf_adopted_state_vector_to_string( inf_adopted_request_get_vector(request) ); g_set_error( &local_error, g_quark_from_static_string("INF_ADOPTED_ALGORITHM_ERROR"), INF_ADOPTED_ALGORITHM_ERROR_NO_UNDO, _("The request \"%s\" from user \"%s\" is an UNDO request but there " "is no request to be undone."), request_str, inf_user_get_name(INF_USER(user)) ); g_free(request_str); } break; case INF_ADOPTED_REQUEST_REDO: if(!inf_adopted_algorithm_can_redo(algorithm, user)) { request_str = inf_adopted_state_vector_to_string( inf_adopted_request_get_vector(request) ); g_set_error( &local_error, g_quark_from_static_string("INF_ADOPTED_ALGORITHM_ERROR"), INF_ADOPTED_ALGORITHM_ERROR_NO_REDO, _("The request \"%s\" from user \"%s\" is a REDO request but there " "is no request to be redone."), request_str, inf_user_get_name(INF_USER(user)) ); g_free(request_str); } break; default: g_assert_not_reached(); break; } if(local_error != NULL) { g_signal_emit( G_OBJECT(algorithm), algorithm_signals[END_EXECUTE_REQUEST], 0, user, request, NULL, local_error ); priv->execute_request = NULL; g_propagate_error(error, local_error); return FALSE; } log = inf_adopted_user_get_request_log(user); original = inf_adopted_request_log_original_request(log, request); g_assert( inf_adopted_request_get_request_type(original) == INF_ADOPTED_REQUEST_DO ); translated = inf_adopted_algorithm_translate_request( algorithm, original, priv->current ); g_assert( inf_adopted_request_get_request_type(translated) == INF_ADOPTED_REQUEST_DO ); inf_signal_handlers_block_by_func( G_OBJECT(priv->buffer), G_CALLBACK(inf_adopted_algorithm_buffer_notify_modified_cb), algorithm ); if(apply == TRUE) { log_request = inf_adopted_algorithm_apply_request( algorithm, user, request, translated, &local_error ); if(local_error != NULL) { inf_signal_handlers_unblock_by_func( G_OBJECT(priv->buffer), G_CALLBACK(inf_adopted_algorithm_buffer_notify_modified_cb), algorithm ); g_signal_emit( G_OBJECT(algorithm), algorithm_signals[END_EXECUTE_REQUEST], 0, user, request, translated, local_error ); priv->execute_request = NULL; g_object_unref(translated); g_propagate_error(error, local_error); return FALSE; } } else { log_request = request; g_object_ref(request); } inf_adopted_algorithm_log_request( algorithm, user, log_request ); inf_signal_handlers_unblock_by_func( G_OBJECT(priv->buffer), G_CALLBACK(inf_adopted_algorithm_buffer_notify_modified_cb), algorithm ); inf_adopted_algorithm_update_undo_redo(algorithm); g_signal_emit( G_OBJECT(algorithm), algorithm_signals[END_EXECUTE_REQUEST], 0, user, log_request, translated, NULL ); g_object_unref(translated); g_object_unref(log_request); priv->execute_request = NULL; return TRUE; } /** * inf_adopted_algorithm_cleanup: * @algorithm: A #InfAdoptedAlgorithm. * * Removes requests in all users request logs which are no longer needed. This * includes requests which cannot be undone or redone anymore due to the * constraints of the #InfAdoptedAlgorithm:max-total-log-size property, and * requests that every participant is guaranteed to have processed already. * * This function can be called after every executed request to keep memory use * to a minimum, or it can be called in regular intervals, or it can also be * omitted if the request history should be preserved. **/ void inf_adopted_algorithm_cleanup(InfAdoptedAlgorithm* algorithm) { InfAdoptedAlgorithmPrivate* priv; InfAdoptedStateVector* temp; InfAdoptedStateVector* lcp; InfAdoptedUser** user; InfAdoptedRequestLog* log; InfAdoptedRequest* req; InfAdoptedStateVector* req_vec; InfAdoptedStateVector* low_vec; gboolean req_before_lcp; guint n; guint id; guint vdiff; priv = INF_ADOPTED_ALGORITHM_PRIVATE(algorithm); g_assert(priv->users_begin != priv->users_end); /* We don't do cleanup in case the total log size is G_MAXUINT, which * means we keep all requests without limit. */ if(priv->max_total_log_size == G_MAXUINT) return; /* We remove every request whose "lower related" request has a greater * vdiff to the lcp then max-total-log-size from both request log and * the request cache. The lcp is a common state that _all_ sites are * guaranteed to have reached. Related requests not causally before lcp are * always kept, though. This should not happen if max-total-log-size is * reasonably high and the network latency reasonably low, but we can't * guarentee it does not happen. It just means we can't drop a request that * another site has not yet processed, although it is old enough.*/ /* The "upper related" request of a request A is the next-newer request so * that all requests before the "upper related" request can be removed * without any remaining request in the log still refering to a removed * one. See also inf_adopted_request_log_upper_related(). */ /* Note that we could be more intelligent here. It would be enough if the * oldest request of a set of related requests is old enough to be removed. * But we would need to make sure that the requests between the oldest and * the upper related are not required anymore. I am not sure whether there * are additional conditions. However, in the current case, some requests * are just kept a bit longer than necessary, in favor of simplicity. */ lcp = inf_adopted_state_vector_copy(priv->current); for(user = priv->users_begin; user != priv->users_end; ++ user) { if(inf_user_get_status(INF_USER(*user)) != INF_USER_UNAVAILABLE) { temp = inf_adopted_algorithm_least_common_predecessor( algorithm, lcp, inf_adopted_user_get_vector(*user) ); inf_adopted_state_vector_free(lcp); lcp = temp; } } for(user = priv->users_begin; user != priv->users_end; ++ user) { id = inf_user_get_id(INF_USER(*user)); log = inf_adopted_user_get_request_log(*user); n = inf_adopted_request_log_get_begin(log); /* Remove all sets of related requests whose upper related request has * a large enough vdiff to lcp. */ while(n < inf_adopted_request_log_get_end(log)) { req = inf_adopted_request_log_upper_related(log, n); req_vec = inf_adopted_request_get_vector(req); /* We can only remove requests that are causally before lcp, * as explained above. We need to compare the target vector time of the * request, though, and not the source which is why we increase the * request's user's component by one. This is because of the fact that * the request needs to be available to reach its target vector time. */ req_before_lcp = inf_adopted_state_vector_causally_before_inc( req_vec, lcp, id ); if(!req_before_lcp) break; /* TODO: Experimentally, I try using the lower related for the vdiff * here. If it doesn't work out, then we will need to use the upper * related. Note that changing this requires changing the cleanup * tests, too. */ low_vec = inf_adopted_request_get_vector( inf_adopted_request_log_get_request(log, n) ); vdiff = inf_adopted_state_vector_vdiff(low_vec, lcp); /* TODO: Again, I experimentally changed <= to < here. If the vdiff is * equal to the log size, then nobody can do anything with the request * set anymore: Everybody already processed every request in the set * (otherwise, the causally_before_ check above would have failed), and * the user in question cannot Undo anymore since this would require one * too much request in the request log. Note again that changing this * requires changing the cleanup tests, too. */ if(vdiff < priv->max_total_log_size) break; /* Check next set of related requests */ n = inf_adopted_state_vector_get(req_vec, id) + 1; } inf_adopted_request_log_remove_requests(log, n); } inf_adopted_state_vector_free(lcp); } /** * inf_adopted_algorithm_can_undo: * @algorithm: A #InfAdoptedAlgorithm. * @user: A local #InfAdoptedUser. * * Returns whether @user can issue an undo request in the current state. Note * that if @user is non-local, then the result of this function does not * depend on the current state but on the state that we know @user is * guaranteed to have reached. This is because @user might still issue an * Undo request even if the max-total-log-size is already exceeded if @user * does not know yet that it is exceeded. * * Returns: %TRUE if Undo is possible, %FALSE otherwise. **/ gboolean inf_adopted_algorithm_can_undo(InfAdoptedAlgorithm* algorithm, InfAdoptedUser* user) { InfAdoptedAlgorithmLocalUser* local; InfAdoptedRequestLog* log; g_return_val_if_fail(INF_ADOPTED_IS_ALGORITHM(algorithm), FALSE); g_return_val_if_fail(INF_ADOPTED_IS_USER(user), FALSE); local = inf_adopted_algorithm_find_local_user(algorithm, user); if(local != NULL) { return local->can_undo; } else { log = inf_adopted_user_get_request_log(user); return inf_adopted_algorithm_can_undo_redo( algorithm, user, inf_adopted_request_log_next_undo(log) ); } } /** * inf_adopted_algorithm_can_redo: * @algorithm: A #InfAdoptedAlgorithm. * @user: A local #InfAdoptedUser. * * Returns whether @user can issue a redo request in the current state. Note * that if @user is non-local, then the result of this function does not * depend on the current state but on the state that we know @user is * guaranteed to have reached. This is because @user might still issue a * Redo request even if the max-total-log-size is already exceeded if @user * does not know yet that it is exceeded. * * Returns: %TRUE if Redo is possible, %FALSE otherwise. **/ gboolean inf_adopted_algorithm_can_redo(InfAdoptedAlgorithm* algorithm, InfAdoptedUser* user) { InfAdoptedAlgorithmLocalUser* local; InfAdoptedRequestLog* log; g_return_val_if_fail(INF_ADOPTED_IS_ALGORITHM(algorithm), FALSE); g_return_val_if_fail(INF_ADOPTED_IS_USER(user), FALSE); local = inf_adopted_algorithm_find_local_user(algorithm, user); if(local != NULL) { return local->can_redo; } else { log = inf_adopted_user_get_request_log(user); return inf_adopted_algorithm_can_undo_redo( algorithm, user, inf_adopted_request_log_next_redo(log) ); } } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/adopted/PaxHeaders.26529/inf-adopted-undo-grouping.h0000644000000000000000000000013113034342512024675 xustar0030 mtime=1483851082.025718404 30 atime=1483851082.025718404 29 ctime=1488261588.92013924 libinfinity-0.7.1/libinfinity/adopted/inf-adopted-undo-grouping.h0000644000175000017500000000722013034342512025431 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_ADOPTED_UNDO_GROUPING_H__ #define __INF_ADOPTED_UNDO_GROUPING_H__ #include #include #include G_BEGIN_DECLS #define INF_ADOPTED_TYPE_UNDO_GROUPING (inf_adopted_undo_grouping_get_type()) #define INF_ADOPTED_UNDO_GROUPING(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_ADOPTED_TYPE_UNDO_GROUPING, InfAdoptedUndoGrouping)) #define INF_ADOPTED_UNDO_GROUPING_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INF_ADOPTED_TYPE_UNDO_GROUPING, InfAdoptedUndoGroupingClass)) #define INF_ADOPTED_IS_UNDO_GROUPING(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_ADOPTED_TYPE_UNDO_GROUPING)) #define INF_ADOPTED_IS_UNDO_GROUPING_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INF_ADOPTED_TYPE_UNDO_GROUPING)) #define INF_ADOPTED_UNDO_GROUPING_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INF_ADOPTED_TYPE_UNDO_GROUPING, InfAdoptedUndoGroupingClass)) typedef struct _InfAdoptedUndoGrouping InfAdoptedUndoGrouping; typedef struct _InfAdoptedUndoGroupingClass InfAdoptedUndoGroupingClass; /** * InfAdoptedUndoGroupingClass: * @group_requests: Default signal handler for the * #InfAdoptedUndoGrouping::group-requests signal. * * This structure contains default signal handlers for #InfAdoptedUndoGrouping. */ struct _InfAdoptedUndoGroupingClass { /*< private >*/ GObjectClass parent_class; /*< public >*/ gboolean (*group_requests)(InfAdoptedUndoGrouping* grouping, InfAdoptedRequest* first, InfAdoptedRequest* second); }; /** * InfAdoptedUndoGrouping: * * #InfAdoptedUndoGrouping is an opaque data type. You should only access it via * the public API functions. */ struct _InfAdoptedUndoGrouping { /*< private >*/ GObject parent; }; GType inf_adopted_undo_grouping_get_type(void) G_GNUC_CONST; InfAdoptedUndoGrouping* inf_adopted_undo_grouping_new(void); InfAdoptedAlgorithm* inf_adopted_undo_grouping_get_algorithm(InfAdoptedUndoGrouping* grouping); void inf_adopted_undo_grouping_set_algorithm(InfAdoptedUndoGrouping* grouping, InfAdoptedAlgorithm* algorithm, InfAdoptedUser* user); void inf_adopted_undo_grouping_start_group(InfAdoptedUndoGrouping* grouping, gboolean allow_group_with_prev); void inf_adopted_undo_grouping_end_group(InfAdoptedUndoGrouping* grouping, gboolean allow_group_with_next); guint inf_adopted_undo_grouping_get_undo_size(InfAdoptedUndoGrouping* grouping); guint inf_adopted_undo_grouping_get_redo_size(InfAdoptedUndoGrouping* grouping); G_END_DECLS #endif /* __INF_ADOPTED_UNDO_GROUPING_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/adopted/PaxHeaders.26529/inf-adopted-split-operation.c0000644000000000000000000000013213034342512025225 xustar0030 mtime=1483851082.025718404 30 atime=1483851082.025718404 30 ctime=1488261589.032138995 libinfinity-0.7.1/libinfinity/adopted/inf-adopted-split-operation.c0000644000175000017500000004627213034342512025772 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-adopted-split-operation * @short_description: Operation wrapping two operations * @include: libinfinity/adopted/inf-adopted-split-operation.h * @stability: Unstable * * #InfAdoptedSplitOperation is a wrapper around that two * #InfAdoptedOperations. This is normally not required directly but * may be a result of some transformation. It can also be used to atomically * perform multiple operations at once. * * If A denotes the first operation of the split operation and B denotes * the second operation, the split operation applies first A and then B to * the document. Note that a split operation is not commutative, i.e. the * order of the two operations is important and cannot be interchanged at * will. When the second operation, B, is applied, it is assumed that the * operation A was already applied before. * * The reverse of the split operation (A, B) is (R(B), R(A)) where R indicates * the reverse operation. When the split operation is transformed against an * operation T, the result is (T A, (A T) B). When another operation T * is transformed against the split operation, the result is B (A T). * The functions inf_adopted_operation_revert(), * inf_adopted_operation_transform() and * inf_adopted_split_operation_transform_other() perform these three * operations, respectively. **/ #include #include typedef struct _InfAdoptedSplitOperationPrivate InfAdoptedSplitOperationPrivate; struct _InfAdoptedSplitOperationPrivate { InfAdoptedOperation* first; InfAdoptedOperation* second; }; enum { PROP_0, PROP_FIRST, PROP_SECOND }; #define INF_ADOPTED_SPLIT_OPERATION_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INF_ADOPTED_TYPE_SPLIT_OPERATION, InfAdoptedSplitOperationPrivate)) static void inf_adopted_split_operation_operation_iface_init(InfAdoptedOperationInterface* iface); G_DEFINE_TYPE_WITH_CODE(InfAdoptedSplitOperation, inf_adopted_split_operation, G_TYPE_OBJECT, G_ADD_PRIVATE(InfAdoptedSplitOperation) G_IMPLEMENT_INTERFACE(INF_ADOPTED_TYPE_OPERATION, inf_adopted_split_operation_operation_iface_init)) static void inf_adopted_split_operation_unsplit_impl(InfAdoptedSplitOperation* operation, GSList** list) { InfAdoptedSplitOperationPrivate* priv; priv = INF_ADOPTED_SPLIT_OPERATION_PRIVATE(operation); /* Since we prepend the entries to the list, we begin with the second * operation so that the list actually contains the operations in order. */ if(INF_ADOPTED_IS_SPLIT_OPERATION(priv->second)) { inf_adopted_split_operation_unsplit_impl( INF_ADOPTED_SPLIT_OPERATION(priv->second), list ); } else { *list = g_slist_prepend(*list, priv->second); } if(INF_ADOPTED_IS_SPLIT_OPERATION(priv->first)) { inf_adopted_split_operation_unsplit_impl( INF_ADOPTED_SPLIT_OPERATION(priv->first), list ); } else { *list = g_slist_prepend(*list, priv->first); } } static void inf_adopted_split_operation_init(InfAdoptedSplitOperation* operation) { InfAdoptedSplitOperationPrivate* priv; priv = INF_ADOPTED_SPLIT_OPERATION_PRIVATE(operation); priv->first = NULL; priv->second = NULL; } static void inf_adopted_split_operation_dispose(GObject* object) { InfAdoptedSplitOperation* operation; InfAdoptedSplitOperationPrivate* priv; operation = INF_ADOPTED_SPLIT_OPERATION(object); priv = INF_ADOPTED_SPLIT_OPERATION_PRIVATE(operation); if(priv->first != NULL) { g_object_unref(priv->first); priv->first = NULL; } if(priv->second != NULL) { g_object_unref(priv->second); priv->second = NULL; } G_OBJECT_CLASS(inf_adopted_split_operation_parent_class)->dispose(object); } static void inf_adopted_split_operation_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfAdoptedSplitOperation* operation; InfAdoptedSplitOperationPrivate* priv; operation = INF_ADOPTED_SPLIT_OPERATION(object); priv = INF_ADOPTED_SPLIT_OPERATION_PRIVATE(operation); switch(prop_id) { case PROP_FIRST: if(priv->first != NULL) g_object_unref(G_OBJECT(priv->first)); priv->first = INF_ADOPTED_OPERATION(g_value_dup_object(value)); g_assert(priv->first != INF_ADOPTED_OPERATION(operation)); break; case PROP_SECOND: if(priv->second != NULL) g_object_unref(G_OBJECT(priv->second)); priv->second = INF_ADOPTED_OPERATION(g_value_dup_object(value)); g_assert(priv->second != INF_ADOPTED_OPERATION(operation)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void inf_adopted_split_operation_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfAdoptedSplitOperation* operation; InfAdoptedSplitOperationPrivate* priv; operation = INF_ADOPTED_SPLIT_OPERATION(object); priv = INF_ADOPTED_SPLIT_OPERATION_PRIVATE(operation); switch(prop_id) { case PROP_FIRST: g_value_set_object(value, G_OBJECT(priv->first)); break; case PROP_SECOND: g_value_set_object(value, G_OBJECT(priv->second)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void inf_adopted_split_operation_class_init( InfAdoptedSplitOperationClass* split_operation_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(split_operation_class); object_class->dispose = inf_adopted_split_operation_dispose; object_class->set_property = inf_adopted_split_operation_set_property; object_class->get_property = inf_adopted_split_operation_get_property; g_object_class_install_property( object_class, PROP_FIRST, g_param_spec_object( "first", "First operation", "The first operation of the split operation", INF_ADOPTED_TYPE_OPERATION, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_SECOND, g_param_spec_object( "second", "Second operation", "The second operation of the split operation", INF_ADOPTED_TYPE_OPERATION, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); } static gboolean inf_adopted_split_operation_need_concurrency_id(InfAdoptedOperation* op, InfAdoptedOperation* against) { InfAdoptedSplitOperation* split; InfAdoptedSplitOperationPrivate* priv; InfAdoptedOperation* new_against; gboolean result; split = INF_ADOPTED_SPLIT_OPERATION(op); priv = INF_ADOPTED_SPLIT_OPERATION_PRIVATE(split); if(inf_adopted_operation_need_concurrency_id(priv->first, against) == TRUE) return TRUE; /* Note that for this transformation there is no concurrency ID required */ new_against = inf_adopted_operation_transform( against, priv->first, NULL, NULL, INF_ADOPTED_CONCURRENCY_NONE ); result = inf_adopted_operation_need_concurrency_id( priv->second, new_against ); g_object_unref(new_against); return result; } static InfAdoptedOperation* inf_adopted_split_operation_transform(InfAdoptedOperation* operation, InfAdoptedOperation* against, InfAdoptedOperation* operation_lcs, InfAdoptedOperation* against_lcs, InfAdoptedConcurrencyId concurrency_id) { InfAdoptedSplitOperation* split; InfAdoptedSplitOperationPrivate* priv; InfAdoptedOperation* new_first; InfAdoptedOperation* new_against; InfAdoptedOperation* new_second; InfAdoptedOperation* result; InfAdoptedSplitOperationPrivate* priv_lcs; InfAdoptedOperation* first_lcs; InfAdoptedOperation* second_lcs; InfAdoptedOperation* new_against_lcs; split = INF_ADOPTED_SPLIT_OPERATION(operation); priv = INF_ADOPTED_SPLIT_OPERATION_PRIVATE(split); if(INF_ADOPTED_IS_SPLIT_OPERATION(operation_lcs)) { g_assert(against_lcs != NULL); priv_lcs = INF_ADOPTED_SPLIT_OPERATION_PRIVATE(operation_lcs); first_lcs = priv_lcs->first; second_lcs = priv_lcs->second; new_against_lcs = inf_adopted_operation_transform( against_lcs, first_lcs, against_lcs, first_lcs, -concurrency_id ); } else if(operation_lcs != NULL) { first_lcs = operation_lcs; second_lcs = operation_lcs; new_against_lcs = against_lcs; g_object_ref(new_against_lcs); } else { first_lcs = NULL; second_lcs = NULL; new_against_lcs = NULL; } new_first = inf_adopted_operation_transform( priv->first, against, first_lcs, against_lcs, concurrency_id ); new_against = inf_adopted_operation_transform( against, priv->first, against_lcs, first_lcs, -concurrency_id ); new_second = inf_adopted_operation_transform( priv->second, new_against, second_lcs, new_against_lcs, concurrency_id ); if(new_against_lcs != NULL) g_object_unref(new_against_lcs); g_object_unref(new_against); /* Note that even if one of the two is a no-op, we keep the split operation * at this point. Parts of the split operation implementation relies on the * fact that a split operation is never un-split during transformation. */ result = INF_ADOPTED_OPERATION( inf_adopted_split_operation_new(new_first, new_second) ); g_object_unref(G_OBJECT(new_first)); g_object_unref(G_OBJECT(new_second)); return result; } static InfAdoptedOperation* inf_adopted_split_operation_copy(InfAdoptedOperation* operation) { InfAdoptedSplitOperation* split; InfAdoptedSplitOperationPrivate* priv; split = INF_ADOPTED_SPLIT_OPERATION(operation); priv = INF_ADOPTED_SPLIT_OPERATION_PRIVATE(split); return INF_ADOPTED_OPERATION( inf_adopted_split_operation_new( inf_adopted_operation_copy(priv->first), inf_adopted_operation_copy(priv->second) ) ); } static InfAdoptedOperationFlags inf_adopted_split_operation_get_flags(InfAdoptedOperation* operation) { InfAdoptedSplitOperation* split; InfAdoptedSplitOperationPrivate* priv; InfAdoptedOperationFlags flags1; InfAdoptedOperationFlags flags2; InfAdoptedOperationFlags result; split = INF_ADOPTED_SPLIT_OPERATION(operation); priv = INF_ADOPTED_SPLIT_OPERATION_PRIVATE(split); flags1 = inf_adopted_operation_get_flags(priv->first); flags2 = inf_adopted_operation_get_flags(priv->second); result = 0; if( (flags1 & INF_ADOPTED_OPERATION_AFFECTS_BUFFER) != 0 || (flags2 & INF_ADOPTED_OPERATION_AFFECTS_BUFFER) != 0) { result |= INF_ADOPTED_OPERATION_AFFECTS_BUFFER; } if( (flags1 & INF_ADOPTED_OPERATION_REVERSIBLE) != 0 && (flags2 & INF_ADOPTED_OPERATION_REVERSIBLE) != 0) { result |= INF_ADOPTED_OPERATION_REVERSIBLE; } return result; } static gboolean inf_adopted_split_operation_apply(InfAdoptedOperation* operation, InfAdoptedUser* by, InfBuffer* buffer, GError** error) { InfAdoptedSplitOperation* split; InfAdoptedSplitOperationPrivate* priv; split = INF_ADOPTED_SPLIT_OPERATION(operation); priv = INF_ADOPTED_SPLIT_OPERATION_PRIVATE(split); if(!inf_adopted_operation_apply(priv->first, by, buffer, error)) return FALSE; if(!inf_adopted_operation_apply(priv->second, by, buffer, error)) return FALSE; return TRUE; } static InfAdoptedOperation* inf_adopted_split_operation_apply_transformed(InfAdoptedOperation* operation, InfAdoptedOperation* transformed, InfAdoptedUser* by, InfBuffer* buffer, GError** error) { InfAdoptedSplitOperation* split; InfAdoptedSplitOperation* trans_split; InfAdoptedSplitOperationPrivate* priv; InfAdoptedSplitOperationPrivate* trans_priv; InfAdoptedOperation* ret_first; InfAdoptedOperation* ret_second; InfAdoptedSplitOperation* result; split = INF_ADOPTED_SPLIT_OPERATION(operation); priv = INF_ADOPTED_SPLIT_OPERATION_PRIVATE(split); /* The transformed operation must be a split operation, too, * since we do no never unsplit operations when transforming */ g_assert(INF_ADOPTED_IS_SPLIT_OPERATION(transformed)); trans_split = INF_ADOPTED_SPLIT_OPERATION(transformed); trans_priv = INF_ADOPTED_SPLIT_OPERATION_PRIVATE(trans_split); ret_first = inf_adopted_operation_apply_transformed( priv->first, trans_priv->first, by, buffer, error ); if(ret_first == NULL) return NULL; ret_second = inf_adopted_operation_apply_transformed( priv->second, trans_priv->second, by, buffer, error ); if(ret_second == NULL) { g_object_unref(ret_first); return NULL; } if(ret_first == priv->first && ret_second == priv->second) { /* No operation was modified to be reversible; skip this case */ g_object_unref(ret_first); g_object_unref(ret_second); return operation; } else { /* Otherwise create a new operation */ result = inf_adopted_split_operation_new( ret_first, ret_second ); g_object_unref(ret_first); g_object_unref(ret_second); return INF_ADOPTED_OPERATION(result); } } static InfAdoptedOperation* inf_adopted_split_operation_revert(InfAdoptedOperation* operation) { InfAdoptedSplitOperation* split; InfAdoptedSplitOperationPrivate* priv; InfAdoptedOperation* revert_first; InfAdoptedOperation* revert_second; InfAdoptedSplitOperation* result; split = INF_ADOPTED_SPLIT_OPERATION(operation); priv = INF_ADOPTED_SPLIT_OPERATION_PRIVATE(split); revert_first = inf_adopted_operation_revert(priv->first); revert_second = inf_adopted_operation_revert(priv->second); result = inf_adopted_split_operation_new(revert_second, revert_first); g_object_unref(revert_first); g_object_unref(revert_second); return INF_ADOPTED_OPERATION(result); } static void inf_adopted_split_operation_operation_iface_init( InfAdoptedOperationInterface* iface) { iface->need_concurrency_id = inf_adopted_split_operation_need_concurrency_id; iface->transform = inf_adopted_split_operation_transform; iface->copy = inf_adopted_split_operation_copy; iface->get_flags = inf_adopted_split_operation_get_flags; iface->apply = inf_adopted_split_operation_apply; iface->apply_transformed = inf_adopted_split_operation_apply_transformed; iface->revert = inf_adopted_split_operation_revert; } /** * inf_adopted_split_operation_new: (constructor) * @first: one of the #InfAdoptedOperations to be wrapped * @second: the other #InfAdoptedOperation to be wrapped * * Creates a new #InfAdoptedSplitOperation. A split operation is simply a * wrapper around two operations (which may in turn be split operations). * * Returns: (transfer full): A new #InfAdoptedSplitOperation. **/ InfAdoptedSplitOperation* inf_adopted_split_operation_new(InfAdoptedOperation* first, InfAdoptedOperation* second) { GObject* object; g_return_val_if_fail(INF_ADOPTED_IS_OPERATION(first), NULL); g_return_val_if_fail(INF_ADOPTED_IS_OPERATION(second), NULL); object = g_object_new( INF_ADOPTED_TYPE_SPLIT_OPERATION, "first", first, "second", second, NULL ); return INF_ADOPTED_SPLIT_OPERATION(object); } /** * inf_adopted_split_operation_unsplit: * @operation: A #InfAdoptedSplitOperation. * * Returns a list of the operations contained by the split operation. If the * splitted operation are in turn split operations, they will also be * unsplitted. The returned list is guarenteed to not contain a * #InfAdoptedSplitOperation. * * Returns: (transfer container) (element-type InfAdoptedOperation): A * list of operations. Free with g_slist_free() when done. **/ GSList* inf_adopted_split_operation_unsplit(InfAdoptedSplitOperation* operation) { GSList* result; result = NULL; inf_adopted_split_operation_unsplit_impl(operation, &result); return result; } /** * inf_adopted_split_operation_transform_other: * @op: A #InfAdoptedSplitOperation. * @other: An arbitrary #InfAdoptedOperation. * @op_lcs: The operation @op at a previous state, or %NULL. * @other_lcs: The operation @other at a previous state, or %NULL. * @concurrency_id: The concurrency id for the transformation of * @other against @op. * * Transforms @other against @op. * * Returns: (transfer full): The transformed operation. **/ InfAdoptedOperation* inf_adopted_split_operation_transform_other(InfAdoptedSplitOperation* op, InfAdoptedOperation* other, InfAdoptedOperation* op_lcs, InfAdoptedOperation* other_lcs, gint concurrency_id) { InfAdoptedSplitOperationPrivate* priv; InfAdoptedSplitOperationPrivate* priv_lcs; InfAdoptedOperation* tmp; InfAdoptedOperation* result; InfAdoptedOperation* first_lcs; InfAdoptedOperation* second_lcs; InfAdoptedOperation* tmp_lcs; g_return_val_if_fail(INF_ADOPTED_IS_SPLIT_OPERATION(op), NULL); g_return_val_if_fail(INF_ADOPTED_IS_OPERATION(other), NULL); priv = INF_ADOPTED_SPLIT_OPERATION_PRIVATE(op); if(INF_ADOPTED_IS_SPLIT_OPERATION(op_lcs)) { g_assert(other_lcs != NULL); priv_lcs = INF_ADOPTED_SPLIT_OPERATION_PRIVATE(op_lcs); first_lcs = priv_lcs->first; second_lcs = priv_lcs->second; tmp_lcs = inf_adopted_operation_transform( other_lcs, first_lcs, other_lcs, first_lcs, concurrency_id ); } else if(op_lcs != NULL) { g_assert(other_lcs != NULL); first_lcs = op_lcs; second_lcs = op_lcs; tmp_lcs = other_lcs; g_object_ref(tmp_lcs); } else { first_lcs = NULL; second_lcs = NULL; tmp_lcs = NULL; } tmp = inf_adopted_operation_transform( other, priv->first, other_lcs, first_lcs, concurrency_id ); result = inf_adopted_operation_transform( tmp, priv->second, tmp_lcs, second_lcs, concurrency_id ); if(tmp_lcs != NULL) g_object_unref(tmp_lcs); g_object_unref(tmp); return result; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/adopted/PaxHeaders.26529/inf-adopted-session-replay.c0000644000000000000000000000013213034342512025051 xustar0030 mtime=1483851082.025718404 30 atime=1483851082.025718404 30 ctime=1488261589.028139004 libinfinity-0.7.1/libinfinity/adopted/inf-adopted-session-replay.c0000644000175000017500000006647113034342512025621 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-adopted-session-replay * @title: InfAdoptedSessionReplay * @short_description: Replay a record of a session * @include: libinfinity/adopted/inf-adopted-session-replay.h * @see_also: #InfAdoptedSession, #InfAdoptedSessionRecord * @stability: Unstable * * #InfAdoptedSessionReplay can be used to replay a record created with * #InfAdoptedSessionRecord. * * Use inf_adopted_session_replay_set_record() to specify the recording to * replay, and then use inf_adopted_session_replay_get_session() to obtain * the replayed session. */ #include #include #include #include #include #include #include /* cf. * http://www.gnu.org/software/dotgnu/pnetlib-doc/System/Xml/XmlNodeType.html */ #define XML_READER_TYPE_NONE 0 #define XML_READER_TYPE_ELEMENT 1 #define XML_READER_TYPE_SIGNIFICANT_WHITESPACE 14 #define XML_READER_TYPE_END_ELEMENT 15 typedef struct _InfAdoptedSessionReplayPrivate InfAdoptedSessionReplayPrivate; struct _InfAdoptedSessionReplayPrivate { gchar* filename; xmlTextReaderPtr reader; GError* error; InfCommunicationManager* publisher_manager; InfCommunicationHostedGroup* publisher_group; InfSimulatedConnection* publisher_conn; InfCommunicationManager* client_manager; InfCommunicationJoinedGroup* client_group; InfSimulatedConnection* client_conn; InfAdoptedSession* session; }; enum { PROP_0, PROP_FILENAME, PROP_SESSION }; #define INF_ADOPTED_SESSION_REPLAY_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INF_ADOPTED_TYPE_SESSION_REPLAY, InfAdoptedSessionReplayPrivate)) static GQuark session_replay_error_quark; G_DEFINE_TYPE_WITH_CODE(InfAdoptedSessionReplay, inf_adopted_session_replay, G_TYPE_OBJECT, G_ADD_PRIVATE(InfAdoptedSessionReplay)) static xmlNodePtr inf_adopted_session_replay_read_current(xmlTextReaderPtr reader, GError** error) { xmlErrorPtr xml_error; xmlNodePtr cur; cur = xmlTextReaderExpand(reader); if(!cur) { xml_error = xmlGetLastError(); g_set_error_literal( error, session_replay_error_quark, INF_ADOPTED_SESSION_REPLAY_ERROR_BAD_XML, xml_error->message ); return NULL; } return cur; } static gboolean inf_adopted_session_replay_handle_advance_result(int result, GError** error) { xmlErrorPtr xml_error; switch(result) { case -1: xml_error = xmlGetLastError(); g_set_error_literal( error, session_replay_error_quark, INF_ADOPTED_SESSION_REPLAY_ERROR_BAD_XML, xml_error->message ); return FALSE; case 0: case 1: return TRUE; default: g_assert_not_reached(); return FALSE; } } static gboolean inf_adopted_session_replay_handle_advance_required_result(int result, GError** error) { xmlErrorPtr xml_error; switch(result) { case -1: xml_error = xmlGetLastError(); g_set_error_literal( error, session_replay_error_quark, INF_ADOPTED_SESSION_REPLAY_ERROR_BAD_XML, xml_error->message ); return FALSE; case 0: g_set_error_literal( error, session_replay_error_quark, INF_ADOPTED_SESSION_REPLAY_ERROR_UNEXPECTED_EOF, _("Unexpected end of recording") ); return FALSE; case 1: return TRUE; default: g_assert_not_reached(); return FALSE; } } static gboolean inf_adopted_session_replay_advance(xmlTextReaderPtr reader, GError** error) { int result; result = xmlTextReaderRead(reader); return inf_adopted_session_replay_handle_advance_result(result, error); } static gboolean inf_adopted_session_replay_advance_required(xmlTextReaderPtr reader, GError** error) { int result; result = xmlTextReaderRead(reader); return inf_adopted_session_replay_handle_advance_required_result( result, error ); } static gboolean inf_adopted_session_replay_advance_subtree_required(xmlTextReaderPtr reader, GError** error) { int result; result = xmlTextReaderNext(reader); return inf_adopted_session_replay_handle_advance_required_result( result, error ); } static gboolean inf_adopted_session_replay_skip_whitespace(xmlTextReaderPtr reader, GError** error) { while(xmlTextReaderNodeType(reader) == XML_READER_TYPE_SIGNIFICANT_WHITESPACE) { if(inf_adopted_session_replay_advance(reader, error) == FALSE) return FALSE; } return TRUE; } static gboolean inf_adopted_session_replay_skip_whitespace_required(xmlTextReaderPtr reader, GError** error) { while(xmlTextReaderNodeType(reader) == XML_READER_TYPE_SIGNIFICANT_WHITESPACE) { if(inf_adopted_session_replay_advance_required(reader, error) == FALSE) return FALSE; } return TRUE; } static void inf_adopted_session_replay_clear(InfAdoptedSessionReplay* replay) { InfAdoptedSessionReplayPrivate* priv; priv = INF_ADOPTED_SESSION_REPLAY_PRIVATE(replay); g_object_freeze_notify(G_OBJECT(replay)); if(priv->filename != NULL) { g_free(priv->filename); priv->filename = NULL; g_object_notify(G_OBJECT(replay), "filename"); } if(priv->reader != NULL) { if(xmlTextReaderClose(priv->reader) == -1) g_warning("Failed to close XML reader: %s", xmlGetLastError()->message); xmlFreeTextReader(priv->reader); priv->reader = NULL; } g_assert(priv->error == NULL); if(priv->publisher_group != NULL) { g_object_unref(priv->publisher_group); priv->publisher_group = NULL; } if(priv->publisher_conn != NULL) { g_object_unref(priv->publisher_conn); priv->publisher_conn = NULL; } if(priv->publisher_manager != NULL) { g_object_unref(priv->publisher_manager); priv->publisher_manager = NULL; } if(priv->client_group != NULL) { g_object_unref(priv->client_group); priv->client_group = NULL; } if(priv->client_conn != NULL) { g_object_unref(priv->client_conn); priv->client_conn = NULL; } if(priv->client_manager != NULL) { g_object_unref(priv->client_manager); priv->client_manager = NULL; } if(priv->session != NULL) { g_object_unref(priv->session); priv->session = NULL; g_object_notify(G_OBJECT(replay), "session"); } g_object_thaw_notify(G_OBJECT(replay)); } static void inf_adopted_session_replay_synchronization_failed_cb(InfSession* session, InfXmlConnection* conn, GError* error, gpointer user_data) { InfAdoptedSessionReplay* replay; InfAdoptedSessionReplayPrivate* priv; replay = INF_ADOPTED_SESSION_REPLAY(user_data); priv = INF_ADOPTED_SESSION_REPLAY_PRIVATE(replay); g_assert(priv->error == NULL); priv->error = g_error_copy(error); } static gboolean inf_adopted_session_replay_play_initial(InfAdoptedSessionReplay* replay, const InfcNotePlugin* plugin, GError** error) { InfAdoptedSessionReplayPrivate* priv; xmlTextReaderPtr reader; xmlNodePtr cur; const xmlChar* name; xmlChar* value; gulong handler; priv = INF_ADOPTED_SESSION_REPLAY_PRIVATE(replay); reader = priv->reader; /* Advance to root node */ if(xmlTextReaderNodeType(reader) != XML_READER_TYPE_ELEMENT) if(!inf_adopted_session_replay_advance_required(reader, error)) return FALSE; name = xmlTextReaderConstName(reader); if(strcmp((const char*)name, "infinote-adopted-session-record") != 0) { g_set_error_literal( error, session_replay_error_quark, INF_ADOPTED_SESSION_REPLAY_ERROR_BAD_DOCUMENT, _("Document is not a session recording") ); return FALSE; } value = xmlTextReaderGetAttribute(reader, (const xmlChar*)"session-type"); if(value && strcmp((const char*)name, plugin->note_type) != 0) { xmlFree(value); g_set_error_literal( error, session_replay_error_quark, INF_ADOPTED_SESSION_REPLAY_ERROR_BAD_SESSION_TYPE, _("Session type of the recording does not match") ); return FALSE; } if(value) xmlFree(value); if(!inf_adopted_session_replay_advance_required(reader, error)) return FALSE; if(!inf_adopted_session_replay_skip_whitespace_required(reader, error)) return FALSE; name = xmlTextReaderConstName(reader); if(strcmp((const char*)name, "initial") != 0) { g_set_error_literal( error, session_replay_error_quark, INF_ADOPTED_SESSION_REPLAY_ERROR_BAD_FORMAT, _("Initial session state missing in recording") ); return FALSE; } if(!inf_adopted_session_replay_advance_required(reader, error)) return FALSE; if(!inf_adopted_session_replay_skip_whitespace_required(reader, error)) return FALSE; handler = g_signal_connect( priv->session, "synchronization-failed", G_CALLBACK(inf_adopted_session_replay_synchronization_failed_cb), replay ); while(xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) { switch(inf_session_get_status(INF_SESSION(priv->session))) { case INF_SESSION_CLOSED: g_assert_not_reached(); g_signal_handler_disconnect(priv->session, handler); return FALSE; case INF_SESSION_SYNCHRONIZING: cur = inf_adopted_session_replay_read_current(reader, error); if(!cur) { g_signal_handler_disconnect(priv->session, handler); return FALSE; } inf_communication_group_send_message( INF_COMMUNICATION_GROUP(priv->publisher_group), INF_XML_CONNECTION(priv->publisher_conn), xmlCopyNode(cur, 1) ); /* TODO: Check whether this caused an error. Maybe there should be an * error signal for InfCommunicationGroup, delegating * inf_net_object_received's error. */ inf_simulated_connection_flush(priv->publisher_conn); /* error can be set if the synchronization failed */ if(priv->error != NULL) { g_signal_handler_disconnect(priv->session, handler); g_propagate_error(error, priv->error); priv->error = NULL; return FALSE; } if(!inf_adopted_session_replay_advance_subtree_required(reader, error)) { g_signal_handler_disconnect(priv->session, handler); return FALSE; } if(!inf_adopted_session_replay_skip_whitespace_required(reader, error)) { g_signal_handler_disconnect(priv->session, handler); return FALSE; } break; case INF_SESSION_RUNNING: g_signal_handler_disconnect(priv->session, handler); g_set_error_literal( error, session_replay_error_quark, INF_ADOPTED_SESSION_REPLAY_ERROR_BAD_FORMAT, _("Session switched to running without having finished playing " "the initial") ); return FALSE; case INF_SESSION_PRESYNC: default: g_assert_not_reached(); break; } } g_signal_handler_disconnect(priv->session, handler); if(xmlTextReaderNodeType(reader) != XML_READER_TYPE_END_ELEMENT) { g_set_error_literal( error, session_replay_error_quark, INF_ADOPTED_SESSION_REPLAY_ERROR_BAD_FORMAT, _("Superfluous XML in initial session section") ); return FALSE; } if(inf_session_get_status(INF_SESSION(priv->session)) == INF_SESSION_SYNCHRONIZING) { g_set_error_literal( error, session_replay_error_quark, INF_ADOPTED_SESSION_REPLAY_ERROR_BAD_FORMAT, _("Session is still in synchronizing state after having " "played the initial") ); return FALSE; } /* Jump over end element */ if(!inf_adopted_session_replay_advance_required(reader, error)) return FALSE; /* Not "_required"; recording might end right after initial */ if(!inf_adopted_session_replay_skip_whitespace(reader, error)) return FALSE; return TRUE; } /* * GObject overrides. */ static void inf_adopted_session_replay_init(InfAdoptedSessionReplay* replay) { InfAdoptedSessionReplayPrivate* priv; priv = INF_ADOPTED_SESSION_REPLAY_PRIVATE(replay); priv->filename = NULL; priv->reader = NULL; priv->error = NULL; priv->publisher_manager = NULL; priv->publisher_group = NULL; priv->publisher_conn = NULL; priv->client_manager = NULL; priv->client_group = NULL; priv->client_conn = NULL; priv->session = NULL; } static void inf_adopted_session_replay_dispose(GObject* object) { InfAdoptedSessionReplay* replay; InfAdoptedSessionReplayPrivate* priv; replay = INF_ADOPTED_SESSION_REPLAY(object); priv = INF_ADOPTED_SESSION_REPLAY_PRIVATE(replay); inf_adopted_session_replay_clear(replay); G_OBJECT_CLASS(inf_adopted_session_replay_parent_class)->dispose(object); } static void inf_adopted_session_replay_finalize(GObject* object) { InfAdoptedSessionReplay* replay; InfAdoptedSessionReplayPrivate* priv; replay = INF_ADOPTED_SESSION_REPLAY(object); priv = INF_ADOPTED_SESSION_REPLAY_PRIVATE(replay); g_assert(priv->filename == NULL); G_OBJECT_CLASS(inf_adopted_session_replay_parent_class)->finalize(object); } static void inf_adopted_session_replay_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfAdoptedSessionReplay* replay; InfAdoptedSessionReplayPrivate* priv; replay = INF_ADOPTED_SESSION_REPLAY(object); priv = INF_ADOPTED_SESSION_REPLAY_PRIVATE(replay); switch(prop_id) { case PROP_FILENAME: case PROP_SESSION: /* read only */ default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void inf_adopted_session_replay_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfAdoptedSessionReplay* replay; InfAdoptedSessionReplayPrivate* priv; replay = INF_ADOPTED_SESSION_REPLAY(object); priv = INF_ADOPTED_SESSION_REPLAY_PRIVATE(replay); switch(prop_id) { case PROP_FILENAME: g_value_set_string(value, priv->filename); break; case PROP_SESSION: g_value_set_object(value, G_OBJECT(priv->session)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } /* * Gype registration. */ static void inf_adopted_session_replay_class_init( InfAdoptedSessionReplayClass* replay_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(replay_class); object_class->dispose = inf_adopted_session_replay_dispose; object_class->finalize = inf_adopted_session_replay_finalize; object_class->set_property = inf_adopted_session_replay_set_property; object_class->get_property = inf_adopted_session_replay_get_property; session_replay_error_quark = g_quark_from_static_string("INF_ADOPTED_SESSION_REPLAY_ERROR"); g_object_class_install_property( object_class, PROP_FILENAME, g_param_spec_string( "filename", "Filename", "The filename of the record to play", NULL, G_PARAM_READABLE ) ); g_object_class_install_property( object_class, PROP_SESSION, g_param_spec_object( "session", "Session", "The replayed session", INF_ADOPTED_TYPE_SESSION, G_PARAM_READABLE ) ); } /* * Public API. */ /** * inf_adopted_session_replay_new: (constructor) * * Creates a new #InfAdoptedSessionReplay. Use * inf_adopted_session_replay_set_record() to start the recording, and * inf_adopted_session_replay_play_next() or * inf_adopted_session_replay_play_to_end() to play it. * * Returns: (transfer full): A new #InfAdoptedSessionReplay. Free with * g_object_unref() when no longer in use. **/ InfAdoptedSessionReplay* inf_adopted_session_replay_new(void) { GObject* object; object = g_object_new(INF_ADOPTED_TYPE_SESSION_REPLAY, NULL); return INF_ADOPTED_SESSION_REPLAY(object); } /** * inf_adopted_session_replay_set_record: * @replay: A #InfAdoptedSessionReplay. * @filename: (type filename): Path to the record file to play. * @plugin: A #InfcNotePlugin for the note type of the recorded session. * @error: Location to store error information, if any. * * Set the record file for @replay to play. It should have been created with * #InfAdoptedSessionRecord. @plugin should match the type of the recorded * session. If an error occurs, the function returns %FALSE and @error is set. * * Returns: %TRUE on success, or %FALSE if the record file could not be set. */ gboolean inf_adopted_session_replay_set_record(InfAdoptedSessionReplay* replay, const gchar* filename, const InfcNotePlugin* plugin, GError** error) { InfAdoptedSessionReplayPrivate* priv; xmlTextReaderPtr reader; InfIo* io; gboolean result; xmlErrorPtr xml_error; g_return_val_if_fail(INF_ADOPTED_IS_SESSION_REPLAY(replay), FALSE); g_return_val_if_fail(filename != NULL, FALSE); g_return_val_if_fail(plugin != NULL, FALSE); g_return_val_if_fail(error == NULL || *error == NULL, FALSE); priv = INF_ADOPTED_SESSION_REPLAY_PRIVATE(replay); reader = xmlReaderForFile( filename, NULL, XML_PARSE_NOERROR | XML_PARSE_NOWARNING ); if(!reader) { xml_error = xmlGetLastError(); g_set_error_literal( error, session_replay_error_quark, INF_ADOPTED_SESSION_REPLAY_ERROR_BAD_FILE, xml_error->message ); return FALSE; } /* TODO: Keep current staet if playing the initial fails */ g_object_freeze_notify(G_OBJECT(replay)); inf_adopted_session_replay_clear(replay); priv->filename = g_strdup(filename); priv->reader = reader; priv->publisher_conn = inf_simulated_connection_new(); priv->client_conn = inf_simulated_connection_new(); inf_simulated_connection_connect(priv->publisher_conn, priv->client_conn); inf_simulated_connection_set_mode( priv->publisher_conn, INF_SIMULATED_CONNECTION_DELAYED ); inf_simulated_connection_set_mode( priv->client_conn, INF_SIMULATED_CONNECTION_DELAYED ); priv->publisher_manager = inf_communication_manager_new(); priv->publisher_group = inf_communication_manager_open_group( priv->publisher_manager, "InfAdoptedSessionReplay", NULL ); inf_communication_hosted_group_add_member( priv->publisher_group, INF_XML_CONNECTION(priv->publisher_conn) ); priv->client_manager = inf_communication_manager_new(); priv->client_group = inf_communication_manager_join_group( priv->client_manager, "InfAdoptedSessionReplay", INF_XML_CONNECTION(priv->client_conn), "central" ); /* This is not used anyway, but it needs to be present: */ io = INF_IO(inf_standalone_io_new()); priv->session = INF_ADOPTED_SESSION( plugin->session_new( io, priv->client_manager, INF_SESSION_SYNCHRONIZING, INF_COMMUNICATION_GROUP(priv->client_group), INF_XML_CONNECTION(priv->client_conn), NULL, plugin->user_data ) ); g_object_unref(io); inf_communication_group_set_target( INF_COMMUNICATION_GROUP(priv->client_group), INF_COMMUNICATION_OBJECT(priv->session) ); inf_simulated_connection_flush(priv->publisher_conn); inf_simulated_connection_flush(priv->client_conn); if(!inf_adopted_session_replay_play_initial(replay, plugin, error)) { inf_adopted_session_replay_clear(replay); result = FALSE; } else { g_object_notify(G_OBJECT(replay), "filename"); g_object_notify(G_OBJECT(replay), "session"); result = TRUE; } g_object_thaw_notify(G_OBJECT(replay)); return result; } /** * inf_adopted_session_replay_get_session: * @replay: A #InfAdoptedSessionReplay. * * Returns the played back session, or %NULL if * inf_adopted_session_replay_set_record() was not yet called. * * Returns: (transfer none): A #InfAdoptedSessionReplay, or %NULL. */ InfAdoptedSession* inf_adopted_session_replay_get_session(InfAdoptedSessionReplay* replay) { g_return_val_if_fail(INF_ADOPTED_IS_SESSION_REPLAY(replay), NULL); return INF_ADOPTED_SESSION_REPLAY_PRIVATE(replay)->session; } /** * inf_adopted_session_replay_play_next: * @replay: A #InfAdoptedSessionReplay. * @error: Location to store error information, if any. * * Reads the next request from the record and passes it to the session. Note * that this might do nothing if that request is not yet causally ready, * meaning that it depends on another request that has not yet been played. In * that case it will be executed as soon as it is ready, that is after some * future inf_adopted_session_replay_play_next() call. Therefore, it is also * possible that this function executes more than one request. * * If an error occurs, then this function returns %FALSE and @error is set. * If the end of the recording is reached, then it also returns %FALSE, but * @error is left untouched. If the next request has been read, then it * returns %TRUE. * * Returns: %TRUE if a request was read, otherwise %FALSE. */ gboolean inf_adopted_session_replay_play_next(InfAdoptedSessionReplay* replay, GError** error) { InfAdoptedSessionReplayPrivate* priv; xmlTextReaderPtr reader; int type; xmlNodePtr cur; guint id; InfUser* user; InfSessionClass* session_class; GArray* user_props; GParameter* param; gboolean result; guint i; g_return_val_if_fail(INF_ADOPTED_IS_SESSION_REPLAY(replay), FALSE); g_return_val_if_fail(error == NULL || *error == NULL, FALSE); priv = INF_ADOPTED_SESSION_REPLAY_PRIVATE(replay); reader = priv->reader; type = xmlTextReaderNodeType(reader); /* EOF, maybe the writer crashed and could not finish the record properly */ if(type == XML_READER_TYPE_NONE) return FALSE; /* */ if(type == XML_READER_TYPE_END_ELEMENT) return FALSE; if(type != XML_READER_TYPE_ELEMENT) { g_set_error_literal( error, session_replay_error_quark, INF_ADOPTED_SESSION_REPLAY_ERROR_BAD_FORMAT, _("Superfluous XML in requests section") ); return FALSE; } cur = inf_adopted_session_replay_read_current(reader, error); if(cur == NULL) return FALSE; if(strcmp((const char*)cur->name, "request") == 0) { /* TODO: Add user join/leaves to record. * Until that is done, make users available when they issue a request. */ if(!inf_xml_util_get_attribute_uint_required(cur, "user", &id, error)) return FALSE; user = inf_user_table_lookup_user_by_id( inf_session_get_user_table(INF_SESSION(priv->session)), id ); if(!user) { g_set_error( error, session_replay_error_quark, INF_ADOPTED_SESSION_REPLAY_ERROR_BAD_FORMAT, _("No such user with ID \"%u\""), id ); return FALSE; } if(inf_user_get_status(user) == INF_USER_UNAVAILABLE) { g_object_set( G_OBJECT(user), "status", INF_USER_ACTIVE, "connection", priv->client_conn, NULL ); } inf_communication_group_send_group_message( INF_COMMUNICATION_GROUP(priv->publisher_group), xmlCopyNode(cur, 1) ); /* TODO: Check whether this caused an error. Maybe there should be an * error signal for InfCommunicationGroup, delegating * inf_net_object_received's error. */ inf_simulated_connection_flush(priv->publisher_conn); } else if(strcmp((const char*)cur->name, "user") == 0) { /* User join */ session_class = INF_SESSION_GET_CLASS(priv->session); user_props = session_class->get_xml_user_props( INF_SESSION(priv->session), INF_XML_CONNECTION(priv->publisher_conn), cur ); param = inf_session_get_user_property(user_props, "connection"); if(!G_IS_VALUE(¶m->value)) { g_value_init(¶m->value, INF_TYPE_XML_CONNECTION); g_value_set_object(¶m->value, G_OBJECT(priv->client_conn)); } result = session_class->validate_user_props( INF_SESSION(priv->session), (const GParameter*)user_props->data, user_props->len, NULL, error ); if(result == TRUE) { user = inf_session_add_user( INF_SESSION(priv->session), (const GParameter*)user_props->data, user_props->len ); } for(i = 0; i < user_props->len; ++i) g_value_unset(&g_array_index(user_props, GParameter, i).value); g_array_free(user_props, TRUE); if(user == NULL) return FALSE; } else { g_set_error( error, session_replay_error_quark, INF_ADOPTED_SESSION_REPLAY_ERROR_BAD_FORMAT, _("Unexpected node \"%s\" in requests section"), id ); return FALSE; } if(!inf_adopted_session_replay_advance_subtree_required(reader, error)) return FALSE; if(!inf_adopted_session_replay_skip_whitespace(reader, error)) return FALSE; return TRUE; } /** * inf_adopted_session_replay_play_to_end: * @replay: A #InfAdoptedSessionReplay. * @error: Location to store error information, if any. * * Plays all requests that are contained in the recording, so that the * replay's session has the same state as the recorded session when the * recording was stopped. * * Note that, depending on the size of the record, this function may take * some time to finish. * * If an error occurs during replay, then the function returns %FALSE and * @error is set. Otherwise it returns %TRUE. * * Returns: %TRUE on success, or %FALSE if an error occurs. */ gboolean inf_adopted_session_replay_play_to_end(InfAdoptedSessionReplay* replay, GError** error) { GError* local_error; gboolean result; g_return_val_if_fail(INF_ADOPTED_IS_SESSION_REPLAY(replay), FALSE); g_return_val_if_fail(error == NULL || *error == NULL, FALSE); local_error = NULL; do { result = inf_adopted_session_replay_play_next(replay, &local_error); } while(result); if(local_error != NULL) { g_propagate_error(error, local_error); return FALSE; } return TRUE; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/adopted/PaxHeaders.26529/inf-adopted-state-vector.c0000644000000000000000000000013213034342512024514 xustar0030 mtime=1483851082.025718404 30 atime=1483851082.025718404 30 ctime=1488261589.032138995 libinfinity-0.7.1/libinfinity/adopted/inf-adopted-state-vector.c0000644000175000017500000005653713034342512025266 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-adopted-state-vector * @title: InfAdoptedStateVector * @short_description: Represents a state in the interaction model * @see_also: #InfAdoptedAlgorithm * @include: libinfinity/adopted/inf-adopted-state-vector.h * @stability: Unstable * * The #InfAdoptedStateVector represents a state in the current state space. * It basically maps user IDs to operation counts and states how many * operations of the corresponding user have already been performed. **/ #include #include #include #include #include G_DEFINE_BOXED_TYPE(InfAdoptedStateVector, inf_adopted_state_vector, inf_adopted_state_vector_copy, inf_adopted_state_vector_free) /* NOTE: What the state vector actually counts is the amount of operations * performed by each user. This number is called a timestamp, although it has * nothing to do with actual time. */ typedef struct _InfAdoptedStateVectorComponent InfAdoptedStateVectorComponent; struct _InfAdoptedStateVectorComponent { guint id; guint n; /* timestamp */ }; typedef struct _InfAdoptedStateVectorForeachData InfAdoptedStateVectorForeachData; struct _InfAdoptedStateVectorForeachData { InfAdoptedStateVectorForeachFunc func; gpointer user_data; }; struct _InfAdoptedStateVector { gsize size; gsize max_size; InfAdoptedStateVectorComponent* data; }; static gsize inf_adopted_state_vector_find_insert_pos(const InfAdoptedStateVector* vec, guint id) { gsize begin; gsize end; gsize middle; InfAdoptedStateVectorComponent* comp; if(vec->size == 0) return 0; begin = 0; end = vec->size; /* The vector is sorted, so we perform a binary search */ while(begin != end) { middle = begin + (end - begin) / 2; comp = vec->data + middle; if (comp->id == id) { return middle; } if (comp->id < id) { begin = middle + 1; } else { end = middle; } } return begin; } static InfAdoptedStateVectorComponent* inf_adopted_state_vector_lookup(const InfAdoptedStateVector* vec, guint id) { gsize pos; pos = inf_adopted_state_vector_find_insert_pos(vec, id); if(pos < vec->size && vec->data[pos].id == id) return vec->data + pos; return NULL; } static InfAdoptedStateVectorComponent* inf_adopted_state_vector_insert(InfAdoptedStateVector* vec, guint id, guint value, gsize insert_pos) { InfAdoptedStateVectorComponent* comp; if(vec->max_size <= vec->size) { vec->max_size += 5; vec->data = g_realloc(vec->data, vec->max_size * sizeof(InfAdoptedStateVectorComponent)); } comp = vec->data + insert_pos; if(insert_pos < vec->size) { gsize move_count; g_assert(comp->id != id); move_count = (vec->size - insert_pos); g_memmove(comp + 1, comp, move_count * sizeof(InfAdoptedStateVectorComponent)); } ++vec->size; comp->id = id; comp->n = value; return comp; } /** * inf_adopted_state_vector_error_quark: * * The domain for #InfAdoptedStateVectorError errors. * * Returns: A #GQuark for that domain. **/ GQuark inf_adopted_state_vector_error_quark(void) { return g_quark_from_static_string("INF_ADOPTED_STATE_VECTOR_ERROR"); } /** * inf_adopted_state_vector_new: (constructor) * * Returns a new state vector with all components set to zero. * * Returns: (transfer full): A new #InfAdoptedStateVector. **/ InfAdoptedStateVector* inf_adopted_state_vector_new(void) { InfAdoptedStateVector* vec; vec = g_slice_new(InfAdoptedStateVector); vec->size = 0; vec->max_size = 0; vec->data = NULL; return vec; } /** * inf_adopted_state_vector_copy: * @vec: The #InfAdoptedStateVector to copy * * Returns a copy of @vec. * * Returns: (transfer full): A copy of @vec. **/ InfAdoptedStateVector* inf_adopted_state_vector_copy(InfAdoptedStateVector* vec) { InfAdoptedStateVector* new_vec; g_return_val_if_fail(vec != NULL, NULL); new_vec = g_slice_new(InfAdoptedStateVector); new_vec->size = vec->size; new_vec->max_size = vec->max_size; if(new_vec->max_size == 0) { new_vec->data = NULL; } else { new_vec->data = g_malloc(new_vec->max_size * sizeof(InfAdoptedStateVectorComponent)); memcpy(new_vec->data, vec->data, new_vec->size * sizeof(InfAdoptedStateVectorComponent)); } return new_vec; } /** * inf_adopted_state_vector_free: * @vec: A #InfAdoptedStateVector. * * Frees a state vector allocated by inf_adopted_state_vector_new() or * inf_adopted_state_vector_copy(). **/ void inf_adopted_state_vector_free(InfAdoptedStateVector* vec) { g_return_if_fail(vec != NULL); g_free(vec->data); g_slice_free(InfAdoptedStateVector, vec); } /** * inf_adopted_state_vector_get: * @vec: A #InfAdoptedStateVector. * @id: The component whose timestamp to look for. * * Returns the timestamp for the given component. Implicitely, all IDs * that the vector does not contain are assigned the timestamp 0. * * Returns: The @component'th entry in the vector. */ guint inf_adopted_state_vector_get(const InfAdoptedStateVector* vec, guint id) { InfAdoptedStateVectorComponent* comp; g_return_val_if_fail(vec != NULL, 0); comp = inf_adopted_state_vector_lookup(vec, id); if(comp == NULL) return 0; return comp->n; } /** * inf_adopted_state_vector_set: * @vec: A #InfAdoptedStateVector. * @id: The component to change. * @value: The value to set the component to. * * Sets the given component of @vec to @value. **/ void inf_adopted_state_vector_set(InfAdoptedStateVector* vec, guint id, guint value) { gsize pos; g_return_if_fail(vec != NULL); pos = inf_adopted_state_vector_find_insert_pos(vec, id); if(pos < vec->size && vec->data[pos].id == id) vec->data[pos].n = value; else inf_adopted_state_vector_insert(vec, id, value, pos); } /** * inf_adopted_state_vector_add: * @vec: A #InfAdoptedStateVector. * @id: The component to change. * @value: The value by which to change the component. * * Adds @value to the current value of @component. @value may be negative in * which case the current value is actually decreased. Make sure to not drop * below zero this way. **/ void inf_adopted_state_vector_add(InfAdoptedStateVector* vec, guint id, gint value) { InfAdoptedStateVectorComponent* comp; gsize pos; g_return_if_fail(vec != NULL); pos = inf_adopted_state_vector_find_insert_pos(vec, id); comp = vec->data + pos; if(pos == vec->size || comp->id != id) { g_assert(value > 0); comp = inf_adopted_state_vector_insert(vec, id, value, pos); } else { g_assert(value > 0 || comp->n >= (guint)-value); comp->n += value; } } /** * inf_adopted_state_vector_foreach: * @vec: A #InfAdoptedStateVector. * @func: (scope call): The function to call. * @user_data: Additional data to pass to @func. * * Calls @func for each component in @vec. Note that there may be users for * which @func will not be called if their timestamp is 0. **/ void inf_adopted_state_vector_foreach(const InfAdoptedStateVector* vec, InfAdoptedStateVectorForeachFunc func, gpointer user_data) { gsize pos; g_return_if_fail(vec != NULL); g_return_if_fail(func != NULL); for(pos = 0; pos < vec->size; ++pos) { func(vec->data[pos].id, vec->data[pos].n, user_data); } } /** * inf_adopted_state_vector_compare: * @first: A #InfAdoptedStateVector. * @second: Another #InfAdoptedStateVector. * * Performs a comparison suited for strict-weak ordering so that state vectors * can be sorted. This function returns -1 if @first compares before @second, * 0 if they compare equal and 1 if @first compares after @second. * * Returns: -1, 0 or 1. **/ int inf_adopted_state_vector_compare(const InfAdoptedStateVector* first, const InfAdoptedStateVector* second) { gsize first_pos; gsize second_pos; InfAdoptedStateVectorComponent* first_comp; InfAdoptedStateVectorComponent* second_comp; g_return_val_if_fail(first != NULL, 0); g_return_val_if_fail(second != NULL, 0); first_pos = 0; second_pos = 0; /* TODO: Some test that verifies that this function * provides strict weak ordering */ for(;;) { /* Jump over components whose value is 0. This is necessary because * components that are not in the sequence are treated like having the * value zero and should be compared equal. */ while(first_pos < first->size) { first_comp = first->data + first_pos; if(first_comp->n > 0) break; ++first_pos; } while(second_pos < second->size) { second_comp = second->data + second_pos; if(second_comp->n > 0) break; ++second_pos; } if(first_pos == first->size || second_pos == second->size) { break; } /* first_comp and second_comp are set here */ if(first_comp->id < second_comp->id) { return -1; } else if(first_comp->id > second_comp->id) { return 1; } else if(first_comp->n < second_comp->n) { return -1; } else if(first_comp->n > second_comp->n) { return 1; } /* Component matches, check next */ ++first_pos; ++second_pos; } if(first_pos == first->size && second_pos == second->size) { return 0; } else if(first_pos == first->size) { return -1; } else { return 1; } } /** * inf_adopted_state_vector_causally_before: * @first: A #InfAdoptedStateVector. * @second: Another #InfAdoptedStateVector. * * Checks whether an event that occured at time @second is causally * dependant on an event that occured at time @first, that is all * components of @first are less or equal to the corresponding component in * @second. * * Returns: Whether @second depends on @first. **/ gboolean inf_adopted_state_vector_causally_before(const InfAdoptedStateVector* first, const InfAdoptedStateVector* second) { gsize first_pos; gsize second_pos; InfAdoptedStateVectorComponent* first_comp; InfAdoptedStateVectorComponent* second_comp; g_return_val_if_fail(first != NULL, FALSE); g_return_val_if_fail(second != NULL, FALSE); first_pos = 0; second_pos = 0; while(first_pos < first->size) { first_comp = first->data + first_pos++; if(second_pos == second->size) { /* That component is not contained in second (thus 0) */ if(first_comp->n > 0) return FALSE; } else { second_comp = second->data + second_pos; while(second_comp != NULL && first_comp->id > second_comp->id) { ++second_pos; if(second_pos != second->size) second_comp = second->data + second_pos; else second_comp = NULL; } if(second_comp == NULL || first_comp->id < second_comp->id) { /* That component is not contained in second (thus 0) */ if(first_comp->n > 0) return FALSE; else /* 0 <= 0 */ continue; } g_assert(first_comp->id == second_comp->id); if(first_comp->n > second_comp->n) return FALSE; } } return TRUE; } /** * inf_adopted_state_vector_causally_before_inc: * @first: A #InfAdoptedStateVector. * @second: Another #InfAdoptedStateVector. * @inc_component: The component to increment before comparing. * * This function does the equivalent of * * |[ * inf_adopted_state_vector_add(first, inc_component, 1); * gboolean result = inf_adopted_state_vector_causally_before(first, second); * inf_adopted_state_vector_add(first, inc_component, -1); * return result; * ]| * * But it is more efficient. * * Returns: Whether @second depends on @first with the * @inc_componentth component increased by one. **/ gboolean inf_adopted_state_vector_causally_before_inc( const InfAdoptedStateVector* first, const InfAdoptedStateVector* second, guint inc_component) { gsize first_pos; gsize second_pos; gboolean inc_comp_seen; InfAdoptedStateVectorComponent* first_comp; InfAdoptedStateVectorComponent* second_comp; InfAdoptedStateVectorComponent inc_comp; g_return_val_if_fail(first != NULL, FALSE); g_return_val_if_fail(second != NULL, FALSE); first_pos = 0; second_pos = 0; inc_comp.id = inc_component; inc_comp_seen = FALSE; while(first_pos < first->size || !inc_comp_seen) { /* Set first_comp as if there was inc_component increased by one */ if(!inc_comp_seen) { if(first_pos < first->size) { first_comp = first->data + first_pos; if(first_comp->id < inc_component) { ++ first_pos; } else if(first_comp->id == inc_component) { inc_comp.n = first_comp->n + 1; first_comp = &inc_comp; inc_comp_seen = TRUE; ++ first_pos; } else { inc_comp.n = 1; first_comp = &inc_comp; inc_comp_seen = TRUE; } } else { /* inc_comp is the only component of first */ inc_comp.n = 1; first_comp = &inc_comp; inc_comp_seen = TRUE; } } else { /* inc_comp already handled, business as usual */ first_comp = first->data + first_pos; ++ first_pos; } if(second_pos == second->size) { /* That component is not contained in second (thus 0) */ if(first_comp->n > 0) return FALSE; } else { second_comp = second->data + second_pos; while(second_comp != NULL && first_comp->id > second_comp->id) { ++second_pos; if(second_pos != second->size) second_comp = second->data + second_pos; else second_comp = NULL; } if(second_comp == NULL || first_comp->id < second_comp->id) { /* That component is not contained in second (thus 0) */ if(first_comp->n > 0) return FALSE; else /* 0 <= 0 */ continue; } g_assert(first_comp->id == second_comp->id); if(first_comp->n > second_comp->n) return FALSE; } } return TRUE; } /** * inf_adopted_state_vector_vdiff: * @first: A #InfAdoptedStateVector. * @second: Another #InfAdoptedStateVector. * * This function returns the sum of the differences between each component * of @first and @second. This function can only be called if * inf_adopted_state_vector_causally_before() returns %TRUE. * * Returns: The sum of the differences between each component of @first and * @second. */ guint inf_adopted_state_vector_vdiff(const InfAdoptedStateVector* first, const InfAdoptedStateVector* second) { gsize n; guint first_sum; guint second_sum; g_return_val_if_fail( inf_adopted_state_vector_causally_before(first, second) == TRUE, 0 ); first_sum = 0; second_sum = 0; for(n = 0; n < first->size; ++ n) first_sum += first->data[n].n; for(n = 0; n < second->size; ++ n) second_sum += second->data[n].n; g_assert(second_sum >= first_sum); return second_sum - first_sum; } /** * inf_adopted_state_vector_to_string: * @vec: A #InfAdoptedStateVector. * * Returns a string representation of @vec. * * Returns: (transfer full): A newly-allocated string to be freed by the * caller. **/ gchar* inf_adopted_state_vector_to_string(const InfAdoptedStateVector* vec) { GString* str; gsize pos; InfAdoptedStateVectorComponent* component; g_return_val_if_fail(vec != NULL, NULL); str = g_string_sized_new(vec->size * 12); for(pos = 0; pos < vec->size; ++pos) { component = vec->data + pos; if(component->n > 0) { if(str->len > 0) g_string_append_c(str, ';'); g_string_append_printf(str, "%u:%u", component->id, component->n); } } return g_string_free(str, FALSE); } /** * inf_adopted_state_vector_from_string: * @str: A string representation of a #InfAdoptedStateVector. * @error: Location to place an error, if any. * * Recreates the #InfAdoptedStateVector from its string representation. If * an error occurs, the function returns %NULL and @error is set. * * Returns: (transfer full): A new #InfAdoptedStateVector, or %NULL. **/ InfAdoptedStateVector* inf_adopted_state_vector_from_string(const gchar* str, GError** error) { InfAdoptedStateVector* vec; const char* strpos; char* endpos; gsize pos; guint id; guint n; g_return_val_if_fail(str != NULL, NULL); vec = inf_adopted_state_vector_new(); strpos = str; while(*strpos) { id = strtoul(strpos, &endpos, 10); if(*endpos != ':') { g_set_error_literal( error, inf_adopted_state_vector_error_quark(), INF_ADOPTED_STATE_VECTOR_BAD_FORMAT, _("Expected \":\" after ID") ); inf_adopted_state_vector_free(vec); return NULL; } pos = inf_adopted_state_vector_find_insert_pos(vec, id); if(pos < vec->size && vec->data[pos].id == id) { g_set_error( error, inf_adopted_state_vector_error_quark(), INF_ADOPTED_STATE_VECTOR_BAD_FORMAT, _("ID '%u' already occured before"), id ); inf_adopted_state_vector_free(vec); return NULL; } strpos = endpos + 1; /* step over ':' */ n = strtoul(strpos, &endpos, 10); if(*endpos != ';' && *endpos != '\0') { g_set_error( error, inf_adopted_state_vector_error_quark(), INF_ADOPTED_STATE_VECTOR_BAD_FORMAT, _("Expected ';' or end of string after component of ID '%u'"), id ); inf_adopted_state_vector_free(vec); return NULL; } inf_adopted_state_vector_insert(vec, id, n, pos); strpos = endpos; if(*strpos != '\0') ++ strpos; /* step over ';' */ } return vec; } /** * inf_adopted_state_vector_to_string_diff: * @vec: A #InfAdoptedStateVector. * @orig: Another #InfAdoptedStateVector. * * Returns the string representation of a diff between @orig and @vec. This * is possibly smaller than the representation created by * inf_adopted_state_vector_to_string(), but the same @orig vector is needed * to recreate @vec from the string representation. Additionally, * inf_adopted_state_vector_causally_before(@orig, @vec) must hold. * * Returns: (transfer full): A newly allocated string to be freed by the * caller. **/ gchar* inf_adopted_state_vector_to_string_diff(const InfAdoptedStateVector* vec, const InfAdoptedStateVector* orig) { gsize vec_pos; gsize orig_pos; InfAdoptedStateVectorComponent* vec_comp; InfAdoptedStateVectorComponent* orig_comp; GString* str; g_return_val_if_fail(vec != NULL, NULL); g_return_val_if_fail(orig != NULL, NULL); g_return_val_if_fail( inf_adopted_state_vector_causally_before(orig, vec) == TRUE, NULL ); g_assert(vec->data != NULL || vec->size == 0); str = g_string_sized_new(vec->size * 12); vec_pos = 0; for(orig_pos = 0; orig_pos < orig->size; ++orig_pos) { orig_comp = orig->data + orig_pos; if(orig_comp->n == 0) continue; g_assert(vec_pos < vec->size); vec_comp = vec->data + vec_pos; while(vec_comp->id < orig_comp->id) { /* There does not seem to be a corresponding entry in orig_comp, so * it is implicitely zero. */ if(str->len > 0) g_string_append_c(str, ';'); g_string_append_printf(str, "%u:%u", vec_comp->id, vec_comp->n); ++vec_pos; g_assert(vec_pos < vec->size); vec_comp = vec->data + vec_pos; } /* Otherwise the inf_adopted_state_vector_causally_before test above * should not have passed since orig_comp->n is not 0. */ g_assert(vec_comp->id == orig_comp->id); g_assert(vec_comp->n >= orig_comp->n); if(vec_comp->n > orig_comp->n) { if(str->len > 0) g_string_append_c(str, ';'); g_string_append_printf( str, "%u:%u", vec_comp->id, vec_comp->n - orig_comp->n ); } ++vec_pos; } /* All remaining components in vec have no counterpart in orig, meaning * their values in orig are implicitely zero. */ while(vec_pos < vec->size) { vec_comp = vec->data + vec_pos; if (vec_comp->n > 0) { if(str->len > 0) g_string_append_c(str, ';'); g_string_append_printf(str, "%u:%u", vec_comp->id, vec_comp->n); } ++vec_pos; } return g_string_free(str, FALSE); } /** * inf_adopted_state_vector_from_string_diff: * @str: A string representation of a diff between state vectors. * @orig: The state vector used to create @str in * inf_adopted_state_vector_to_string_diff(). * @error: Location to place an error, if any. * * Recreates a vector from its string representation diff and the original * vector. If an error returns, the function returns %NULL and @error is set. * * Returns: (transfer full): The created state vector, or %NULL on error. * Free with inf_adopted_state_vector_free() when no longer needed. **/ InfAdoptedStateVector* inf_adopted_state_vector_from_string_diff(const gchar* str, const InfAdoptedStateVector* orig, GError** error) { InfAdoptedStateVector* vec; gsize vec_pos; gsize orig_pos; InfAdoptedStateVectorComponent* vec_comp; InfAdoptedStateVectorComponent* orig_comp; g_return_val_if_fail(str != NULL, NULL); g_return_val_if_fail(orig != NULL, NULL); vec = inf_adopted_state_vector_from_string(str, error); if(vec == NULL) return NULL; vec_pos = 0; for(orig_pos = 0; orig_pos < orig->size; ++orig_pos) { orig_comp = orig->data + orig_pos; if(orig_comp->n == 0) continue; if(vec_pos == vec->size) { inf_adopted_state_vector_insert( vec, orig_comp->id, orig_comp->n, vec_pos ); } else { vec_comp = vec->data + vec_pos; while(vec_comp->id < orig_comp->id) { ++vec_pos; if(vec_pos < vec->size) { vec_comp = vec->data + vec_pos; } else { break; } } if(vec_comp->id == orig_comp->id) { vec_comp->n += orig_comp->n; ++vec_pos; } else { inf_adopted_state_vector_insert( vec, orig_comp->id, orig_comp->n, vec_pos ); } } } return vec; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/adopted/PaxHeaders.26529/inf-adopted-request.h0000644000000000000000000000013213034342512023571 xustar0030 mtime=1483851082.025718404 30 atime=1483851082.025718404 30 ctime=1488261588.908139266 libinfinity-0.7.1/libinfinity/adopted/inf-adopted-request.h0000644000175000017500000001175113034342512024330 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_ADOPTED_REQUEST_H__ #define __INF_ADOPTED_REQUEST_H__ #include #include #include G_BEGIN_DECLS #define INF_ADOPTED_TYPE_REQUEST (inf_adopted_request_get_type()) #define INF_ADOPTED_REQUEST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_ADOPTED_TYPE_REQUEST, InfAdoptedRequest)) #define INF_ADOPTED_REQUEST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INF_ADOPTED_TYPE_REQUEST, InfAdoptedRequestClass)) #define INF_ADOPTED_IS_REQUEST(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_ADOPTED_TYPE_REQUEST)) #define INF_ADOPTED_IS_REQUEST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INF_ADOPTED_TYPE_REQUEST)) #define INF_ADOPTED_REQUEST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INF_ADOPTED_TYPE_REQUEST, InfAdoptedRequestClass)) #define INF_ADOPTED_TYPE_REQUEST_TYPE (inf_adopted_request_type_get_type()) typedef struct _InfAdoptedRequest InfAdoptedRequest; typedef struct _InfAdoptedRequestClass InfAdoptedRequestClass; /** * InfAdoptedRequestClass: * * This structure does not contain any public fields. */ struct _InfAdoptedRequestClass { /*< private >*/ GObjectClass parent_class; }; /** * InfAdoptedRequest: * * #InfAdoptedRequest is an opaque data type. You should only access it via * the public API functions. */ struct _InfAdoptedRequest { /*< private >*/ GObject parent; gpointer priv; }; /** * InfAdoptedRequestType: * @INF_ADOPTED_REQUEST_DO: A request that performs an operation. * @INF_ADOPTED_REQUEST_UNDO: A request that undoes a previously applied * request. * @INF_ADOPTED_REQUEST_REDO: A request that redoes a previously undone * request. * * Possible types for an #InfAdoptedRequest. */ typedef enum _InfAdoptedRequestType { INF_ADOPTED_REQUEST_DO, INF_ADOPTED_REQUEST_UNDO, INF_ADOPTED_REQUEST_REDO } InfAdoptedRequestType; GType inf_adopted_request_type_get_type(void) G_GNUC_CONST; GType inf_adopted_request_get_type(void) G_GNUC_CONST; InfAdoptedRequest* inf_adopted_request_new_do(InfAdoptedStateVector* vector, guint user_id, InfAdoptedOperation* operation, gint64 received); InfAdoptedRequest* inf_adopted_request_new_undo(InfAdoptedStateVector* vector, guint user_id, gint64 received); InfAdoptedRequest* inf_adopted_request_new_redo(InfAdoptedStateVector* vector, guint user_id, gint64 received); InfAdoptedRequest* inf_adopted_request_copy(InfAdoptedRequest* request); InfAdoptedRequestType inf_adopted_request_get_request_type(InfAdoptedRequest* request); InfAdoptedStateVector* inf_adopted_request_get_vector(InfAdoptedRequest* request); guint inf_adopted_request_get_user_id(InfAdoptedRequest* request); InfAdoptedOperation* inf_adopted_request_get_operation(InfAdoptedRequest* request); guint inf_adopted_request_get_index(InfAdoptedRequest* request); gint64 inf_adopted_request_get_receive_time(InfAdoptedRequest* request); gint64 inf_adopted_request_get_execute_time(InfAdoptedRequest* request); void inf_adopted_request_set_execute_time(InfAdoptedRequest* request, gint64 time); gboolean inf_adopted_request_need_concurrency_id(InfAdoptedRequest* request, InfAdoptedRequest* against); InfAdoptedRequest* inf_adopted_request_transform(InfAdoptedRequest* request, InfAdoptedRequest* against, InfAdoptedRequest* request_lcs, InfAdoptedRequest* against_lcs); InfAdoptedRequest* inf_adopted_request_mirror(InfAdoptedRequest* request, guint by); InfAdoptedRequest* inf_adopted_request_fold(InfAdoptedRequest* request, guint into, guint by); gboolean inf_adopted_request_affects_buffer(InfAdoptedRequest* request); G_END_DECLS #endif /* __INF_ADOPTED_REQUEST_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/adopted/PaxHeaders.26529/inf-adopted-operation.c0000644000000000000000000000013213034342512024074 xustar0030 mtime=1483851082.025718404 30 atime=1483851082.025718404 30 ctime=1488261589.020139022 libinfinity-0.7.1/libinfinity/adopted/inf-adopted-operation.c0000644000175000017500000003270413034342512024634 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-adopted-operation * @title: InfAdoptedOperation * @short_description: Operation that can be processed by * #InfAdoptedAlgorithm. * @include: libinfinity/adopted/inf-adopted-operation.h * @see_also: #InfAdoptedRequest, #InfAdoptedAlgorithm * @stability: Unstable * * The #InfAdoptedOperation interface must be implemented by operations that * are supposed to be used by #InfAdoptedAlgorithm. They basically need to * define transformation rules for transformation against other operations. **/ #include #include #include #include static const GEnumValue inf_adopted_concurrency_id_values[] = { { INF_ADOPTED_CONCURRENCY_SELF, "INF_ADOPTED_CONCURRENCY_SELF", "self" }, { INF_ADOPTED_CONCURRENCY_NONE, "INF_ADOPTED_CONCURRENCY_NONE", "none" }, { INF_ADOPTED_CONCURRENCY_OTHER, "INF_ADOPTED_CONCURRENCY_OTHER", "other" }, { 0, NULL, NULL } }; static const GFlagsValue inf_adopted_operation_flags_values[] = { { INF_ADOPTED_OPERATION_AFFECTS_BUFFER, "INF_ADOPTED_OPERATION_AFFECTS_BUFFER", "affects_buffer", }, { INF_ADOPTED_OPERATION_REVERSIBLE, "INF_ADOPTED_OPERATION_REVERSIBLE", "reversible", }, { 0, NULL, NULL } }; INF_DEFINE_ENUM_TYPE(InfAdoptedConcurrencyId, inf_adopted_concurrency_id, inf_adopted_concurrency_id_values) INF_DEFINE_FLAGS_TYPE(InfAdoptedOperationFlags, inf_adopted_operation_flags, inf_adopted_operation_flags_values) G_DEFINE_INTERFACE(InfAdoptedOperation, inf_adopted_operation, G_TYPE_OBJECT) static void inf_adopted_operation_default_init(InfAdoptedOperationInterface* iface) { } /** * inf_adopted_operation_need_concurrency_id: * @operation: The #InfAdoptedOperation to transform. * @against: The operation to transform against. * * This function returns whether transforming @operation against @against * is not defined unambiguously. In that case, transformation requires a * so-called concurrency ID which determines which of the two operations * is transformed. * * Returns: Whether transformation of @operation against @against requires a * concurrency ID to be defined. */ gboolean inf_adopted_operation_need_concurrency_id(InfAdoptedOperation* operation, InfAdoptedOperation* against) { InfAdoptedOperationInterface* iface; g_return_val_if_fail(INF_ADOPTED_IS_OPERATION(operation), FALSE); g_return_val_if_fail(INF_ADOPTED_IS_OPERATION(against), FALSE); if(INF_ADOPTED_IS_SPLIT_OPERATION(against)) { iface = INF_ADOPTED_OPERATION_GET_IFACE(against); g_assert(iface->need_concurrency_id != NULL); return iface->need_concurrency_id(against, operation); } else { iface = INF_ADOPTED_OPERATION_GET_IFACE(operation); g_assert(iface->need_concurrency_id != NULL); return iface->need_concurrency_id(operation, against); } } /** * inf_adopted_operation_transform: * @operation: The #InfAdoptedOperation to transform. * @against: The operation to transform against. * @operation_lcs: The operation at a previous state, or %NULL. * @against_lcs: The @against operation at a previous state, or %NULL. * @concurrency_id: The concurrency ID for the transformation. * * Performs an inclusion transformation of @operation against @against, * meaning that the effect of @against is included in @operation. * * If inf_adopted_operation_need_concurrency_id() returns %TRUE for @operation * and @against, then @operation_lcs and @against_lcs must not be %NULL. In * this case they must be the same operations as @operation and @against at * the earlierst state to which both of them can be transformed. This * information can then be used to resolve any conflicts in the transformation * of @operation against @against. * * The @concurrency_id parameter is used if * inf_adopted_operation_need_concurrency_id() returns %TRUE and no conflict * resolution can be deduced from @operation_lcs and @against_lcs. In this * case @concurrency_id defines a unique way to transform the two operations. * Usually, this is derived from the user IDs of the users who issued the two * conflicting operations. * * Returns: (transfer full) (allow-none): The transformed * #InfAdoptedOperation, or %NULL if the transformation failed. **/ InfAdoptedOperation* inf_adopted_operation_transform(InfAdoptedOperation* operation, InfAdoptedOperation* against, InfAdoptedOperation* operation_lcs, InfAdoptedOperation* against_lcs, InfAdoptedConcurrencyId concurrency_id) { InfAdoptedOperationInterface* iface; g_return_val_if_fail(INF_ADOPTED_IS_OPERATION(operation), NULL); g_return_val_if_fail(INF_ADOPTED_IS_OPERATION(against), NULL); /* Transform against both parts of split operation if we are transforming * against split operation. */ if(INF_ADOPTED_IS_SPLIT_OPERATION(against)) { return inf_adopted_split_operation_transform_other( INF_ADOPTED_SPLIT_OPERATION(against), operation, against_lcs, operation_lcs, concurrency_id ); } else { iface = INF_ADOPTED_OPERATION_GET_IFACE(operation); g_assert(iface->transform != NULL); return (*iface->transform)( operation, against, operation_lcs, against_lcs, concurrency_id ); } } /** * inf_adopted_operation_copy: * @operation: The #InfAdoptedOperation to copy. * * Returns a copy of @operation. * * Returns: (transfer full): A copy of @operation. **/ InfAdoptedOperation* inf_adopted_operation_copy(InfAdoptedOperation* operation) { InfAdoptedOperationInterface* iface; g_return_val_if_fail(INF_ADOPTED_IS_OPERATION(operation), NULL); iface = INF_ADOPTED_OPERATION_GET_IFACE(operation); g_assert(iface->copy != NULL); return (*iface->copy)(operation); } /** * inf_adopted_operation_get_flags: * @operation: A #InfAdoptedOperation. * * Returns the flags for @operation. * * Returns: #InfAdoptedOperationFlags for @operation. **/ InfAdoptedOperationFlags inf_adopted_operation_get_flags(InfAdoptedOperation* operation) { InfAdoptedOperationInterface* iface; g_return_val_if_fail(INF_ADOPTED_IS_OPERATION(operation), 0); iface = INF_ADOPTED_OPERATION_GET_IFACE(operation); if(iface->get_flags != NULL) return (*iface->get_flags)(operation); else return 0; } /** * inf_adopted_operation_apply: * @operation: A #InfAdoptedOperation. * @by: A #InfAdoptedUser. * @buffer: The #InfBuffer to apply the operation to. * @error: Location to store error information, if any, or %NULL. * * Applies @operation to @buffer. The operation is considered to be applied by * user @by. If the operation cannot be applied then @error is set and the * function returns %FALSE. * * Returns: %TRUE on success or %FALSE on error. **/ gboolean inf_adopted_operation_apply(InfAdoptedOperation* operation, InfAdoptedUser* by, InfBuffer* buffer, GError** error) { InfAdoptedOperationInterface* iface; g_return_val_if_fail(INF_ADOPTED_IS_OPERATION(operation), FALSE); g_return_val_if_fail(INF_ADOPTED_IS_USER(by), FALSE); g_return_val_if_fail(INF_IS_BUFFER(buffer), FALSE); g_return_val_if_fail(error == NULL || *error == NULL, FALSE); iface = INF_ADOPTED_OPERATION_GET_IFACE(operation); /* apply must be implemented */ g_assert(iface->apply != NULL); return (*iface->apply)(operation, by, buffer, error); } /** * inf_adopted_operation_apply_transformed: * @operation: A #InfAdoptedOperation. * @transformed: A transformed version of @operation. * @by: The #InfAdoptedUser applying the operation. * @buffer: The #InfBuffer to apply the operation to. * @error: Location to store error information, if any, or %NULL. * * Applies @transformed to @buffer. The operation is considered to be applied * by user @by. The operation @transformed must have originated from * @operation by transformation with inf_adopted_operation_transform(). * * If @operation is reversible or does not affect the buffer (see * #InfAdoptedOperationFlags), this function is equivalent to * inf_adopted_operation_apply(transformed, by, buffer), with * the exception of the return value. In that case the return value will be * @operation itself, with a reference added. * * However, if @operation is not reversible and affects the buffer, the * function attempts to construct an operation which is identical to * @operation, but reversible, and returns it. The function can use * information from the transformed operation and the buffer to construct * the reversible operation. If a reversible operation cannot be constructed, * the function returns an additional reference on @operation, and still * applies the transformed operation * to the buffer. * * For example, an operation that deletes text in a text editor would be * transmitting only the position and the length of the text to delete over * the network. From that information alone, the operation cannot be made * reversible. However, when the operation is applied to the buffer, the * actual text that is being removed can be restored by looking it up in * the buffer, making the operation reversible. * * Returns: (transfer full): A #InfAdoptedOperation, or %NULL on error. * Free with g_object_unref() when no longer needed. */ InfAdoptedOperation* inf_adopted_operation_apply_transformed(InfAdoptedOperation* operation, InfAdoptedOperation* transformed, InfAdoptedUser* by, InfBuffer* buffer, GError** error) { InfAdoptedOperationInterface* iface; InfAdoptedOperationFlags flags; InfAdoptedOperationFlags check_flags; g_return_val_if_fail(INF_ADOPTED_IS_OPERATION(operation), NULL); g_return_val_if_fail(INF_ADOPTED_IS_OPERATION(transformed), NULL); g_return_val_if_fail(INF_ADOPTED_IS_USER(by), NULL); g_return_val_if_fail(INF_IS_BUFFER(buffer), NULL); g_return_val_if_fail(error == NULL || *error == NULL, NULL); iface = INF_ADOPTED_OPERATION_GET_IFACE(operation); flags = inf_adopted_operation_get_flags(operation); check_flags = INF_ADOPTED_OPERATION_REVERSIBLE | INF_ADOPTED_OPERATION_AFFECTS_BUFFER; if( (flags & check_flags) == INF_ADOPTED_OPERATION_AFFECTS_BUFFER) { if(iface->apply_transformed != NULL) { return (*iface->apply_transformed)( operation, transformed, by, buffer, error ); } else { /* apply must be implemented */ g_assert(iface->apply != NULL); if(!(*iface->apply)(transformed, by, buffer, error)) return NULL; g_object_ref(operation); return operation; } } else { /* apply must be implemented */ g_assert(iface->apply != NULL); if(!(*iface->apply)(transformed, by, buffer, error)) return NULL; g_object_ref(operation); return operation; } } /** * inf_adopted_operation_is_reversible: * @operation: A #InfAdoptedOperation. * * Returns whether @operation is reversible. * * Returns: Whether @operation is reversible. **/ gboolean inf_adopted_operation_is_reversible(InfAdoptedOperation* operation) { InfAdoptedOperationFlags flags; g_return_val_if_fail(INF_ADOPTED_IS_OPERATION(operation), FALSE); flags = inf_adopted_operation_get_flags(operation); if( (flags & INF_ADOPTED_OPERATION_REVERSIBLE) != 0) return TRUE; else return FALSE; } /** * inf_adopted_operation_revert: * @operation: A #InfAdoptedOperation. * * Returns a new #InfAdoptedOperation that undoes the effect of @operation. If * @operation and then its reverse operation are applied to a buffer (in that * order), the buffer remains unchanged. * * @operation must be reversible for this function to be called (i.e. * inf_adopted_operation_is_reversible() must return TRUE). * * Returns: (transfer full): The reverse operation of @operation. **/ InfAdoptedOperation* inf_adopted_operation_revert(InfAdoptedOperation* operation) { InfAdoptedOperationInterface* iface; g_return_val_if_fail(INF_ADOPTED_IS_OPERATION(operation), NULL); g_assert(inf_adopted_operation_is_reversible(operation) == TRUE); iface = INF_ADOPTED_OPERATION_GET_IFACE(operation); /* When inf_adopted_operation_is_reversible() returns TRUE for an operation * it must implement revert. */ g_assert(iface->revert != NULL); return (*iface->revert)(operation); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/adopted/PaxHeaders.26529/inf-adopted-request-log.h0000644000000000000000000000013213034342512024350 xustar0030 mtime=1483851082.025718404 30 atime=1483851082.025718404 30 ctime=1488261588.912139258 libinfinity-0.7.1/libinfinity/adopted/inf-adopted-request-log.h0000644000175000017500000001126213034342512025104 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_ADOPTED_REQUEST_LOG_H__ #define __INF_ADOPTED_REQUEST_LOG_H__ #include #include G_BEGIN_DECLS #define INF_ADOPTED_TYPE_REQUEST_LOG (inf_adopted_request_log_get_type()) #define INF_ADOPTED_REQUEST_LOG(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_ADOPTED_TYPE_REQUEST_LOG, InfAdoptedRequestLog)) #define INF_ADOPTED_REQUEST_LOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INF_ADOPTED_TYPE_REQUEST_LOG, InfAdoptedRequestLogClass)) #define INF_ADOPTED_IS_REQUEST_LOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_ADOPTED_TYPE_REQUEST_LOG)) #define INF_ADOPTED_IS_REQUEST_LOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INF_ADOPTED_TYPE_REQUEST_LOG)) #define INF_ADOPTED_REQUEST_LOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INF_ADOPTED_TYPE_REQUEST_LOG, InfAdoptedRequestLogClass)) typedef struct _InfAdoptedRequestLog InfAdoptedRequestLog; typedef struct _InfAdoptedRequestLogClass InfAdoptedRequestLogClass; /** * InfAdoptedRequestLogClass: * @add_request: Default signal handler for the * #InfAdoptedRequestLog::add-request signal. * * This structure contains the default signal handlers for * #InfAdoptedRequestLog. */ struct _InfAdoptedRequestLogClass { /*< private >*/ GObjectClass parent_class; /*< public >*/ void(*add_request)(InfAdoptedRequestLog* log, InfAdoptedRequest* request); }; /** * InfAdoptedRequestLog: * * #InfAdoptedRequestLog is an opaque data type. You should only access it via * the public API functions. */ struct _InfAdoptedRequestLog { /*< private >*/ GObject parent; gpointer priv; }; GType inf_adopted_request_log_get_type(void) G_GNUC_CONST; InfAdoptedRequestLog* inf_adopted_request_log_new(guint user_id); guint inf_adopted_request_log_get_user_id(InfAdoptedRequestLog* log); guint inf_adopted_request_log_get_begin(InfAdoptedRequestLog* log); guint inf_adopted_request_log_get_end(InfAdoptedRequestLog* log); gboolean inf_adopted_request_log_is_empty(InfAdoptedRequestLog* log); void inf_adopted_request_log_set_begin(InfAdoptedRequestLog* log, guint n); InfAdoptedRequest* inf_adopted_request_log_get_request(InfAdoptedRequestLog* log, guint n); void inf_adopted_request_log_add_request(InfAdoptedRequestLog* log, InfAdoptedRequest* request); void inf_adopted_request_log_remove_requests(InfAdoptedRequestLog* log, guint up_to); InfAdoptedRequest* inf_adopted_request_log_next_associated(InfAdoptedRequestLog* log, InfAdoptedRequest* request); InfAdoptedRequest* inf_adopted_request_log_prev_associated(InfAdoptedRequestLog* log, InfAdoptedRequest* request); InfAdoptedRequest* inf_adopted_request_log_original_request(InfAdoptedRequestLog* log, InfAdoptedRequest* request); InfAdoptedRequest* inf_adopted_request_log_next_undo(InfAdoptedRequestLog* log); InfAdoptedRequest* inf_adopted_request_log_next_redo(InfAdoptedRequestLog* log); InfAdoptedRequest* inf_adopted_request_log_upper_related(InfAdoptedRequestLog* log, guint n); InfAdoptedRequest* inf_adopted_request_log_lower_related(InfAdoptedRequestLog* log, guint n); void inf_adopted_request_log_add_cached_request(InfAdoptedRequestLog* log, InfAdoptedRequest* request); InfAdoptedRequest* inf_adopted_request_log_lookup_cached_request(InfAdoptedRequestLog* log, InfAdoptedStateVector* vec); G_END_DECLS #endif /* __INF_ADOPTED_REQUEST_LOG_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/adopted/PaxHeaders.26529/inf-adopted-user.c0000644000000000000000000000013213034342512023052 xustar0030 mtime=1483851082.025718404 30 atime=1483851082.025718404 30 ctime=1488261589.036138987 libinfinity-0.7.1/libinfinity/adopted/inf-adopted-user.c0000644000175000017500000001752213034342512023613 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-adopted-user * @title: InfAdoptedUser * @short_description: User in a #InfAdoptedUser. * @include: libinfinity/adopted/inf-adopted-user.h * @see_also: #InfAdoptedSession, #InfAdoptedAlgorithm * @stability: Unstable * * #InfAdoptedUser is a #InfUser-derived class that is used in * #InfAdoptedSession. It holds all user-specific information that is needed * by #InfAdoptedAlgorithm to handle the concurrency control. This includes * the user's request log which stores all the requests made by the user and * a state vector which specifies the document state that the user has, as * known to the local host. This information is extracted from the most recent * request received from the user. */ #include #include typedef struct _InfAdoptedUserPrivate InfAdoptedUserPrivate; struct _InfAdoptedUserPrivate { InfAdoptedStateVector* vector; InfAdoptedRequestLog* log; }; enum { PROP_0, PROP_VECTOR, PROP_REQUEST_LOG }; #define INF_ADOPTED_USER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INF_ADOPTED_TYPE_USER, InfAdoptedUserPrivate)) #define INF_ADOPTED_USER_PRIVATE(obj) ((InfAdoptedUserPrivate*)(obj)->priv) G_DEFINE_TYPE_WITH_CODE(InfAdoptedUser, inf_adopted_user, INF_TYPE_USER, G_ADD_PRIVATE(InfAdoptedUser)) static void inf_adopted_user_init(InfAdoptedUser* user) { InfAdoptedUserPrivate* priv; user->priv = INF_ADOPTED_USER_GET_PRIVATE(user); priv = INF_ADOPTED_USER_PRIVATE(user); priv->vector = inf_adopted_state_vector_new(); priv->log = NULL; } static void inf_adopted_user_constructed(GObject* object) { InfAdoptedUser* user; InfAdoptedUserPrivate* priv; G_OBJECT_CLASS(inf_adopted_user_parent_class)->constructed(object); user = INF_ADOPTED_USER(object); priv = INF_ADOPTED_USER_PRIVATE(user); /* Create empty request log if none was set during construction */ priv->log = inf_adopted_request_log_new(inf_user_get_id(INF_USER(user))); } static void inf_adopted_user_dispose(GObject* object) { InfAdoptedUser* user; InfAdoptedUserPrivate* priv; user = INF_ADOPTED_USER(object); priv = INF_ADOPTED_USER_PRIVATE(user); if(priv->log != NULL) { g_object_unref(priv->log); priv->log = NULL; } G_OBJECT_CLASS(inf_adopted_user_parent_class)->dispose(object); } static void inf_adopted_user_finalize(GObject* object) { InfAdoptedUser* user; InfAdoptedUserPrivate* priv; user = INF_ADOPTED_USER(object); priv = INF_ADOPTED_USER_PRIVATE(user); inf_adopted_state_vector_free(priv->vector); G_OBJECT_CLASS(inf_adopted_user_parent_class)->finalize(object); } static void inf_adopted_user_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfAdoptedUser* user; InfAdoptedUserPrivate* priv; InfAdoptedRequestLog* log; user = INF_ADOPTED_USER(object); priv = INF_ADOPTED_USER_PRIVATE(user); switch(prop_id) { case PROP_VECTOR: inf_adopted_state_vector_free(priv->vector); priv->vector = g_value_dup_boxed(value); break; case PROP_REQUEST_LOG: g_assert(priv->log == NULL); /* construct only */ if(g_value_get_object(value) != NULL) { log = INF_ADOPTED_REQUEST_LOG(g_value_get_object(value)); g_assert( inf_adopted_request_log_get_user_id(log) == inf_user_get_id(INF_USER(user)) ); priv->log = log; g_object_ref(log); } break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void inf_adopted_user_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfAdoptedUser* user; InfAdoptedUserPrivate* priv; user = INF_ADOPTED_USER(object); priv = INF_ADOPTED_USER_PRIVATE(user); switch(prop_id) { case PROP_VECTOR: g_value_set_boxed(value, priv->vector); break; case PROP_REQUEST_LOG: g_value_set_object(value, G_OBJECT(priv->log)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void inf_adopted_user_class_init(InfAdoptedUserClass* user_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(user_class); object_class->constructed = inf_adopted_user_constructed; object_class->dispose = inf_adopted_user_dispose; object_class->finalize = inf_adopted_user_finalize; object_class->set_property = inf_adopted_user_set_property; object_class->get_property = inf_adopted_user_get_property; g_object_class_install_property( object_class, PROP_VECTOR, g_param_spec_boxed( "vector", "State vector", "The state this user is currently at", INF_ADOPTED_TYPE_STATE_VECTOR, G_PARAM_READWRITE ) ); g_object_class_install_property( object_class, PROP_REQUEST_LOG, g_param_spec_object( "request-log", "Request log", "Request log of this user", INF_ADOPTED_TYPE_REQUEST_LOG, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); } /** * inf_adopted_user_get_component: * @user: A #InfAdoptedUser. * @id: The component to retrieve. * * Returns the amount of requests @user is guaranteed to have processed from * the user with ID @id. * * Returns: The number of requests @user has processed from @id. **/ guint inf_adopted_user_get_component(InfAdoptedUser* user, guint id) { g_return_val_if_fail(INF_ADOPTED_IS_USER(user), 0); g_return_val_if_fail(id != 0, 0); return inf_adopted_state_vector_get( INF_ADOPTED_USER_PRIVATE(user)->vector, id ); } /** * inf_adopted_user_get_vector: * @user: A #InfAdoptedUser. * * Returns the current vector time of @user. * * Returns: (transfer none): The current vector time of @user. **/ InfAdoptedStateVector* inf_adopted_user_get_vector(InfAdoptedUser* user) { g_return_val_if_fail(INF_ADOPTED_IS_USER(user), NULL); return INF_ADOPTED_USER_PRIVATE(user)->vector; } /** * inf_adopted_user_set_vector: * @user: A #InfAdoptedUser. * @vec: A #InfAdoptedStateVector. * * Updates the state vector of @user. This function takes ownership of @vec. **/ void inf_adopted_user_set_vector(InfAdoptedUser* user, InfAdoptedStateVector* vec) { InfAdoptedUserPrivate* priv; g_return_if_fail(INF_ADOPTED_IS_USER(user)); g_return_if_fail(vec != NULL); priv = INF_ADOPTED_USER_PRIVATE(user); inf_adopted_state_vector_free(priv->vector); priv->vector = vec; g_object_notify(G_OBJECT(user), "vector"); } /** * inf_adopted_user_get_request_log: * @user: A #InfAdoptedUser. * * Returns the request log of @user. * * Returns: (transfer none): User's #InfAdoptedRequestLog. **/ InfAdoptedRequestLog* inf_adopted_user_get_request_log(InfAdoptedUser* user) { g_return_val_if_fail(INF_ADOPTED_IS_USER(user), NULL); return INF_ADOPTED_USER_PRIVATE(user)->log; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/adopted/PaxHeaders.26529/inf-adopted-request.c0000644000000000000000000000013213034342512023564 xustar0030 mtime=1483851082.025718404 30 atime=1483851082.025718404 30 ctime=1488261589.024139013 libinfinity-0.7.1/libinfinity/adopted/inf-adopted-request.c0000644000175000017500000006643013034342512024327 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-adopted-request * @title: InfAdoptedRequest * @short_description: Request processed by #InfAdoptedAlgorithm. * @include: libinfinity/adopted/inf-adopted-request.h * @see_also: #InfAdoptedAlgorithm * @stability: Unstable * * An #InfAdoptedRequest is basically an #InfAdoptedOperation with some * metadata used by #InfAdoptedAlgorithm to determine which operations to * transform against each other. If the type of the request is * %INF_ADOPTED_REQUEST_DO, then it contains the operation to perform, * otherwise it does not because the request does not know the operation, it * is computed by #InfAdoptedAlgorithm when required. A #InfAdoptedRequest * also contains the state in which the operation can be applied to the * buffer and the user ID of the #InfAdoptedUser having generated the request. */ #include #include static const GEnumValue inf_adopted_request_type_values[] = { { INF_ADOPTED_REQUEST_DO, "INF_ADOPTED_REQUEST_DO", "do", }, { INF_ADOPTED_REQUEST_UNDO, "INF_ADOPTED_REQUEST_UNDO", "undo", }, { INF_ADOPTED_REQUEST_REDO, "INF_ADOPTED_REQUEST_REDO", "redo" }, { 0, NULL, NULL } }; typedef struct _InfAdoptedRequestPrivate InfAdoptedRequestPrivate; struct _InfAdoptedRequestPrivate { InfAdoptedRequestType type; InfAdoptedStateVector* vector; guint user_id; InfAdoptedOperation* operation; gint64 received; gint64 executed; }; enum { PROP_0, /* construct only */ PROP_TYPE, PROP_VECTOR, PROP_USER_ID, PROP_OPERATION, PROP_RECEIVED, /* read/write */ PROP_EXECUTED }; #define INF_ADOPTED_REQUEST_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INF_ADOPTED_TYPE_REQUEST, InfAdoptedRequestPrivate)) #define INF_ADOPTED_REQUEST_PRIVATE(obj) ((InfAdoptedRequestPrivate*)(obj)->priv) INF_DEFINE_ENUM_TYPE(InfAdoptedRequestType, inf_adopted_request_type, inf_adopted_request_type_values) G_DEFINE_TYPE_WITH_CODE(InfAdoptedRequest, inf_adopted_request, G_TYPE_OBJECT, G_ADD_PRIVATE(InfAdoptedRequest)) static void inf_adopted_request_init(InfAdoptedRequest* request) { InfAdoptedRequestPrivate* priv; request->priv = INF_ADOPTED_REQUEST_GET_PRIVATE(request); priv = INF_ADOPTED_REQUEST_PRIVATE(request); priv->type = INF_ADOPTED_REQUEST_DO; priv->vector = NULL; priv->user_id = 0; priv->operation = NULL; priv->received = 0; priv->executed = 0; } static void inf_adopted_request_dispose(GObject* object) { InfAdoptedRequest* request; InfAdoptedRequestPrivate* priv; request = INF_ADOPTED_REQUEST(object); priv = INF_ADOPTED_REQUEST_PRIVATE(request); if(priv->operation != NULL) { g_object_unref(G_OBJECT(priv->operation)); priv->operation = NULL; } G_OBJECT_CLASS(inf_adopted_request_parent_class)->dispose(object); } static void inf_adopted_request_finalize(GObject* object) { InfAdoptedRequest* request; InfAdoptedRequestPrivate* priv; request = INF_ADOPTED_REQUEST(object); priv = INF_ADOPTED_REQUEST_PRIVATE(request); if(priv->vector != NULL) inf_adopted_state_vector_free(priv->vector); G_OBJECT_CLASS(inf_adopted_request_parent_class)->finalize(object); } static void inf_adopted_request_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfAdoptedRequest* request; InfAdoptedRequestPrivate* priv; request = INF_ADOPTED_REQUEST(object); priv = INF_ADOPTED_REQUEST_PRIVATE(request); switch(prop_id) { case PROP_TYPE: priv->type = g_value_get_enum(value); break; case PROP_VECTOR: g_assert(priv->vector == NULL); /* construct only */ priv->vector = g_value_dup_boxed(value); break; case PROP_USER_ID: g_assert(priv->user_id == 0); /* construct only */ g_assert(g_value_get_uint(value) != 0); /* 0 is invalid ID */ priv->user_id = g_value_get_uint(value); break; case PROP_OPERATION: g_assert(priv->operation == NULL); /* construct only */ priv->operation = INF_ADOPTED_OPERATION(g_value_dup_object(value)); break; case PROP_RECEIVED: g_assert(priv->received == 0); /* construct only */ priv->received = g_value_get_int64(value); break; case PROP_EXECUTED: priv->executed = g_value_get_int64(value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void inf_adopted_request_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfAdoptedRequest* request; InfAdoptedRequestPrivate* priv; request = INF_ADOPTED_REQUEST(object); priv = INF_ADOPTED_REQUEST_PRIVATE(request); switch(prop_id) { case PROP_TYPE: g_value_set_enum(value, priv->type); break; case PROP_VECTOR: g_value_set_boxed(value, priv->vector); break; case PROP_USER_ID: g_value_set_uint(value, priv->user_id); break; case PROP_OPERATION: g_value_set_object(value, G_OBJECT(priv->operation)); break; case PROP_RECEIVED: g_value_set_int64(value, priv->received); break; case PROP_EXECUTED: g_value_set_int64(value, priv->executed); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void inf_adopted_request_class_init(InfAdoptedRequestClass* request_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(request_class); object_class->dispose = inf_adopted_request_dispose; object_class->finalize = inf_adopted_request_finalize; object_class->set_property = inf_adopted_request_set_property; object_class->get_property = inf_adopted_request_get_property; g_object_class_install_property( object_class, PROP_TYPE, g_param_spec_enum( "type", "Type", "The type of the operation", INF_ADOPTED_TYPE_REQUEST_TYPE, INF_ADOPTED_REQUEST_DO, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_VECTOR, g_param_spec_boxed( "vector", "Vector", "The vector time at which the request was made", INF_ADOPTED_TYPE_STATE_VECTOR, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_USER_ID, g_param_spec_uint( "user-id", "User ID", "The ID of the user that made the request", 0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_OPERATION, g_param_spec_object( "operation", "Operation", "The operation of the request", INF_ADOPTED_TYPE_OPERATION, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_RECEIVED, g_param_spec_int64( "received", "Received", "Time the request was received, in microseconds", G_MININT64, G_MAXINT64, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_EXECUTED, g_param_spec_int64( "executed", "Executed", "Time the request was executed, in microseconds", G_MININT64, G_MAXINT64, 0, G_PARAM_READWRITE ) ); } /** * inf_adopted_request_new_do: (constructor) * @vector: The vector time at which the request was made. * @user_id: The ID of the user that made the request. * @operation: The operation the user performed. * @received: Time the request was received, in microseconds since the epoch. * * Creates a new #InfAdoptedRequest with type %INF_ADOPTED_REQUEST_DO. * * Returns: (transfer full): A new DO request. **/ InfAdoptedRequest* inf_adopted_request_new_do(InfAdoptedStateVector* vector, guint user_id, InfAdoptedOperation* operation, gint64 received) { GObject* object; g_return_val_if_fail(vector != NULL, NULL); g_return_val_if_fail(user_id != 0, NULL); g_return_val_if_fail(INF_ADOPTED_IS_OPERATION(operation), NULL); object = g_object_new( INF_ADOPTED_TYPE_REQUEST, "type", INF_ADOPTED_REQUEST_DO, "vector", vector, "user-id", user_id, "operation", operation, "received", received, NULL ); return INF_ADOPTED_REQUEST(object); } /** * inf_adopted_request_new_undo: (constructor) * @vector: The vector time at which the request was made. * @user_id: The ID of the user that made the request. * @received: Time the request was received, in microseconds since the epoch. * * Creates a new #InfAdoptedRequest with type %INF_ADOPTED_REQUEST_UNDO. * The operation performed is implicitely defined by reverting the operation * of the associated DO or REDO request, but must still be computed by * #InfAdoptedAlgorithm. * * Returns: (transfer full): A new UNDO request. **/ InfAdoptedRequest* inf_adopted_request_new_undo(InfAdoptedStateVector* vector, guint user_id, gint64 received) { GObject* object; g_return_val_if_fail(vector != NULL, NULL); g_return_val_if_fail(user_id != 0, NULL); object = g_object_new( INF_ADOPTED_TYPE_REQUEST, "type", INF_ADOPTED_REQUEST_UNDO, "vector", vector, "user-id", user_id, "received", received, NULL ); return INF_ADOPTED_REQUEST(object); } /** * inf_adopted_request_new_redo: (constructor) * @vector: The vector time at which the request was made. * @user_id: The ID of the user that made the request. * @received: Time the request was received, in microseconds since the epoch. * * Creates a new #InfAdoptedRequest with type %INF_ADOPTED_REQUEST_REDO. The * operation performed is implicitely defined by reverting the operation of * the associated UNDO request, but must still be computed by * #InfAdoptedAlgorithm. * * Returns: (transfer full): A new REDO request. **/ InfAdoptedRequest* inf_adopted_request_new_redo(InfAdoptedStateVector* vector, guint user_id, gint64 received) { GObject* object; g_return_val_if_fail(vector != NULL, NULL); g_return_val_if_fail(user_id != 0, NULL); object = g_object_new( INF_ADOPTED_TYPE_REQUEST, "type", INF_ADOPTED_REQUEST_REDO, "vector", vector, "user-id", user_id, "received", received, NULL ); return INF_ADOPTED_REQUEST(object); } /** * inf_adopted_request_copy: * @request: The #InfAdoptedRequest to copy. * * Creates a copy of @request with an initial reference count of 1. * * Returns: (transfer full): A new #InfAdoptedRequest. **/ InfAdoptedRequest* inf_adopted_request_copy(InfAdoptedRequest* request) { InfAdoptedRequestPrivate* priv; InfAdoptedRequestPrivate* new_priv; GObject* object; g_return_val_if_fail(INF_ADOPTED_IS_REQUEST(request), NULL); priv = INF_ADOPTED_REQUEST_PRIVATE(request); if(priv->type == INF_ADOPTED_REQUEST_DO) { object = g_object_new( INF_ADOPTED_TYPE_REQUEST, "type", priv->type, "vector", priv->vector, "user-id", priv->user_id, "operation", priv->operation, "received", priv->received, NULL ); } else { object = g_object_new( INF_ADOPTED_TYPE_REQUEST, "type", priv->type, "vector", priv->vector, "user-id", priv->user_id, "received", priv->received, NULL ); } new_priv = INF_ADOPTED_REQUEST_PRIVATE(INF_ADOPTED_REQUEST(object)); new_priv->executed = priv->executed; return INF_ADOPTED_REQUEST(object); } /** * inf_adopted_request_get_request_type: * @request: A #InfAdoptedRequest. * * Returns the request type of @request. * * Returns: The type of @request. **/ InfAdoptedRequestType inf_adopted_request_get_request_type(InfAdoptedRequest* request) { g_return_val_if_fail( INF_ADOPTED_IS_REQUEST(request), INF_ADOPTED_REQUEST_DO ); return INF_ADOPTED_REQUEST_PRIVATE(request)->type; } /** * inf_adopted_request_get_vector: * @request: A #InfAdoptedRequest. * * Returns the vector time the request was made i.e. its operation can be * applied to the buffer. * * Returns: (transfer none): The state vector of @request. The returned value * should not be freed, it is owned by the #InfAdoptedRequest. **/ InfAdoptedStateVector* inf_adopted_request_get_vector(InfAdoptedRequest* request) { g_return_val_if_fail(INF_ADOPTED_IS_REQUEST(request), NULL); return INF_ADOPTED_REQUEST_PRIVATE(request)->vector; } /** * inf_adopted_request_get_user_id: * @request: A #InfAdoptedRequest. * * Returns the user ID of the user that issued @request. * * Returns: The request's user ID. **/ guint inf_adopted_request_get_user_id(InfAdoptedRequest* request) { g_return_val_if_fail(INF_ADOPTED_IS_REQUEST(request), 0); return INF_ADOPTED_REQUEST_PRIVATE(request)->user_id; } /** * inf_adopted_request_get_operation: * @request: A #InfAdoptedRequest. * * Returns the operation carried by the request. This can only be called if * the request's type is %INF_ADOPTED_REQUEST_DO. * * Returns: (transfer none): The request's operation. **/ InfAdoptedOperation* inf_adopted_request_get_operation(InfAdoptedRequest* request) { InfAdoptedRequestPrivate* priv; g_return_val_if_fail(INF_ADOPTED_IS_REQUEST(request), NULL); priv = INF_ADOPTED_REQUEST_PRIVATE(request); g_return_val_if_fail(priv->operation != NULL, NULL); return priv->operation; } /** * inf_adopted_request_get_index: * @request: A #InfAdoptedRequest. * * Returns the vector time component of the request's own users. This * corresponds to the request index by that user. * * Returns: The vector time component of the request's own user. */ guint inf_adopted_request_get_index(InfAdoptedRequest* request) { InfAdoptedRequestPrivate* priv; g_return_val_if_fail(INF_ADOPTED_IS_REQUEST(request), 0); priv = INF_ADOPTED_REQUEST_PRIVATE(request); return inf_adopted_state_vector_get(priv->vector, priv->user_id); } /** * inf_adopted_request_get_receive_time: * @request: A #InfAdoptedRequest. * * Returns the time when the request was received, or, if it's a local * request, generated. The time is given in microseconds since January 1, * 1970. * * Returns: Time when the request was received. */ gint64 inf_adopted_request_get_receive_time(InfAdoptedRequest* request) { InfAdoptedRequestPrivate* priv; g_return_val_if_fail(INF_ADOPTED_IS_REQUEST(request), 0); priv = INF_ADOPTED_REQUEST_PRIVATE(request); return priv->received; } /** * inf_adopted_request_get_execute_time: * @request: A #InfAdoptedRequest. * * Returns the time when the request was executed by an #InfAdoptedAlgorithm, * see inf_adopted_algorithm_execute_request(). The time is * given in microseconds since January 1, 1970. If the request was not yet * executed, the function returns 0. * * Returns: The time when the function was executed, or 0. */ gint64 inf_adopted_request_get_execute_time(InfAdoptedRequest* request) { InfAdoptedRequestPrivate* priv; g_return_val_if_fail(INF_ADOPTED_IS_REQUEST(request), 0); priv = INF_ADOPTED_REQUEST_PRIVATE(request); return priv->executed; } /** * inf_adopted_request_set_execute_time: * @request: A #InfAdoptedRequest. * @time: A time in microseconds since January 1, 1970. * * Sets the time when @request was executed. Usually this is called by * #InfAdoptedAlgorithm when it executes a request, i.e. translates it to the * current state of the document. */ void inf_adopted_request_set_execute_time(InfAdoptedRequest* request, gint64 time) { InfAdoptedRequestPrivate* priv; g_return_if_fail(INF_ADOPTED_IS_REQUEST(request)); priv = INF_ADOPTED_REQUEST_PRIVATE(request); if(priv->executed != time) { priv->executed = time; g_object_notify(G_OBJECT(request), "executed"); } } /** * inf_adopted_request_need_concurrency_id: * @request: The request to transform. * @against: The request to transform against. * * Returns whether transforming @request against @against requires a * concurrency ID. If this function returns %TRUE, you must provide the * @request_lcs and @against_lcs parameters when calling * inf_adopted_request_transform(). * * Both request need to be of type %INF_ADOPTED_REQUEST_DO, and their state * vectors must be the same. * * Returns: Whether transformation of @request against @against requires a * concurrency ID. */ gboolean inf_adopted_request_need_concurrency_id(InfAdoptedRequest* request, InfAdoptedRequest* against) { InfAdoptedRequestPrivate* request_priv; InfAdoptedRequestPrivate* against_priv; g_return_val_if_fail(INF_ADOPTED_IS_REQUEST(request), FALSE); g_return_val_if_fail(INF_ADOPTED_IS_REQUEST(against), FALSE); request_priv = INF_ADOPTED_REQUEST_PRIVATE(request); against_priv = INF_ADOPTED_REQUEST_PRIVATE(against); g_return_val_if_fail(request_priv->type == INF_ADOPTED_REQUEST_DO, FALSE); g_return_val_if_fail(against_priv->type == INF_ADOPTED_REQUEST_DO, FALSE); g_return_val_if_fail(request_priv->user_id != against_priv->user_id, FALSE); g_return_val_if_fail( inf_adopted_state_vector_compare( request_priv->vector, against_priv->vector ) == 0, FALSE ); return inf_adopted_operation_need_concurrency_id( request_priv->operation, against_priv->operation ); } /** * inf_adopted_request_transform: * @request: The request to transform. * @against: The request to transform against. * @request_lcs: The request to transform in a previous state, or %NULL. * @against_lcs: The request to transform against in a previous state, or * %NULL. * * Transforms the operation of @request against the operation of @against. * Both requests must be of type %INF_ADOPTED_REQUEST_DO, and their state * vectors must be the same. * * If the function inf_adopted_request_need_concurrency_id() returns %TRUE, * @request_lcs and @against_lcs must not be %NULL. * * Returns: (transfer full): A new #InfAdoptedRequest, the result of the * transformation. **/ InfAdoptedRequest* inf_adopted_request_transform(InfAdoptedRequest* request, InfAdoptedRequest* against, InfAdoptedRequest* request_lcs, InfAdoptedRequest* against_lcs) { InfAdoptedRequestPrivate* request_priv; InfAdoptedRequestPrivate* against_priv; InfAdoptedRequestPrivate* request_lcs_priv; InfAdoptedRequestPrivate* against_lcs_priv; InfAdoptedRequestPrivate* new_priv; InfAdoptedOperation* new_operation; InfAdoptedStateVector* new_vector; InfAdoptedRequest* new_request; g_return_val_if_fail(INF_ADOPTED_IS_REQUEST(request), NULL); g_return_val_if_fail(INF_ADOPTED_IS_REQUEST(against), NULL); request_priv = INF_ADOPTED_REQUEST_PRIVATE(request); against_priv = INF_ADOPTED_REQUEST_PRIVATE(against); if(request_lcs != NULL) request_lcs_priv = INF_ADOPTED_REQUEST_PRIVATE(request_lcs); if(against_lcs != NULL) against_lcs_priv = INF_ADOPTED_REQUEST_PRIVATE(against_lcs); g_return_val_if_fail(request_priv->type == INF_ADOPTED_REQUEST_DO, NULL); g_return_val_if_fail(against_priv->type == INF_ADOPTED_REQUEST_DO, NULL); g_return_val_if_fail( request_lcs == NULL || request_lcs_priv->type == INF_ADOPTED_REQUEST_DO, NULL ); g_return_val_if_fail( against_lcs == NULL || against_lcs_priv->type == INF_ADOPTED_REQUEST_DO, NULL ); g_return_val_if_fail(request_priv->user_id != against_priv->user_id, NULL); g_return_val_if_fail( request_lcs == NULL || request_priv->user_id == request_lcs_priv->user_id, NULL ); g_return_val_if_fail( against_lcs == NULL || against_priv->user_id == against_lcs_priv->user_id, NULL ); g_return_val_if_fail( request_lcs == NULL || inf_adopted_state_vector_causally_before( request_lcs_priv->vector, request_priv->vector ), NULL ); g_return_val_if_fail( against_lcs == NULL || inf_adopted_state_vector_causally_before( against_lcs_priv->vector, against_priv->vector ), NULL ); g_return_val_if_fail( inf_adopted_state_vector_compare( request_priv->vector, against_priv->vector ) == 0, NULL ); g_return_val_if_fail( inf_adopted_operation_need_concurrency_id( request_priv->operation, against_priv->operation ) == FALSE || (request_lcs != NULL && against_lcs != NULL), NULL ); if(request_priv->user_id > against_priv->user_id) { new_operation = inf_adopted_operation_transform( request_priv->operation, against_priv->operation, request_lcs == NULL ? NULL : request_lcs_priv->operation, against_lcs == NULL ? NULL : against_lcs_priv->operation, INF_ADOPTED_CONCURRENCY_OTHER ); } else { new_operation = inf_adopted_operation_transform( request_priv->operation, against_priv->operation, request_lcs == NULL ? NULL : request_lcs_priv->operation, against_lcs == NULL ? NULL : against_lcs_priv->operation, INF_ADOPTED_CONCURRENCY_SELF ); } new_vector = inf_adopted_state_vector_copy(request_priv->vector); inf_adopted_state_vector_add(new_vector, against_priv->user_id, 1); new_request = inf_adopted_request_new_do( new_vector, request_priv->user_id, new_operation, request_priv->received ); new_priv = INF_ADOPTED_REQUEST_PRIVATE(new_request); new_priv->executed = request_priv->executed; g_object_unref(new_operation); inf_adopted_state_vector_free(new_vector); return new_request; } /** * inf_adopted_request_mirror: * @request: A #InfAdoptedRequest. * @by: The number of requests between the original and the mirrored * operation. * * Mirrors @request as described in "Reducing the Problems of Group Undo" by * Matthias Ressel and Rul Gunzenhäuser * (http://portal.acm.org/citation.cfm?doid=320297.320312). * * Note that @by is the total amount of requests between the original and * mirrored request, and thus equivalent to 2j-1 in the paper's definition. * * @request must be of type %INF_ADOPTED_REQUEST_DO and its operation must * be reversible. * * Returns: (transfer full): The mirrored request as a new #InfAdoptedRequest. **/ InfAdoptedRequest* inf_adopted_request_mirror(InfAdoptedRequest* request, guint by) { InfAdoptedRequestPrivate* priv; InfAdoptedRequestPrivate* new_priv; InfAdoptedOperation* new_operation; InfAdoptedStateVector* new_vector; InfAdoptedRequest* new_request; g_return_val_if_fail(INF_ADOPTED_IS_REQUEST(request), NULL); g_return_val_if_fail(by % 2 == 1, NULL); priv = INF_ADOPTED_REQUEST_PRIVATE(request); g_return_val_if_fail(priv->type == INF_ADOPTED_REQUEST_DO, NULL); g_return_val_if_fail( inf_adopted_operation_is_reversible(priv->operation), NULL ); new_operation = inf_adopted_operation_revert(priv->operation); new_vector = inf_adopted_state_vector_copy(priv->vector); inf_adopted_state_vector_add(new_vector, priv->user_id, by); new_request = inf_adopted_request_new_do( new_vector, priv->user_id, new_operation, priv->received ); new_priv = INF_ADOPTED_REQUEST_PRIVATE(new_request); new_priv->executed = priv->executed; g_object_unref(new_operation); inf_adopted_state_vector_free(new_vector); return new_request; } /** * inf_adopted_request_fold: * @request: A #InfAdoptedRequest. * @into: The direction into which to fold. * @by: The number of operations between the original and the fold request. * * Folds @request as described in "Reducing the Problems of Group Undo" by * Matthias Ressel and Rul Gunzenhäuser * (http://portal.acm.org/citation.cfm?doid=320297.320312). * * Note that @by is the total amount of requests between the original and * the fold request, and thus equivalent to 2j in the paper's definition. * * @into must not be the same user as the one that issued @request. * * Returns: (transfer full): The folded request as a new #InfAdoptedRequest. **/ InfAdoptedRequest* inf_adopted_request_fold(InfAdoptedRequest* request, guint into, guint by) { InfAdoptedRequestPrivate* priv; InfAdoptedRequestPrivate* new_priv; InfAdoptedStateVector* new_vector; InfAdoptedRequest* new_request; g_return_val_if_fail(INF_ADOPTED_IS_REQUEST(request), NULL); g_return_val_if_fail(into != 0, NULL); g_return_val_if_fail(by % 2 == 0, NULL); priv = INF_ADOPTED_REQUEST_PRIVATE(request); g_return_val_if_fail(priv->user_id != into, NULL); new_vector = inf_adopted_state_vector_copy(priv->vector); inf_adopted_state_vector_add(new_vector, into, by); if(priv->type == INF_ADOPTED_REQUEST_DO) { new_request = INF_ADOPTED_REQUEST( g_object_new( INF_ADOPTED_TYPE_REQUEST, "type", priv->type, "operation", priv->operation, "vector", new_vector, "user-id", priv->user_id, "received", priv->received, NULL ) ); } else { new_request = INF_ADOPTED_REQUEST( g_object_new( INF_ADOPTED_TYPE_REQUEST, "type", priv->type, "vector", new_vector, "user-id", priv->user_id, "received", priv->received, NULL ) ); } new_priv = INF_ADOPTED_REQUEST_PRIVATE(new_request); new_priv->executed = priv->executed; inf_adopted_state_vector_free(new_vector); return new_request; } /** * inf_adopted_request_affects_buffer: * @request: A #InfAdoptedRequest. * * Returns whether this request, when applied, changes the content of the * buffer. If this is a %INF_ADOPTED_REQUEST_UNDO or %INF_ADOPTED_REQUEST_REDO * request, than it always affects the buffer, because only requests that * affect the buffer can be undone or redone. If it is a * %INF_ADOPTED_REQUEST_DO request, than it returns whether its operation * has the %INF_ADOPTED_OPERATION_AFFECTS_BUFFER flag set. * * Returns: Whether @request affects the session's buffer. **/ gboolean inf_adopted_request_affects_buffer(InfAdoptedRequest* request) { InfAdoptedRequestPrivate* priv; g_return_val_if_fail(INF_ADOPTED_IS_REQUEST(request), FALSE); priv = INF_ADOPTED_REQUEST_PRIVATE(request); switch(priv->type) { case INF_ADOPTED_REQUEST_DO: if(inf_adopted_operation_get_flags(priv->operation) & INF_ADOPTED_OPERATION_AFFECTS_BUFFER) { return TRUE; } else { return FALSE; } case INF_ADOPTED_REQUEST_UNDO: case INF_ADOPTED_REQUEST_REDO: return TRUE; default: g_assert_not_reached(); return FALSE; } } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/adopted/PaxHeaders.26529/inf-adopted-algorithm.h0000644000000000000000000000013213034342512024067 xustar0030 mtime=1483851082.021718383 30 atime=1483851082.021718383 30 ctime=1488261588.904139275 libinfinity-0.7.1/libinfinity/adopted/inf-adopted-algorithm.h0000644000175000017500000001367513034342512024635 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_ADOPTED_ALGORITHM_H__ #define __INF_ADOPTED_ALGORITHM_H__ #include #include #include #include #include G_BEGIN_DECLS #define INF_ADOPTED_TYPE_ALGORITHM (inf_adopted_algorithm_get_type()) #define INF_ADOPTED_ALGORITHM(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_ADOPTED_TYPE_ALGORITHM, InfAdoptedAlgorithm)) #define INF_ADOPTED_ALGORITHM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INF_ADOPTED_TYPE_ALGORITHM, InfAdoptedAlgorithmClass)) #define INF_ADOPTED_IS_ALGORITHM(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_ADOPTED_TYPE_ALGORITHM)) #define INF_ADOPTED_IS_ALGORITHM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INF_ADOPTED_TYPE_ALGORITHM)) #define INF_ADOPTED_ALGORITHM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INF_ADOPTED_TYPE_ALGORITHM, InfAdoptedAlgorithmClass)) typedef struct _InfAdoptedAlgorithm InfAdoptedAlgorithm; typedef struct _InfAdoptedAlgorithmClass InfAdoptedAlgorithmClass; /** * InfAdoptedAlgorithmError: * @INF_ADOPTED_ALGORITHM_ERROR_NO_UNDO: An undo request was about to be * executed but there is no operation to undo. * @INF_ADOPTED_ALGORITHM_ERROR_NO_REDO: A redo request was about to be * executed but there is no operation to redo. * @INF_ADOPTED_ALGORITHM_ERROR_FAILED: No further specified error code. * * Error codes for #InfAdoptedAlgorithm. These can occur when invalid requests * are passed to inf_adopted_algorithm_execute_request(). */ typedef enum _InfAdoptedAlgorithmError { INF_ADOPTED_ALGORITHM_ERROR_NO_UNDO, INF_ADOPTED_ALGORITHM_ERROR_NO_REDO, INF_ADOPTED_ALGORITHM_ERROR_FAILED } InfAdoptedAlgorithmError; /** * InfAdoptedAlgorithmClass: * @can_undo_changed: Default signal handler for the * #InfAdoptedAlgorithm::can_undo_changed signal. * @can_redo_changed: Default signal handler for the * #InfAdoptedAlgorithm::can_redo_changed signal. * @begin_execute_request: Default signal handler for the * #InfAdoptedAlgorithm::begin-execute-request signal. * @end_execute_request: Default signal handler for the * #InfAdoptedAlgorithm::end-execute-request signal. * * Signals for the #InfAdoptedAlgorithm class. */ struct _InfAdoptedAlgorithmClass { /*< private >*/ GObjectClass parent_class; /* Signals */ /*< public >*/ void(*can_undo_changed)(InfAdoptedAlgorithm* algorithm, InfAdoptedUser* user, gboolean can_undo); void(*can_redo_changed)(InfAdoptedAlgorithm* algorithm, InfAdoptedUser* user, gboolean can_redo); void(*begin_execute_request)(InfAdoptedAlgorithm* algorithm, InfAdoptedUser* user, InfAdoptedRequest* request); void(*end_execute_request)(InfAdoptedAlgorithm* algorithm, InfAdoptedUser* user, InfAdoptedRequest* request, InfAdoptedRequest* translated_request, const GError* error); }; /** * InfAdoptedAlgorithm: * * #InfAdoptedAlgorithm is an opaque data type. You should only access it via * the public API functions. */ struct _InfAdoptedAlgorithm { /*< private >*/ GObject parent; gpointer priv; }; GType inf_adopted_algorithm_get_type(void) G_GNUC_CONST; InfAdoptedAlgorithm* inf_adopted_algorithm_new(InfUserTable* user_table, InfBuffer* buffer); InfAdoptedAlgorithm* inf_adopted_algorithm_new_full(InfUserTable* user_table, InfBuffer* buffer, guint max_total_log_size); InfAdoptedStateVector* inf_adopted_algorithm_get_current(InfAdoptedAlgorithm* algorithm); InfAdoptedRequest* inf_adopted_algorithm_get_execute_request(InfAdoptedAlgorithm* algorithm); InfAdoptedRequest* inf_adopted_algorithm_generate_request(InfAdoptedAlgorithm* algorithm, InfAdoptedRequestType type, InfAdoptedUser* user, InfAdoptedOperation* operation); InfAdoptedRequest* inf_adopted_algorithm_translate_request(InfAdoptedAlgorithm* algorithm, InfAdoptedRequest* request, InfAdoptedStateVector* to); gboolean inf_adopted_algorithm_execute_request(InfAdoptedAlgorithm* algorithm, InfAdoptedRequest* request, gboolean apply, GError** error); void inf_adopted_algorithm_cleanup(InfAdoptedAlgorithm* algorithm); gboolean inf_adopted_algorithm_can_undo(InfAdoptedAlgorithm* algorithm, InfAdoptedUser* user); gboolean inf_adopted_algorithm_can_redo(InfAdoptedAlgorithm* algorithm, InfAdoptedUser* user); G_END_DECLS #endif /* __INF_ADOPTED_ALGORITHM_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/PaxHeaders.26529/Makefile.in0000644000000000000000000000013113051241010020152 xustar0030 mtime=1487225352.269150215 30 atime=1487225352.269150215 29 ctime=1488261589.01613903 libinfinity-0.7.1/libinfinity/Makefile.in0000644000175000017500000052633613051241010020724 0ustar00arminarmin00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 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__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) 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@ subdir = libinfinity ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/gtk-doc.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(adopted_HEADERS) \ $(client_HEADERS) $(common_HEADERS) $(communication_HEADERS) \ $(libinfinity_0_7_la_HEADERS) $(noinst_HEADERS) \ $(server_HEADERS) $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h inf-config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(girdir)" \ "$(DESTDIR)$(typelibdir)" "$(DESTDIR)$(adopteddir)" \ "$(DESTDIR)$(clientdir)" "$(DESTDIR)$(commondir)" \ "$(DESTDIR)$(communicationdir)" \ "$(DESTDIR)$(libinfinity_0_7_ladir)" "$(DESTDIR)$(serverdir)" LTLIBRARIES = $(lib_LTLIBRARIES) am__DEPENDENCIES_1 = libinfinity_0_7_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) am__dirstamp = $(am__leading_dot)dirstamp am__objects_1 = adopted/libinfinity_0_7_la-inf-adopted-algorithm.lo \ adopted/libinfinity_0_7_la-inf-adopted-no-operation.lo \ adopted/libinfinity_0_7_la-inf-adopted-operation.lo \ adopted/libinfinity_0_7_la-inf-adopted-request.lo \ adopted/libinfinity_0_7_la-inf-adopted-request-log.lo \ adopted/libinfinity_0_7_la-inf-adopted-session.lo \ adopted/libinfinity_0_7_la-inf-adopted-session-record.lo \ adopted/libinfinity_0_7_la-inf-adopted-session-replay.lo \ adopted/libinfinity_0_7_la-inf-adopted-split-operation.lo \ adopted/libinfinity_0_7_la-inf-adopted-state-vector.lo \ adopted/libinfinity_0_7_la-inf-adopted-undo-grouping.lo \ adopted/libinfinity_0_7_la-inf-adopted-user.lo \ common/libinfinity_0_7_la-inf-acl.lo \ common/libinfinity_0_7_la-inf-async-operation.lo \ common/libinfinity_0_7_la-inf-browser.lo \ common/libinfinity_0_7_la-inf-browser-iter.lo \ common/libinfinity_0_7_la-inf-buffer.lo \ common/libinfinity_0_7_la-inf-certificate-chain.lo \ common/libinfinity_0_7_la-inf-certificate-credentials.lo \ common/libinfinity_0_7_la-inf-certificate-verify.lo \ common/libinfinity_0_7_la-inf-cert-util.lo \ common/libinfinity_0_7_la-inf-chat-buffer.lo \ common/libinfinity_0_7_la-inf-chat-session.lo \ common/libinfinity_0_7_la-inf-discovery-avahi.lo \ common/libinfinity_0_7_la-inf-discovery.lo \ common/libinfinity_0_7_la-inf-error.lo \ common/libinfinity_0_7_la-inf-file-util.lo \ common/libinfinity_0_7_la-inf-init.lo \ common/libinfinity_0_7_la-inf-io.lo \ common/libinfinity_0_7_la-inf-ip-address.lo \ common/libinfinity_0_7_la-inf-keepalive.lo \ common/libinfinity_0_7_la-inf-local-publisher.lo \ common/libinfinity_0_7_la-inf-name-resolver.lo \ common/libinfinity_0_7_la-inf-native-socket.lo \ common/libinfinity_0_7_la-inf-protocol.lo \ common/libinfinity_0_7_la-inf-request.lo \ common/libinfinity_0_7_la-inf-request-result.lo \ common/libinfinity_0_7_la-inf-sasl-context.lo \ common/libinfinity_0_7_la-inf-session.lo \ common/libinfinity_0_7_la-inf-session-proxy.lo \ common/libinfinity_0_7_la-inf-simulated-connection.lo \ common/libinfinity_0_7_la-inf-standalone-io.lo \ common/libinfinity_0_7_la-inf-tcp-connection.lo \ common/libinfinity_0_7_la-inf-user.lo \ common/libinfinity_0_7_la-inf-user-table.lo \ common/libinfinity_0_7_la-inf-xml-connection.lo \ common/libinfinity_0_7_la-inf-xml-util.lo \ common/libinfinity_0_7_la-inf-xmpp-connection.lo \ common/libinfinity_0_7_la-inf-xmpp-manager.lo \ communication/libinfinity_0_7_la-inf-communication-central-factory.lo \ communication/libinfinity_0_7_la-inf-communication-central-method.lo \ communication/libinfinity_0_7_la-inf-communication-factory.lo \ communication/libinfinity_0_7_la-inf-communication-group.lo \ communication/libinfinity_0_7_la-inf-communication-hosted-group.lo \ communication/libinfinity_0_7_la-inf-communication-joined-group.lo \ communication/libinfinity_0_7_la-inf-communication-manager.lo \ communication/libinfinity_0_7_la-inf-communication-method.lo \ communication/libinfinity_0_7_la-inf-communication-object.lo \ communication/libinfinity_0_7_la-inf-communication-registry.lo am__objects_2 = client/libinfinity_0_7_la-infc-browser.lo \ client/libinfinity_0_7_la-infc-progress-request.lo \ client/libinfinity_0_7_la-infc-request.lo \ client/libinfinity_0_7_la-infc-request-manager.lo \ client/libinfinity_0_7_la-infc-session-proxy.lo am__objects_3 = server/libinfinity_0_7_la-infd-account-storage.lo \ server/libinfinity_0_7_la-infd-chat-filesystem-format.lo \ server/libinfinity_0_7_la-infd-directory.lo \ server/libinfinity_0_7_la-infd-filesystem-account-storage.lo \ server/libinfinity_0_7_la-infd-filesystem-storage.lo \ server/libinfinity_0_7_la-infd-progress-request.lo \ server/libinfinity_0_7_la-infd-request.lo \ server/libinfinity_0_7_la-infd-server-pool.lo \ server/libinfinity_0_7_la-infd-session-proxy.lo \ server/libinfinity_0_7_la-infd-storage.lo \ server/libinfinity_0_7_la-infd-tcp-server.lo \ server/libinfinity_0_7_la-infd-xml-server.lo \ server/libinfinity_0_7_la-infd-xmpp-server.lo am_libinfinity_0_7_la_OBJECTS = $(am__objects_1) $(am__objects_2) \ $(am__objects_3) libinfinity_0_7_la-inf-dll.lo \ libinfinity_0_7_la-inf-i18n.lo \ libinfinity_0_7_la-inf-signals.lo libinfinity_0_7_la_OBJECTS = $(am_libinfinity_0_7_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libinfinity_0_7_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libinfinity_0_7_la_LDFLAGS) \ $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = 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_CC_1 = 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_CCLD_1 = SOURCES = $(libinfinity_0_7_la_SOURCES) DIST_SOURCES = $(libinfinity_0_7_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(gir_DATA) $(typelib_DATA) HEADERS = $(adopted_HEADERS) $(client_HEADERS) $(common_HEADERS) \ $(communication_HEADERS) $(libinfinity_0_7_la_HEADERS) \ $(noinst_HEADERS) $(server_HEADERS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \ $(LISP)inf-config.h.in # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/inf-config.h.in \ $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ 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@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIRNAME = @DATADIRNAME@ 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@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ GTKDOC_CHECK = @GTKDOC_CHECK@ GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ GTKDOC_MKPDF = @GTKDOC_MKPDF@ GTKDOC_REBASE = @GTKDOC_REBASE@ HTML_DIR = @HTML_DIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INSTOBJEXT = @INSTOBJEXT@ INTLLIBS = @INTLLIBS@ INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBINFINITY_API_VERSION = @LIBINFINITY_API_VERSION@ LIBINFINITY_LIBTOOL_VERSION = @LIBINFINITY_LIBTOOL_VERSION@ LIBINFINITY_VERSION = @LIBINFINITY_VERSION@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGFMT_OPTS = @MSGFMT_OPTS@ 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@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ 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@ avahi_CFLAGS = @avahi_CFLAGS@ avahi_LIBS = @avahi_LIBS@ 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@ gio_CFLAGS = @gio_CFLAGS@ gio_LIBS = @gio_LIBS@ gtk_requirement = @gtk_requirement@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infgtk_CFLAGS = @infgtk_CFLAGS@ infgtk_LIBS = @infgtk_LIBS@ infinity_CFLAGS = @infinity_CFLAGS@ infinity_LIBS = @infinity_LIBS@ infinoted_CFLAGS = @infinoted_CFLAGS@ infinoted_LIBS = @infinoted_LIBS@ infodir = @infodir@ inftext_CFLAGS = @inftext_CFLAGS@ inftext_LIBS = @inftext_LIBS@ inftextgtk_CFLAGS = @inftextgtk_CFLAGS@ inftextgtk_LIBS = @inftextgtk_LIBS@ install_sh = @install_sh@ libdaemon_CFLAGS = @libdaemon_CFLAGS@ libdaemon_LIBS = @libdaemon_LIBS@ 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@ runstatedir = @runstatedir@ 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@ # TODO: Find a way to have the version number set automatically. lib_LTLIBRARIES = libinfinity-0.7.la libinfinity_0_7_la_CPPFLAGS = \ -I$(top_srcdir) \ $(infinity_CFLAGS) \ $(avahi_CFLAGS) libinfinity_0_7_la_LDFLAGS = \ -no-undefined \ -version-info $(LIBINFINITY_LIBTOOL_VERSION) libinfinity_0_7_la_LIBADD = \ $(infinity_LIBS) \ $(glib_LIBS) \ $(avahi_LIBS) libinfinity_0_7_ladir = \ $(includedir)/libinfinity-$(LIBINFINITY_API_VERSION)/libinfinity adopteddir = $(libinfinity_0_7_ladir)/adopted adopted_HEADERS = \ adopted/inf-adopted-algorithm.h \ adopted/inf-adopted-no-operation.h \ adopted/inf-adopted-operation.h \ adopted/inf-adopted-request.h \ adopted/inf-adopted-request-log.h \ adopted/inf-adopted-session.h \ adopted/inf-adopted-session-record.h \ adopted/inf-adopted-session-replay.h \ adopted/inf-adopted-split-operation.h \ adopted/inf-adopted-state-vector.h \ adopted/inf-adopted-undo-grouping.h \ adopted/inf-adopted-user.h commondir = $(libinfinity_0_7_ladir)/common common_HEADERS = \ common/inf-acl.h \ common/inf-async-operation.h \ common/inf-browser.h \ common/inf-browser-iter.h \ common/inf-buffer.h \ common/inf-certificate-chain.h \ common/inf-certificate-credentials.h \ common/inf-certificate-verify.h \ common/inf-cert-util.h \ common/inf-chat-buffer.h \ common/inf-chat-session.h \ common/inf-discovery.h \ common/inf-discovery-avahi.h \ common/inf-error.h \ common/inf-file-util.h \ common/inf-init.h \ common/inf-io.h \ common/inf-ip-address.h \ common/inf-keepalive.h \ common/inf-local-publisher.h \ common/inf-name-resolver.h \ common/inf-native-socket.h \ common/inf-protocol.h \ common/inf-request.h \ common/inf-request-result.h \ common/inf-sasl-context.h \ common/inf-session.h \ common/inf-session-proxy.h \ common/inf-simulated-connection.h \ common/inf-standalone-io.h \ common/inf-tcp-connection.h \ common/inf-user.h \ common/inf-user-table.h \ common/inf-xml-connection.h \ common/inf-xml-util.h \ common/inf-xmpp-connection.h \ common/inf-xmpp-manager.h communicationdir = $(libinfinity_0_7_ladir)/communication communication_HEADERS = \ communication/inf-communication-central-factory.h \ communication/inf-communication-central-method.h \ communication/inf-communication-factory.h \ communication/inf-communication-group.h \ communication/inf-communication-hosted-group.h \ communication/inf-communication-joined-group.h \ communication/inf-communication-manager.h \ communication/inf-communication-method.h \ communication/inf-communication-object.h \ communication/inf-communication-registry.h clientdir = $(libinfinity_0_7_ladir)/client client_HEADERS = \ client/infc-browser.h \ client/infc-note-plugin.h \ client/infc-progress-request.h \ client/infc-request.h \ client/infc-request-manager.h \ client/infc-session-proxy.h serverdir = $(libinfinity_0_7_ladir)/server server_HEADERS = \ server/infd-account-storage.h \ server/infd-chat-filesystem-format.h \ server/infd-directory.h \ server/infd-filesystem-account-storage.h \ server/infd-filesystem-storage.h \ server/infd-note-plugin.h \ server/infd-progress-request.h \ server/infd-request.h \ server/infd-server-pool.h \ server/infd-session-proxy.h \ server/infd-storage.h \ server/infd-tcp-server.h \ server/infd-xml-server.h \ server/infd-xmpp-server.h libinfinity_0_7_la_HEADERS = \ inf-config.h noinst_HEADERS = \ common/inf-tcp-connection-private.h \ communication/inf-communication-group-private.h \ inf-define-enum.h \ inf-dll.h \ inf-i18n.h \ inf-signals.h commonSOURCES = \ adopted/inf-adopted-algorithm.c \ adopted/inf-adopted-no-operation.c \ adopted/inf-adopted-operation.c \ adopted/inf-adopted-request.c \ adopted/inf-adopted-request-log.c \ adopted/inf-adopted-session.c \ adopted/inf-adopted-session-record.c \ adopted/inf-adopted-session-replay.c \ adopted/inf-adopted-split-operation.c \ adopted/inf-adopted-state-vector.c \ adopted/inf-adopted-undo-grouping.c \ adopted/inf-adopted-user.c \ common/inf-acl.c \ common/inf-async-operation.c \ common/inf-browser.c \ common/inf-browser-iter.c \ common/inf-buffer.c \ common/inf-certificate-chain.c \ common/inf-certificate-credentials.c \ common/inf-certificate-verify.c \ common/inf-cert-util.c \ common/inf-chat-buffer.c \ common/inf-chat-session.c \ common/inf-discovery-avahi.c \ common/inf-discovery.c \ common/inf-error.c \ common/inf-file-util.c \ common/inf-init.c \ common/inf-io.c \ common/inf-ip-address.c \ common/inf-keepalive.c \ common/inf-local-publisher.c \ common/inf-name-resolver.c \ common/inf-native-socket.c \ common/inf-protocol.c \ common/inf-request.c \ common/inf-request-result.c \ common/inf-sasl-context.c \ common/inf-session.c \ common/inf-session-proxy.c \ common/inf-simulated-connection.c \ common/inf-standalone-io.c \ common/inf-tcp-connection.c \ common/inf-user.c \ common/inf-user-table.c \ common/inf-xml-connection.c \ common/inf-xml-util.c \ common/inf-xmpp-connection.c \ common/inf-xmpp-manager.c \ communication/inf-communication-central-factory.c \ communication/inf-communication-central-method.c \ communication/inf-communication-factory.c \ communication/inf-communication-group.c \ communication/inf-communication-hosted-group.c \ communication/inf-communication-joined-group.c \ communication/inf-communication-manager.c \ communication/inf-communication-method.c \ communication/inf-communication-object.c \ communication/inf-communication-registry.c clientSOURCES = \ client/infc-browser.c \ client/infc-progress-request.c \ client/infc-request.c \ client/infc-request-manager.c \ client/infc-session-proxy.c serverSOURCES = \ server/infd-account-storage.c \ server/infd-chat-filesystem-format.c \ server/infd-directory.c \ server/infd-filesystem-account-storage.c \ server/infd-filesystem-storage.c \ server/infd-progress-request.c \ server/infd-request.c \ server/infd-server-pool.c \ server/infd-session-proxy.c \ server/infd-storage.c \ server/infd-tcp-server.c \ server/infd-xml-server.c \ server/infd-xmpp-server.c libinfinity_0_7_la_SOURCES = \ ${commonSOURCES} \ ${clientSOURCES} \ ${serverSOURCES} \ inf-dll.c \ inf-i18n.c \ inf-signals.c @HAVE_INTROSPECTION_TRUE@INTROSPECTION_GIRS = Infinity-0.7.gir Infinityc-0.7.gir Infinityd-0.7.gir @HAVE_INTROSPECTION_TRUE@INTROSPECTION_SCANNER_ENV = CC="${CC}" @HAVE_INTROSPECTION_TRUE@INTROSPECTION_COMPILER_ARGS = \ @HAVE_INTROSPECTION_TRUE@ --includedir=${top_srcdir}/libinfinity @HAVE_INTROSPECTION_TRUE@Infinity_0_7_gir_SCANNERFLAGS = \ @HAVE_INTROSPECTION_TRUE@ -I${top_srcdir} \ @HAVE_INTROSPECTION_TRUE@ -n Infinity \ @HAVE_INTROSPECTION_TRUE@ --add-include-path=${top_srcdir}/libinfinity \ @HAVE_INTROSPECTION_TRUE@ --identifier-prefix=Inf @HAVE_INTROSPECTION_TRUE@Infinity_0_7_gir_NAMESPACE = Infinity @HAVE_INTROSPECTION_TRUE@Infinity_0_7_gir_VERSION = 0.7 @HAVE_INTROSPECTION_TRUE@Infinity_0_7_gir_CFLAGS = $(infinity_CFLAGS) @HAVE_INTROSPECTION_TRUE@Infinity_0_7_gir_LIBS = libinfinity-0.7.la @HAVE_INTROSPECTION_TRUE@Infinity_0_7_gir_FILES = \ @HAVE_INTROSPECTION_TRUE@ $(commonSOURCES) \ @HAVE_INTROSPECTION_TRUE@ $(adopted_HEADERS) \ @HAVE_INTROSPECTION_TRUE@ $(common_HEADERS) \ @HAVE_INTROSPECTION_TRUE@ $(communication_HEADERS) # We ship simple "stub" .gir files for gnutls and gsasl, since we expose some # of these objects and expect the user of the library to use their API. @HAVE_INTROSPECTION_TRUE@Infinity_0_7_gir_INCLUDES = GObject-2.0 libxml2-2.0 InfGnutls-3.0 InfGsasl-1.0 @HAVE_INTROSPECTION_TRUE@Infinity_0_7_gir_PACKAGES = gobject-2.0 @HAVE_INTROSPECTION_TRUE@Infinity_0_7_gir_EXPORT_PACKAGES = libinfinity-0.7 # TODO: I would prefer to have all symbols in one gir, however that does not # work at the moment since the prefix for client or server specific functions # have a different prefix. We should just rename those classes, so that all # prefixes inside libinfinity are the same. @HAVE_INTROSPECTION_TRUE@Infinityc_0_7_gir_SCANNERFLAGS = \ @HAVE_INTROSPECTION_TRUE@ -I${top_srcdir} \ @HAVE_INTROSPECTION_TRUE@ --add-include-path=${top_srcdir}/libinfinity \ @HAVE_INTROSPECTION_TRUE@ --add-include-path=${top_builddir}/libinfinity \ @HAVE_INTROSPECTION_TRUE@ -n Infinityc \ @HAVE_INTROSPECTION_TRUE@ --identifier-prefix=Infc @HAVE_INTROSPECTION_TRUE@Infinityc_0_7_gir_NAMESPACE = Infinityc @HAVE_INTROSPECTION_TRUE@Infinityc_0_7_gir_VERSION = 0.7 @HAVE_INTROSPECTION_TRUE@Infinityc_0_7_gir_CFLAGS = $(infinity_CFLAGS) @HAVE_INTROSPECTION_TRUE@Infinityc_0_7_gir_LIBS = libinfinity-0.7.la @HAVE_INTROSPECTION_TRUE@Infinityc_0_7_gir_FILES = \ @HAVE_INTROSPECTION_TRUE@ $(clientSOURCES) \ @HAVE_INTROSPECTION_TRUE@ $(client_HEADERS) @HAVE_INTROSPECTION_TRUE@Infinityc_0_7_gir_INCLUDES = Infinity-0.7 @HAVE_INTROSPECTION_TRUE@Infinityc_0_7_gir_PACKAGES = gobject-2.0 @HAVE_INTROSPECTION_TRUE@Infinityc_0_7_gir_EXPORT_PACKAGES = libinfinity-0.7 @HAVE_INTROSPECTION_TRUE@Infinityd_0_7_gir_SCANNERFLAGS = \ @HAVE_INTROSPECTION_TRUE@ -I${top_srcdir} \ @HAVE_INTROSPECTION_TRUE@ --add-include-path=${top_srcdir}/libinfinity \ @HAVE_INTROSPECTION_TRUE@ --add-include-path=${top_builddir}/libinfinity \ @HAVE_INTROSPECTION_TRUE@ -n Infinityd \ @HAVE_INTROSPECTION_TRUE@ --identifier-prefix=Infd @HAVE_INTROSPECTION_TRUE@Infinityd_0_7_gir_NAMESPACE = Infinityd @HAVE_INTROSPECTION_TRUE@Infinityd_0_7_gir_VERSION = 0.7 @HAVE_INTROSPECTION_TRUE@Infinityd_0_7_gir_CFLAGS = $(infinity_CFLAGS) @HAVE_INTROSPECTION_TRUE@Infinityd_0_7_gir_LIBS = libinfinity-0.7.la @HAVE_INTROSPECTION_TRUE@Infinityd_0_7_gir_FILES = \ @HAVE_INTROSPECTION_TRUE@ $(serverSOURCES) \ @HAVE_INTROSPECTION_TRUE@ $(server_HEADERS) @HAVE_INTROSPECTION_TRUE@Infinityd_0_7_gir_INCLUDES = Infinity-0.7 @HAVE_INTROSPECTION_TRUE@Infinityd_0_7_gir_PACKAGES = gobject-2.0 @HAVE_INTROSPECTION_TRUE@Infinityd_0_7_gir_EXPORT_PACKAGES = libinfinity-0.7 @HAVE_INTROSPECTION_TRUE@girdir = $(datadir)/gir-1.0 @HAVE_INTROSPECTION_TRUE@gir_DATA = InfGnutls-3.0.gir InfGsasl-1.0.gir Infinity-0.7.gir Infinityc-0.7.gir Infinityd-0.7.gir @HAVE_INTROSPECTION_TRUE@typelibdir = $(libdir)/girepository-1.0 @HAVE_INTROSPECTION_TRUE@typelib_DATA = InfGnutls-3.0.typelib InfGsasl-1.0.typelib Infinity-0.7.typelib Infinityc-0.7.typelib Infinityd-0.7.typelib @HAVE_INTROSPECTION_TRUE@CLEANFILES = \ @HAVE_INTROSPECTION_TRUE@ $(INTROSPECTION_GIRS) \ @HAVE_INTROSPECTION_TRUE@ $(typelib_DATA) @HAVE_INTROSPECTION_TRUE@EXTRA_DIST = \ @HAVE_INTROSPECTION_TRUE@ InfGnutls-3.0.gir \ @HAVE_INTROSPECTION_TRUE@ InfGsasl-1.0.gir all: inf-config.h $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(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) --foreign libinfinity/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign libinfinity/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: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): inf-config.h: stamp-h2 @test -f $@ || rm -f stamp-h2 @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h2 stamp-h2: $(srcdir)/inf-config.h.in $(top_builddir)/config.status @rm -f stamp-h2 cd $(top_builddir) && $(SHELL) ./config.status libinfinity/inf-config.h distclean-hdr: -rm -f inf-config.h stamp-h2 install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } adopted/$(am__dirstamp): @$(MKDIR_P) adopted @: > adopted/$(am__dirstamp) adopted/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) adopted/$(DEPDIR) @: > adopted/$(DEPDIR)/$(am__dirstamp) adopted/libinfinity_0_7_la-inf-adopted-algorithm.lo: \ adopted/$(am__dirstamp) adopted/$(DEPDIR)/$(am__dirstamp) adopted/libinfinity_0_7_la-inf-adopted-no-operation.lo: \ adopted/$(am__dirstamp) adopted/$(DEPDIR)/$(am__dirstamp) adopted/libinfinity_0_7_la-inf-adopted-operation.lo: \ adopted/$(am__dirstamp) adopted/$(DEPDIR)/$(am__dirstamp) adopted/libinfinity_0_7_la-inf-adopted-request.lo: \ adopted/$(am__dirstamp) adopted/$(DEPDIR)/$(am__dirstamp) adopted/libinfinity_0_7_la-inf-adopted-request-log.lo: \ adopted/$(am__dirstamp) adopted/$(DEPDIR)/$(am__dirstamp) adopted/libinfinity_0_7_la-inf-adopted-session.lo: \ adopted/$(am__dirstamp) adopted/$(DEPDIR)/$(am__dirstamp) adopted/libinfinity_0_7_la-inf-adopted-session-record.lo: \ adopted/$(am__dirstamp) adopted/$(DEPDIR)/$(am__dirstamp) adopted/libinfinity_0_7_la-inf-adopted-session-replay.lo: \ adopted/$(am__dirstamp) adopted/$(DEPDIR)/$(am__dirstamp) adopted/libinfinity_0_7_la-inf-adopted-split-operation.lo: \ adopted/$(am__dirstamp) adopted/$(DEPDIR)/$(am__dirstamp) adopted/libinfinity_0_7_la-inf-adopted-state-vector.lo: \ adopted/$(am__dirstamp) adopted/$(DEPDIR)/$(am__dirstamp) adopted/libinfinity_0_7_la-inf-adopted-undo-grouping.lo: \ adopted/$(am__dirstamp) adopted/$(DEPDIR)/$(am__dirstamp) adopted/libinfinity_0_7_la-inf-adopted-user.lo: \ adopted/$(am__dirstamp) adopted/$(DEPDIR)/$(am__dirstamp) common/$(am__dirstamp): @$(MKDIR_P) common @: > common/$(am__dirstamp) common/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) common/$(DEPDIR) @: > common/$(DEPDIR)/$(am__dirstamp) common/libinfinity_0_7_la-inf-acl.lo: common/$(am__dirstamp) \ common/$(DEPDIR)/$(am__dirstamp) common/libinfinity_0_7_la-inf-async-operation.lo: \ common/$(am__dirstamp) common/$(DEPDIR)/$(am__dirstamp) common/libinfinity_0_7_la-inf-browser.lo: common/$(am__dirstamp) \ common/$(DEPDIR)/$(am__dirstamp) common/libinfinity_0_7_la-inf-browser-iter.lo: common/$(am__dirstamp) \ common/$(DEPDIR)/$(am__dirstamp) common/libinfinity_0_7_la-inf-buffer.lo: common/$(am__dirstamp) \ common/$(DEPDIR)/$(am__dirstamp) common/libinfinity_0_7_la-inf-certificate-chain.lo: \ common/$(am__dirstamp) common/$(DEPDIR)/$(am__dirstamp) common/libinfinity_0_7_la-inf-certificate-credentials.lo: \ common/$(am__dirstamp) common/$(DEPDIR)/$(am__dirstamp) common/libinfinity_0_7_la-inf-certificate-verify.lo: \ common/$(am__dirstamp) common/$(DEPDIR)/$(am__dirstamp) common/libinfinity_0_7_la-inf-cert-util.lo: common/$(am__dirstamp) \ common/$(DEPDIR)/$(am__dirstamp) common/libinfinity_0_7_la-inf-chat-buffer.lo: common/$(am__dirstamp) \ common/$(DEPDIR)/$(am__dirstamp) common/libinfinity_0_7_la-inf-chat-session.lo: common/$(am__dirstamp) \ common/$(DEPDIR)/$(am__dirstamp) common/libinfinity_0_7_la-inf-discovery-avahi.lo: \ common/$(am__dirstamp) common/$(DEPDIR)/$(am__dirstamp) common/libinfinity_0_7_la-inf-discovery.lo: common/$(am__dirstamp) \ common/$(DEPDIR)/$(am__dirstamp) common/libinfinity_0_7_la-inf-error.lo: common/$(am__dirstamp) \ common/$(DEPDIR)/$(am__dirstamp) common/libinfinity_0_7_la-inf-file-util.lo: common/$(am__dirstamp) \ common/$(DEPDIR)/$(am__dirstamp) common/libinfinity_0_7_la-inf-init.lo: common/$(am__dirstamp) \ common/$(DEPDIR)/$(am__dirstamp) common/libinfinity_0_7_la-inf-io.lo: common/$(am__dirstamp) \ common/$(DEPDIR)/$(am__dirstamp) common/libinfinity_0_7_la-inf-ip-address.lo: common/$(am__dirstamp) \ common/$(DEPDIR)/$(am__dirstamp) common/libinfinity_0_7_la-inf-keepalive.lo: common/$(am__dirstamp) \ common/$(DEPDIR)/$(am__dirstamp) common/libinfinity_0_7_la-inf-local-publisher.lo: \ common/$(am__dirstamp) common/$(DEPDIR)/$(am__dirstamp) common/libinfinity_0_7_la-inf-name-resolver.lo: \ common/$(am__dirstamp) common/$(DEPDIR)/$(am__dirstamp) common/libinfinity_0_7_la-inf-native-socket.lo: \ common/$(am__dirstamp) common/$(DEPDIR)/$(am__dirstamp) common/libinfinity_0_7_la-inf-protocol.lo: common/$(am__dirstamp) \ common/$(DEPDIR)/$(am__dirstamp) common/libinfinity_0_7_la-inf-request.lo: common/$(am__dirstamp) \ common/$(DEPDIR)/$(am__dirstamp) common/libinfinity_0_7_la-inf-request-result.lo: \ common/$(am__dirstamp) common/$(DEPDIR)/$(am__dirstamp) common/libinfinity_0_7_la-inf-sasl-context.lo: common/$(am__dirstamp) \ common/$(DEPDIR)/$(am__dirstamp) common/libinfinity_0_7_la-inf-session.lo: common/$(am__dirstamp) \ common/$(DEPDIR)/$(am__dirstamp) common/libinfinity_0_7_la-inf-session-proxy.lo: \ common/$(am__dirstamp) common/$(DEPDIR)/$(am__dirstamp) common/libinfinity_0_7_la-inf-simulated-connection.lo: \ common/$(am__dirstamp) common/$(DEPDIR)/$(am__dirstamp) common/libinfinity_0_7_la-inf-standalone-io.lo: \ common/$(am__dirstamp) common/$(DEPDIR)/$(am__dirstamp) common/libinfinity_0_7_la-inf-tcp-connection.lo: \ common/$(am__dirstamp) common/$(DEPDIR)/$(am__dirstamp) common/libinfinity_0_7_la-inf-user.lo: common/$(am__dirstamp) \ common/$(DEPDIR)/$(am__dirstamp) common/libinfinity_0_7_la-inf-user-table.lo: common/$(am__dirstamp) \ common/$(DEPDIR)/$(am__dirstamp) common/libinfinity_0_7_la-inf-xml-connection.lo: \ common/$(am__dirstamp) common/$(DEPDIR)/$(am__dirstamp) common/libinfinity_0_7_la-inf-xml-util.lo: common/$(am__dirstamp) \ common/$(DEPDIR)/$(am__dirstamp) common/libinfinity_0_7_la-inf-xmpp-connection.lo: \ common/$(am__dirstamp) common/$(DEPDIR)/$(am__dirstamp) common/libinfinity_0_7_la-inf-xmpp-manager.lo: common/$(am__dirstamp) \ common/$(DEPDIR)/$(am__dirstamp) communication/$(am__dirstamp): @$(MKDIR_P) communication @: > communication/$(am__dirstamp) communication/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) communication/$(DEPDIR) @: > communication/$(DEPDIR)/$(am__dirstamp) communication/libinfinity_0_7_la-inf-communication-central-factory.lo: \ communication/$(am__dirstamp) \ communication/$(DEPDIR)/$(am__dirstamp) communication/libinfinity_0_7_la-inf-communication-central-method.lo: \ communication/$(am__dirstamp) \ communication/$(DEPDIR)/$(am__dirstamp) communication/libinfinity_0_7_la-inf-communication-factory.lo: \ communication/$(am__dirstamp) \ communication/$(DEPDIR)/$(am__dirstamp) communication/libinfinity_0_7_la-inf-communication-group.lo: \ communication/$(am__dirstamp) \ communication/$(DEPDIR)/$(am__dirstamp) communication/libinfinity_0_7_la-inf-communication-hosted-group.lo: \ communication/$(am__dirstamp) \ communication/$(DEPDIR)/$(am__dirstamp) communication/libinfinity_0_7_la-inf-communication-joined-group.lo: \ communication/$(am__dirstamp) \ communication/$(DEPDIR)/$(am__dirstamp) communication/libinfinity_0_7_la-inf-communication-manager.lo: \ communication/$(am__dirstamp) \ communication/$(DEPDIR)/$(am__dirstamp) communication/libinfinity_0_7_la-inf-communication-method.lo: \ communication/$(am__dirstamp) \ communication/$(DEPDIR)/$(am__dirstamp) communication/libinfinity_0_7_la-inf-communication-object.lo: \ communication/$(am__dirstamp) \ communication/$(DEPDIR)/$(am__dirstamp) communication/libinfinity_0_7_la-inf-communication-registry.lo: \ communication/$(am__dirstamp) \ communication/$(DEPDIR)/$(am__dirstamp) client/$(am__dirstamp): @$(MKDIR_P) client @: > client/$(am__dirstamp) client/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) client/$(DEPDIR) @: > client/$(DEPDIR)/$(am__dirstamp) client/libinfinity_0_7_la-infc-browser.lo: client/$(am__dirstamp) \ client/$(DEPDIR)/$(am__dirstamp) client/libinfinity_0_7_la-infc-progress-request.lo: \ client/$(am__dirstamp) client/$(DEPDIR)/$(am__dirstamp) client/libinfinity_0_7_la-infc-request.lo: client/$(am__dirstamp) \ client/$(DEPDIR)/$(am__dirstamp) client/libinfinity_0_7_la-infc-request-manager.lo: \ client/$(am__dirstamp) client/$(DEPDIR)/$(am__dirstamp) client/libinfinity_0_7_la-infc-session-proxy.lo: \ client/$(am__dirstamp) client/$(DEPDIR)/$(am__dirstamp) server/$(am__dirstamp): @$(MKDIR_P) server @: > server/$(am__dirstamp) server/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) server/$(DEPDIR) @: > server/$(DEPDIR)/$(am__dirstamp) server/libinfinity_0_7_la-infd-account-storage.lo: \ server/$(am__dirstamp) server/$(DEPDIR)/$(am__dirstamp) server/libinfinity_0_7_la-infd-chat-filesystem-format.lo: \ server/$(am__dirstamp) server/$(DEPDIR)/$(am__dirstamp) server/libinfinity_0_7_la-infd-directory.lo: server/$(am__dirstamp) \ server/$(DEPDIR)/$(am__dirstamp) server/libinfinity_0_7_la-infd-filesystem-account-storage.lo: \ server/$(am__dirstamp) server/$(DEPDIR)/$(am__dirstamp) server/libinfinity_0_7_la-infd-filesystem-storage.lo: \ server/$(am__dirstamp) server/$(DEPDIR)/$(am__dirstamp) server/libinfinity_0_7_la-infd-progress-request.lo: \ server/$(am__dirstamp) server/$(DEPDIR)/$(am__dirstamp) server/libinfinity_0_7_la-infd-request.lo: server/$(am__dirstamp) \ server/$(DEPDIR)/$(am__dirstamp) server/libinfinity_0_7_la-infd-server-pool.lo: server/$(am__dirstamp) \ server/$(DEPDIR)/$(am__dirstamp) server/libinfinity_0_7_la-infd-session-proxy.lo: \ server/$(am__dirstamp) server/$(DEPDIR)/$(am__dirstamp) server/libinfinity_0_7_la-infd-storage.lo: server/$(am__dirstamp) \ server/$(DEPDIR)/$(am__dirstamp) server/libinfinity_0_7_la-infd-tcp-server.lo: server/$(am__dirstamp) \ server/$(DEPDIR)/$(am__dirstamp) server/libinfinity_0_7_la-infd-xml-server.lo: server/$(am__dirstamp) \ server/$(DEPDIR)/$(am__dirstamp) server/libinfinity_0_7_la-infd-xmpp-server.lo: server/$(am__dirstamp) \ server/$(DEPDIR)/$(am__dirstamp) libinfinity-0.7.la: $(libinfinity_0_7_la_OBJECTS) $(libinfinity_0_7_la_DEPENDENCIES) $(EXTRA_libinfinity_0_7_la_DEPENDENCIES) $(AM_V_CCLD)$(libinfinity_0_7_la_LINK) -rpath $(libdir) $(libinfinity_0_7_la_OBJECTS) $(libinfinity_0_7_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) -rm -f adopted/*.$(OBJEXT) -rm -f adopted/*.lo -rm -f client/*.$(OBJEXT) -rm -f client/*.lo -rm -f common/*.$(OBJEXT) -rm -f common/*.lo -rm -f communication/*.$(OBJEXT) -rm -f communication/*.lo -rm -f server/*.$(OBJEXT) -rm -f server/*.lo distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libinfinity_0_7_la-inf-dll.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libinfinity_0_7_la-inf-i18n.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libinfinity_0_7_la-inf-signals.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@adopted/$(DEPDIR)/libinfinity_0_7_la-inf-adopted-algorithm.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@adopted/$(DEPDIR)/libinfinity_0_7_la-inf-adopted-no-operation.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@adopted/$(DEPDIR)/libinfinity_0_7_la-inf-adopted-operation.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@adopted/$(DEPDIR)/libinfinity_0_7_la-inf-adopted-request-log.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@adopted/$(DEPDIR)/libinfinity_0_7_la-inf-adopted-request.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@adopted/$(DEPDIR)/libinfinity_0_7_la-inf-adopted-session-record.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@adopted/$(DEPDIR)/libinfinity_0_7_la-inf-adopted-session-replay.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@adopted/$(DEPDIR)/libinfinity_0_7_la-inf-adopted-session.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@adopted/$(DEPDIR)/libinfinity_0_7_la-inf-adopted-split-operation.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@adopted/$(DEPDIR)/libinfinity_0_7_la-inf-adopted-state-vector.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@adopted/$(DEPDIR)/libinfinity_0_7_la-inf-adopted-undo-grouping.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@adopted/$(DEPDIR)/libinfinity_0_7_la-inf-adopted-user.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@client/$(DEPDIR)/libinfinity_0_7_la-infc-browser.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@client/$(DEPDIR)/libinfinity_0_7_la-infc-progress-request.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@client/$(DEPDIR)/libinfinity_0_7_la-infc-request-manager.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@client/$(DEPDIR)/libinfinity_0_7_la-infc-request.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@client/$(DEPDIR)/libinfinity_0_7_la-infc-session-proxy.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/libinfinity_0_7_la-inf-acl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/libinfinity_0_7_la-inf-async-operation.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/libinfinity_0_7_la-inf-browser-iter.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/libinfinity_0_7_la-inf-browser.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/libinfinity_0_7_la-inf-buffer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/libinfinity_0_7_la-inf-cert-util.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/libinfinity_0_7_la-inf-certificate-chain.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/libinfinity_0_7_la-inf-certificate-credentials.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/libinfinity_0_7_la-inf-certificate-verify.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/libinfinity_0_7_la-inf-chat-buffer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/libinfinity_0_7_la-inf-chat-session.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/libinfinity_0_7_la-inf-discovery-avahi.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/libinfinity_0_7_la-inf-discovery.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/libinfinity_0_7_la-inf-error.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/libinfinity_0_7_la-inf-file-util.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/libinfinity_0_7_la-inf-init.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/libinfinity_0_7_la-inf-io.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/libinfinity_0_7_la-inf-ip-address.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/libinfinity_0_7_la-inf-keepalive.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/libinfinity_0_7_la-inf-local-publisher.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/libinfinity_0_7_la-inf-name-resolver.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/libinfinity_0_7_la-inf-native-socket.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/libinfinity_0_7_la-inf-protocol.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/libinfinity_0_7_la-inf-request-result.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/libinfinity_0_7_la-inf-request.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/libinfinity_0_7_la-inf-sasl-context.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/libinfinity_0_7_la-inf-session-proxy.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/libinfinity_0_7_la-inf-session.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/libinfinity_0_7_la-inf-simulated-connection.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/libinfinity_0_7_la-inf-standalone-io.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/libinfinity_0_7_la-inf-tcp-connection.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/libinfinity_0_7_la-inf-user-table.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/libinfinity_0_7_la-inf-user.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/libinfinity_0_7_la-inf-xml-connection.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/libinfinity_0_7_la-inf-xml-util.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/libinfinity_0_7_la-inf-xmpp-connection.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@common/$(DEPDIR)/libinfinity_0_7_la-inf-xmpp-manager.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@communication/$(DEPDIR)/libinfinity_0_7_la-inf-communication-central-factory.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@communication/$(DEPDIR)/libinfinity_0_7_la-inf-communication-central-method.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@communication/$(DEPDIR)/libinfinity_0_7_la-inf-communication-factory.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@communication/$(DEPDIR)/libinfinity_0_7_la-inf-communication-group.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@communication/$(DEPDIR)/libinfinity_0_7_la-inf-communication-hosted-group.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@communication/$(DEPDIR)/libinfinity_0_7_la-inf-communication-joined-group.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@communication/$(DEPDIR)/libinfinity_0_7_la-inf-communication-manager.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@communication/$(DEPDIR)/libinfinity_0_7_la-inf-communication-method.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@communication/$(DEPDIR)/libinfinity_0_7_la-inf-communication-object.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@communication/$(DEPDIR)/libinfinity_0_7_la-inf-communication-registry.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@server/$(DEPDIR)/libinfinity_0_7_la-infd-account-storage.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@server/$(DEPDIR)/libinfinity_0_7_la-infd-chat-filesystem-format.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@server/$(DEPDIR)/libinfinity_0_7_la-infd-directory.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@server/$(DEPDIR)/libinfinity_0_7_la-infd-filesystem-account-storage.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@server/$(DEPDIR)/libinfinity_0_7_la-infd-filesystem-storage.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@server/$(DEPDIR)/libinfinity_0_7_la-infd-progress-request.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@server/$(DEPDIR)/libinfinity_0_7_la-infd-request.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@server/$(DEPDIR)/libinfinity_0_7_la-infd-server-pool.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@server/$(DEPDIR)/libinfinity_0_7_la-infd-session-proxy.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@server/$(DEPDIR)/libinfinity_0_7_la-infd-storage.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@server/$(DEPDIR)/libinfinity_0_7_la-infd-tcp-server.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@server/$(DEPDIR)/libinfinity_0_7_la-infd-xml-server.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@server/$(DEPDIR)/libinfinity_0_7_la-infd-xmpp-server.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.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 -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.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 -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.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 $@ $< adopted/libinfinity_0_7_la-inf-adopted-algorithm.lo: adopted/inf-adopted-algorithm.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT adopted/libinfinity_0_7_la-inf-adopted-algorithm.lo -MD -MP -MF adopted/$(DEPDIR)/libinfinity_0_7_la-inf-adopted-algorithm.Tpo -c -o adopted/libinfinity_0_7_la-inf-adopted-algorithm.lo `test -f 'adopted/inf-adopted-algorithm.c' || echo '$(srcdir)/'`adopted/inf-adopted-algorithm.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) adopted/$(DEPDIR)/libinfinity_0_7_la-inf-adopted-algorithm.Tpo adopted/$(DEPDIR)/libinfinity_0_7_la-inf-adopted-algorithm.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='adopted/inf-adopted-algorithm.c' object='adopted/libinfinity_0_7_la-inf-adopted-algorithm.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o adopted/libinfinity_0_7_la-inf-adopted-algorithm.lo `test -f 'adopted/inf-adopted-algorithm.c' || echo '$(srcdir)/'`adopted/inf-adopted-algorithm.c adopted/libinfinity_0_7_la-inf-adopted-no-operation.lo: adopted/inf-adopted-no-operation.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT adopted/libinfinity_0_7_la-inf-adopted-no-operation.lo -MD -MP -MF adopted/$(DEPDIR)/libinfinity_0_7_la-inf-adopted-no-operation.Tpo -c -o adopted/libinfinity_0_7_la-inf-adopted-no-operation.lo `test -f 'adopted/inf-adopted-no-operation.c' || echo '$(srcdir)/'`adopted/inf-adopted-no-operation.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) adopted/$(DEPDIR)/libinfinity_0_7_la-inf-adopted-no-operation.Tpo adopted/$(DEPDIR)/libinfinity_0_7_la-inf-adopted-no-operation.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='adopted/inf-adopted-no-operation.c' object='adopted/libinfinity_0_7_la-inf-adopted-no-operation.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o adopted/libinfinity_0_7_la-inf-adopted-no-operation.lo `test -f 'adopted/inf-adopted-no-operation.c' || echo '$(srcdir)/'`adopted/inf-adopted-no-operation.c adopted/libinfinity_0_7_la-inf-adopted-operation.lo: adopted/inf-adopted-operation.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT adopted/libinfinity_0_7_la-inf-adopted-operation.lo -MD -MP -MF adopted/$(DEPDIR)/libinfinity_0_7_la-inf-adopted-operation.Tpo -c -o adopted/libinfinity_0_7_la-inf-adopted-operation.lo `test -f 'adopted/inf-adopted-operation.c' || echo '$(srcdir)/'`adopted/inf-adopted-operation.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) adopted/$(DEPDIR)/libinfinity_0_7_la-inf-adopted-operation.Tpo adopted/$(DEPDIR)/libinfinity_0_7_la-inf-adopted-operation.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='adopted/inf-adopted-operation.c' object='adopted/libinfinity_0_7_la-inf-adopted-operation.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o adopted/libinfinity_0_7_la-inf-adopted-operation.lo `test -f 'adopted/inf-adopted-operation.c' || echo '$(srcdir)/'`adopted/inf-adopted-operation.c adopted/libinfinity_0_7_la-inf-adopted-request.lo: adopted/inf-adopted-request.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT adopted/libinfinity_0_7_la-inf-adopted-request.lo -MD -MP -MF adopted/$(DEPDIR)/libinfinity_0_7_la-inf-adopted-request.Tpo -c -o adopted/libinfinity_0_7_la-inf-adopted-request.lo `test -f 'adopted/inf-adopted-request.c' || echo '$(srcdir)/'`adopted/inf-adopted-request.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) adopted/$(DEPDIR)/libinfinity_0_7_la-inf-adopted-request.Tpo adopted/$(DEPDIR)/libinfinity_0_7_la-inf-adopted-request.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='adopted/inf-adopted-request.c' object='adopted/libinfinity_0_7_la-inf-adopted-request.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o adopted/libinfinity_0_7_la-inf-adopted-request.lo `test -f 'adopted/inf-adopted-request.c' || echo '$(srcdir)/'`adopted/inf-adopted-request.c adopted/libinfinity_0_7_la-inf-adopted-request-log.lo: adopted/inf-adopted-request-log.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT adopted/libinfinity_0_7_la-inf-adopted-request-log.lo -MD -MP -MF adopted/$(DEPDIR)/libinfinity_0_7_la-inf-adopted-request-log.Tpo -c -o adopted/libinfinity_0_7_la-inf-adopted-request-log.lo `test -f 'adopted/inf-adopted-request-log.c' || echo '$(srcdir)/'`adopted/inf-adopted-request-log.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) adopted/$(DEPDIR)/libinfinity_0_7_la-inf-adopted-request-log.Tpo adopted/$(DEPDIR)/libinfinity_0_7_la-inf-adopted-request-log.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='adopted/inf-adopted-request-log.c' object='adopted/libinfinity_0_7_la-inf-adopted-request-log.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o adopted/libinfinity_0_7_la-inf-adopted-request-log.lo `test -f 'adopted/inf-adopted-request-log.c' || echo '$(srcdir)/'`adopted/inf-adopted-request-log.c adopted/libinfinity_0_7_la-inf-adopted-session.lo: adopted/inf-adopted-session.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT adopted/libinfinity_0_7_la-inf-adopted-session.lo -MD -MP -MF adopted/$(DEPDIR)/libinfinity_0_7_la-inf-adopted-session.Tpo -c -o adopted/libinfinity_0_7_la-inf-adopted-session.lo `test -f 'adopted/inf-adopted-session.c' || echo '$(srcdir)/'`adopted/inf-adopted-session.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) adopted/$(DEPDIR)/libinfinity_0_7_la-inf-adopted-session.Tpo adopted/$(DEPDIR)/libinfinity_0_7_la-inf-adopted-session.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='adopted/inf-adopted-session.c' object='adopted/libinfinity_0_7_la-inf-adopted-session.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o adopted/libinfinity_0_7_la-inf-adopted-session.lo `test -f 'adopted/inf-adopted-session.c' || echo '$(srcdir)/'`adopted/inf-adopted-session.c adopted/libinfinity_0_7_la-inf-adopted-session-record.lo: adopted/inf-adopted-session-record.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT adopted/libinfinity_0_7_la-inf-adopted-session-record.lo -MD -MP -MF adopted/$(DEPDIR)/libinfinity_0_7_la-inf-adopted-session-record.Tpo -c -o adopted/libinfinity_0_7_la-inf-adopted-session-record.lo `test -f 'adopted/inf-adopted-session-record.c' || echo '$(srcdir)/'`adopted/inf-adopted-session-record.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) adopted/$(DEPDIR)/libinfinity_0_7_la-inf-adopted-session-record.Tpo adopted/$(DEPDIR)/libinfinity_0_7_la-inf-adopted-session-record.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='adopted/inf-adopted-session-record.c' object='adopted/libinfinity_0_7_la-inf-adopted-session-record.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o adopted/libinfinity_0_7_la-inf-adopted-session-record.lo `test -f 'adopted/inf-adopted-session-record.c' || echo '$(srcdir)/'`adopted/inf-adopted-session-record.c adopted/libinfinity_0_7_la-inf-adopted-session-replay.lo: adopted/inf-adopted-session-replay.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT adopted/libinfinity_0_7_la-inf-adopted-session-replay.lo -MD -MP -MF adopted/$(DEPDIR)/libinfinity_0_7_la-inf-adopted-session-replay.Tpo -c -o adopted/libinfinity_0_7_la-inf-adopted-session-replay.lo `test -f 'adopted/inf-adopted-session-replay.c' || echo '$(srcdir)/'`adopted/inf-adopted-session-replay.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) adopted/$(DEPDIR)/libinfinity_0_7_la-inf-adopted-session-replay.Tpo adopted/$(DEPDIR)/libinfinity_0_7_la-inf-adopted-session-replay.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='adopted/inf-adopted-session-replay.c' object='adopted/libinfinity_0_7_la-inf-adopted-session-replay.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o adopted/libinfinity_0_7_la-inf-adopted-session-replay.lo `test -f 'adopted/inf-adopted-session-replay.c' || echo '$(srcdir)/'`adopted/inf-adopted-session-replay.c adopted/libinfinity_0_7_la-inf-adopted-split-operation.lo: adopted/inf-adopted-split-operation.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT adopted/libinfinity_0_7_la-inf-adopted-split-operation.lo -MD -MP -MF adopted/$(DEPDIR)/libinfinity_0_7_la-inf-adopted-split-operation.Tpo -c -o adopted/libinfinity_0_7_la-inf-adopted-split-operation.lo `test -f 'adopted/inf-adopted-split-operation.c' || echo '$(srcdir)/'`adopted/inf-adopted-split-operation.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) adopted/$(DEPDIR)/libinfinity_0_7_la-inf-adopted-split-operation.Tpo adopted/$(DEPDIR)/libinfinity_0_7_la-inf-adopted-split-operation.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='adopted/inf-adopted-split-operation.c' object='adopted/libinfinity_0_7_la-inf-adopted-split-operation.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o adopted/libinfinity_0_7_la-inf-adopted-split-operation.lo `test -f 'adopted/inf-adopted-split-operation.c' || echo '$(srcdir)/'`adopted/inf-adopted-split-operation.c adopted/libinfinity_0_7_la-inf-adopted-state-vector.lo: adopted/inf-adopted-state-vector.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT adopted/libinfinity_0_7_la-inf-adopted-state-vector.lo -MD -MP -MF adopted/$(DEPDIR)/libinfinity_0_7_la-inf-adopted-state-vector.Tpo -c -o adopted/libinfinity_0_7_la-inf-adopted-state-vector.lo `test -f 'adopted/inf-adopted-state-vector.c' || echo '$(srcdir)/'`adopted/inf-adopted-state-vector.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) adopted/$(DEPDIR)/libinfinity_0_7_la-inf-adopted-state-vector.Tpo adopted/$(DEPDIR)/libinfinity_0_7_la-inf-adopted-state-vector.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='adopted/inf-adopted-state-vector.c' object='adopted/libinfinity_0_7_la-inf-adopted-state-vector.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o adopted/libinfinity_0_7_la-inf-adopted-state-vector.lo `test -f 'adopted/inf-adopted-state-vector.c' || echo '$(srcdir)/'`adopted/inf-adopted-state-vector.c adopted/libinfinity_0_7_la-inf-adopted-undo-grouping.lo: adopted/inf-adopted-undo-grouping.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT adopted/libinfinity_0_7_la-inf-adopted-undo-grouping.lo -MD -MP -MF adopted/$(DEPDIR)/libinfinity_0_7_la-inf-adopted-undo-grouping.Tpo -c -o adopted/libinfinity_0_7_la-inf-adopted-undo-grouping.lo `test -f 'adopted/inf-adopted-undo-grouping.c' || echo '$(srcdir)/'`adopted/inf-adopted-undo-grouping.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) adopted/$(DEPDIR)/libinfinity_0_7_la-inf-adopted-undo-grouping.Tpo adopted/$(DEPDIR)/libinfinity_0_7_la-inf-adopted-undo-grouping.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='adopted/inf-adopted-undo-grouping.c' object='adopted/libinfinity_0_7_la-inf-adopted-undo-grouping.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o adopted/libinfinity_0_7_la-inf-adopted-undo-grouping.lo `test -f 'adopted/inf-adopted-undo-grouping.c' || echo '$(srcdir)/'`adopted/inf-adopted-undo-grouping.c adopted/libinfinity_0_7_la-inf-adopted-user.lo: adopted/inf-adopted-user.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT adopted/libinfinity_0_7_la-inf-adopted-user.lo -MD -MP -MF adopted/$(DEPDIR)/libinfinity_0_7_la-inf-adopted-user.Tpo -c -o adopted/libinfinity_0_7_la-inf-adopted-user.lo `test -f 'adopted/inf-adopted-user.c' || echo '$(srcdir)/'`adopted/inf-adopted-user.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) adopted/$(DEPDIR)/libinfinity_0_7_la-inf-adopted-user.Tpo adopted/$(DEPDIR)/libinfinity_0_7_la-inf-adopted-user.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='adopted/inf-adopted-user.c' object='adopted/libinfinity_0_7_la-inf-adopted-user.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o adopted/libinfinity_0_7_la-inf-adopted-user.lo `test -f 'adopted/inf-adopted-user.c' || echo '$(srcdir)/'`adopted/inf-adopted-user.c common/libinfinity_0_7_la-inf-acl.lo: common/inf-acl.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT common/libinfinity_0_7_la-inf-acl.lo -MD -MP -MF common/$(DEPDIR)/libinfinity_0_7_la-inf-acl.Tpo -c -o common/libinfinity_0_7_la-inf-acl.lo `test -f 'common/inf-acl.c' || echo '$(srcdir)/'`common/inf-acl.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) common/$(DEPDIR)/libinfinity_0_7_la-inf-acl.Tpo common/$(DEPDIR)/libinfinity_0_7_la-inf-acl.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='common/inf-acl.c' object='common/libinfinity_0_7_la-inf-acl.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o common/libinfinity_0_7_la-inf-acl.lo `test -f 'common/inf-acl.c' || echo '$(srcdir)/'`common/inf-acl.c common/libinfinity_0_7_la-inf-async-operation.lo: common/inf-async-operation.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT common/libinfinity_0_7_la-inf-async-operation.lo -MD -MP -MF common/$(DEPDIR)/libinfinity_0_7_la-inf-async-operation.Tpo -c -o common/libinfinity_0_7_la-inf-async-operation.lo `test -f 'common/inf-async-operation.c' || echo '$(srcdir)/'`common/inf-async-operation.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) common/$(DEPDIR)/libinfinity_0_7_la-inf-async-operation.Tpo common/$(DEPDIR)/libinfinity_0_7_la-inf-async-operation.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='common/inf-async-operation.c' object='common/libinfinity_0_7_la-inf-async-operation.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o common/libinfinity_0_7_la-inf-async-operation.lo `test -f 'common/inf-async-operation.c' || echo '$(srcdir)/'`common/inf-async-operation.c common/libinfinity_0_7_la-inf-browser.lo: common/inf-browser.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT common/libinfinity_0_7_la-inf-browser.lo -MD -MP -MF common/$(DEPDIR)/libinfinity_0_7_la-inf-browser.Tpo -c -o common/libinfinity_0_7_la-inf-browser.lo `test -f 'common/inf-browser.c' || echo '$(srcdir)/'`common/inf-browser.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) common/$(DEPDIR)/libinfinity_0_7_la-inf-browser.Tpo common/$(DEPDIR)/libinfinity_0_7_la-inf-browser.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='common/inf-browser.c' object='common/libinfinity_0_7_la-inf-browser.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o common/libinfinity_0_7_la-inf-browser.lo `test -f 'common/inf-browser.c' || echo '$(srcdir)/'`common/inf-browser.c common/libinfinity_0_7_la-inf-browser-iter.lo: common/inf-browser-iter.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT common/libinfinity_0_7_la-inf-browser-iter.lo -MD -MP -MF common/$(DEPDIR)/libinfinity_0_7_la-inf-browser-iter.Tpo -c -o common/libinfinity_0_7_la-inf-browser-iter.lo `test -f 'common/inf-browser-iter.c' || echo '$(srcdir)/'`common/inf-browser-iter.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) common/$(DEPDIR)/libinfinity_0_7_la-inf-browser-iter.Tpo common/$(DEPDIR)/libinfinity_0_7_la-inf-browser-iter.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='common/inf-browser-iter.c' object='common/libinfinity_0_7_la-inf-browser-iter.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o common/libinfinity_0_7_la-inf-browser-iter.lo `test -f 'common/inf-browser-iter.c' || echo '$(srcdir)/'`common/inf-browser-iter.c common/libinfinity_0_7_la-inf-buffer.lo: common/inf-buffer.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT common/libinfinity_0_7_la-inf-buffer.lo -MD -MP -MF common/$(DEPDIR)/libinfinity_0_7_la-inf-buffer.Tpo -c -o common/libinfinity_0_7_la-inf-buffer.lo `test -f 'common/inf-buffer.c' || echo '$(srcdir)/'`common/inf-buffer.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) common/$(DEPDIR)/libinfinity_0_7_la-inf-buffer.Tpo common/$(DEPDIR)/libinfinity_0_7_la-inf-buffer.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='common/inf-buffer.c' object='common/libinfinity_0_7_la-inf-buffer.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o common/libinfinity_0_7_la-inf-buffer.lo `test -f 'common/inf-buffer.c' || echo '$(srcdir)/'`common/inf-buffer.c common/libinfinity_0_7_la-inf-certificate-chain.lo: common/inf-certificate-chain.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT common/libinfinity_0_7_la-inf-certificate-chain.lo -MD -MP -MF common/$(DEPDIR)/libinfinity_0_7_la-inf-certificate-chain.Tpo -c -o common/libinfinity_0_7_la-inf-certificate-chain.lo `test -f 'common/inf-certificate-chain.c' || echo '$(srcdir)/'`common/inf-certificate-chain.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) common/$(DEPDIR)/libinfinity_0_7_la-inf-certificate-chain.Tpo common/$(DEPDIR)/libinfinity_0_7_la-inf-certificate-chain.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='common/inf-certificate-chain.c' object='common/libinfinity_0_7_la-inf-certificate-chain.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o common/libinfinity_0_7_la-inf-certificate-chain.lo `test -f 'common/inf-certificate-chain.c' || echo '$(srcdir)/'`common/inf-certificate-chain.c common/libinfinity_0_7_la-inf-certificate-credentials.lo: common/inf-certificate-credentials.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT common/libinfinity_0_7_la-inf-certificate-credentials.lo -MD -MP -MF common/$(DEPDIR)/libinfinity_0_7_la-inf-certificate-credentials.Tpo -c -o common/libinfinity_0_7_la-inf-certificate-credentials.lo `test -f 'common/inf-certificate-credentials.c' || echo '$(srcdir)/'`common/inf-certificate-credentials.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) common/$(DEPDIR)/libinfinity_0_7_la-inf-certificate-credentials.Tpo common/$(DEPDIR)/libinfinity_0_7_la-inf-certificate-credentials.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='common/inf-certificate-credentials.c' object='common/libinfinity_0_7_la-inf-certificate-credentials.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o common/libinfinity_0_7_la-inf-certificate-credentials.lo `test -f 'common/inf-certificate-credentials.c' || echo '$(srcdir)/'`common/inf-certificate-credentials.c common/libinfinity_0_7_la-inf-certificate-verify.lo: common/inf-certificate-verify.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT common/libinfinity_0_7_la-inf-certificate-verify.lo -MD -MP -MF common/$(DEPDIR)/libinfinity_0_7_la-inf-certificate-verify.Tpo -c -o common/libinfinity_0_7_la-inf-certificate-verify.lo `test -f 'common/inf-certificate-verify.c' || echo '$(srcdir)/'`common/inf-certificate-verify.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) common/$(DEPDIR)/libinfinity_0_7_la-inf-certificate-verify.Tpo common/$(DEPDIR)/libinfinity_0_7_la-inf-certificate-verify.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='common/inf-certificate-verify.c' object='common/libinfinity_0_7_la-inf-certificate-verify.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o common/libinfinity_0_7_la-inf-certificate-verify.lo `test -f 'common/inf-certificate-verify.c' || echo '$(srcdir)/'`common/inf-certificate-verify.c common/libinfinity_0_7_la-inf-cert-util.lo: common/inf-cert-util.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT common/libinfinity_0_7_la-inf-cert-util.lo -MD -MP -MF common/$(DEPDIR)/libinfinity_0_7_la-inf-cert-util.Tpo -c -o common/libinfinity_0_7_la-inf-cert-util.lo `test -f 'common/inf-cert-util.c' || echo '$(srcdir)/'`common/inf-cert-util.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) common/$(DEPDIR)/libinfinity_0_7_la-inf-cert-util.Tpo common/$(DEPDIR)/libinfinity_0_7_la-inf-cert-util.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='common/inf-cert-util.c' object='common/libinfinity_0_7_la-inf-cert-util.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o common/libinfinity_0_7_la-inf-cert-util.lo `test -f 'common/inf-cert-util.c' || echo '$(srcdir)/'`common/inf-cert-util.c common/libinfinity_0_7_la-inf-chat-buffer.lo: common/inf-chat-buffer.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT common/libinfinity_0_7_la-inf-chat-buffer.lo -MD -MP -MF common/$(DEPDIR)/libinfinity_0_7_la-inf-chat-buffer.Tpo -c -o common/libinfinity_0_7_la-inf-chat-buffer.lo `test -f 'common/inf-chat-buffer.c' || echo '$(srcdir)/'`common/inf-chat-buffer.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) common/$(DEPDIR)/libinfinity_0_7_la-inf-chat-buffer.Tpo common/$(DEPDIR)/libinfinity_0_7_la-inf-chat-buffer.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='common/inf-chat-buffer.c' object='common/libinfinity_0_7_la-inf-chat-buffer.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o common/libinfinity_0_7_la-inf-chat-buffer.lo `test -f 'common/inf-chat-buffer.c' || echo '$(srcdir)/'`common/inf-chat-buffer.c common/libinfinity_0_7_la-inf-chat-session.lo: common/inf-chat-session.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT common/libinfinity_0_7_la-inf-chat-session.lo -MD -MP -MF common/$(DEPDIR)/libinfinity_0_7_la-inf-chat-session.Tpo -c -o common/libinfinity_0_7_la-inf-chat-session.lo `test -f 'common/inf-chat-session.c' || echo '$(srcdir)/'`common/inf-chat-session.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) common/$(DEPDIR)/libinfinity_0_7_la-inf-chat-session.Tpo common/$(DEPDIR)/libinfinity_0_7_la-inf-chat-session.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='common/inf-chat-session.c' object='common/libinfinity_0_7_la-inf-chat-session.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o common/libinfinity_0_7_la-inf-chat-session.lo `test -f 'common/inf-chat-session.c' || echo '$(srcdir)/'`common/inf-chat-session.c common/libinfinity_0_7_la-inf-discovery-avahi.lo: common/inf-discovery-avahi.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT common/libinfinity_0_7_la-inf-discovery-avahi.lo -MD -MP -MF common/$(DEPDIR)/libinfinity_0_7_la-inf-discovery-avahi.Tpo -c -o common/libinfinity_0_7_la-inf-discovery-avahi.lo `test -f 'common/inf-discovery-avahi.c' || echo '$(srcdir)/'`common/inf-discovery-avahi.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) common/$(DEPDIR)/libinfinity_0_7_la-inf-discovery-avahi.Tpo common/$(DEPDIR)/libinfinity_0_7_la-inf-discovery-avahi.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='common/inf-discovery-avahi.c' object='common/libinfinity_0_7_la-inf-discovery-avahi.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o common/libinfinity_0_7_la-inf-discovery-avahi.lo `test -f 'common/inf-discovery-avahi.c' || echo '$(srcdir)/'`common/inf-discovery-avahi.c common/libinfinity_0_7_la-inf-discovery.lo: common/inf-discovery.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT common/libinfinity_0_7_la-inf-discovery.lo -MD -MP -MF common/$(DEPDIR)/libinfinity_0_7_la-inf-discovery.Tpo -c -o common/libinfinity_0_7_la-inf-discovery.lo `test -f 'common/inf-discovery.c' || echo '$(srcdir)/'`common/inf-discovery.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) common/$(DEPDIR)/libinfinity_0_7_la-inf-discovery.Tpo common/$(DEPDIR)/libinfinity_0_7_la-inf-discovery.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='common/inf-discovery.c' object='common/libinfinity_0_7_la-inf-discovery.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o common/libinfinity_0_7_la-inf-discovery.lo `test -f 'common/inf-discovery.c' || echo '$(srcdir)/'`common/inf-discovery.c common/libinfinity_0_7_la-inf-error.lo: common/inf-error.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT common/libinfinity_0_7_la-inf-error.lo -MD -MP -MF common/$(DEPDIR)/libinfinity_0_7_la-inf-error.Tpo -c -o common/libinfinity_0_7_la-inf-error.lo `test -f 'common/inf-error.c' || echo '$(srcdir)/'`common/inf-error.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) common/$(DEPDIR)/libinfinity_0_7_la-inf-error.Tpo common/$(DEPDIR)/libinfinity_0_7_la-inf-error.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='common/inf-error.c' object='common/libinfinity_0_7_la-inf-error.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o common/libinfinity_0_7_la-inf-error.lo `test -f 'common/inf-error.c' || echo '$(srcdir)/'`common/inf-error.c common/libinfinity_0_7_la-inf-file-util.lo: common/inf-file-util.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT common/libinfinity_0_7_la-inf-file-util.lo -MD -MP -MF common/$(DEPDIR)/libinfinity_0_7_la-inf-file-util.Tpo -c -o common/libinfinity_0_7_la-inf-file-util.lo `test -f 'common/inf-file-util.c' || echo '$(srcdir)/'`common/inf-file-util.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) common/$(DEPDIR)/libinfinity_0_7_la-inf-file-util.Tpo common/$(DEPDIR)/libinfinity_0_7_la-inf-file-util.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='common/inf-file-util.c' object='common/libinfinity_0_7_la-inf-file-util.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o common/libinfinity_0_7_la-inf-file-util.lo `test -f 'common/inf-file-util.c' || echo '$(srcdir)/'`common/inf-file-util.c common/libinfinity_0_7_la-inf-init.lo: common/inf-init.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT common/libinfinity_0_7_la-inf-init.lo -MD -MP -MF common/$(DEPDIR)/libinfinity_0_7_la-inf-init.Tpo -c -o common/libinfinity_0_7_la-inf-init.lo `test -f 'common/inf-init.c' || echo '$(srcdir)/'`common/inf-init.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) common/$(DEPDIR)/libinfinity_0_7_la-inf-init.Tpo common/$(DEPDIR)/libinfinity_0_7_la-inf-init.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='common/inf-init.c' object='common/libinfinity_0_7_la-inf-init.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o common/libinfinity_0_7_la-inf-init.lo `test -f 'common/inf-init.c' || echo '$(srcdir)/'`common/inf-init.c common/libinfinity_0_7_la-inf-io.lo: common/inf-io.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT common/libinfinity_0_7_la-inf-io.lo -MD -MP -MF common/$(DEPDIR)/libinfinity_0_7_la-inf-io.Tpo -c -o common/libinfinity_0_7_la-inf-io.lo `test -f 'common/inf-io.c' || echo '$(srcdir)/'`common/inf-io.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) common/$(DEPDIR)/libinfinity_0_7_la-inf-io.Tpo common/$(DEPDIR)/libinfinity_0_7_la-inf-io.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='common/inf-io.c' object='common/libinfinity_0_7_la-inf-io.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o common/libinfinity_0_7_la-inf-io.lo `test -f 'common/inf-io.c' || echo '$(srcdir)/'`common/inf-io.c common/libinfinity_0_7_la-inf-ip-address.lo: common/inf-ip-address.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT common/libinfinity_0_7_la-inf-ip-address.lo -MD -MP -MF common/$(DEPDIR)/libinfinity_0_7_la-inf-ip-address.Tpo -c -o common/libinfinity_0_7_la-inf-ip-address.lo `test -f 'common/inf-ip-address.c' || echo '$(srcdir)/'`common/inf-ip-address.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) common/$(DEPDIR)/libinfinity_0_7_la-inf-ip-address.Tpo common/$(DEPDIR)/libinfinity_0_7_la-inf-ip-address.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='common/inf-ip-address.c' object='common/libinfinity_0_7_la-inf-ip-address.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o common/libinfinity_0_7_la-inf-ip-address.lo `test -f 'common/inf-ip-address.c' || echo '$(srcdir)/'`common/inf-ip-address.c common/libinfinity_0_7_la-inf-keepalive.lo: common/inf-keepalive.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT common/libinfinity_0_7_la-inf-keepalive.lo -MD -MP -MF common/$(DEPDIR)/libinfinity_0_7_la-inf-keepalive.Tpo -c -o common/libinfinity_0_7_la-inf-keepalive.lo `test -f 'common/inf-keepalive.c' || echo '$(srcdir)/'`common/inf-keepalive.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) common/$(DEPDIR)/libinfinity_0_7_la-inf-keepalive.Tpo common/$(DEPDIR)/libinfinity_0_7_la-inf-keepalive.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='common/inf-keepalive.c' object='common/libinfinity_0_7_la-inf-keepalive.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o common/libinfinity_0_7_la-inf-keepalive.lo `test -f 'common/inf-keepalive.c' || echo '$(srcdir)/'`common/inf-keepalive.c common/libinfinity_0_7_la-inf-local-publisher.lo: common/inf-local-publisher.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT common/libinfinity_0_7_la-inf-local-publisher.lo -MD -MP -MF common/$(DEPDIR)/libinfinity_0_7_la-inf-local-publisher.Tpo -c -o common/libinfinity_0_7_la-inf-local-publisher.lo `test -f 'common/inf-local-publisher.c' || echo '$(srcdir)/'`common/inf-local-publisher.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) common/$(DEPDIR)/libinfinity_0_7_la-inf-local-publisher.Tpo common/$(DEPDIR)/libinfinity_0_7_la-inf-local-publisher.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='common/inf-local-publisher.c' object='common/libinfinity_0_7_la-inf-local-publisher.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o common/libinfinity_0_7_la-inf-local-publisher.lo `test -f 'common/inf-local-publisher.c' || echo '$(srcdir)/'`common/inf-local-publisher.c common/libinfinity_0_7_la-inf-name-resolver.lo: common/inf-name-resolver.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT common/libinfinity_0_7_la-inf-name-resolver.lo -MD -MP -MF common/$(DEPDIR)/libinfinity_0_7_la-inf-name-resolver.Tpo -c -o common/libinfinity_0_7_la-inf-name-resolver.lo `test -f 'common/inf-name-resolver.c' || echo '$(srcdir)/'`common/inf-name-resolver.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) common/$(DEPDIR)/libinfinity_0_7_la-inf-name-resolver.Tpo common/$(DEPDIR)/libinfinity_0_7_la-inf-name-resolver.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='common/inf-name-resolver.c' object='common/libinfinity_0_7_la-inf-name-resolver.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o common/libinfinity_0_7_la-inf-name-resolver.lo `test -f 'common/inf-name-resolver.c' || echo '$(srcdir)/'`common/inf-name-resolver.c common/libinfinity_0_7_la-inf-native-socket.lo: common/inf-native-socket.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT common/libinfinity_0_7_la-inf-native-socket.lo -MD -MP -MF common/$(DEPDIR)/libinfinity_0_7_la-inf-native-socket.Tpo -c -o common/libinfinity_0_7_la-inf-native-socket.lo `test -f 'common/inf-native-socket.c' || echo '$(srcdir)/'`common/inf-native-socket.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) common/$(DEPDIR)/libinfinity_0_7_la-inf-native-socket.Tpo common/$(DEPDIR)/libinfinity_0_7_la-inf-native-socket.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='common/inf-native-socket.c' object='common/libinfinity_0_7_la-inf-native-socket.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o common/libinfinity_0_7_la-inf-native-socket.lo `test -f 'common/inf-native-socket.c' || echo '$(srcdir)/'`common/inf-native-socket.c common/libinfinity_0_7_la-inf-protocol.lo: common/inf-protocol.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT common/libinfinity_0_7_la-inf-protocol.lo -MD -MP -MF common/$(DEPDIR)/libinfinity_0_7_la-inf-protocol.Tpo -c -o common/libinfinity_0_7_la-inf-protocol.lo `test -f 'common/inf-protocol.c' || echo '$(srcdir)/'`common/inf-protocol.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) common/$(DEPDIR)/libinfinity_0_7_la-inf-protocol.Tpo common/$(DEPDIR)/libinfinity_0_7_la-inf-protocol.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='common/inf-protocol.c' object='common/libinfinity_0_7_la-inf-protocol.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o common/libinfinity_0_7_la-inf-protocol.lo `test -f 'common/inf-protocol.c' || echo '$(srcdir)/'`common/inf-protocol.c common/libinfinity_0_7_la-inf-request.lo: common/inf-request.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT common/libinfinity_0_7_la-inf-request.lo -MD -MP -MF common/$(DEPDIR)/libinfinity_0_7_la-inf-request.Tpo -c -o common/libinfinity_0_7_la-inf-request.lo `test -f 'common/inf-request.c' || echo '$(srcdir)/'`common/inf-request.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) common/$(DEPDIR)/libinfinity_0_7_la-inf-request.Tpo common/$(DEPDIR)/libinfinity_0_7_la-inf-request.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='common/inf-request.c' object='common/libinfinity_0_7_la-inf-request.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o common/libinfinity_0_7_la-inf-request.lo `test -f 'common/inf-request.c' || echo '$(srcdir)/'`common/inf-request.c common/libinfinity_0_7_la-inf-request-result.lo: common/inf-request-result.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT common/libinfinity_0_7_la-inf-request-result.lo -MD -MP -MF common/$(DEPDIR)/libinfinity_0_7_la-inf-request-result.Tpo -c -o common/libinfinity_0_7_la-inf-request-result.lo `test -f 'common/inf-request-result.c' || echo '$(srcdir)/'`common/inf-request-result.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) common/$(DEPDIR)/libinfinity_0_7_la-inf-request-result.Tpo common/$(DEPDIR)/libinfinity_0_7_la-inf-request-result.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='common/inf-request-result.c' object='common/libinfinity_0_7_la-inf-request-result.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o common/libinfinity_0_7_la-inf-request-result.lo `test -f 'common/inf-request-result.c' || echo '$(srcdir)/'`common/inf-request-result.c common/libinfinity_0_7_la-inf-sasl-context.lo: common/inf-sasl-context.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT common/libinfinity_0_7_la-inf-sasl-context.lo -MD -MP -MF common/$(DEPDIR)/libinfinity_0_7_la-inf-sasl-context.Tpo -c -o common/libinfinity_0_7_la-inf-sasl-context.lo `test -f 'common/inf-sasl-context.c' || echo '$(srcdir)/'`common/inf-sasl-context.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) common/$(DEPDIR)/libinfinity_0_7_la-inf-sasl-context.Tpo common/$(DEPDIR)/libinfinity_0_7_la-inf-sasl-context.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='common/inf-sasl-context.c' object='common/libinfinity_0_7_la-inf-sasl-context.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o common/libinfinity_0_7_la-inf-sasl-context.lo `test -f 'common/inf-sasl-context.c' || echo '$(srcdir)/'`common/inf-sasl-context.c common/libinfinity_0_7_la-inf-session.lo: common/inf-session.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT common/libinfinity_0_7_la-inf-session.lo -MD -MP -MF common/$(DEPDIR)/libinfinity_0_7_la-inf-session.Tpo -c -o common/libinfinity_0_7_la-inf-session.lo `test -f 'common/inf-session.c' || echo '$(srcdir)/'`common/inf-session.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) common/$(DEPDIR)/libinfinity_0_7_la-inf-session.Tpo common/$(DEPDIR)/libinfinity_0_7_la-inf-session.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='common/inf-session.c' object='common/libinfinity_0_7_la-inf-session.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o common/libinfinity_0_7_la-inf-session.lo `test -f 'common/inf-session.c' || echo '$(srcdir)/'`common/inf-session.c common/libinfinity_0_7_la-inf-session-proxy.lo: common/inf-session-proxy.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT common/libinfinity_0_7_la-inf-session-proxy.lo -MD -MP -MF common/$(DEPDIR)/libinfinity_0_7_la-inf-session-proxy.Tpo -c -o common/libinfinity_0_7_la-inf-session-proxy.lo `test -f 'common/inf-session-proxy.c' || echo '$(srcdir)/'`common/inf-session-proxy.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) common/$(DEPDIR)/libinfinity_0_7_la-inf-session-proxy.Tpo common/$(DEPDIR)/libinfinity_0_7_la-inf-session-proxy.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='common/inf-session-proxy.c' object='common/libinfinity_0_7_la-inf-session-proxy.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o common/libinfinity_0_7_la-inf-session-proxy.lo `test -f 'common/inf-session-proxy.c' || echo '$(srcdir)/'`common/inf-session-proxy.c common/libinfinity_0_7_la-inf-simulated-connection.lo: common/inf-simulated-connection.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT common/libinfinity_0_7_la-inf-simulated-connection.lo -MD -MP -MF common/$(DEPDIR)/libinfinity_0_7_la-inf-simulated-connection.Tpo -c -o common/libinfinity_0_7_la-inf-simulated-connection.lo `test -f 'common/inf-simulated-connection.c' || echo '$(srcdir)/'`common/inf-simulated-connection.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) common/$(DEPDIR)/libinfinity_0_7_la-inf-simulated-connection.Tpo common/$(DEPDIR)/libinfinity_0_7_la-inf-simulated-connection.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='common/inf-simulated-connection.c' object='common/libinfinity_0_7_la-inf-simulated-connection.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o common/libinfinity_0_7_la-inf-simulated-connection.lo `test -f 'common/inf-simulated-connection.c' || echo '$(srcdir)/'`common/inf-simulated-connection.c common/libinfinity_0_7_la-inf-standalone-io.lo: common/inf-standalone-io.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT common/libinfinity_0_7_la-inf-standalone-io.lo -MD -MP -MF common/$(DEPDIR)/libinfinity_0_7_la-inf-standalone-io.Tpo -c -o common/libinfinity_0_7_la-inf-standalone-io.lo `test -f 'common/inf-standalone-io.c' || echo '$(srcdir)/'`common/inf-standalone-io.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) common/$(DEPDIR)/libinfinity_0_7_la-inf-standalone-io.Tpo common/$(DEPDIR)/libinfinity_0_7_la-inf-standalone-io.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='common/inf-standalone-io.c' object='common/libinfinity_0_7_la-inf-standalone-io.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o common/libinfinity_0_7_la-inf-standalone-io.lo `test -f 'common/inf-standalone-io.c' || echo '$(srcdir)/'`common/inf-standalone-io.c common/libinfinity_0_7_la-inf-tcp-connection.lo: common/inf-tcp-connection.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT common/libinfinity_0_7_la-inf-tcp-connection.lo -MD -MP -MF common/$(DEPDIR)/libinfinity_0_7_la-inf-tcp-connection.Tpo -c -o common/libinfinity_0_7_la-inf-tcp-connection.lo `test -f 'common/inf-tcp-connection.c' || echo '$(srcdir)/'`common/inf-tcp-connection.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) common/$(DEPDIR)/libinfinity_0_7_la-inf-tcp-connection.Tpo common/$(DEPDIR)/libinfinity_0_7_la-inf-tcp-connection.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='common/inf-tcp-connection.c' object='common/libinfinity_0_7_la-inf-tcp-connection.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o common/libinfinity_0_7_la-inf-tcp-connection.lo `test -f 'common/inf-tcp-connection.c' || echo '$(srcdir)/'`common/inf-tcp-connection.c common/libinfinity_0_7_la-inf-user.lo: common/inf-user.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT common/libinfinity_0_7_la-inf-user.lo -MD -MP -MF common/$(DEPDIR)/libinfinity_0_7_la-inf-user.Tpo -c -o common/libinfinity_0_7_la-inf-user.lo `test -f 'common/inf-user.c' || echo '$(srcdir)/'`common/inf-user.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) common/$(DEPDIR)/libinfinity_0_7_la-inf-user.Tpo common/$(DEPDIR)/libinfinity_0_7_la-inf-user.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='common/inf-user.c' object='common/libinfinity_0_7_la-inf-user.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o common/libinfinity_0_7_la-inf-user.lo `test -f 'common/inf-user.c' || echo '$(srcdir)/'`common/inf-user.c common/libinfinity_0_7_la-inf-user-table.lo: common/inf-user-table.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT common/libinfinity_0_7_la-inf-user-table.lo -MD -MP -MF common/$(DEPDIR)/libinfinity_0_7_la-inf-user-table.Tpo -c -o common/libinfinity_0_7_la-inf-user-table.lo `test -f 'common/inf-user-table.c' || echo '$(srcdir)/'`common/inf-user-table.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) common/$(DEPDIR)/libinfinity_0_7_la-inf-user-table.Tpo common/$(DEPDIR)/libinfinity_0_7_la-inf-user-table.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='common/inf-user-table.c' object='common/libinfinity_0_7_la-inf-user-table.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o common/libinfinity_0_7_la-inf-user-table.lo `test -f 'common/inf-user-table.c' || echo '$(srcdir)/'`common/inf-user-table.c common/libinfinity_0_7_la-inf-xml-connection.lo: common/inf-xml-connection.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT common/libinfinity_0_7_la-inf-xml-connection.lo -MD -MP -MF common/$(DEPDIR)/libinfinity_0_7_la-inf-xml-connection.Tpo -c -o common/libinfinity_0_7_la-inf-xml-connection.lo `test -f 'common/inf-xml-connection.c' || echo '$(srcdir)/'`common/inf-xml-connection.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) common/$(DEPDIR)/libinfinity_0_7_la-inf-xml-connection.Tpo common/$(DEPDIR)/libinfinity_0_7_la-inf-xml-connection.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='common/inf-xml-connection.c' object='common/libinfinity_0_7_la-inf-xml-connection.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o common/libinfinity_0_7_la-inf-xml-connection.lo `test -f 'common/inf-xml-connection.c' || echo '$(srcdir)/'`common/inf-xml-connection.c common/libinfinity_0_7_la-inf-xml-util.lo: common/inf-xml-util.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT common/libinfinity_0_7_la-inf-xml-util.lo -MD -MP -MF common/$(DEPDIR)/libinfinity_0_7_la-inf-xml-util.Tpo -c -o common/libinfinity_0_7_la-inf-xml-util.lo `test -f 'common/inf-xml-util.c' || echo '$(srcdir)/'`common/inf-xml-util.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) common/$(DEPDIR)/libinfinity_0_7_la-inf-xml-util.Tpo common/$(DEPDIR)/libinfinity_0_7_la-inf-xml-util.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='common/inf-xml-util.c' object='common/libinfinity_0_7_la-inf-xml-util.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o common/libinfinity_0_7_la-inf-xml-util.lo `test -f 'common/inf-xml-util.c' || echo '$(srcdir)/'`common/inf-xml-util.c common/libinfinity_0_7_la-inf-xmpp-connection.lo: common/inf-xmpp-connection.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT common/libinfinity_0_7_la-inf-xmpp-connection.lo -MD -MP -MF common/$(DEPDIR)/libinfinity_0_7_la-inf-xmpp-connection.Tpo -c -o common/libinfinity_0_7_la-inf-xmpp-connection.lo `test -f 'common/inf-xmpp-connection.c' || echo '$(srcdir)/'`common/inf-xmpp-connection.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) common/$(DEPDIR)/libinfinity_0_7_la-inf-xmpp-connection.Tpo common/$(DEPDIR)/libinfinity_0_7_la-inf-xmpp-connection.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='common/inf-xmpp-connection.c' object='common/libinfinity_0_7_la-inf-xmpp-connection.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o common/libinfinity_0_7_la-inf-xmpp-connection.lo `test -f 'common/inf-xmpp-connection.c' || echo '$(srcdir)/'`common/inf-xmpp-connection.c common/libinfinity_0_7_la-inf-xmpp-manager.lo: common/inf-xmpp-manager.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT common/libinfinity_0_7_la-inf-xmpp-manager.lo -MD -MP -MF common/$(DEPDIR)/libinfinity_0_7_la-inf-xmpp-manager.Tpo -c -o common/libinfinity_0_7_la-inf-xmpp-manager.lo `test -f 'common/inf-xmpp-manager.c' || echo '$(srcdir)/'`common/inf-xmpp-manager.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) common/$(DEPDIR)/libinfinity_0_7_la-inf-xmpp-manager.Tpo common/$(DEPDIR)/libinfinity_0_7_la-inf-xmpp-manager.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='common/inf-xmpp-manager.c' object='common/libinfinity_0_7_la-inf-xmpp-manager.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o common/libinfinity_0_7_la-inf-xmpp-manager.lo `test -f 'common/inf-xmpp-manager.c' || echo '$(srcdir)/'`common/inf-xmpp-manager.c communication/libinfinity_0_7_la-inf-communication-central-factory.lo: communication/inf-communication-central-factory.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT communication/libinfinity_0_7_la-inf-communication-central-factory.lo -MD -MP -MF communication/$(DEPDIR)/libinfinity_0_7_la-inf-communication-central-factory.Tpo -c -o communication/libinfinity_0_7_la-inf-communication-central-factory.lo `test -f 'communication/inf-communication-central-factory.c' || echo '$(srcdir)/'`communication/inf-communication-central-factory.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) communication/$(DEPDIR)/libinfinity_0_7_la-inf-communication-central-factory.Tpo communication/$(DEPDIR)/libinfinity_0_7_la-inf-communication-central-factory.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='communication/inf-communication-central-factory.c' object='communication/libinfinity_0_7_la-inf-communication-central-factory.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o communication/libinfinity_0_7_la-inf-communication-central-factory.lo `test -f 'communication/inf-communication-central-factory.c' || echo '$(srcdir)/'`communication/inf-communication-central-factory.c communication/libinfinity_0_7_la-inf-communication-central-method.lo: communication/inf-communication-central-method.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT communication/libinfinity_0_7_la-inf-communication-central-method.lo -MD -MP -MF communication/$(DEPDIR)/libinfinity_0_7_la-inf-communication-central-method.Tpo -c -o communication/libinfinity_0_7_la-inf-communication-central-method.lo `test -f 'communication/inf-communication-central-method.c' || echo '$(srcdir)/'`communication/inf-communication-central-method.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) communication/$(DEPDIR)/libinfinity_0_7_la-inf-communication-central-method.Tpo communication/$(DEPDIR)/libinfinity_0_7_la-inf-communication-central-method.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='communication/inf-communication-central-method.c' object='communication/libinfinity_0_7_la-inf-communication-central-method.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o communication/libinfinity_0_7_la-inf-communication-central-method.lo `test -f 'communication/inf-communication-central-method.c' || echo '$(srcdir)/'`communication/inf-communication-central-method.c communication/libinfinity_0_7_la-inf-communication-factory.lo: communication/inf-communication-factory.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT communication/libinfinity_0_7_la-inf-communication-factory.lo -MD -MP -MF communication/$(DEPDIR)/libinfinity_0_7_la-inf-communication-factory.Tpo -c -o communication/libinfinity_0_7_la-inf-communication-factory.lo `test -f 'communication/inf-communication-factory.c' || echo '$(srcdir)/'`communication/inf-communication-factory.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) communication/$(DEPDIR)/libinfinity_0_7_la-inf-communication-factory.Tpo communication/$(DEPDIR)/libinfinity_0_7_la-inf-communication-factory.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='communication/inf-communication-factory.c' object='communication/libinfinity_0_7_la-inf-communication-factory.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o communication/libinfinity_0_7_la-inf-communication-factory.lo `test -f 'communication/inf-communication-factory.c' || echo '$(srcdir)/'`communication/inf-communication-factory.c communication/libinfinity_0_7_la-inf-communication-group.lo: communication/inf-communication-group.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT communication/libinfinity_0_7_la-inf-communication-group.lo -MD -MP -MF communication/$(DEPDIR)/libinfinity_0_7_la-inf-communication-group.Tpo -c -o communication/libinfinity_0_7_la-inf-communication-group.lo `test -f 'communication/inf-communication-group.c' || echo '$(srcdir)/'`communication/inf-communication-group.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) communication/$(DEPDIR)/libinfinity_0_7_la-inf-communication-group.Tpo communication/$(DEPDIR)/libinfinity_0_7_la-inf-communication-group.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='communication/inf-communication-group.c' object='communication/libinfinity_0_7_la-inf-communication-group.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o communication/libinfinity_0_7_la-inf-communication-group.lo `test -f 'communication/inf-communication-group.c' || echo '$(srcdir)/'`communication/inf-communication-group.c communication/libinfinity_0_7_la-inf-communication-hosted-group.lo: communication/inf-communication-hosted-group.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT communication/libinfinity_0_7_la-inf-communication-hosted-group.lo -MD -MP -MF communication/$(DEPDIR)/libinfinity_0_7_la-inf-communication-hosted-group.Tpo -c -o communication/libinfinity_0_7_la-inf-communication-hosted-group.lo `test -f 'communication/inf-communication-hosted-group.c' || echo '$(srcdir)/'`communication/inf-communication-hosted-group.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) communication/$(DEPDIR)/libinfinity_0_7_la-inf-communication-hosted-group.Tpo communication/$(DEPDIR)/libinfinity_0_7_la-inf-communication-hosted-group.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='communication/inf-communication-hosted-group.c' object='communication/libinfinity_0_7_la-inf-communication-hosted-group.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o communication/libinfinity_0_7_la-inf-communication-hosted-group.lo `test -f 'communication/inf-communication-hosted-group.c' || echo '$(srcdir)/'`communication/inf-communication-hosted-group.c communication/libinfinity_0_7_la-inf-communication-joined-group.lo: communication/inf-communication-joined-group.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT communication/libinfinity_0_7_la-inf-communication-joined-group.lo -MD -MP -MF communication/$(DEPDIR)/libinfinity_0_7_la-inf-communication-joined-group.Tpo -c -o communication/libinfinity_0_7_la-inf-communication-joined-group.lo `test -f 'communication/inf-communication-joined-group.c' || echo '$(srcdir)/'`communication/inf-communication-joined-group.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) communication/$(DEPDIR)/libinfinity_0_7_la-inf-communication-joined-group.Tpo communication/$(DEPDIR)/libinfinity_0_7_la-inf-communication-joined-group.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='communication/inf-communication-joined-group.c' object='communication/libinfinity_0_7_la-inf-communication-joined-group.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o communication/libinfinity_0_7_la-inf-communication-joined-group.lo `test -f 'communication/inf-communication-joined-group.c' || echo '$(srcdir)/'`communication/inf-communication-joined-group.c communication/libinfinity_0_7_la-inf-communication-manager.lo: communication/inf-communication-manager.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT communication/libinfinity_0_7_la-inf-communication-manager.lo -MD -MP -MF communication/$(DEPDIR)/libinfinity_0_7_la-inf-communication-manager.Tpo -c -o communication/libinfinity_0_7_la-inf-communication-manager.lo `test -f 'communication/inf-communication-manager.c' || echo '$(srcdir)/'`communication/inf-communication-manager.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) communication/$(DEPDIR)/libinfinity_0_7_la-inf-communication-manager.Tpo communication/$(DEPDIR)/libinfinity_0_7_la-inf-communication-manager.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='communication/inf-communication-manager.c' object='communication/libinfinity_0_7_la-inf-communication-manager.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o communication/libinfinity_0_7_la-inf-communication-manager.lo `test -f 'communication/inf-communication-manager.c' || echo '$(srcdir)/'`communication/inf-communication-manager.c communication/libinfinity_0_7_la-inf-communication-method.lo: communication/inf-communication-method.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT communication/libinfinity_0_7_la-inf-communication-method.lo -MD -MP -MF communication/$(DEPDIR)/libinfinity_0_7_la-inf-communication-method.Tpo -c -o communication/libinfinity_0_7_la-inf-communication-method.lo `test -f 'communication/inf-communication-method.c' || echo '$(srcdir)/'`communication/inf-communication-method.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) communication/$(DEPDIR)/libinfinity_0_7_la-inf-communication-method.Tpo communication/$(DEPDIR)/libinfinity_0_7_la-inf-communication-method.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='communication/inf-communication-method.c' object='communication/libinfinity_0_7_la-inf-communication-method.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o communication/libinfinity_0_7_la-inf-communication-method.lo `test -f 'communication/inf-communication-method.c' || echo '$(srcdir)/'`communication/inf-communication-method.c communication/libinfinity_0_7_la-inf-communication-object.lo: communication/inf-communication-object.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT communication/libinfinity_0_7_la-inf-communication-object.lo -MD -MP -MF communication/$(DEPDIR)/libinfinity_0_7_la-inf-communication-object.Tpo -c -o communication/libinfinity_0_7_la-inf-communication-object.lo `test -f 'communication/inf-communication-object.c' || echo '$(srcdir)/'`communication/inf-communication-object.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) communication/$(DEPDIR)/libinfinity_0_7_la-inf-communication-object.Tpo communication/$(DEPDIR)/libinfinity_0_7_la-inf-communication-object.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='communication/inf-communication-object.c' object='communication/libinfinity_0_7_la-inf-communication-object.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o communication/libinfinity_0_7_la-inf-communication-object.lo `test -f 'communication/inf-communication-object.c' || echo '$(srcdir)/'`communication/inf-communication-object.c communication/libinfinity_0_7_la-inf-communication-registry.lo: communication/inf-communication-registry.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT communication/libinfinity_0_7_la-inf-communication-registry.lo -MD -MP -MF communication/$(DEPDIR)/libinfinity_0_7_la-inf-communication-registry.Tpo -c -o communication/libinfinity_0_7_la-inf-communication-registry.lo `test -f 'communication/inf-communication-registry.c' || echo '$(srcdir)/'`communication/inf-communication-registry.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) communication/$(DEPDIR)/libinfinity_0_7_la-inf-communication-registry.Tpo communication/$(DEPDIR)/libinfinity_0_7_la-inf-communication-registry.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='communication/inf-communication-registry.c' object='communication/libinfinity_0_7_la-inf-communication-registry.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o communication/libinfinity_0_7_la-inf-communication-registry.lo `test -f 'communication/inf-communication-registry.c' || echo '$(srcdir)/'`communication/inf-communication-registry.c client/libinfinity_0_7_la-infc-browser.lo: client/infc-browser.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT client/libinfinity_0_7_la-infc-browser.lo -MD -MP -MF client/$(DEPDIR)/libinfinity_0_7_la-infc-browser.Tpo -c -o client/libinfinity_0_7_la-infc-browser.lo `test -f 'client/infc-browser.c' || echo '$(srcdir)/'`client/infc-browser.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) client/$(DEPDIR)/libinfinity_0_7_la-infc-browser.Tpo client/$(DEPDIR)/libinfinity_0_7_la-infc-browser.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='client/infc-browser.c' object='client/libinfinity_0_7_la-infc-browser.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o client/libinfinity_0_7_la-infc-browser.lo `test -f 'client/infc-browser.c' || echo '$(srcdir)/'`client/infc-browser.c client/libinfinity_0_7_la-infc-progress-request.lo: client/infc-progress-request.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT client/libinfinity_0_7_la-infc-progress-request.lo -MD -MP -MF client/$(DEPDIR)/libinfinity_0_7_la-infc-progress-request.Tpo -c -o client/libinfinity_0_7_la-infc-progress-request.lo `test -f 'client/infc-progress-request.c' || echo '$(srcdir)/'`client/infc-progress-request.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) client/$(DEPDIR)/libinfinity_0_7_la-infc-progress-request.Tpo client/$(DEPDIR)/libinfinity_0_7_la-infc-progress-request.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='client/infc-progress-request.c' object='client/libinfinity_0_7_la-infc-progress-request.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o client/libinfinity_0_7_la-infc-progress-request.lo `test -f 'client/infc-progress-request.c' || echo '$(srcdir)/'`client/infc-progress-request.c client/libinfinity_0_7_la-infc-request.lo: client/infc-request.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT client/libinfinity_0_7_la-infc-request.lo -MD -MP -MF client/$(DEPDIR)/libinfinity_0_7_la-infc-request.Tpo -c -o client/libinfinity_0_7_la-infc-request.lo `test -f 'client/infc-request.c' || echo '$(srcdir)/'`client/infc-request.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) client/$(DEPDIR)/libinfinity_0_7_la-infc-request.Tpo client/$(DEPDIR)/libinfinity_0_7_la-infc-request.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='client/infc-request.c' object='client/libinfinity_0_7_la-infc-request.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o client/libinfinity_0_7_la-infc-request.lo `test -f 'client/infc-request.c' || echo '$(srcdir)/'`client/infc-request.c client/libinfinity_0_7_la-infc-request-manager.lo: client/infc-request-manager.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT client/libinfinity_0_7_la-infc-request-manager.lo -MD -MP -MF client/$(DEPDIR)/libinfinity_0_7_la-infc-request-manager.Tpo -c -o client/libinfinity_0_7_la-infc-request-manager.lo `test -f 'client/infc-request-manager.c' || echo '$(srcdir)/'`client/infc-request-manager.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) client/$(DEPDIR)/libinfinity_0_7_la-infc-request-manager.Tpo client/$(DEPDIR)/libinfinity_0_7_la-infc-request-manager.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='client/infc-request-manager.c' object='client/libinfinity_0_7_la-infc-request-manager.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o client/libinfinity_0_7_la-infc-request-manager.lo `test -f 'client/infc-request-manager.c' || echo '$(srcdir)/'`client/infc-request-manager.c client/libinfinity_0_7_la-infc-session-proxy.lo: client/infc-session-proxy.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT client/libinfinity_0_7_la-infc-session-proxy.lo -MD -MP -MF client/$(DEPDIR)/libinfinity_0_7_la-infc-session-proxy.Tpo -c -o client/libinfinity_0_7_la-infc-session-proxy.lo `test -f 'client/infc-session-proxy.c' || echo '$(srcdir)/'`client/infc-session-proxy.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) client/$(DEPDIR)/libinfinity_0_7_la-infc-session-proxy.Tpo client/$(DEPDIR)/libinfinity_0_7_la-infc-session-proxy.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='client/infc-session-proxy.c' object='client/libinfinity_0_7_la-infc-session-proxy.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o client/libinfinity_0_7_la-infc-session-proxy.lo `test -f 'client/infc-session-proxy.c' || echo '$(srcdir)/'`client/infc-session-proxy.c server/libinfinity_0_7_la-infd-account-storage.lo: server/infd-account-storage.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT server/libinfinity_0_7_la-infd-account-storage.lo -MD -MP -MF server/$(DEPDIR)/libinfinity_0_7_la-infd-account-storage.Tpo -c -o server/libinfinity_0_7_la-infd-account-storage.lo `test -f 'server/infd-account-storage.c' || echo '$(srcdir)/'`server/infd-account-storage.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) server/$(DEPDIR)/libinfinity_0_7_la-infd-account-storage.Tpo server/$(DEPDIR)/libinfinity_0_7_la-infd-account-storage.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='server/infd-account-storage.c' object='server/libinfinity_0_7_la-infd-account-storage.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o server/libinfinity_0_7_la-infd-account-storage.lo `test -f 'server/infd-account-storage.c' || echo '$(srcdir)/'`server/infd-account-storage.c server/libinfinity_0_7_la-infd-chat-filesystem-format.lo: server/infd-chat-filesystem-format.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT server/libinfinity_0_7_la-infd-chat-filesystem-format.lo -MD -MP -MF server/$(DEPDIR)/libinfinity_0_7_la-infd-chat-filesystem-format.Tpo -c -o server/libinfinity_0_7_la-infd-chat-filesystem-format.lo `test -f 'server/infd-chat-filesystem-format.c' || echo '$(srcdir)/'`server/infd-chat-filesystem-format.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) server/$(DEPDIR)/libinfinity_0_7_la-infd-chat-filesystem-format.Tpo server/$(DEPDIR)/libinfinity_0_7_la-infd-chat-filesystem-format.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='server/infd-chat-filesystem-format.c' object='server/libinfinity_0_7_la-infd-chat-filesystem-format.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o server/libinfinity_0_7_la-infd-chat-filesystem-format.lo `test -f 'server/infd-chat-filesystem-format.c' || echo '$(srcdir)/'`server/infd-chat-filesystem-format.c server/libinfinity_0_7_la-infd-directory.lo: server/infd-directory.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT server/libinfinity_0_7_la-infd-directory.lo -MD -MP -MF server/$(DEPDIR)/libinfinity_0_7_la-infd-directory.Tpo -c -o server/libinfinity_0_7_la-infd-directory.lo `test -f 'server/infd-directory.c' || echo '$(srcdir)/'`server/infd-directory.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) server/$(DEPDIR)/libinfinity_0_7_la-infd-directory.Tpo server/$(DEPDIR)/libinfinity_0_7_la-infd-directory.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='server/infd-directory.c' object='server/libinfinity_0_7_la-infd-directory.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o server/libinfinity_0_7_la-infd-directory.lo `test -f 'server/infd-directory.c' || echo '$(srcdir)/'`server/infd-directory.c server/libinfinity_0_7_la-infd-filesystem-account-storage.lo: server/infd-filesystem-account-storage.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT server/libinfinity_0_7_la-infd-filesystem-account-storage.lo -MD -MP -MF server/$(DEPDIR)/libinfinity_0_7_la-infd-filesystem-account-storage.Tpo -c -o server/libinfinity_0_7_la-infd-filesystem-account-storage.lo `test -f 'server/infd-filesystem-account-storage.c' || echo '$(srcdir)/'`server/infd-filesystem-account-storage.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) server/$(DEPDIR)/libinfinity_0_7_la-infd-filesystem-account-storage.Tpo server/$(DEPDIR)/libinfinity_0_7_la-infd-filesystem-account-storage.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='server/infd-filesystem-account-storage.c' object='server/libinfinity_0_7_la-infd-filesystem-account-storage.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o server/libinfinity_0_7_la-infd-filesystem-account-storage.lo `test -f 'server/infd-filesystem-account-storage.c' || echo '$(srcdir)/'`server/infd-filesystem-account-storage.c server/libinfinity_0_7_la-infd-filesystem-storage.lo: server/infd-filesystem-storage.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT server/libinfinity_0_7_la-infd-filesystem-storage.lo -MD -MP -MF server/$(DEPDIR)/libinfinity_0_7_la-infd-filesystem-storage.Tpo -c -o server/libinfinity_0_7_la-infd-filesystem-storage.lo `test -f 'server/infd-filesystem-storage.c' || echo '$(srcdir)/'`server/infd-filesystem-storage.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) server/$(DEPDIR)/libinfinity_0_7_la-infd-filesystem-storage.Tpo server/$(DEPDIR)/libinfinity_0_7_la-infd-filesystem-storage.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='server/infd-filesystem-storage.c' object='server/libinfinity_0_7_la-infd-filesystem-storage.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o server/libinfinity_0_7_la-infd-filesystem-storage.lo `test -f 'server/infd-filesystem-storage.c' || echo '$(srcdir)/'`server/infd-filesystem-storage.c server/libinfinity_0_7_la-infd-progress-request.lo: server/infd-progress-request.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT server/libinfinity_0_7_la-infd-progress-request.lo -MD -MP -MF server/$(DEPDIR)/libinfinity_0_7_la-infd-progress-request.Tpo -c -o server/libinfinity_0_7_la-infd-progress-request.lo `test -f 'server/infd-progress-request.c' || echo '$(srcdir)/'`server/infd-progress-request.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) server/$(DEPDIR)/libinfinity_0_7_la-infd-progress-request.Tpo server/$(DEPDIR)/libinfinity_0_7_la-infd-progress-request.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='server/infd-progress-request.c' object='server/libinfinity_0_7_la-infd-progress-request.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o server/libinfinity_0_7_la-infd-progress-request.lo `test -f 'server/infd-progress-request.c' || echo '$(srcdir)/'`server/infd-progress-request.c server/libinfinity_0_7_la-infd-request.lo: server/infd-request.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT server/libinfinity_0_7_la-infd-request.lo -MD -MP -MF server/$(DEPDIR)/libinfinity_0_7_la-infd-request.Tpo -c -o server/libinfinity_0_7_la-infd-request.lo `test -f 'server/infd-request.c' || echo '$(srcdir)/'`server/infd-request.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) server/$(DEPDIR)/libinfinity_0_7_la-infd-request.Tpo server/$(DEPDIR)/libinfinity_0_7_la-infd-request.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='server/infd-request.c' object='server/libinfinity_0_7_la-infd-request.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o server/libinfinity_0_7_la-infd-request.lo `test -f 'server/infd-request.c' || echo '$(srcdir)/'`server/infd-request.c server/libinfinity_0_7_la-infd-server-pool.lo: server/infd-server-pool.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT server/libinfinity_0_7_la-infd-server-pool.lo -MD -MP -MF server/$(DEPDIR)/libinfinity_0_7_la-infd-server-pool.Tpo -c -o server/libinfinity_0_7_la-infd-server-pool.lo `test -f 'server/infd-server-pool.c' || echo '$(srcdir)/'`server/infd-server-pool.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) server/$(DEPDIR)/libinfinity_0_7_la-infd-server-pool.Tpo server/$(DEPDIR)/libinfinity_0_7_la-infd-server-pool.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='server/infd-server-pool.c' object='server/libinfinity_0_7_la-infd-server-pool.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o server/libinfinity_0_7_la-infd-server-pool.lo `test -f 'server/infd-server-pool.c' || echo '$(srcdir)/'`server/infd-server-pool.c server/libinfinity_0_7_la-infd-session-proxy.lo: server/infd-session-proxy.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT server/libinfinity_0_7_la-infd-session-proxy.lo -MD -MP -MF server/$(DEPDIR)/libinfinity_0_7_la-infd-session-proxy.Tpo -c -o server/libinfinity_0_7_la-infd-session-proxy.lo `test -f 'server/infd-session-proxy.c' || echo '$(srcdir)/'`server/infd-session-proxy.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) server/$(DEPDIR)/libinfinity_0_7_la-infd-session-proxy.Tpo server/$(DEPDIR)/libinfinity_0_7_la-infd-session-proxy.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='server/infd-session-proxy.c' object='server/libinfinity_0_7_la-infd-session-proxy.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o server/libinfinity_0_7_la-infd-session-proxy.lo `test -f 'server/infd-session-proxy.c' || echo '$(srcdir)/'`server/infd-session-proxy.c server/libinfinity_0_7_la-infd-storage.lo: server/infd-storage.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT server/libinfinity_0_7_la-infd-storage.lo -MD -MP -MF server/$(DEPDIR)/libinfinity_0_7_la-infd-storage.Tpo -c -o server/libinfinity_0_7_la-infd-storage.lo `test -f 'server/infd-storage.c' || echo '$(srcdir)/'`server/infd-storage.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) server/$(DEPDIR)/libinfinity_0_7_la-infd-storage.Tpo server/$(DEPDIR)/libinfinity_0_7_la-infd-storage.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='server/infd-storage.c' object='server/libinfinity_0_7_la-infd-storage.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o server/libinfinity_0_7_la-infd-storage.lo `test -f 'server/infd-storage.c' || echo '$(srcdir)/'`server/infd-storage.c server/libinfinity_0_7_la-infd-tcp-server.lo: server/infd-tcp-server.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT server/libinfinity_0_7_la-infd-tcp-server.lo -MD -MP -MF server/$(DEPDIR)/libinfinity_0_7_la-infd-tcp-server.Tpo -c -o server/libinfinity_0_7_la-infd-tcp-server.lo `test -f 'server/infd-tcp-server.c' || echo '$(srcdir)/'`server/infd-tcp-server.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) server/$(DEPDIR)/libinfinity_0_7_la-infd-tcp-server.Tpo server/$(DEPDIR)/libinfinity_0_7_la-infd-tcp-server.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='server/infd-tcp-server.c' object='server/libinfinity_0_7_la-infd-tcp-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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o server/libinfinity_0_7_la-infd-tcp-server.lo `test -f 'server/infd-tcp-server.c' || echo '$(srcdir)/'`server/infd-tcp-server.c server/libinfinity_0_7_la-infd-xml-server.lo: server/infd-xml-server.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT server/libinfinity_0_7_la-infd-xml-server.lo -MD -MP -MF server/$(DEPDIR)/libinfinity_0_7_la-infd-xml-server.Tpo -c -o server/libinfinity_0_7_la-infd-xml-server.lo `test -f 'server/infd-xml-server.c' || echo '$(srcdir)/'`server/infd-xml-server.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) server/$(DEPDIR)/libinfinity_0_7_la-infd-xml-server.Tpo server/$(DEPDIR)/libinfinity_0_7_la-infd-xml-server.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='server/infd-xml-server.c' object='server/libinfinity_0_7_la-infd-xml-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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o server/libinfinity_0_7_la-infd-xml-server.lo `test -f 'server/infd-xml-server.c' || echo '$(srcdir)/'`server/infd-xml-server.c server/libinfinity_0_7_la-infd-xmpp-server.lo: server/infd-xmpp-server.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT server/libinfinity_0_7_la-infd-xmpp-server.lo -MD -MP -MF server/$(DEPDIR)/libinfinity_0_7_la-infd-xmpp-server.Tpo -c -o server/libinfinity_0_7_la-infd-xmpp-server.lo `test -f 'server/infd-xmpp-server.c' || echo '$(srcdir)/'`server/infd-xmpp-server.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) server/$(DEPDIR)/libinfinity_0_7_la-infd-xmpp-server.Tpo server/$(DEPDIR)/libinfinity_0_7_la-infd-xmpp-server.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='server/infd-xmpp-server.c' object='server/libinfinity_0_7_la-infd-xmpp-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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o server/libinfinity_0_7_la-infd-xmpp-server.lo `test -f 'server/infd-xmpp-server.c' || echo '$(srcdir)/'`server/infd-xmpp-server.c libinfinity_0_7_la-inf-dll.lo: inf-dll.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libinfinity_0_7_la-inf-dll.lo -MD -MP -MF $(DEPDIR)/libinfinity_0_7_la-inf-dll.Tpo -c -o libinfinity_0_7_la-inf-dll.lo `test -f 'inf-dll.c' || echo '$(srcdir)/'`inf-dll.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libinfinity_0_7_la-inf-dll.Tpo $(DEPDIR)/libinfinity_0_7_la-inf-dll.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='inf-dll.c' object='libinfinity_0_7_la-inf-dll.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libinfinity_0_7_la-inf-dll.lo `test -f 'inf-dll.c' || echo '$(srcdir)/'`inf-dll.c libinfinity_0_7_la-inf-i18n.lo: inf-i18n.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libinfinity_0_7_la-inf-i18n.lo -MD -MP -MF $(DEPDIR)/libinfinity_0_7_la-inf-i18n.Tpo -c -o libinfinity_0_7_la-inf-i18n.lo `test -f 'inf-i18n.c' || echo '$(srcdir)/'`inf-i18n.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libinfinity_0_7_la-inf-i18n.Tpo $(DEPDIR)/libinfinity_0_7_la-inf-i18n.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='inf-i18n.c' object='libinfinity_0_7_la-inf-i18n.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libinfinity_0_7_la-inf-i18n.lo `test -f 'inf-i18n.c' || echo '$(srcdir)/'`inf-i18n.c libinfinity_0_7_la-inf-signals.lo: inf-signals.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libinfinity_0_7_la-inf-signals.lo -MD -MP -MF $(DEPDIR)/libinfinity_0_7_la-inf-signals.Tpo -c -o libinfinity_0_7_la-inf-signals.lo `test -f 'inf-signals.c' || echo '$(srcdir)/'`inf-signals.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libinfinity_0_7_la-inf-signals.Tpo $(DEPDIR)/libinfinity_0_7_la-inf-signals.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='inf-signals.c' object='libinfinity_0_7_la-inf-signals.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) $(libinfinity_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libinfinity_0_7_la-inf-signals.lo `test -f 'inf-signals.c' || echo '$(srcdir)/'`inf-signals.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs -rm -rf adopted/.libs adopted/_libs -rm -rf client/.libs client/_libs -rm -rf common/.libs common/_libs -rm -rf communication/.libs communication/_libs -rm -rf server/.libs server/_libs install-girDATA: $(gir_DATA) @$(NORMAL_INSTALL) @list='$(gir_DATA)'; test -n "$(girdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(girdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(girdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(girdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(girdir)" || exit $$?; \ done uninstall-girDATA: @$(NORMAL_UNINSTALL) @list='$(gir_DATA)'; test -n "$(girdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(girdir)'; $(am__uninstall_files_from_dir) install-typelibDATA: $(typelib_DATA) @$(NORMAL_INSTALL) @list='$(typelib_DATA)'; test -n "$(typelibdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(typelibdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(typelibdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(typelibdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(typelibdir)" || exit $$?; \ done uninstall-typelibDATA: @$(NORMAL_UNINSTALL) @list='$(typelib_DATA)'; test -n "$(typelibdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(typelibdir)'; $(am__uninstall_files_from_dir) install-adoptedHEADERS: $(adopted_HEADERS) @$(NORMAL_INSTALL) @list='$(adopted_HEADERS)'; test -n "$(adopteddir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(adopteddir)'"; \ $(MKDIR_P) "$(DESTDIR)$(adopteddir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(adopteddir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(adopteddir)" || exit $$?; \ done uninstall-adoptedHEADERS: @$(NORMAL_UNINSTALL) @list='$(adopted_HEADERS)'; test -n "$(adopteddir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(adopteddir)'; $(am__uninstall_files_from_dir) install-clientHEADERS: $(client_HEADERS) @$(NORMAL_INSTALL) @list='$(client_HEADERS)'; test -n "$(clientdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(clientdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(clientdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(clientdir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(clientdir)" || exit $$?; \ done uninstall-clientHEADERS: @$(NORMAL_UNINSTALL) @list='$(client_HEADERS)'; test -n "$(clientdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(clientdir)'; $(am__uninstall_files_from_dir) install-commonHEADERS: $(common_HEADERS) @$(NORMAL_INSTALL) @list='$(common_HEADERS)'; test -n "$(commondir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(commondir)'"; \ $(MKDIR_P) "$(DESTDIR)$(commondir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(commondir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(commondir)" || exit $$?; \ done uninstall-commonHEADERS: @$(NORMAL_UNINSTALL) @list='$(common_HEADERS)'; test -n "$(commondir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(commondir)'; $(am__uninstall_files_from_dir) install-communicationHEADERS: $(communication_HEADERS) @$(NORMAL_INSTALL) @list='$(communication_HEADERS)'; test -n "$(communicationdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(communicationdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(communicationdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(communicationdir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(communicationdir)" || exit $$?; \ done uninstall-communicationHEADERS: @$(NORMAL_UNINSTALL) @list='$(communication_HEADERS)'; test -n "$(communicationdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(communicationdir)'; $(am__uninstall_files_from_dir) install-libinfinity_0_7_laHEADERS: $(libinfinity_0_7_la_HEADERS) @$(NORMAL_INSTALL) @list='$(libinfinity_0_7_la_HEADERS)'; test -n "$(libinfinity_0_7_ladir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libinfinity_0_7_ladir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libinfinity_0_7_ladir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libinfinity_0_7_ladir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(libinfinity_0_7_ladir)" || exit $$?; \ done uninstall-libinfinity_0_7_laHEADERS: @$(NORMAL_UNINSTALL) @list='$(libinfinity_0_7_la_HEADERS)'; test -n "$(libinfinity_0_7_ladir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(libinfinity_0_7_ladir)'; $(am__uninstall_files_from_dir) install-serverHEADERS: $(server_HEADERS) @$(NORMAL_INSTALL) @list='$(server_HEADERS)'; test -n "$(serverdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(serverdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(serverdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(serverdir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(serverdir)" || exit $$?; \ done uninstall-serverHEADERS: @$(NORMAL_UNINSTALL) @list='$(server_HEADERS)'; test -n "$(serverdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(serverdir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ 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-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ 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" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files 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: check-am all-am: Makefile $(LTLIBRARIES) $(DATA) $(HEADERS) inf-config.h installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(girdir)" "$(DESTDIR)$(typelibdir)" "$(DESTDIR)$(adopteddir)" "$(DESTDIR)$(clientdir)" "$(DESTDIR)$(commondir)" "$(DESTDIR)$(communicationdir)" "$(DESTDIR)$(libinfinity_0_7_ladir)" "$(DESTDIR)$(serverdir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: 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) -rm -f adopted/$(DEPDIR)/$(am__dirstamp) -rm -f adopted/$(am__dirstamp) -rm -f client/$(DEPDIR)/$(am__dirstamp) -rm -f client/$(am__dirstamp) -rm -f common/$(DEPDIR)/$(am__dirstamp) -rm -f common/$(am__dirstamp) -rm -f communication/$(DEPDIR)/$(am__dirstamp) -rm -f communication/$(am__dirstamp) -rm -f server/$(DEPDIR)/$(am__dirstamp) -rm -f server/$(am__dirstamp) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." clean: clean-am clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) adopted/$(DEPDIR) client/$(DEPDIR) common/$(DEPDIR) communication/$(DEPDIR) server/$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-hdr distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-adoptedHEADERS install-clientHEADERS \ install-commonHEADERS install-communicationHEADERS \ install-girDATA install-libinfinity_0_7_laHEADERS \ install-serverHEADERS install-typelibDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-libLTLIBRARIES 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) adopted/$(DEPDIR) client/$(DEPDIR) common/$(DEPDIR) communication/$(DEPDIR) server/$(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-adoptedHEADERS uninstall-clientHEADERS \ uninstall-commonHEADERS uninstall-communicationHEADERS \ uninstall-girDATA uninstall-libLTLIBRARIES \ uninstall-libinfinity_0_7_laHEADERS uninstall-serverHEADERS \ uninstall-typelibDATA .MAKE: all install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libLTLIBRARIES clean-libtool cscopelist-am ctags \ ctags-am distclean distclean-compile distclean-generic \ distclean-hdr distclean-libtool distclean-tags distdir dvi \ dvi-am html html-am info info-am install \ install-adoptedHEADERS install-am install-clientHEADERS \ install-commonHEADERS install-communicationHEADERS \ install-data install-data-am install-dvi install-dvi-am \ install-exec install-exec-am install-girDATA install-html \ install-html-am install-info install-info-am \ install-libLTLIBRARIES install-libinfinity_0_7_laHEADERS \ install-man install-pdf install-pdf-am install-ps \ install-ps-am install-serverHEADERS install-strip \ install-typelibDATA installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am tags tags-am uninstall \ uninstall-adoptedHEADERS uninstall-am uninstall-clientHEADERS \ uninstall-commonHEADERS uninstall-communicationHEADERS \ uninstall-girDATA uninstall-libLTLIBRARIES \ uninstall-libinfinity_0_7_laHEADERS uninstall-serverHEADERS \ uninstall-typelibDATA .PRECIOUS: Makefile @HAVE_INTROSPECTION_TRUE@-include $(INTROSPECTION_MAKEFILE) @HAVE_INTROSPECTION_TRUE@Infinity-0.7.gir: libinfinity-0.7.la @HAVE_INTROSPECTION_TRUE@Infinityc-0.7.gir: libinfinity-0.7.la Infinity-0.7.typelib @HAVE_INTROSPECTION_TRUE@Infinityd-0.7.gir: libinfinity-0.7.la Infinity-0.7.typelib # 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: libinfinity-0.7.1/libinfinity/PaxHeaders.26529/inf-config.h.in0000644000000000000000000000013113034342512020714 xustar0030 mtime=1483851082.041718492 30 atime=1483851082.041718492 29 ctime=1488261589.01613903 libinfinity-0.7.1/libinfinity/inf-config.h.in0000644000175000017500000000232713034342512021453 0ustar00arminarmin00000000000000/* infinote - Collaborative notetaking application * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /* Defines representing support for what features has been compiled into * libinfinity. All these defines are prefixed, so it is safe to be installed * and used by other packages. */ /* Whether avahi support is enabled */ #undef LIBINFINITY_HAVE_AVAHI /* Whether libdaemon support is enabled */ #undef LIBINFINITY_HAVE_LIBDAEMON /* Whether pam support is enabled */ #undef LIBINFINITY_HAVE_PAM libinfinity-0.7.1/libinfinity/PaxHeaders.26529/common0000644000000000000000000000013213055210725017336 xustar0030 mtime=1488261589.092138864 30 atime=1488261588.904139275 30 ctime=1488261589.092138864 libinfinity-0.7.1/libinfinity/common/0000755000175000017500000000000013055210725020145 5ustar00arminarmin00000000000000libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-request.c0000644000000000000000000000013213034342512022016 xustar0030 mtime=1483851082.033718448 30 atime=1483851082.033718448 30 ctime=1488261589.072138908 libinfinity-0.7.1/libinfinity/common/inf-request.c0000644000175000017500000001052413034342512022552 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-request * @title: InfRequest * @short_description: Asynchronous request * @include: libinfinity/common/inf-request.h * @stability: Unstable * * #InfRequest represents a potentially asynchronous operation. This is a * basic interface which allows to query the type of the operation and * to be notified when the request finishes. */ #include #include G_DEFINE_INTERFACE(InfRequest, inf_request, G_TYPE_OBJECT) enum { FINISHED, LAST_SIGNAL }; static guint request_signals[LAST_SIGNAL]; static void inf_request_default_init(InfRequestInterface* iface) { g_object_interface_install_property( iface, g_param_spec_string( "type", "Type", "A string identifier for the type of the request", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_interface_install_property( iface, g_param_spec_double( "progress", "Progress", "Percentage of completion of the request", 0.0, 1.0, 0.0, G_PARAM_READABLE ) ); /** * InfRequest::finished: * @request: The #InfRequest which finished. * @result: A #InfRequestResult which contains the result of the request. * @error: Error information in case the request failed, or %NULL * otherwise. * * This signal is emitted when the request finishes. If @error is * non-%NULL the request failed, otherwise it finished successfully. */ request_signals[FINISHED] = g_signal_new( "finished", INF_TYPE_REQUEST, G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfRequestInterface, finished), NULL, NULL, NULL, G_TYPE_NONE, 2, INF_TYPE_REQUEST_RESULT | G_SIGNAL_TYPE_STATIC_SCOPE, G_TYPE_ERROR /* GError* */ ); } /* * Public API */ /** * inf_request_fail: * @request: A #InfRequest. * @error: A #GError describing the reason for why the request failed. * * Declares the request as failed by emitting the #InfRequest::finished * signal with the given error. */ void inf_request_fail(InfRequest* request, const GError* error) { g_return_if_fail(INF_IS_REQUEST(request)); g_return_if_fail(error != NULL); g_signal_emit( request, request_signals[FINISHED], 0, NULL, error ); } /** * inf_request_finish: * @request: A #InfRequest. * @result: (transfer full): A #InfRequestResult containing the result of * the request. * * Declares the request as succeeded by emitting the #InfRequest::finished * signal with the given result. The function takes ownership of @result. */ void inf_request_finish(InfRequest* request, InfRequestResult* result) { g_return_if_fail(INF_IS_REQUEST(request)); g_return_if_fail(result != NULL); g_signal_emit( request, request_signals[FINISHED], 0, result, NULL ); inf_request_result_free(result); } /** * inf_request_is_local: * @request: A #InfRequest. * * Returns whether @request is local or remote. A local request was triggered * by a local API call, whereas a remote request was caused by a remote * participant from the network. * * Returns: %TRUE if the request is local and %FALSE if it is remote. */ gboolean inf_request_is_local(InfRequest* request) { InfRequestInterface* iface; g_return_val_if_fail(INF_IS_REQUEST(request), FALSE); iface = INF_REQUEST_GET_IFACE(request); g_return_val_if_fail(iface->is_local != NULL, FALSE); return iface->is_local(request); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-xmpp-connection.h0000644000000000000000000000013013034342512023452 xustar0029 mtime=1483851082.03771847 29 atime=1483851082.03771847 30 ctime=1488261588.972139127 libinfinity-0.7.1/libinfinity/common/inf-xmpp-connection.h0000644000175000017500000004214513034342512024214 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_XMPP_CONNECTION_H__ #define __INF_XMPP_CONNECTION_H__ #include #include #include #include #include /* Get ssize_t on MSVC, required by gnutls.h */ #include /*#include */ #include G_BEGIN_DECLS #define INF_TYPE_XMPP_CONNECTION (inf_xmpp_connection_get_type()) #define INF_XMPP_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_TYPE_XMPP_CONNECTION, InfXmppConnection)) #define INF_XMPP_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INF_TYPE_XMPP_CONNECTION, InfXmppConnectionClass)) #define INF_IS_XMPP_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_TYPE_XMPP_CONNECTION)) #define INF_IS_XMPP_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INF_TYPE_XMPP_CONNECTION)) #define INF_XMPP_CONNECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INF_TYPE_XMPP_CONNECTION, InfXmppConnectionClass)) #define INF_TYPE_XMPP_CONNECTION_SITE (inf_xmpp_connection_site_get_type()) #define INF_TYPE_XMPP_CONNECTION_SECURITY_POLICY (inf_xmpp_connection_security_policy_get_type()) typedef struct _InfXmppConnection InfXmppConnection; typedef struct _InfXmppConnectionClass InfXmppConnectionClass; /** * InfXmppConnectionSite: * @INF_XMPP_CONNECTION_SERVER: The local site of this connection is an * XMPP server and the remote counterpart is a client. * @INF_XMPP_CONNECTION_CLIENT: The local site of this connection is a * XMPP client and the remote counterpart is a server. * * Specifies whether the local site of the connection is a client or a * server. */ typedef enum _InfXmppConnectionSite { INF_XMPP_CONNECTION_SERVER, INF_XMPP_CONNECTION_CLIENT } InfXmppConnectionSite; /** * InfXmppConnectionSecurityPolicy: * @INF_XMPP_CONNECTION_SECURITY_ONLY_UNSECURED: In the case of a server, do * not offer TLS to the client. As a client, only connect if the server does * not require TLS. * @INF_XMPP_CONNECTION_SECURITY_ONLY_TLS: In the case of a server, require * all connections to be TLS-secured. As a client, only connect if the server * supports TLS. * @INF_XMPP_CONNECTION_SECURITY_BOTH_PREFER_UNSECURED: In the case of a * server, offer both unsecured and secured messaging to the client. As a * client, use unsecured communication unless TLS is required by the server. * @INF_XMPP_CONNECTION_SECURITY_BOTH_PREFER_TLS: In the case of a server, * offer both unsecured and secured messaging to the client. As a client, * use TLS unless not supported by the server. * * The #InfXmppConnectionSecurityPolicy enumeration specifies various options * of how to deal with the other site allowing or requiring TLS-secured * connections. Note that if the local site is a server, then * @INF_XMPP_CONNECTION_SECURITY_BOTH_PREFER_UNSECURED and * @INF_XMPP_CONNECTION_SECURITY_BOTH_PREFER_TLS are equivalent. */ typedef enum _InfXmppConnectionSecurityPolicy { INF_XMPP_CONNECTION_SECURITY_ONLY_UNSECURED, INF_XMPP_CONNECTION_SECURITY_ONLY_TLS, INF_XMPP_CONNECTION_SECURITY_BOTH_PREFER_UNSECURED, INF_XMPP_CONNECTION_SECURITY_BOTH_PREFER_TLS } InfXmppConnectionSecurityPolicy; /** * InfXmppConnectionError: * @INF_XMPP_CONNECTION_ERROR_TLS_UNSUPPORTED: Server does not support TLS, * but the security policy is set to %INF_XMPP_CONNECTION_SECURITY_ONLY_TLS. * @INF_XMPP_CONNECTION_ERROR_TLS_REQUIRED: The server requires TLS, but the * security policy is set to %INF_XMPP_CONNECTION_SECURITY_ONLY_UNSECURED. * @INF_XMPP_CONNECTION_ERROR_TLS_FAILURE: Server cannot proceed with the TLS * handshake. * @INF_XMPP_CONNECTION_ERROR_NO_CERTIFICATE_PROVIDED: The server did not * provide a certificate. * @INF_XMPP_CONNECTION_ERROR_CERTIFICATE_NOT_TRUSTED: The server certificate * is not trusted. Whether the server certificate is trusted or not is defined * by the API user, by providing a certificate callback with * inf_xmpp_connection_set_certificate_callback(). * @INF_XMPP_CONNECTION_ERROR_AUTHENTICATION_UNSUPPORTED: The server does not * provide any authentication mechanisms. * @INF_XMPP_CONNECTION_ERROR_NO_SUITABLE_MECHANISM: The server does not offer * a suitable authentication mechanism that is accepted by the client. * @INF_XMPP_CONNECTION_ERROR_FAILED: General error code for otherwise * unknown errors. * * Specifies the error codes in the * INF_XMPP_CONNECTION_ERROR error domain. */ typedef enum _InfXmppConnectionError { INF_XMPP_CONNECTION_ERROR_TLS_UNSUPPORTED, INF_XMPP_CONNECTION_ERROR_TLS_REQUIRED, INF_XMPP_CONNECTION_ERROR_TLS_FAILURE, INF_XMPP_CONNECTION_ERROR_NO_CERTIFICATE_PROVIDED, INF_XMPP_CONNECTION_ERROR_CERTIFICATE_NOT_TRUSTED, INF_XMPP_CONNECTION_ERROR_AUTHENTICATION_UNSUPPORTED, INF_XMPP_CONNECTION_ERROR_NO_SUITABLE_MECHANISM, INF_XMPP_CONNECTION_ERROR_FAILED } InfXmppConnectionError; /** * InfXmppConnectionStreamError: * @INF_XMPP_CONNECTION_STREAM_ERROR_BAD_FORMAT: The entity has sent XML that * cannot be processed. * @INF_XMPP_CONNECTION_STREAM_ERROR_BAD_NAMESPACE_PREFIX: The entity has sent * a namespace prefix that is unsupported, or has sent no namespace prefix on * an element that requires such a prefix. * @INF_XMPP_CONNECTION_STREAM_ERROR_CONFLICT: The server is closing the * active stream for this entity because a new stream has been initiated * that conflicts with the existing stream. * @INF_XMPP_CONNECTION_STREAM_ERROR_CONNECTION_TIMEOUT: The entity has not * generated any traffic over the stream for some period of time. * @INF_XMPP_CONNECTION_STREAM_ERROR_HOST_GONE: The value of the 'to' * attribute provided by the initiating entity in the stream header * corresponds to a hostname that is no longer hosted by the server. * @INF_XMPP_CONNECTION_STREAM_ERROR_HOST_UNKNOWN: The value of the 'to' * attribute provided by the initiating entity in the stream header does * not correspond to a hostname that is hosted by the server. * @INF_XMPP_CONNECTION_STREAM_ERROR_IMPROPER_ADDRESSING: A stanza sent * between two servers lacks a 'to' or 'from' attribute. * @INF_XMPP_CONNECTION_STREAM_ERROR_INTERNAL_SERVER_ERROR: The server has * experienced a misconfiguration or an otherwise-undefined internal error * that prevents it from servicing the stream. * @INF_XMPP_CONNECTION_STREAM_ERROR_INVALID_FROM: The JID or hostname * provided in a 'from' address does not match an authorized JID or * validated domain negotiated between servers via SASL or dialback, or * between a client and a server via authentication and resource binding. * @INF_XMPP_CONNECTION_STREAM_ERROR_INVALID_ID: The stream ID or dialback * ID is invalid or does not match an ID previously provided. * @INF_XMPP_CONNECTION_STREAM_ERROR_INVALID_NAMESPACE: The streams namespace * is something other than http://etherx.jabber.org/streams * or the dialback namespace name is something other than * jabber:server:dialback. * @INF_XMPP_CONNECTION_STREAM_ERROR_INVALID_XML: The entity has sent invalid * XML over the stream to a server that performs validation. * @INF_XMPP_CONNECTION_STREAM_ERROR_NOT_AUTHORIZED: The entity has attempted * to send data before the stream has been authenticated, or otherwise is not * authorized to perform an action related to stream negotiation. * @INF_XMPP_CONNECTION_STREAM_ERROR_POLICY_VIOLATION: The entity has violated * some local service policy. * @INF_XMPP_CONNECTION_STREAM_ERROR_REMOTE_CONNECTION_FAILED: The server is * unable to properly connect to a remote entity that is required for * authentication or authorization. * @INF_XMPP_CONNECTION_STREAM_ERROR_RESOURCE_CONSTRAINT: The server lacks the * system resources necessary to service the stream. * @INF_XMPP_CONNECTION_STREAM_ERROR_RESTRICTED_XML: The entity has attempted * to send restricted XML features. * @INF_XMPP_CONNECTION_STREAM_ERROR_SEE_OTHER_HOST: The server will not * provide service to the initiating entity but is redirecting traffic * to another host. * @INF_XMPP_CONNECTION_STREAM_ERROR_SYSTEM_SHUTDOWN: The server is being * shut down and all active streams are being closed. * @INF_XMPP_CONNECTION_STREAM_ERROR_UNDEFINED_CONDITION: The error condition * is not one of those defined by the other conditions. * @INF_XMPP_CONNECTION_STREAM_ERROR_UNSUPPORTED_ENCODING: The initiating * entity has encoded the stream in an encoding that is not supported by * the server. * @INF_XMPP_CONNECTION_STREAM_ERROR_UNSUPPORTED_STANZA_TYPE: The initiating * entity has sent a first-level child of the stream that is not supported * by the server. * @INF_XMPP_CONNECTION_STREAM_ERROR_UNSUPPORTED_VERSION: The value of the * 'version' attribute provided by the initiating entity in the stream header * specifies a version of XMPP that is not supported by the server. * @INF_XMPP_CONNECTION_STREAM_ERROR_XML_NOT_WELL_FORMED: The initiating * entity has sent XML that is not well-formed. * @INF_XMPP_CONNECTION_STREAM_ERROR_FAILED: General error code for otherwise * unknown errors. * * Specifies the error codes in the * INF_XMPP_CONNECTION_STREAM_ERROR error domain. These * errors correspond to the ones defined in RFC 3920, section 4.7.3. */ typedef enum _InfXmppConnectionStreamError { INF_XMPP_CONNECTION_STREAM_ERROR_BAD_FORMAT, INF_XMPP_CONNECTION_STREAM_ERROR_BAD_NAMESPACE_PREFIX, INF_XMPP_CONNECTION_STREAM_ERROR_CONFLICT, INF_XMPP_CONNECTION_STREAM_ERROR_CONNECTION_TIMEOUT, INF_XMPP_CONNECTION_STREAM_ERROR_HOST_GONE, INF_XMPP_CONNECTION_STREAM_ERROR_HOST_UNKNOWN, INF_XMPP_CONNECTION_STREAM_ERROR_IMPROPER_ADDRESSING, INF_XMPP_CONNECTION_STREAM_ERROR_INTERNAL_SERVER_ERROR, INF_XMPP_CONNECTION_STREAM_ERROR_INVALID_FROM, INF_XMPP_CONNECTION_STREAM_ERROR_INVALID_ID, INF_XMPP_CONNECTION_STREAM_ERROR_INVALID_NAMESPACE, INF_XMPP_CONNECTION_STREAM_ERROR_INVALID_XML, INF_XMPP_CONNECTION_STREAM_ERROR_NOT_AUTHORIZED, INF_XMPP_CONNECTION_STREAM_ERROR_POLICY_VIOLATION, INF_XMPP_CONNECTION_STREAM_ERROR_REMOTE_CONNECTION_FAILED, INF_XMPP_CONNECTION_STREAM_ERROR_RESOURCE_CONSTRAINT, INF_XMPP_CONNECTION_STREAM_ERROR_RESTRICTED_XML, INF_XMPP_CONNECTION_STREAM_ERROR_SEE_OTHER_HOST, INF_XMPP_CONNECTION_STREAM_ERROR_SYSTEM_SHUTDOWN, INF_XMPP_CONNECTION_STREAM_ERROR_UNDEFINED_CONDITION, INF_XMPP_CONNECTION_STREAM_ERROR_UNSUPPORTED_ENCODING, INF_XMPP_CONNECTION_STREAM_ERROR_UNSUPPORTED_STANZA_TYPE, INF_XMPP_CONNECTION_STREAM_ERROR_UNSUPPORTED_VERSION, INF_XMPP_CONNECTION_STREAM_ERROR_XML_NOT_WELL_FORMED, INF_XMPP_CONNECTION_STREAM_ERROR_FAILED } InfXmppConnectionStreamError; /** * InfXmppConnectionAuthError: * @INF_XMPP_CONNECTION_AUTH_ERROR_ABORTED: The receiving entity acknowledged * an <abort/> element sent by the initiating entity. * @INF_XMPP_CONNECTION_AUTH_ERROR_INCORRECT_ENCODING: The data provided by * the initiating entity could not be processed because the Base64 encoding * is incorrect. * @INF_XMPP_CONNECTION_AUTH_ERROR_INVALID_AUTHZID: The authzid provided by * the initiating entity is invalid, either because it is incorrectly * formatted or because the initiating entity does not have permissions * to authorize that ID. * @INF_XMPP_CONNECTION_AUTH_ERROR_INVALID_MECHANISM: The initiating entity * did not provide a mechanism or requested a mechanism that is not supported * by the receiving entity. * @INF_XMPP_CONNECTION_AUTH_ERROR_MECHANISM_TOO_WEAK: The mechanism requsted * by the initiating entity is weaker than server policy permits for that * initiating entity. * @INF_XMPP_CONNECTION_AUTH_ERROR_NOT_AUTHORIZED: The authentication failed * because the initiating entity did not provide valid credentials. * @INF_XMPP_CONNECTION_AUTH_ERROR_TEMPORARY_AUTH_FAILURE: The authentication * failed because of a temporary error condition within the receiving entity. * @INF_XMPP_CONNECTION_AUTH_ERROR_FAILED: General error code for otherwise * unknown errors. * * Specifies the error codes in the * INF_XMPP_CONNECTION_AUTH_ERROR error domain. These * errors correspond to the ones defined in RFC 3920, section 6.4. */ typedef enum _InfXmppConnectionAuthError { INF_XMPP_CONNECTION_AUTH_ERROR_ABORTED, INF_XMPP_CONNECTION_AUTH_ERROR_INCORRECT_ENCODING, INF_XMPP_CONNECTION_AUTH_ERROR_INVALID_AUTHZID, INF_XMPP_CONNECTION_AUTH_ERROR_INVALID_MECHANISM, INF_XMPP_CONNECTION_AUTH_ERROR_MECHANISM_TOO_WEAK, INF_XMPP_CONNECTION_AUTH_ERROR_NOT_AUTHORIZED, INF_XMPP_CONNECTION_AUTH_ERROR_TEMPORARY_AUTH_FAILURE, INF_XMPP_CONNECTION_AUTH_ERROR_FAILED } InfXmppConnectionAuthError; /** * InfXmppConnectionClass: * * This structure does not contain any public fields. */ struct _InfXmppConnectionClass { /*< private >*/ GObjectClass parent_class; }; /** * InfXmppConnection: * * #InfXmppConnection is an opaque data type. You should only access it via * the public API functions. */ struct _InfXmppConnection { /*< private >*/ GObject parent; }; /** * InfXmppConnectionCrtCallback: * @xmpp: The #InfXmppConnection validating a certificate. * @session: The underlying GnuTLS session. * @chain: The certificate chain presented by the remote host. * @user_data: Additional data supplied when * inf_xmpp_connection_set_certificate_callback() was called. * * Specifies the callback signature for the certificate callback set with * inf_xmpp_connection_set_certificate_callback(). The callback should decide * whether to trust the certificate in @chain or not. */ typedef void(*InfXmppConnectionCrtCallback)(InfXmppConnection* xmpp, gnutls_session_t session, InfCertificateChain* chain, gpointer user_data); GType inf_xmpp_connection_security_policy_get_type(void) G_GNUC_CONST; GType inf_xmpp_connection_site_get_type(void) G_GNUC_CONST; GType inf_xmpp_connection_get_type(void) G_GNUC_CONST; GQuark inf_xmpp_connection_error_quark(void); InfXmppConnection* inf_xmpp_connection_new(InfTcpConnection* tcp, InfXmppConnectionSite site, const gchar* local_hostname, const gchar* remote_hostname, InfXmppConnectionSecurityPolicy security_policy, InfCertificateCredentials* creds, InfSaslContext* sasl_context, const gchar* sasl_mechanisms); gboolean inf_xmpp_connection_get_tls_enabled(InfXmppConnection* xmpp); gnutls_x509_crt_t inf_xmpp_connection_get_own_certificate(InfXmppConnection* xmpp); InfCertificateChain* inf_xmpp_connection_get_peer_certificate(InfXmppConnection* xmpp); gnutls_kx_algorithm_t inf_xmpp_connection_get_kx_algorithm(InfXmppConnection* xmpp); gnutls_cipher_algorithm_t inf_xmpp_connection_get_cipher_algorithm(InfXmppConnection* xmpp); gnutls_mac_algorithm_t inf_xmpp_connection_get_mac_algorithm(InfXmppConnection* xmpp); gnutls_protocol_t inf_xmpp_connection_get_tls_protocol(InfXmppConnection* xmpp); guint inf_xmpp_connection_get_dh_prime_bits(InfXmppConnection* xmpp); void inf_xmpp_connection_set_certificate_callback(InfXmppConnection* xmpp, gnutls_certificate_request_t req, InfXmppConnectionCrtCallback cb, gpointer user_data, GDestroyNotify notify); void inf_xmpp_connection_certificate_verify_continue(InfXmppConnection* xmpp); void inf_xmpp_connection_certificate_verify_cancel(InfXmppConnection* xmpp, const GError* error); void inf_xmpp_connection_reset_sasl_authentication(InfXmppConnection* xmpp, InfSaslContext* new_context, const gchar* new_mechanisms); gboolean inf_xmpp_connection_retry_sasl_authentication(InfXmppConnection* xmpp, GError** error); void inf_xmpp_connection_set_sasl_error(InfXmppConnection* xmpp, const GError* error); const GError* inf_xmpp_connection_get_sasl_error(InfXmppConnection* xmpp); G_END_DECLS #endif /* __INF_XMPP_CONNECTION_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-session-proxy.c0000644000000000000000000000013113034342512023167 xustar0030 mtime=1483851082.033718448 30 atime=1483851082.033718448 29 ctime=1488261589.08013889 libinfinity-0.7.1/libinfinity/common/inf-session-proxy.c0000644000175000017500000000754713034342512023737 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-session-proxy * @title: InfSessionProxy * @short_description: Joining users into a session * @include: libinfinity/common/inf-session_proxy.h * @see_also: #InfSession, #InfBrowser, #InfcSessionProxy, #InfdSessionProxy * @stability: Unstable * * A #InfSessionProxy is a network-architecture-aware layer on top of a * #InfSession. A #InfSession has no idea about what kind of network it is in, * all it has is a possibility to send messages to one user or to all users. * * A #InfSessionProxy implements the part of the infinote protocol which * depends on whether the session is at an infinote server or an infinote * client. This interface provides a method to join a user into a session so * that it does not need to be known to the caller whether the session at * hand is on a server or a client. */ #include #include G_DEFINE_INTERFACE(InfSessionProxy, inf_session_proxy, G_TYPE_OBJECT) static void inf_session_proxy_default_init(InfSessionProxyInterface* iface) { g_object_interface_install_property( iface, g_param_spec_object( "session", "Session", "The underlying session object", INF_TYPE_SESSION, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); } /** * inf_session_proxy_join_user: * @proxy: A #InfSessionProxy. * @n_params: Number of parameters. * @params: (array length=n_params): Construction properties for the * #InfUser (or derived) object. * @func: (scope async): Function to be called on completion of the user * join, or %NULL. * @user_data: Additional data to be passed to @func. * * Requests a user join for a user with the given properties (which must not * include #InfUser:id or #InfUser:flags since these are chosen by the session * proxy). The #InfUser:status property is optional and defaults to * %INF_USER_ACTIVE if not given. It must not be %INF_USER_UNAVAILABLE. * * The request might either finish during the call to this function, in which * case @func will be called and %NULL being returned. If the request does not * finish within the function call, a #InfRequest object is returned, * where @func has been installed for the #InfRequest::finished signal, * so that it is called as soon as the request finishes. * * Returns: (transfer none): A #InfRequest object that may be used to get * notified when the request finishes, or %NULL. */ InfRequest* inf_session_proxy_join_user(InfSessionProxy* proxy, guint n_params, const GParameter* params, InfRequestFunc func, gpointer user_data) { InfSessionProxyInterface* iface; g_return_val_if_fail(INF_IS_SESSION_PROXY(proxy), NULL); g_return_val_if_fail(n_params == 0 || params != NULL, NULL); iface = INF_SESSION_PROXY_GET_IFACE(proxy); g_return_val_if_fail(iface->join_user != NULL, NULL); return iface->join_user(proxy, n_params, params, func, user_data); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-xml-util.c0000644000000000000000000000013013034342512022077 xustar0029 mtime=1483851082.03771847 29 atime=1483851082.03771847 30 ctime=1488261589.088138873 libinfinity-0.7.1/libinfinity/common/inf-xml-util.c0000644000175000017500000006616713034342512022653 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-xml-util * @title: XML utility functions * @short_description: Helper functions to read basic data types from XML * @include: libinfinity/common/inf-xml-util.h * @stability: Unstable * * In the infinote protocol XML attributes are often required to contain * numbers. These function provide some convenience to set and retrieve them. * They are mostly used in libinfinity itself but can also be useful when * implementing new session types so they are public API. **/ #include #include #include #include #include #include /* HUGE_VAL */ #include static gboolean inf_xml_util_string_to_long(const gchar* attribute, const xmlChar* value, glong* output, GError** error) { long converted; char* endptr; errno = 0; converted = strtol((const char*)value, &endptr, 0); if(*value == '\0' || *endptr != '\0') { g_set_error( error, inf_request_error_quark(), INF_REQUEST_ERROR_INVALID_NUMBER, _("Attribute '%s' does not contain a valid number"), attribute ); return FALSE; } else if( (errno == ERANGE && converted == LONG_MAX)) { g_set_error( error, inf_request_error_quark(), INF_REQUEST_ERROR_INVALID_NUMBER, _("Attribute '%s' causes overflow (%s)"), attribute, (const gchar*)value ); return FALSE; } else if( (errno == ERANGE && converted == LONG_MIN)) { g_set_error( error, inf_request_error_quark(), INF_REQUEST_ERROR_INVALID_NUMBER, _("Attribute '%s' causes underflow (%s)"), attribute, (const gchar*)value ); return FALSE; } else { *output = converted; return TRUE; } } static gboolean inf_xml_util_string_to_ulong(const gchar* attribute, const xmlChar* value, gulong* output, GError** error) { unsigned long converted; char* endptr; errno = 0; converted = strtoul((const char*)value, &endptr, 0); if(*value == '\0' || *endptr != '\0') { g_set_error( error, inf_request_error_quark(), INF_REQUEST_ERROR_INVALID_NUMBER, _("Attribute '%s' does not contain a valid number"), attribute ); return FALSE; } else if(errno == ERANGE) { g_set_error( error, inf_request_error_quark(), INF_REQUEST_ERROR_INVALID_NUMBER, _("Attribute '%s' causes overflow (%s)"), attribute, (const gchar*)value ); return FALSE; } else { *output = converted; return TRUE; } } static gboolean inf_xml_util_string_to_int(const gchar* attribute, const xmlChar* value, gint* output, GError** error) { glong converted; if(!inf_xml_util_string_to_long(attribute, value, &converted, error)) return FALSE; if(converted > (long)G_MAXINT) { g_set_error( error, inf_request_error_quark(), INF_REQUEST_ERROR_INVALID_NUMBER, _("Attribute '%s' causes overflow (%s)"), attribute, (const gchar*)value ); return FALSE; } else if(converted < (long)G_MININT) { g_set_error( error, inf_request_error_quark(), INF_REQUEST_ERROR_INVALID_NUMBER, _("Attribute '%s' causes underflow (%s)"), attribute, (const gchar*)value ); return FALSE; } else { *output = (gint)converted; return TRUE; } } static gboolean inf_xml_util_string_to_uint(const gchar* attribute, const xmlChar* value, guint* output, GError** error) { unsigned long converted; if(!inf_xml_util_string_to_ulong(attribute, value, &converted, error)) return FALSE; if(converted > (unsigned long)G_MAXUINT) { g_set_error( error, inf_request_error_quark(), INF_REQUEST_ERROR_INVALID_NUMBER, _("Attribute '%s' causes overflow (%s)"), attribute, (const gchar*)value ); return FALSE; } else { *output = (guint)converted; return TRUE; } } static gboolean inf_xml_util_string_to_double(const gchar* attribute, const xmlChar* value, gdouble* output, GError** error) { double converted; char* endptr; errno = 0; converted = g_ascii_strtod((const char*)value, &endptr); if(*value == '\0' || *endptr != '\0') { g_set_error( error, inf_request_error_quark(), INF_REQUEST_ERROR_INVALID_NUMBER, _("Attribute '%s' does not contain a valid number"), attribute ); return FALSE; } else if(errno == ERANGE && (converted == HUGE_VAL || converted == -HUGE_VAL)) { g_set_error( error, inf_request_error_quark(), INF_REQUEST_ERROR_INVALID_NUMBER, _("Attribute '%s' causes overflow (%s)"), attribute, (const gchar*)value ); return FALSE; } else if(errno == ERANGE && converted == 0.0) { g_set_error( error, inf_request_error_quark(), INF_REQUEST_ERROR_INVALID_NUMBER, _("Attribute '%s' causes underflow (%s)"), attribute, (const gchar*)value ); return FALSE; } else { *output = converted; return TRUE; } } static gboolean inf_xml_util_valid_xml_char(gunichar codepoint) { /* cf. http://www.w3.org/TR/REC-xml/#dt-text */ return (codepoint >= 0x00020 && codepoint <= 0x00d7ff) /* probably most common */ || codepoint == 0xd || codepoint == 0xa || codepoint == 0x9 || (codepoint >= 0x0e000 && codepoint <= 0x00fffd) || (codepoint >= 0x10000 && codepoint <= 0x10ffff); } /* like the g_utf8_next_char macro, but without the cast to char* at the end */ #define inf_utf8_next_char(p) ((p) + g_utf8_skip[*(const guchar *)(p)]) /** * inf_xml_util_add_child_text: * @xml: A #xmlNodePtr. * @text: (array length=bytes): The child text to add. * @bytes: The number of bytes of @text. * * Adds the given text as child text to @xml in the same way * xmlNodeAddContentLen() would do. The difference is that @text is allowed * to contain characters that are not valid in * XML text, such * as formfeed characters \f. In case one occurs in @text, the function adds * an <uchar /> element node instead to @xml as specified in the * infinote protocol. */ void inf_xml_util_add_child_text(xmlNodePtr xml, const gchar* text, gsize bytes) { const gchar* p; const gchar* next; gchar* node_value; xmlNodePtr child_node; gunichar ch; gsize i; for(i = 0, p = text; i < bytes; i += next - p, p = next) { next = inf_utf8_next_char(p); ch = g_utf8_get_char(p); if(!inf_xml_util_valid_xml_char(ch)) { xmlNodeAddContentLen(xml, (const xmlChar*) text, p - text); child_node = xmlNewNode(NULL, (const xmlChar*)"uchar"); node_value = g_strdup_printf("%"G_GUINT32_FORMAT, ch); xmlNewProp(child_node, (const xmlChar*) "codepoint", (const xmlChar*) node_value); g_free(node_value); xmlAddChild(xml, child_node); text = next; } } if(p != text) xmlNodeAddContentLen(xml, (const xmlChar*) text, p - text); } /** * inf_xml_util_get_child_text: * @xml: A #xmlNodePtr * @bytes: (out) (allow-none): Location to store number of bytes of child * text, or %NULL. * @chars: (out) (allow-none): Location to store number of characters of child * text, or %NULL. * @error: Locatian to store error information, if any, or %NULL. * * Reads a node's child text. If there are <uchar /> child elements, as * added by inf_xml_util_add_child_text() this function will convert them * back to character codes. There should not be any other child elements in * @xml. * * Returns: (array length=bytes) (transfer full): The node's child text, or %NULL on * error. Free with g_free() when no longer needed. */ gchar* inf_xml_util_get_child_text(xmlNodePtr xml, gsize* bytes, guint* chars, GError** error) { xmlNodePtr child; /* Every keypress will have to be get_child_text'ed, so * we assume that most child texts are very short. */ GString* result = g_string_sized_new(16); guint num_codepoint; gsize char_count = 0; for(child = xml->children; child; child = child->next) { switch(child->type) { case XML_TEXT_NODE: g_string_append(result, (const gchar*)child->content); char_count += g_utf8_strlen((const gchar*)child->content, -1); break; case XML_ELEMENT_NODE: if(strcmp((const char*) child->name, "uchar") != 0) { g_warning("unexpected child element in child text: %s", child->name); break; } if(!inf_xml_util_get_attribute_uint_required(child, "codepoint", &num_codepoint, error)) { g_string_free(result, TRUE); return NULL; } g_string_append_unichar(result, (gunichar) num_codepoint); ++char_count; break; default: g_warning( "unexpected node type in child text: %d", (int) child->type); break; } } if(chars) *chars = char_count; if(bytes) *bytes = result->len; return g_string_free(result, FALSE); } /** * inf_xml_util_get_attribute: * @xml: A #xmlNodePtr. * @attribute: The name of the attribute to query. * * Returns the value of the attribute called @attribute in the XML element * @xml. This function is a thin wrapper around xmlGetProp() which exists * mostly for consistency, and for not having to cast the @attribute argument * from char* to xmlChar*. The return value is a xmlChar*, though. * * Returns: (transfer full): The value of the attribute, or %NULL. Free with * xmlFree() when no longer needed. */ xmlChar* inf_xml_util_get_attribute(xmlNodePtr xml, const gchar* attribute) { return xmlGetProp(xml, (const xmlChar*)attribute); } /** * inf_xml_util_get_attribute_required: * @xml: A #xmlNodePtr. * @attribute: The name of the attribute to query. * @error: Location to store error information, if any. * * Returns the value of the attribute called @attribute in the XML element * @xml. If there is no such attribute then the function returns %NULL and * @error is set. * * Returns: (transfer full): The attribute's value, or %NULL on error. * Free with xmlFree() when no longer needed. */ xmlChar* inf_xml_util_get_attribute_required(xmlNodePtr xml, const gchar* attribute, GError** error) { xmlChar* value; value = xmlGetProp(xml, (const xmlChar*)attribute); if(value == NULL) { g_set_error( error, inf_request_error_quark(), INF_REQUEST_ERROR_NO_SUCH_ATTRIBUTE, _("Request '%s' does not contain required attribute '%s'"), (const gchar*)xml->name, attribute ); } return value; } /** * inf_xml_util_get_attribute_int: * @xml: A #xmlNodePtr. * @attribute: The name of the attribute to query. * @result: (out): Location to store the read value. * @error: Location to store error information, if any. * * Reads the attribute named @attribute from the XML element @xml. The * attribute value is expected to be a signed integral number. If it is the * function converts the text to an integer and stores the result into * @result. In this case, %TRUE is returned and @error is left untouched. * * If the value is not a signed integral number, then the function returns * %FALSE, @error is set and @result is left untouched. * * If the attribute does not exist the function returns %FALSE but @error is * not set. * * Returns: Whether @result was set. */ gboolean inf_xml_util_get_attribute_int(xmlNodePtr xml, const gchar* attribute, gint* result, GError** error) { xmlChar* value; gboolean retval; value = xmlGetProp(xml, (const xmlChar*)attribute); if(value == NULL) return FALSE; retval = inf_xml_util_string_to_int(attribute, value, result, error); xmlFree(value); return retval; } /** * inf_xml_util_get_attribute_int_required: * @xml: A #xmlNodePtr. * @attribute: The name of the attribute to query. * @result: (out): Location to store the read value. * @error: Location to store error information, if any. * * Reads the attribute named @attribute from the XML element @xml. The * attribute value is expected to be a signed integral number. If it is the * function converts the text to an integere and stores the result into * @result. In this case, %TRUE is returned and @error is left untouched. * * If the value is not a signed integral number or the attribute does not * exist, then the function returns %FALSE, @error is set and @result is * left untouched. * * Returns: Whether @result was set. */ gboolean inf_xml_util_get_attribute_int_required(xmlNodePtr xml, const gchar* attribute, gint* result, GError** error) { xmlChar* value; gboolean retval; value = inf_xml_util_get_attribute_required(xml, attribute, error); if(value == NULL) return FALSE; retval = inf_xml_util_string_to_int(attribute, value, result, error); xmlFree(value); return retval; } /** * inf_xml_util_get_attribute_long: * @xml: A #xmlNodePtr. * @attribute: The name of the attribute to query. * @result: (out): Location to store the read value. * @error: Location to store error information, if any. * * Behaves exactly like inf_xml_util_get_attribute_int(). The only difference * is that the function reads a signed long integral number. * * Returns: Whether @result was set. */ gboolean inf_xml_util_get_attribute_long(xmlNodePtr xml, const gchar* attribute, glong* result, GError** error) { xmlChar* value; gboolean retval; value = xmlGetProp(xml, (const xmlChar*)attribute); if(value == NULL) return FALSE; retval = inf_xml_util_string_to_long(attribute, value, result, error); xmlFree(value); return retval; } /** * inf_xml_util_get_attribute_long_required: * @xml: A #xmlNodePtr. * @attribute: The name of the attribute to query. * @result: (out): Location to store the read value. * @error: Location to store error information, if any. * * Behaves exactly like inf_xml_util_get_attribute_int_required(). The only * difference is that the function reads a signed long integral number. * * Returns: Whether @result was set. */ gboolean inf_xml_util_get_attribute_long_required(xmlNodePtr xml, const gchar* attribute, glong* result, GError** error) { xmlChar* value; gboolean retval; value = inf_xml_util_get_attribute_required(xml, attribute, error); if(value == NULL) return FALSE; retval = inf_xml_util_string_to_long(attribute, value, result, error); xmlFree(value); return retval; } /** * inf_xml_util_get_attribute_uint: * @xml: A #xmlNodePtr. * @attribute: The name of the attribute to query. * @result: (out): Location to store the read value. * @error: Location to store error information, if any. * * Behaves exactly like inf_xml_util_get_attribute_int(). The only difference * is that the function reads an unsigned integral number. * * Returns: Whether @result was set. */ gboolean inf_xml_util_get_attribute_uint(xmlNodePtr xml, const gchar* attribute, guint* result, GError** error) { xmlChar* value; gboolean retval; value = xmlGetProp(xml, (const xmlChar*)attribute); if(value == NULL) return FALSE; retval = inf_xml_util_string_to_uint(attribute, value, result, error); xmlFree(value); return retval; } /** * inf_xml_util_get_attribute_uint_required: * @xml: A #xmlNodePtr. * @attribute: The name of the attribute to query. * @result: (out): Location to store the read value. * @error: Location to store error information, if any. * * Behaves exactly like inf_xml_util_get_attribute_int_required(). The only * difference is that the function reads an unsigned integral number. * * Returns: Whether @result was set. */ gboolean inf_xml_util_get_attribute_uint_required(xmlNodePtr xml, const gchar* attribute, guint* result, GError** error) { xmlChar* value; gboolean retval; value = inf_xml_util_get_attribute_required(xml, attribute, error); if(value == NULL) return FALSE; retval = inf_xml_util_string_to_uint(attribute, value, result, error); xmlFree(value); return retval; } /** * inf_xml_util_get_attribute_ulong: * @xml: A #xmlNodePtr. * @attribute: The name of the attribute to query. * @result: (out): Location to store the read value. * @error: Location to store error information, if any. * * Behaves exactly like inf_xml_util_get_attribute_int(). The only difference * is that the function reads an unsigned long integral number. * * Returns: Whether @result was set. */ gboolean inf_xml_util_get_attribute_ulong(xmlNodePtr xml, const gchar* attribute, gulong* result, GError** error) { xmlChar* value; gboolean retval; value = xmlGetProp(xml, (const xmlChar*)attribute); if(value == NULL) return FALSE; retval = inf_xml_util_string_to_ulong(attribute, value, result, error); xmlFree(value); return retval; } /** * inf_xml_util_get_attribute_ulong_required: * @xml: A #xmlNodePtr. * @attribute: The name of the attribute to query. * @result: (out): Location to store the read value. * @error: Location to store error information, if any. * * Behaves exactly like inf_xml_util_get_attribute_int_required(). The only * difference is that the function reads an unsigned long integral number. * * Returns: Whether @result was set. */ gboolean inf_xml_util_get_attribute_ulong_required(xmlNodePtr xml, const gchar* attribute, gulong* result, GError** error) { xmlChar* value; gboolean retval; value = inf_xml_util_get_attribute_required(xml, attribute, error); if(value == NULL) return FALSE; retval = inf_xml_util_string_to_ulong(attribute, value, result, error); xmlFree(value); return retval; } /** * inf_xml_util_get_attribute_double: * @xml: A #xmlNodePtr. * @attribute: The name of the attribute to query. * @result: (out): Location to store the read value. * @error: Location to store error information, if any. * * Behaves exactly like inf_xml_util_get_attribute_int(). The only difference * is that the function reads a double-precision floating point number. * * Returns: Whether @result was set. */ gboolean inf_xml_util_get_attribute_double(xmlNodePtr xml, const gchar* attribute, gdouble* result, GError** error) { xmlChar* value; gboolean retval; value = xmlGetProp(xml, (const xmlChar*)attribute); if(value == NULL) return FALSE; retval = inf_xml_util_string_to_double(attribute, value, result, error); xmlFree(value); return retval; } /** * inf_xml_util_get_attribute_double_required: * @xml: A #xmlNodePtr. * @attribute: The name of the attribute to query. * @result: (out): Location to store the read value. * @error: Location to store error information, if any. * * Behaves exactly like inf_xml_util_get_attribute_int_required(). The only * difference is that the function reads a double-precision floating point * number. * * Returns: Whether @result was set. */ gboolean inf_xml_util_get_attribute_double_required(xmlNodePtr xml, const gchar* attribute, gdouble* result, GError** error) { xmlChar* value; gboolean retval; value = inf_xml_util_get_attribute_required(xml, attribute, error); if(value == NULL) return FALSE; retval = inf_xml_util_string_to_double(attribute, value, result, error); xmlFree(value); return retval; } /** * inf_xml_util_set_attribute: * @xml: A #xmlNodePtr. * @attribute: The name of the attribute to set. * @value: The value to set. * * Sets the attribute named @attribute to the given value of the XML element * @xml. This is a thin wrapper around xmlSetProp(), mainly provided for * consistency and for not having to cast the arguments to xmlChar*. */ void inf_xml_util_set_attribute(xmlNodePtr xml, const gchar* attribute, const gchar* value) { xmlSetProp(xml, (const xmlChar*)attribute, (const xmlChar*)value); } /** * inf_xml_util_set_attribute_int: * @xml: A #xmlNodePtr. * @attribute: The name of the attribute to set. * @value: The value to set. * * Sets the attribute named @attribute to the given signed integral value * converted to text. */ void inf_xml_util_set_attribute_int(xmlNodePtr xml, const gchar* attribute, gint value) { char buffer[sizeof(gint) * 3 + 1]; sprintf(buffer, "%d", value); xmlSetProp(xml, (const xmlChar*)attribute, (const xmlChar*)buffer); } /** * inf_xml_util_set_attribute_long: * @xml: A #xmlNodePtr. * @attribute: The name of the attribute to set. * @value: The value to set. * * Sets the attribute named @attribute to the given signed long integral value * converted to text. */ void inf_xml_util_set_attribute_long(xmlNodePtr xml, const gchar* attribute, glong value) { char buffer[sizeof(glong) * 3 + 1]; sprintf(buffer, "%ld", value); xmlSetProp(xml, (const xmlChar*)attribute, (const xmlChar*)buffer); } /** * inf_xml_util_set_attribute_uint: * @xml: A #xmlNodePtr. * @attribute: The name of the attribute to set. * @value: The value to set. * * Sets the attribute named @attribute to the given unsigned integral value * converted to text. */ void inf_xml_util_set_attribute_uint(xmlNodePtr xml, const gchar* attribute, guint value) { char buffer[sizeof(guint) * 3 + 1]; sprintf(buffer, "%u", value); xmlSetProp(xml, (const xmlChar*)attribute, (const xmlChar*)buffer); } /** * inf_xml_util_set_attribute_ulong: * @xml: A #xmlNodePtr. * @attribute: The name of the attribute to set. * @value: The value to set. * * Sets the attribute named @attribute to the given unsigned long integral * value converted to text. */ void inf_xml_util_set_attribute_ulong(xmlNodePtr xml, const gchar* attribute, gulong value) { char buffer[sizeof(gulong) * 3 + 1]; sprintf(buffer, "%lu", value); xmlSetProp(xml, (const xmlChar*)attribute, (const xmlChar*)buffer); } /** * inf_xml_util_set_attribute_double: * @xml: A #xmlNodePtr. * @attribute: The name of the attribute to set. * @value: The value to set. * * Sets the attribute named @attribute to the given double-precision * floating point number converted to text. */ void inf_xml_util_set_attribute_double(xmlNodePtr xml, const gchar* attribute, gdouble value) { char buffer[G_ASCII_DTOSTR_BUF_SIZE]; g_ascii_dtostr(buffer, G_ASCII_DTOSTR_BUF_SIZE, value); xmlSetProp(xml, (const xmlChar*)attribute, (const xmlChar*)buffer); } /** * inf_xml_util_new_node_from_error: * @error: The error object to represent in xml. * @name_space: The element's namespace, or %NULL. * @name: An element name, or %NULL. * * Creates a new #xmlNode that encodes @error. The element's name is * optionally specified by @name, or "error" by default, @error's domain * and code are set as attributes and its message is set as child text using * inf_xml_util_add_child_text(). @name_space is set as the element's * namespace, if not %NULL. * * Returns: (transfer full): A new #xmlNodePtr. It is the caller's * responsibility to dispose it using xmlFreeNode(). */ xmlNodePtr inf_xml_util_new_node_from_error(GError* error, xmlNsPtr name_space, const gchar* name) { xmlNodePtr xml; if(name == NULL) name = "error"; xml = xmlNewNode(name_space, (const xmlChar*) name); inf_xml_util_set_attribute_int(xml, "code", error->code); xmlNewProp( xml, (const xmlChar*) "domain", (const xmlChar*) g_quark_to_string(error->domain) ); inf_xml_util_add_child_text(xml, error->message, strlen(error->message)); return xml; } /** * inf_xml_util_new_error_from_node: * @xml: A #xmlNodePtr as returned by inf_xml_util_new_node_from_error(). * * Creates a new #GError with the domain and erro code given in @xml's * attributes. The message is parsed from the child text as with * inf_xml_util_get_child_text(). The element name and namespace are ignored. * If @xml does not have the attributes as expected, %NULL is returned. * * Returns: (transfer full): A pointer to a new #GError, or %NULL on * failure. It is the caller's responsibility to dispose the #GError * object using g_error_free(). */ GError* inf_xml_util_new_error_from_node(xmlNodePtr xml) { GError* result; xmlChar* domain_str; int code; if(!inf_xml_util_get_attribute_int(xml, "code", &code, NULL)) return NULL; domain_str = xmlGetProp(xml, (const xmlChar*) "domain"); if(domain_str == NULL) return NULL; result = g_slice_new(GError); result->code = code; result->domain = g_quark_from_string((const gchar*) domain_str); result->message = inf_xml_util_get_child_text(xml, NULL, NULL, NULL); xmlFree(domain_str); return result; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-xmpp-connection.c0000644000000000000000000000013013034342512023445 xustar0029 mtime=1483851082.03771847 29 atime=1483851082.03771847 30 ctime=1488261589.092138864 libinfinity-0.7.1/libinfinity/common/inf-xmpp-connection.c0000644000175000017500000043717313034342512024220 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-xmpp-connection * @title: InfXmppConnection * @short_description: Implementation of the XMPP core protocol * @include: libinfinity/common/inf-xmpp-connection.h * @stability: Unstable * * This class implements the XMPP protocol as defined by RFC 3920. It handles * the authentication and authorization. Once the connection is established, * XML messages can be sent and received with the API of the * #InfXmlConnection interface. * * Note that any sort of XML messages can be exchanged, and that the XML does * not need to adhere to the XMPP standard. It is in the responsibility of the * user of this class to send only XML message that the remote counterpart can * understand. **/ #include #include #include #include #include #include #include #include #include #include #include #include #include "config.h" static const GEnumValue inf_xmpp_connection_site_values[] = { { INF_XMPP_CONNECTION_CLIENT, "INF_XMPP_CONNECTION_CLIENT", "client" }, { INF_XMPP_CONNECTION_SERVER, "INF_XMPP_CONNECTION_SERVER", "server" }, { 0, NULL, NULL } }; static const GEnumValue inf_xmpp_connection_security_policy_values[] = { { INF_XMPP_CONNECTION_SECURITY_ONLY_UNSECURED, "INF_XMPP_CONNECTION_SECURITY_ONLY_UNSECURED", "only-unsecured" }, { INF_XMPP_CONNECTION_SECURITY_ONLY_TLS, "INF_XMPP_CONNECTION_SECURITY_ONLY_TLS", "only-tls" }, { INF_XMPP_CONNECTION_SECURITY_BOTH_PREFER_UNSECURED, "INF_XMPP_CONNECTION_SECURITY_BOTH_PREFER_UNSECURED", "both-prefer-unsecured" }, { INF_XMPP_CONNECTION_SECURITY_BOTH_PREFER_TLS, "INF_XMPP_CONNECTION_SECURITY_BOTH_PREFER_TLS", "both-prefer-tls" }, { 0, NULL, NULL } }; /* This is set in inf_init() in inf-init.c based on the existance of the * environment variable LIBINFINITY_DEBUG_PRINT_TRAFFIC. */ gboolean INF_XMPP_CONNECTION_PRINT_TRAFFIC = FALSE; /* This is an implementation of the XMPP protocol as specified in RFC 3920. * Note that it is neither complete nor very standard-compliant at this time. */ typedef enum _InfXmppConnectionStatus { /* Underlaying TCP connection is being established */ INF_XMPP_CONNECTION_CONNECTING, /* Underlaying TCP connection is established */ INF_XMPP_CONNECTION_CONNECTED, /* Same as above, but the stream has already been authenticated */ INF_XMPP_CONNECTION_AUTH_CONNECTED, /* Initial has been sent */ INF_XMPP_CONNECTION_INITIATED, /* Same as above, but the stream has already been authenticated */ INF_XMPP_CONNECTION_AUTH_INITIATED, /* has been received, waiting for features (client only) */ INF_XMPP_CONNECTION_AWAITING_FEATURES, /* Same as above, but the stream has already been authenticated */ INF_XMPP_CONNECTION_AUTH_AWAITING_FEATURES, /* request has been sent (client only) */ INF_XMPP_CONNECTION_ENCRYPTION_REQUESTED, /* TLS handshake is being performed */ INF_XMPP_CONNECTION_HANDSHAKING, /* SASL authentication is in progress */ INF_XMPP_CONNECTION_AUTHENTICATING, /* Connection is ready to send XML */ INF_XMPP_CONNECTION_READY, /* Connection is being closed, but we did not yet get * from the other site */ INF_XMPP_CONNECTION_CLOSING_STREAM, /* Connection is being closed, we got but are still * waiting for any final data to be sent. */ /* TODO: Rename this. */ INF_XMPP_CONNECTION_CLOSING_GNUTLS, /* Connection is closed */ INF_XMPP_CONNECTION_CLOSED } InfXmppConnectionStatus; typedef void(*InfXmppConnectionSentFunc)(InfXmppConnection* xmpp, gpointer user_data); typedef void(*InfXmppConnectionFreeFunc)(InfXmppConnection* xmpp, gpointer user_data); typedef struct _InfXmppConnectionMessage InfXmppConnectionMessage; struct _InfXmppConnectionMessage { InfXmppConnectionMessage* next; guint position; gboolean sent; InfXmppConnectionSentFunc sent_func; InfXmppConnectionFreeFunc free_func; gpointer user_data; }; typedef struct _InfXmppConnectionPrivate InfXmppConnectionPrivate; struct _InfXmppConnectionPrivate { InfTcpConnection* tcp; InfXmppConnectionSite site; gchar* local_hostname; gchar* remote_hostname; InfXmppConnectionSecurityPolicy security_policy; InfXmppConnectionStatus status; gnutls_certificate_request_t certificate_request; InfXmppConnectionCrtCallback certificate_callback; gpointer certificate_callback_user_data; GDestroyNotify certificate_callback_notify; /* The number of chars given to the TCP connection * waiting for being sent. */ guint position; /* Message queue */ xmlDocPtr doc; xmlBufferPtr buf; InfXmppConnectionMessage* messages; InfXmppConnectionMessage* last_message; /* XML parsing */ guint parsing; /* Whether we are currently in an XML parser or GnuTLS callback */ xmlParserCtxtPtr parser; xmlNodePtr root; xmlNodePtr cur; /* Transport layer security */ gnutls_session_t session; InfCertificateCredentials* creds; gnutls_x509_crt_t own_cert; InfCertificateChain* peer_cert; const gchar* pull_data; gsize pull_len; /* SASL */ InfSaslContext* sasl_context; InfSaslContext* sasl_own_context; InfSaslContextSession* sasl_session; gchar* sasl_local_mechanisms; gchar* sasl_remote_mechanisms; GError* sasl_error; }; enum { PROP_0, PROP_TCP, PROP_SITE, PROP_LOCAL_HOSTNAME, PROP_REMOTE_HOSTNAME, PROP_SECURITY_POLICY, PROP_TLS_ENABLED, PROP_CREDENTIALS, PROP_SASL_CONTEXT, PROP_SASL_MECHANISMS, /* From InfXmlConnection */ PROP_STATUS, PROP_NETWORK, PROP_LOCAL_ID, PROP_REMOTE_ID, PROP_LOCAL_CERTIFICATE, PROP_REMOTE_CERTIFICATE }; #define INF_XMPP_CONNECTION_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INF_TYPE_XMPP_CONNECTION, InfXmppConnectionPrivate)) static GQuark inf_xmpp_connection_stream_error_quark; static GQuark inf_xmpp_connection_auth_error_quark; static void inf_xmpp_connection_xml_connection_iface_init(InfXmlConnectionInterface* iface); INF_DEFINE_ENUM_TYPE(InfXmppConnectionSite, inf_xmpp_connection_site, inf_xmpp_connection_site_values) INF_DEFINE_ENUM_TYPE(InfXmppConnectionSecurityPolicy, inf_xmpp_connection_security_policy, inf_xmpp_connection_security_policy_values) G_DEFINE_TYPE_WITH_CODE(InfXmppConnection, inf_xmpp_connection, G_TYPE_OBJECT, G_ADD_PRIVATE(InfXmppConnection) G_IMPLEMENT_INTERFACE(INF_TYPE_XML_CONNECTION, inf_xmpp_connection_xml_connection_iface_init)) /* * XMPP error handling */ typedef struct _InfXmppConnectionErrorCondition { const gchar* condition; guint code; } InfXmppConnectionErrorCondition; static const InfXmppConnectionErrorCondition inf_xmpp_connection_stream_error_conditions[] = { { "bad-format", INF_XMPP_CONNECTION_STREAM_ERROR_BAD_FORMAT }, { "bad-namespace-prefix", INF_XMPP_CONNECTION_STREAM_ERROR_BAD_NAMESPACE_PREFIX }, { "conflict", INF_XMPP_CONNECTION_STREAM_ERROR_CONFLICT }, { "connection-timeout", INF_XMPP_CONNECTION_STREAM_ERROR_CONNECTION_TIMEOUT }, { "host-gone", INF_XMPP_CONNECTION_STREAM_ERROR_HOST_GONE }, { "host-unknown", INF_XMPP_CONNECTION_STREAM_ERROR_HOST_UNKNOWN }, { "improper-addressing", INF_XMPP_CONNECTION_STREAM_ERROR_IMPROPER_ADDRESSING }, { "internal-server-error", INF_XMPP_CONNECTION_STREAM_ERROR_INTERNAL_SERVER_ERROR }, { "invalid-from", INF_XMPP_CONNECTION_STREAM_ERROR_INVALID_FROM }, { "invalid-id", INF_XMPP_CONNECTION_STREAM_ERROR_INVALID_ID }, { "invalid-namespace", INF_XMPP_CONNECTION_STREAM_ERROR_INVALID_NAMESPACE }, { "invalid-xml", INF_XMPP_CONNECTION_STREAM_ERROR_INVALID_XML }, { "not-authorized", INF_XMPP_CONNECTION_STREAM_ERROR_NOT_AUTHORIZED }, { "policy-violation", INF_XMPP_CONNECTION_STREAM_ERROR_POLICY_VIOLATION }, { "remote-connection-failed", INF_XMPP_CONNECTION_STREAM_ERROR_REMOTE_CONNECTION_FAILED }, { "resource-constraint", INF_XMPP_CONNECTION_STREAM_ERROR_RESOURCE_CONSTRAINT }, { "restricted-xml", INF_XMPP_CONNECTION_STREAM_ERROR_RESTRICTED_XML }, { "see-other-host", INF_XMPP_CONNECTION_STREAM_ERROR_SEE_OTHER_HOST }, { "system-shutdown", INF_XMPP_CONNECTION_STREAM_ERROR_SYSTEM_SHUTDOWN }, { "undefined-condition", INF_XMPP_CONNECTION_STREAM_ERROR_UNDEFINED_CONDITION }, { /* Also map unknown failure to undefined-condition */ "undefined-condition", INF_XMPP_CONNECTION_STREAM_ERROR_FAILED }, { "unsupported-encoding", INF_XMPP_CONNECTION_STREAM_ERROR_UNSUPPORTED_ENCODING }, { "unsupported-stanza-type", INF_XMPP_CONNECTION_STREAM_ERROR_UNSUPPORTED_STANZA_TYPE }, { "unsupported-version", INF_XMPP_CONNECTION_STREAM_ERROR_UNSUPPORTED_VERSION }, { "xml-not-well-formed", INF_XMPP_CONNECTION_STREAM_ERROR_XML_NOT_WELL_FORMED }, { NULL, 0 } }; static const InfXmppConnectionErrorCondition inf_xmpp_connection_auth_error_conditions[] = { { "aborted", INF_XMPP_CONNECTION_AUTH_ERROR_ABORTED }, { "incorrect-encoding", INF_XMPP_CONNECTION_AUTH_ERROR_INCORRECT_ENCODING }, { "invalid-authzid", INF_XMPP_CONNECTION_AUTH_ERROR_INVALID_AUTHZID }, { "invalid-mechanism", INF_XMPP_CONNECTION_AUTH_ERROR_INVALID_MECHANISM }, { "mechanism-too-weak", INF_XMPP_CONNECTION_AUTH_ERROR_MECHANISM_TOO_WEAK }, { "not-authorized", INF_XMPP_CONNECTION_AUTH_ERROR_NOT_AUTHORIZED }, { "temporary-auth-failure", INF_XMPP_CONNECTION_AUTH_ERROR_TEMPORARY_AUTH_FAILURE }, { NULL, 0 } }; static InfXmppConnectionStreamError inf_xmpp_connection_stream_error_from_condition(const gchar* condition) { const InfXmppConnectionErrorCondition* cond; for(cond = inf_xmpp_connection_stream_error_conditions; cond->condition != NULL; ++ cond) { if(strcmp(condition, cond->condition) == 0) return cond->code; } return INF_XMPP_CONNECTION_STREAM_ERROR_FAILED; } static const gchar* inf_xmpp_connection_stream_error_to_condition(InfXmppConnectionStreamError code) { const InfXmppConnectionErrorCondition* cond; for(cond = inf_xmpp_connection_stream_error_conditions; cond->condition != NULL; ++ cond) { if(code == cond->code) return cond->condition; } g_assert_not_reached(); return NULL; } /* TODO: These are directly copied from RFC 3920, section 4.7.3, probably * they have to be adjusted to be more useful to the user. */ static const gchar* inf_xmpp_connection_stream_strerror(InfXmppConnectionStreamError code) { switch(code) { case INF_XMPP_CONNECTION_STREAM_ERROR_BAD_FORMAT: return _("The entity has sent XML that cannot be processed"); case INF_XMPP_CONNECTION_STREAM_ERROR_BAD_NAMESPACE_PREFIX: return _("The entity has sent a namespace prefix that is unsupported, or " "has sent no namespace prefix on an element that requires such " "a prefix"); case INF_XMPP_CONNECTION_STREAM_ERROR_CONFLICT: return _("The server is closing the active stream for this entity " "because a new stream has been initiated that conflicts with " "the existing stream"); case INF_XMPP_CONNECTION_STREAM_ERROR_CONNECTION_TIMEOUT: return _("The entity has not generated any traffic over the stream for " "some period of time"); case INF_XMPP_CONNECTION_STREAM_ERROR_HOST_GONE: return _("The value of the 'to' attribute provided by the initiating " "entity in the stream header corresponds to a hostname that is " "no longer hosted by the server"); case INF_XMPP_CONNECTION_STREAM_ERROR_HOST_UNKNOWN: return _("The value of the 'to' attribute provided by the initiating " "entity in the stream header does not correspond to a hostname " "that is hosted by the server"); case INF_XMPP_CONNECTION_STREAM_ERROR_IMPROPER_ADDRESSING: return _("A stanza sent between two servers lacks a 'to' or 'from'" "attribute"); case INF_XMPP_CONNECTION_STREAM_ERROR_INTERNAL_SERVER_ERROR: return _("The server has experienced a misconfiguration or an otherwise-" "undefined internal error that prevents it from servicing " "the stream"); case INF_XMPP_CONNECTION_STREAM_ERROR_INVALID_FROM: return _("The JID or hostname provided in a 'from' address does not " "match an authorized JID or validated domain negotiated between " "servers via SASL or dialback, or between a client and a " "server via authentication and resource binding"); case INF_XMPP_CONNECTION_STREAM_ERROR_INVALID_ID: return _("The stream ID or dialback ID is invalid or does not match an " "ID previously provided"); case INF_XMPP_CONNECTION_STREAM_ERROR_INVALID_NAMESPACE: return _("The streams namespace is something other than " "\"http://etherx.jabber.org/streams\" or the dialback namespace " "name is something other than \"jabber:server:dialback\""); case INF_XMPP_CONNECTION_STREAM_ERROR_INVALID_XML: return _("The entity has sent invalid XML over the stream to a server " "that performs validation"); case INF_XMPP_CONNECTION_STREAM_ERROR_NOT_AUTHORIZED: return _("The entity has attempted to send data before the stream has " "been authenticated, or otherwise is not authorized to perform " "an action related to stream negotiation"); case INF_XMPP_CONNECTION_STREAM_ERROR_POLICY_VIOLATION: return _("The entity has violated some local service policy"); case INF_XMPP_CONNECTION_STREAM_ERROR_REMOTE_CONNECTION_FAILED: return _("The server is unable to properly connect to a remote entity " "that is required for authentication or authorization"); case INF_XMPP_CONNECTION_STREAM_ERROR_RESOURCE_CONSTRAINT: return _("The server lacks the system resources necessary to service the " "stream"); case INF_XMPP_CONNECTION_STREAM_ERROR_RESTRICTED_XML: return _("The entity has attempted to send restricted XML features"); case INF_XMPP_CONNECTION_STREAM_ERROR_SEE_OTHER_HOST: return _("The server will not provide service to the initiating " "entity but is redirecting traffic to another host"); case INF_XMPP_CONNECTION_STREAM_ERROR_SYSTEM_SHUTDOWN: return _("The server is being shut down and all active streams are being " "closed"); case INF_XMPP_CONNECTION_STREAM_ERROR_UNDEFINED_CONDITION: case INF_XMPP_CONNECTION_STREAM_ERROR_FAILED: return _("The error condition is not one of those defined by the other " "conditions"); case INF_XMPP_CONNECTION_STREAM_ERROR_UNSUPPORTED_ENCODING: return _("The initiating entity has encoded the stream in an encoding " "that is not supported by the server"); case INF_XMPP_CONNECTION_STREAM_ERROR_UNSUPPORTED_STANZA_TYPE: return _("The initiating entity has sent a first-level child of the " "stream that is not supported by the server."); case INF_XMPP_CONNECTION_STREAM_ERROR_UNSUPPORTED_VERSION: return _("The value of the 'version' attribute provided by the " "initiating entity in the stream header specifies a version of " "XMPP that is not supported by the server"); case INF_XMPP_CONNECTION_STREAM_ERROR_XML_NOT_WELL_FORMED: return _("The initiating entity has sent XML that is not well-formed"); default: g_assert_not_reached(); break; } } static InfXmppConnectionAuthError inf_xmpp_connection_auth_error_from_condition(const gchar* condition) { const InfXmppConnectionErrorCondition* cond; for(cond = inf_xmpp_connection_auth_error_conditions; cond->condition != NULL; ++ cond) { if(strcmp(condition, cond->condition) == 0) return cond->code; } return INF_XMPP_CONNECTION_AUTH_ERROR_FAILED; } static const gchar* inf_xmpp_connection_auth_error_to_condition(InfXmppConnectionAuthError code) { const InfXmppConnectionErrorCondition* cond; for(cond = inf_xmpp_connection_auth_error_conditions; cond->condition != NULL; ++ cond) { if(cond->code == code) return cond->condition; } g_assert_not_reached(); return NULL; } /* TODO: Again, this is only copied from RFC 3920, section 6.4 */ static const gchar* inf_xmpp_connection_auth_strerror(InfXmppConnectionAuthError code) { switch(code) { case INF_XMPP_CONNECTION_AUTH_ERROR_ABORTED: return _("The receiving entity acknowledged an element sent by " "the initiating entity"); case INF_XMPP_CONNECTION_AUTH_ERROR_INCORRECT_ENCODING: return _("The data provided by the initiating entity could not be " "processed because the Base64 encoding is incorrect"); case INF_XMPP_CONNECTION_AUTH_ERROR_INVALID_AUTHZID: return _("The authzid provided by the initiating entity is invalid, " "either because it is incorrectly formatted or because the " "initiating entity does not have permissions to authorize " "that ID"); case INF_XMPP_CONNECTION_AUTH_ERROR_INVALID_MECHANISM: return _("The initiating entity did not provide a mechanism or requested " "a mechanism that is not supported by the receiving entity"); case INF_XMPP_CONNECTION_AUTH_ERROR_MECHANISM_TOO_WEAK: return _("The mechanism requsted by the initiating entity is weaker than " "server policy permits for that initiating entity"); case INF_XMPP_CONNECTION_AUTH_ERROR_NOT_AUTHORIZED: return _("The authentication failed because the initiating entity did " "not provide valid credentials"); case INF_XMPP_CONNECTION_AUTH_ERROR_TEMPORARY_AUTH_FAILURE: return _("The authentication failed because of a temporary error condition " "within the receiving entity"); case INF_XMPP_CONNECTION_AUTH_ERROR_FAILED: return _("An unknown authentication error has occured"); default: g_assert_not_reached(); return NULL; } } /* * Message queue */ static void inf_xmpp_connection_push_message(InfXmppConnection* xmpp, InfXmppConnectionSentFunc sent_func, InfXmppConnectionFreeFunc free_func, gpointer user_data) { InfXmppConnectionPrivate* priv; InfXmppConnectionMessage* message; priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); if(priv->position == 0) { if(sent_func != NULL) sent_func(xmpp, user_data); if(free_func != NULL) free_func(xmpp, user_data); } else { message = g_slice_new(InfXmppConnectionMessage); message->next = NULL; message->position = priv->position; message->sent = FALSE; message->sent_func = sent_func; message->free_func = free_func; message->user_data = user_data; if(priv->last_message == NULL) priv->messages = message; else priv->last_message->next = message; priv->last_message = message; } } static void inf_xmpp_connection_pop_message(InfXmppConnection* connection) { InfXmppConnectionPrivate* priv; InfXmppConnectionMessage* message; priv = INF_XMPP_CONNECTION_PRIVATE(connection); message = priv->messages; g_assert(message != NULL); priv->messages = message->next; if(priv->messages == NULL) priv->last_message = NULL; if(message->free_func != NULL) message->free_func(connection, message->user_data); g_slice_free(InfXmppConnectionMessage, message); } /* Note that this function does not change the state of xmpp, so it might * rest in a state where it expects to actually have the resources available * that are cleared here. Be sure to adjust state after having called * this function. */ static void inf_xmpp_connection_clear(InfXmppConnection* xmpp) { InfXmppConnectionPrivate* priv; priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); g_object_freeze_notify(G_OBJECT(xmpp)); if(priv->sasl_session != NULL) { inf_sasl_context_stop_session(priv->sasl_context, priv->sasl_session); priv->sasl_session = NULL; } if(priv->sasl_remote_mechanisms != NULL) { g_free(priv->sasl_remote_mechanisms); priv->sasl_remote_mechanisms = NULL; } /* Keep the certificates alive, in case they still need to be accessed after * the connection was closed. They are reset before a new connection is * made. */ #if 0 if(priv->own_cert != NULL) { gnutls_x509_crt_deinit(priv->own_cert); priv->own_cert = NULL; g_object_notify(G_OBJECT(xmpp), "local-certificate"); } if(priv->peer_cert != NULL) { inf_certificate_chain_unref(priv->peer_cert); priv->peer_cert = NULL; g_object_notify(G_OBJECT(xmpp), "remote-certificate"); } #endif if(priv->session != NULL) { gnutls_deinit(priv->session); priv->session = NULL; g_object_notify(G_OBJECT(xmpp), "tls-enabled"); } if(priv->parser != NULL) { xmlFreeParserCtxt(priv->parser); priv->parser = NULL; if(priv->root != NULL) { xmlFreeNode(priv->root); priv->root = NULL; priv->cur = NULL; } } while(priv->messages != NULL) inf_xmpp_connection_pop_message(xmpp); if(priv->buf != NULL) { g_assert(priv->doc != NULL); xmlBufferFree(priv->buf); xmlFreeDoc(priv->doc); priv->buf = NULL; priv->doc = NULL; } priv->pull_data = NULL; priv->pull_len = 0; g_object_thaw_notify(G_OBJECT(xmpp)); } static void inf_xmpp_connection_send_chars(InfXmppConnection* xmpp, gconstpointer data, guint len) { InfXmppConnectionPrivate* priv; ssize_t cur_bytes; GError* error; priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); g_assert(priv->status != INF_XMPP_CONNECTION_HANDSHAKING && priv->status != INF_XMPP_CONNECTION_CLOSED); if(INF_XMPP_CONNECTION_PRINT_TRAFFIC) printf("\033[00;34m%.*s\033[00;00m\n", (int)len, (const char*)data); /* From here on we go into a GnuTLS callback. Set this flag to prevent * premature cleanup -- make sure that if the connection is being brought * down from a GnuTLS callback then we keep the GnuTLS context around * until the gntuls_record_send() call finishes. */ ++priv->parsing; if(priv->session != NULL) { do { cur_bytes = gnutls_record_send(priv->session, data, len); if(cur_bytes < 0) { /* A GnuTLS error occured. It does not make sense to try to send * or a gnutls bye here, since this would again * have to go through GnuTLS, which would fail again, and so on. */ error = NULL; inf_gnutls_set_error(&error, cur_bytes); inf_xml_connection_error(INF_XML_CONNECTION(xmpp), error); g_error_free(error); inf_tcp_connection_close(priv->tcp); break; } else if(cur_bytes == 0) { /* TODO: I am not sure whether this can actually happen and what * it means. */ g_assert_not_reached(); /*inf_tcp_connection_close(priv->tcp);*/ } else { *((const char**)&data) += cur_bytes; len -= cur_bytes; } } while(len > 0); } else { priv->position += len; inf_tcp_connection_send(priv->tcp, data, len); } g_assert(priv->parsing > 0); if(--priv->parsing == 0) { if(priv->status == INF_XMPP_CONNECTION_CLOSED) { /* Status changed to CLOSED, so while attempting to send data we noticed * that the connection is down. Clear up. We didn't clean up in the * disconnection callback because we wanted to keep the gnutls context * alive until gnutls_record_send() returns. */ inf_xmpp_connection_clear(xmpp); g_object_notify(G_OBJECT(xmpp), "status"); } } } static void inf_xmpp_connection_send_xml(InfXmppConnection* xmpp, xmlNodePtr xml) { InfXmppConnectionPrivate* priv; priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); g_return_if_fail(priv->doc != NULL); g_return_if_fail(priv->buf != NULL); xmlDocSetRootElement(priv->doc, xml); xmlNodeDump(priv->buf, priv->doc, xml, 0, 0); xmlUnlinkNode(xml); xmlSetListDoc(xml, NULL); /* Keep the object alive during the send_chars call, so that we can check * the buffer variable afterwards. */ g_object_ref(xmpp); inf_xmpp_connection_send_chars( xmpp, xmlBufferContent(priv->buf), xmlBufferLength(priv->buf) ); /* The connection might be closed & cleared as a result from * inf_xmpp_connection_send_chars(), so make sure the buffer still * exists before emptying it. */ if(priv->buf != NULL) xmlBufferEmpty(priv->buf); g_object_unref(xmpp); } /* * Helper functions */ static xmlNodePtr inf_xmpp_connection_node_new(const gchar* name, const gchar* xmlns) { xmlNodePtr ptr; ptr = xmlNewNode(NULL, (const xmlChar*)name); xmlNewProp(ptr, (const xmlChar*)"xmlns", (const xmlChar*)xmlns); return ptr; } static xmlNodePtr inf_xmpp_connection_node_new_streams(const gchar* name) { return inf_xmpp_connection_node_new( name, "urn:ietf:params:xml:ns:xmpp-streams" ); } static xmlNodePtr inf_xmpp_connection_node_new_tls(const gchar* name) { return inf_xmpp_connection_node_new( name, "urn:ietf:params:xml:ns:xmpp-tls" ); } static xmlNodePtr inf_xmpp_connection_node_new_sasl(const gchar* name) { return inf_xmpp_connection_node_new( name, "urn:ietf:params:xml:ns:xmpp-sasl" ); } /* * XMPP deinitialization */ /* Terminates the XMPP session and closes the connection. */ static void inf_xmpp_connection_terminate(InfXmppConnection* xmpp) { static const gchar xmpp_connection_deinit_request[] = ""; InfXmppConnectionPrivate* priv; xmlNodePtr abort; priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); g_assert(priv->status != INF_XMPP_CONNECTION_CLOSED && priv->status != INF_XMPP_CONNECTION_CLOSING_GNUTLS && priv->status != INF_XMPP_CONNECTION_CONNECTING); /* We cannot send or a gnutls bye in these states * because it would interfere with the handshake. */ if(priv->status != INF_XMPP_CONNECTION_HANDSHAKING && priv->status != INF_XMPP_CONNECTION_ENCRYPTION_REQUESTED) { /* Session termination is not required in these states because the session * did not yet even begin or has already been sent, * respectively. */ if(priv->status != INF_XMPP_CONNECTION_CONNECTED && priv->status != INF_XMPP_CONNECTION_AUTH_CONNECTED && priv->status != INF_XMPP_CONNECTION_CLOSING_STREAM) { if(priv->status == INF_XMPP_CONNECTION_AUTHENTICATING) { /* Abort authentication before sending final */ abort = inf_xmpp_connection_node_new_sasl("abort"); inf_xmpp_connection_send_xml(xmpp, abort); xmlFreeNode(abort); } /* inf_xmpp_connection_send_xml() above might have caused * status update: */ if(priv->status != INF_XMPP_CONNECTION_CLOSED) { inf_xmpp_connection_send_chars( xmpp, xmpp_connection_deinit_request, sizeof(xmpp_connection_deinit_request) - 1 ); } } /* One of the send() calls above might have caused status update */ if(priv->status != INF_XMPP_CONNECTION_CLOSED && priv->session != NULL) gnutls_bye(priv->session, GNUTLS_SHUT_WR); } /* Clear resources such as GnuTLS session and XML parser */ if(priv->parsing == 0) inf_xmpp_connection_clear(xmpp); /* It can happen that the call to gnutls_bye() causes a send error because * the connection is already down. In that case the status is changed to * CLOSED, in which case we do not need further status updates at * this point. */ if(priv->status != INF_XMPP_CONNECTION_CLOSED) { /* The Change from CLOSING_STREAM to CLOSING_GNUTLS does not change * the XML status, so we need no notify in this case. */ if(priv->status != INF_XMPP_CONNECTION_CLOSING_STREAM) { priv->status = INF_XMPP_CONNECTION_CLOSING_GNUTLS; if(priv->parsing == 0) g_object_notify(G_OBJECT(xmpp), "status"); } else { priv->status = INF_XMPP_CONNECTION_CLOSING_GNUTLS; } } } /* This sends a with the given error code, but does not close * the stream for the client to retry authentication. */ static void inf_xmpp_connection_send_auth_error(InfXmppConnection* xmpp, InfXmppConnectionAuthError code) { InfXmppConnectionPrivate* priv; xmlNodePtr xml; xmlNodePtr child; priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); /* SASL should be present, otherwise no auth error could have occured */ g_assert(priv->sasl_context != NULL); xml = inf_xmpp_connection_node_new_sasl("failure"); child = xmlNewChild( xml, NULL, (const xmlChar*)inf_xmpp_connection_auth_error_to_condition(code), NULL ); if(priv->sasl_error != NULL) { xmlAddChild( child, inf_xml_util_new_node_from_error(priv->sasl_error, NULL, "error")); } inf_xmpp_connection_send_xml(xmpp, xml); xmlFreeNode(xml); } /* Emits an error signal for the given auth error code. */ static void inf_xmpp_connection_emit_auth_error(InfXmppConnection* xmpp, InfXmppConnectionAuthError code) { GError* error; error = NULL; g_set_error_literal( &error, inf_xmpp_connection_auth_error_quark, code, inf_xmpp_connection_auth_strerror(code) ); inf_xml_connection_error(INF_XML_CONNECTION(xmpp), error); g_error_free(error); } /* This sends a and then terminates the session using * the inf_xmpp_connection_terminate. message may be NULL. */ static void inf_xmpp_connection_terminate_error(InfXmppConnection* xmpp, InfXmppConnectionStreamError code, const gchar* message) { InfXmppConnectionPrivate* priv; xmlNodePtr node; xmlNodePtr child; GError* error; priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); g_assert(priv->parser != NULL); g_assert(priv->status != INF_XMPP_CONNECTION_HANDSHAKING && priv->status != INF_XMPP_CONNECTION_ENCRYPTION_REQUESTED); error = NULL; g_set_error_literal( &error, inf_xmpp_connection_stream_error_quark, code, message != NULL ? message : inf_xmpp_connection_stream_strerror(code) ); node = xmlNewNode(NULL, (const xmlChar*)"stream:error"); child = inf_xmpp_connection_node_new_streams( inf_xmpp_connection_stream_error_to_condition(code) ); xmlAddChild(node, child); if(message != NULL) { child = inf_xmpp_connection_node_new_streams("text"); xmlNodeAddContent(child, (const xmlChar*)message); /* TODO: Get real language code, probably from gettext */ xmlNodeSetLang(child, (const xmlChar*)"en"); } inf_xmpp_connection_send_xml(xmpp, node); xmlFreeNode(node); inf_xml_connection_error(INF_XML_CONNECTION(xmpp), error); g_error_free(error); inf_xmpp_connection_terminate(xmpp); } /* This attempts to deinitiate the stream by sending a final , * but it waits for the response of the other site. */ static void inf_xmpp_connection_deinitiate(InfXmppConnection* xmpp) { static const gchar xmpp_connection_deinitiate_request[] = ""; InfXmppConnectionPrivate* priv; xmlNodePtr abort; priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); g_assert(priv->status != INF_XMPP_CONNECTION_CLOSING_GNUTLS && priv->status != INF_XMPP_CONNECTION_CLOSING_STREAM && priv->status != INF_XMPP_CONNECTION_CONNECTED && priv->status != INF_XMPP_CONNECTION_AUTH_CONNECTED); /* If we are in an authentication callback and we decide not to continue * the connection then remove the cached SASL server mechanisms as we don't * need them anymore. */ if(priv->site == INF_XMPP_CONNECTION_CLIENT && priv->sasl_remote_mechanisms != NULL) { g_free(priv->sasl_remote_mechanisms); priv->sasl_remote_mechanisms = NULL; } if(priv->status == INF_XMPP_CONNECTION_AUTHENTICATING) { /* If the SASL session is NULL then we have already aborted the * authentication but are still waiting for the server to acknowledge. */ if(priv->sasl_session != NULL) { /* Abort authentication before sending . */ /* TODO: Wait for response of the abort before sending */ abort = inf_xmpp_connection_node_new_sasl("abort"); inf_xmpp_connection_send_xml(xmpp, abort); } } inf_xmpp_connection_send_chars( xmpp, xmpp_connection_deinitiate_request, sizeof(xmpp_connection_deinitiate_request) - 1 ); priv->status = INF_XMPP_CONNECTION_CLOSING_STREAM; g_object_notify(G_OBJECT(xmpp), "status"); } /* * GnuTLS setup */ /* Required by inf_xmpp_connection_tls_handshake */ static void inf_xmpp_connection_initiate(InfXmppConnection* xmpp); static gboolean inf_xmpp_connection_prefers_tls(InfXmppConnection* xmpp) { InfXmppConnectionPrivate* priv; priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); return priv->security_policy == INF_XMPP_CONNECTION_SECURITY_BOTH_PREFER_TLS || priv->security_policy == INF_XMPP_CONNECTION_SECURITY_ONLY_TLS; } static ssize_t inf_xmpp_connection_tls_push(gnutls_transport_ptr_t ptr, const void* data, size_t len) { InfXmppConnection* xmpp; InfXmppConnectionPrivate* priv; xmpp = INF_XMPP_CONNECTION(ptr); priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); priv->position += len; inf_tcp_connection_send(priv->tcp, data, len); return len; } static ssize_t inf_xmpp_connection_tls_pull(gnutls_transport_ptr_t ptr, void* data, size_t len) { InfXmppConnection* xmpp; InfXmppConnectionPrivate* priv; size_t pull_len; xmpp = INF_XMPP_CONNECTION(ptr); priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); /* The data to pull is set in inf_xmpp_connection_received_cb() which then * calls gnutls_record_recv, however, the pull function might also be * called during a call to gnutls_handshake when no data is available. * We return EAGAIN in this case to wait for more data from * inf_xmpp_connection_received_cb(). */ /* No data available */ if(priv->pull_len == 0) { gnutls_transport_set_errno(priv->session, EAGAIN); return -1; } else { pull_len = priv->pull_len; if(len < pull_len) pull_len = len; memcpy(data, priv->pull_data, pull_len); priv->pull_len -= pull_len; priv->pull_data += pull_len; return pull_len; } } static gnutls_x509_crt_t inf_xmpp_connection_tls_import_own_certificate(InfXmppConnection* xmpp, GError** error) { InfXmppConnectionPrivate* priv; const gnutls_datum_t* cert_raw; gnutls_x509_crt_t cert; int res; priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); cert_raw = gnutls_certificate_get_ours(priv->session); if(cert_raw == NULL) return NULL; res = gnutls_x509_crt_init(&cert); if(res != GNUTLS_E_SUCCESS) { inf_gnutls_set_error(error, res); return NULL; } res = gnutls_x509_crt_import(cert, cert_raw, GNUTLS_X509_FMT_DER); if(res != GNUTLS_E_SUCCESS) { gnutls_x509_crt_deinit(cert); inf_gnutls_set_error(error, res); return NULL; } return cert; } static InfCertificateChain* inf_xmpp_connection_tls_import_peer_certificate(InfXmppConnection* xmpp, GError** error) { InfXmppConnectionPrivate* priv; const gnutls_datum_t* certs_raw; unsigned int list_size; unsigned int n_certs; gnutls_x509_crt_t* certs; int res; guint i; priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); certs_raw = gnutls_certificate_get_peers(priv->session, &list_size); if(certs_raw == NULL) return NULL; certs = g_malloc(list_size * sizeof(gnutls_x509_crt_t)); /* TODO: The upper code only imports one certificate, even if there are * more. It's unclear to me why this happens. */ #if 0 n_certs = list_size; res = gnutls_x509_crt_list_import( certs, &n_certs, certs_raw, GNUTLS_X509_FMT_DER, GNUTLS_X509_CRT_LIST_FAIL_IF_UNSORTED ); if(res < 0) { g_free(certs); inf_gnutls_set_error(error, res); return NULL; } g_assert(res == n_certs); g_assert(res == list_size); #else for(i = 0; i < list_size; ++ i) { res = gnutls_x509_crt_init(&certs[i]); if(res == GNUTLS_E_SUCCESS) { res = gnutls_x509_crt_import( certs[i], certs_raw + i, GNUTLS_X509_FMT_DER ); if(res != GNUTLS_E_SUCCESS) gnutls_x509_crt_deinit(certs[i]); } if(res != GNUTLS_E_SUCCESS) { for(; i > 0; -- i) gnutls_x509_crt_deinit(certs[i - 1]); g_free(certs); inf_gnutls_set_error(error, res); return NULL; } } #endif return inf_certificate_chain_new(certs, list_size); } static void inf_xmpp_connection_tls_handshake(InfXmppConnection* xmpp) { InfXmppConnectionPrivate* priv; int ret; InfCertificateChain* chain; GError* error; priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); g_assert(priv->status == INF_XMPP_CONNECTION_HANDSHAKING); g_assert(priv->session != NULL); ret = gnutls_handshake(priv->session); switch(ret) { case GNUTLS_E_AGAIN: /* Wait for more data */ break; case 0: /* Handshake finished successfully */ priv->status = INF_XMPP_CONNECTION_CONNECTED; g_object_notify(G_OBJECT(xmpp), "tls-enabled"); error = NULL; /* Extract own certificate */ g_assert(priv->own_cert == NULL); priv->own_cert = inf_xmpp_connection_tls_import_own_certificate(xmpp, &error); if(error == NULL) { if(priv->own_cert != NULL) g_object_notify(G_OBJECT(xmpp), "local-certificate"); /* Extract peer certificate */ g_assert(priv->peer_cert == NULL); priv->peer_cert = inf_xmpp_connection_tls_import_peer_certificate(xmpp, &error); if(error == NULL) { /* Require the server to show us its certificate */ if(priv->peer_cert == NULL) { if(priv->site == INF_XMPP_CONNECTION_CLIENT) { g_set_error_literal( &error, inf_xmpp_connection_error_quark(), INF_XMPP_CONNECTION_ERROR_NO_CERTIFICATE_PROVIDED, _("The server did not provide a certificate") ); } } else { g_object_notify(G_OBJECT(xmpp), "remote-certificate"); } } } if(error != NULL) { inf_xml_connection_error(INF_XML_CONNECTION(xmpp), error); g_error_free(error); inf_xmpp_connection_terminate(xmpp); } else { /* Ask the user to verify the peer's certificate, or, if there is no * certificate, whether the user still wants to accept the connection or * not. */ if(priv->certificate_callback != NULL) { priv->certificate_callback( xmpp, priv->session, priv->peer_cert, priv->certificate_callback_user_data ); } else { /* The user doesn't seem to be interested, * blindly accept the certificate */ inf_xmpp_connection_initiate(xmpp); } } break; default: error = NULL; inf_gnutls_set_error(&error, ret); inf_xml_connection_error(INF_XML_CONNECTION(xmpp), error); g_error_free(error); gnutls_deinit(priv->session); priv->session = NULL; switch(priv->site) { case INF_XMPP_CONNECTION_CLIENT: /* Terminate connection when GnuTLS handshake fails. Don't wait for * as the server might not be aware of the problem. */ inf_xmpp_connection_terminate(xmpp); break; case INF_XMPP_CONNECTION_SERVER: /* TODO: Just close connection on error, without sending * , as in the client case? */ /* So that inf_xmpp_connection_terminate() doesn't get confused, it will * be overwritten to CLOSING_GNUTLS anyway. */ priv->status = INF_XMPP_CONNECTION_INITIATED; /* Send terminating , close XMPP session */ inf_xmpp_connection_terminate(xmpp); break; default: g_assert_not_reached(); break; } break; } } static void inf_xmpp_connection_tls_init(InfXmppConnection* xmpp) { InfXmppConnectionPrivate* priv; priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); g_assert(priv->session == NULL); /* Make sure credentials are present */ if(priv->creds == NULL) { /* We can create built-in credentials for the client side. However, the * server requires a certificate, and it doesn't make sense to generate * one here, so we require that credentials are given for a server-side * XMPP connection. */ g_assert(priv->site == INF_XMPP_CONNECTION_CLIENT); priv->creds = inf_certificate_credentials_new(); g_object_notify(G_OBJECT(xmpp), "credentials"); } switch(priv->site) { case INF_XMPP_CONNECTION_CLIENT: gnutls_init(&priv->session, GNUTLS_CLIENT); break; case INF_XMPP_CONNECTION_SERVER: gnutls_init(&priv->session, GNUTLS_SERVER); /* If the user wants to check the client's certificate, then require * that the client sends one. */ if(priv->certificate_callback != NULL) { gnutls_certificate_server_set_request( priv->session, priv->certificate_request ); } break; default: g_assert_not_reached(); break; } /* Use the default priority, but make sure that DHE-RSA is preferred * over RSA. At some point during the GnuTLS 3.x cycle, this was changed * due to a compatibility issue: if the server does not offer long * enough primes, the client cannot recover and the handshake would fail. * * However, this is not a practical problem for us at the moment, since * infinoted and Gobby always generate 2048-bit DH primes. If this becomes * an issue in the future, we can revisit this. However, note that the * default priority string prefers ECDH over DH anyway, so if the server * supports ECDH, the client will probably choose that and this is not an * issue either. */ gnutls_priority_set_direct(priv->session, "NORMAL:-RSA:+RSA", NULL); gnutls_credentials_set( priv->session, GNUTLS_CRD_CERTIFICATE, inf_certificate_credentials_get(priv->creds) ); gnutls_transport_set_ptr(priv->session, xmpp); gnutls_transport_set_push_function( priv->session, inf_xmpp_connection_tls_push ); gnutls_transport_set_pull_function( priv->session, inf_xmpp_connection_tls_pull ); priv->status = INF_XMPP_CONNECTION_HANDSHAKING; inf_xmpp_connection_tls_handshake(xmpp); } /* * Gsasl setup */ static gboolean inf_xmpp_connection_sasl_has_mechanism(const char* mechlist, const char* mechanism) { size_t len; const char* res; for(len = strlen(mechanism); mechlist != NULL; mechlist = strchr(res, ' ')) { res = strstr(mechlist, mechanism); if(res == NULL) return FALSE; if( (res == mechlist || isspace(res[ -1])) && (res[len] == '\0' || isspace(res[len]))) return TRUE; } return FALSE; } static void inf_xmpp_connection_sasl_finish(InfXmppConnection* xmpp, gboolean success) { InfXmppConnectionPrivate* priv; priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); /* Can be NULL already if we have aborted the authentication before but were * still waiting for the server to acknowledge. */ if(priv->sasl_session != NULL) { inf_sasl_context_stop_session(priv->sasl_context, priv->sasl_session); priv->sasl_session = NULL; } if(success) { if(priv->sasl_error != NULL) { g_error_free(priv->sasl_error); priv->sasl_error = NULL; } /* Authentication done, switch to AUTH_CONNECTED */ priv->status = INF_XMPP_CONNECTION_AUTH_CONNECTED; if(priv->site == INF_XMPP_CONNECTION_CLIENT) { g_assert(priv->sasl_remote_mechanisms != NULL); g_free(priv->sasl_remote_mechanisms); priv->sasl_remote_mechanisms = NULL; } else { g_assert(priv->sasl_remote_mechanisms == NULL); } /* We might be in a XML callback here, so do not initiate the stream right * now because it replaces the XML parser. The stream is reinitiated in * received_cb(). */ if(priv->parsing == 0) inf_xmpp_connection_initiate(xmpp); } else { /* Authentication failed, switch to AWAITING_FEATURES/INITIATED * for possible retry */ if(priv->site == INF_XMPP_CONNECTION_CLIENT) priv->status = INF_XMPP_CONNECTION_AWAITING_FEATURES; else priv->status = INF_XMPP_CONNECTION_INITIATED; } } /* Emits the error signal for the given SASL error code and sends an * authentication failure to the other site. */ static void inf_xmpp_connection_sasl_error(InfXmppConnection* xmpp, const GError* error) { InfXmppConnectionPrivate* priv; InfXmppConnectionAuthError auth_code; priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); inf_xml_connection_error(INF_XML_CONNECTION(xmpp), error); if(priv->site == INF_XMPP_CONNECTION_SERVER) { /* Find matching auth error code to send to client */ switch(error->code) { case GSASL_UNKNOWN_MECHANISM: case GSASL_MECHANISM_PARSE_ERROR: auth_code = INF_XMPP_CONNECTION_AUTH_ERROR_INVALID_MECHANISM; break; case GSASL_BASE64_ERROR: auth_code = INF_XMPP_CONNECTION_AUTH_ERROR_INCORRECT_ENCODING; break; case GSASL_AUTHENTICATION_ERROR: auth_code = INF_XMPP_CONNECTION_AUTH_ERROR_NOT_AUTHORIZED; break; default: auth_code = INF_XMPP_CONNECTION_AUTH_ERROR_TEMPORARY_AUTH_FAILURE; break; } inf_xmpp_connection_send_auth_error(xmpp, auth_code); /* Reset state to INITIATED so that the client can retry */ priv->status = INF_XMPP_CONNECTION_INITIATED; inf_xmpp_connection_sasl_finish(xmpp, FALSE); } else { inf_xmpp_connection_sasl_finish(xmpp, FALSE); /* Just terminate session on client site when a SASL error occurs */ /* TODO: Better deinitiate here? */ inf_xmpp_connection_terminate(xmpp); } } static void inf_xmpp_connection_sasl_cb(InfSaslContextSession* session, Gsasl_property property, gpointer session_data, gpointer user_data) { InfXmppConnection* xmpp; InfXmppConnectionPrivate* priv; xmpp = INF_XMPP_CONNECTION(user_data); priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); switch(property) { case GSASL_ANONYMOUS_TOKEN: inf_sasl_context_session_set_property( session, GSASL_ANONYMOUS_TOKEN, g_get_user_name() ); inf_sasl_context_session_continue(session, GSASL_OK); break; case GSASL_VALIDATE_ANONYMOUS: /* Authentication always successful */ inf_sasl_context_session_continue(session, GSASL_OK); break; default: /* This callbackfunction is only used when using the built-in SASL * context, and this one only supports anonymous authentication. */ g_assert_not_reached(); inf_sasl_context_session_continue(session, GSASL_NO_CALLBACK); break; } } static gboolean inf_xmpp_connection_sasl_ensure(InfXmppConnection* xmpp) { InfXmppConnectionPrivate* priv; GError* error; priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); if(priv->sasl_context == NULL) { g_assert(priv->sasl_own_context == NULL); error = NULL; priv->sasl_own_context = inf_sasl_context_new(&error); if(priv->sasl_own_context == NULL) { inf_xml_connection_error(INF_XML_CONNECTION(xmpp), error); g_error_free(error); inf_xmpp_connection_terminate(xmpp); return FALSE; } else { priv->sasl_context = priv->sasl_own_context; inf_sasl_context_ref(priv->sasl_context); inf_sasl_context_set_callback( priv->sasl_context, inf_xmpp_connection_sasl_cb, xmpp, NULL ); g_object_notify(G_OBJECT(xmpp), "sasl-context"); } } g_assert(priv->sasl_context != NULL); return TRUE; } static void inf_xmpp_connection_sasl_request_feed_func(InfSaslContextSession* session, const char* data, gboolean needs_more, const GError* error, gpointer user_data) { InfXmppConnection* xmpp; InfXmppConnectionPrivate* priv; xmlNodePtr reply; xmpp = INF_XMPP_CONNECTION(user_data); priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); g_assert(priv->status == INF_XMPP_CONNECTION_AUTHENTICATING); g_assert(priv->sasl_session != NULL); if(error) { inf_xmpp_connection_sasl_error(xmpp, error); } else { /* We do not need to send a challenge when the authentication * has already been completed, but we need to response every * challenge. */ if(data != NULL) { reply = NULL; switch(priv->site) { case INF_XMPP_CONNECTION_SERVER: if(needs_more) reply = inf_xmpp_connection_node_new_sasl("challenge"); break; case INF_XMPP_CONNECTION_CLIENT: reply = inf_xmpp_connection_node_new_sasl("response"); break; default: g_assert_not_reached(); break; } if(reply != NULL) { xmlNodeAddContent(reply, (const xmlChar*)data); inf_xmpp_connection_send_xml(xmpp, reply); xmlFreeNode(reply); } } /* Send authentication success to client when done */ if(!needs_more) { if(priv->site == INF_XMPP_CONNECTION_SERVER) { reply = inf_xmpp_connection_node_new_sasl("success"); inf_xmpp_connection_send_xml(xmpp, reply); xmlFreeNode(reply); inf_xmpp_connection_sasl_finish(xmpp, TRUE); } /* Wait for from server before calling finish on * client side. */ } } } static void inf_xmpp_connection_sasl_request(InfXmppConnection* xmpp, const gchar* input) { InfXmppConnectionPrivate* priv; GError* error; priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); g_assert(priv->status == INF_XMPP_CONNECTION_AUTHENTICATING); g_assert(priv->sasl_session != NULL); if(inf_sasl_context_session_is_processing(priv->sasl_session)) { /* We cannot have two requests at the same time. SASL does not allow this, * the procedure is always * challenge -> response -> challenge -> response -> ... * Also, technically, InfSaslContext does not support * this at the moment. */ error = NULL; inf_gsasl_set_error(&error, GSASL_INTEGRITY_ERROR); inf_xmpp_connection_sasl_error(xmpp, error); g_error_free(error); } else { inf_sasl_context_session_feed( priv->sasl_session, input, inf_xmpp_connection_sasl_request_feed_func, xmpp ); /* Wait for feed_func to be called */ } } static void inf_xmpp_connection_sasl_init(InfXmppConnection* xmpp, const gchar* mechanism) { InfXmppConnectionPrivate* priv; InfIo* io; xmlNodePtr auth; GError* error; priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); g_assert(priv->status != INF_XMPP_CONNECTION_AUTHENTICATING); g_assert(priv->sasl_context != NULL); g_assert(priv->sasl_session == NULL); g_assert(priv->tcp != NULL); if(priv->sasl_error != NULL) { g_error_free(priv->sasl_error); priv->sasl_error = NULL; } g_object_get(G_OBJECT(priv->tcp), "io", &io, NULL); g_assert(io != NULL); switch(priv->site) { case INF_XMPP_CONNECTION_CLIENT: auth = inf_xmpp_connection_node_new_sasl("auth"); xmlNewProp( auth, (const xmlChar*)"mechanism", (const xmlChar*)mechanism ); inf_xmpp_connection_send_xml(xmpp, auth); xmlFreeNode(auth); g_assert(priv->status == INF_XMPP_CONNECTION_AWAITING_FEATURES); error = NULL; priv->sasl_session = inf_sasl_context_client_start_session( priv->sasl_context, io, mechanism, xmpp, &error ); break; case INF_XMPP_CONNECTION_SERVER: g_assert(priv->status == INF_XMPP_CONNECTION_INITIATED); error = NULL; priv->sasl_session = inf_sasl_context_server_start_session( priv->sasl_context, io, mechanism, xmpp, &error ); break; default: g_assert_not_reached(); break; } g_object_unref(io); if(error != NULL) { inf_xmpp_connection_sasl_error(xmpp, error); g_error_free(error); } else { priv->status = INF_XMPP_CONNECTION_AUTHENTICATING; /* Begin on server site */ if(priv->site == INF_XMPP_CONNECTION_SERVER) inf_xmpp_connection_sasl_request(xmpp, NULL); } } /* * XMPP messaging */ /* This does actually process the start_element event after several * special cases have been handled in sax_start_element(). */ static void inf_xmpp_connection_process_start_element(InfXmppConnection* xmpp, const xmlChar* name, const xmlChar** attrs) { InfXmppConnectionPrivate* priv; xmlNodePtr node; const xmlChar** attr; const xmlChar* attr_name; const xmlChar* attr_value; priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); node = xmlNewNode(NULL, name); if(attrs != NULL) { attr = attrs; while(*attr != NULL) { attr_name = *attr; ++ attr; attr_value = *attr; ++ attr; xmlNewProp(node, attr_name, attr_value); } } if(priv->root == NULL) { g_assert(priv->cur == NULL); priv->root = node; priv->cur = node; } else { g_assert(priv->cur != NULL); priv->cur = xmlAddChild(priv->cur, node); } } static void inf_xmpp_connection_process_connected(InfXmppConnection* xmpp, const xmlChar** attrs) { /* TODO: xml:lang and id field are missing here */ static const gchar xmpp_connection_initial_request[] = ""; InfXmppConnectionPrivate* priv; char* mech_list; char* begin; char* end; gchar* reply; xmlNodePtr features; xmlNodePtr starttls; xmlNodePtr mechanisms; xmlNodePtr mechanism; gchar* mechanism_dup; GError* error; priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); g_assert(priv->site == INF_XMPP_CONNECTION_SERVER); g_assert(priv->parser != NULL); g_assert(priv->status == INF_XMPP_CONNECTION_CONNECTED || priv->status == INF_XMPP_CONNECTION_AUTH_CONNECTED); reply = g_strdup_printf( xmpp_connection_initial_request, priv->local_hostname ); inf_xmpp_connection_send_chars(xmpp, reply, strlen(reply)); g_free(reply); /* was sent, so change status to initiated */ switch(priv->status) { case INF_XMPP_CONNECTION_CONNECTED: priv->status = INF_XMPP_CONNECTION_INITIATED; break; case INF_XMPP_CONNECTION_AUTH_CONNECTED: priv->status = INF_XMPP_CONNECTION_AUTH_INITIATED; break; default: g_assert_not_reached(); break; } features = xmlNewNode(NULL, (const xmlChar*)"stream:features"); /* Don't offer TLS if we have already authenticated. It's pointless now. */ if(priv->session == NULL && priv->status != INF_XMPP_CONNECTION_AUTH_INITIATED) { if(priv->security_policy != INF_XMPP_CONNECTION_SECURITY_ONLY_UNSECURED) { starttls = inf_xmpp_connection_node_new_tls("starttls"); xmlAddChild(features, starttls); if(priv->security_policy == INF_XMPP_CONNECTION_SECURITY_ONLY_TLS) xmlNewChild(starttls, NULL, (const xmlChar*)"required", NULL); } } if(priv->status == INF_XMPP_CONNECTION_INITIATED) { /* Not yet authenticated, so give the client a list of authentication * mechanisms. */ mechanisms = inf_xmpp_connection_node_new_sasl("mechanisms"); xmlAddChild(features, mechanisms); /* Ensure that priv->sasl_context exists */ if(inf_xmpp_connection_sasl_ensure(xmpp) == FALSE) { /* Error occured during SASL initialization */ xmlFreeNode(features); return; } else if(priv->sasl_own_context != NULL) { /* Do only provide anonymous authentication when using own context */ xmlNewTextChild( mechanisms, NULL, (const xmlChar*)"mechanism", (const xmlChar*)"ANONYMOUS" ); } else { if(priv->sasl_local_mechanisms == NULL) { error = NULL; mech_list = inf_sasl_context_server_list_mechanisms( priv->sasl_context, &error ); if(error != NULL) { xmlFreeNode(features); inf_xml_connection_error(INF_XML_CONNECTION(xmpp), error); g_error_free(error); inf_xmpp_connection_terminate(xmpp); return; } } else { mech_list = priv->sasl_local_mechanisms; } begin = end = mech_list; while(*end != '\0') { end = strpbrk(begin, " \t\r\n"); if(end == NULL) end = begin + strlen(begin); mechanism_dup = g_strndup(begin, end - begin); if(inf_sasl_context_server_supports_mechanism(priv->sasl_context, mechanism_dup)) { mechanism = xmlNewChild( mechanisms, NULL, (const xmlChar*)"mechanism", NULL ); xmlNodeAddContentLen(mechanism, (const xmlChar*)begin, end - begin); } g_free(mechanism_dup); begin = end + 1; } if(priv->sasl_local_mechanisms == NULL) g_free(mech_list); } } inf_xmpp_connection_send_xml(xmpp, features); xmlFreeNode(features); if(priv->status == INF_XMPP_CONNECTION_AUTH_INITIATED) { /* Authentication done, sent. Session is ready. */ priv->status = INF_XMPP_CONNECTION_READY; g_object_notify(G_OBJECT(xmpp), "status"); } } static void inf_xmpp_connection_process_initiated(InfXmppConnection* xmpp, xmlNodePtr xml) { InfXmppConnectionPrivate* priv; xmlNodePtr proceed; xmlChar* mech; gboolean has_mechanism; priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); g_assert(priv->site == INF_XMPP_CONNECTION_SERVER); g_assert(priv->status == INF_XMPP_CONNECTION_INITIATED); /* TODO: Actually, RFC 3920 specifies in 5.1.3 that we MUST offer the * starttls attribute if the client's stream version is at least 1.0. We * don't do so if security_policy is * INF_XMPP_CONNECTION_SECURITY_ONLY_UNSECURED to allow ad-hoc unsecured * infinote sessions that don't need all this certificate stuff. */ /* I'm not totally sure how to do this in full compliance with the RFC. * Maybe we can ship with a simple self-signed ad-hoc certificate. */ if(priv->session == NULL && priv->security_policy != INF_XMPP_CONNECTION_SECURITY_ONLY_UNSECURED) { if(strcmp((const gchar*)xml->name, "starttls") == 0) { proceed = inf_xmpp_connection_node_new_tls("proceed"); inf_xmpp_connection_send_xml(xmpp, proceed); xmlFreeNode(proceed); inf_xmpp_connection_tls_init(xmpp); } else if(priv->security_policy == INF_XMPP_CONNECTION_SECURITY_ONLY_TLS) { inf_xmpp_connection_terminate_error( xmpp, INF_XMPP_CONNECTION_STREAM_ERROR_NOT_AUTHORIZED, _("Stream is not yet secured with TLS") ); } } /* If we handled one of the cases above, then we don't want to check for * authentication here. In that case, the status has already changed. */ if(priv->status == INF_XMPP_CONNECTION_INITIATED) { /* This should already have been allocated before having sent the list * of mechanisms to the client. */ g_assert(priv->sasl_context != NULL); if(strcmp((const gchar*)xml->name, "auth") == 0) { mech = xmlGetProp(xml, (const xmlChar*)"mechanism"); has_mechanism = TRUE; if(mech == NULL) { has_mechanism = FALSE; } else if(!inf_sasl_context_server_supports_mechanism(priv->sasl_context, (const char*)mech)) { has_mechanism = FALSE; } else if(priv->sasl_own_context == NULL && priv->sasl_local_mechanisms != NULL && !inf_xmpp_connection_sasl_has_mechanism( priv->sasl_local_mechanisms, (const char*)mech)) { has_mechanism = FALSE; } else if(priv->sasl_own_context != NULL && g_ascii_strcasecmp((const char*)mech, "ANONYMOUS") != 0) { has_mechanism = FALSE; } if(has_mechanism) { inf_xmpp_connection_sasl_init(xmpp, (const gchar*)mech); } else { /* Keep state for the client to retry */ inf_xmpp_connection_send_auth_error( xmpp, INF_XMPP_CONNECTION_AUTH_ERROR_INVALID_MECHANISM ); inf_xmpp_connection_emit_auth_error( xmpp, INF_XMPP_CONNECTION_AUTH_ERROR_INVALID_MECHANISM ); } if(mech != NULL) xmlFree(mech); } else { /* Got something else than */ inf_xmpp_connection_terminate_error( xmpp, INF_XMPP_CONNECTION_STREAM_ERROR_NOT_AUTHORIZED, _("Stream is not yet authorized") ); } } } static void inf_xmpp_connection_load_sasl_remote_mechanisms(InfXmppConnection* xmpp, xmlNodePtr xml) { InfXmppConnectionPrivate* priv; GString* mechanisms_string; xmlNodePtr child; priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); g_assert(priv->sasl_remote_mechanisms == NULL); mechanisms_string = g_string_sized_new(128); for(child = xml->children; child != NULL; child = child->next) { if(strcmp((const gchar*)child->name, "mechanism") == 0 && child->children != NULL && child->children->content != NULL) { g_string_append( mechanisms_string, (const char*) child->children->content ); if(child->next != NULL) g_string_append_c(mechanisms_string, ' '); } } priv->sasl_remote_mechanisms = g_string_free(mechanisms_string, FALSE); } static const gchar* inf_xmpp_connection_sasl_suggest_mechanism(InfXmppConnection* xmpp, GError** error) { InfXmppConnectionPrivate* priv; GString* mechanisms_string; GString* mechanism_string; char* iter; char* end; const gchar* suggestion; gboolean has_mechanism; priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); suggestion = NULL; if(priv->sasl_own_context != NULL) { /* We only support ANONYMOUS authentication when using the built-in * SASL context. */ for(iter = priv->sasl_remote_mechanisms; *iter; iter = end + 1) { end = strchr(iter, ' '); if(end == NULL) { if(strcmp(iter, "ANONYMOUS") == 0) suggestion = "ANONYMOUS"; break; } if(strncmp(iter, "ANONYMOUS", MAX((size_t) (end - iter), sizeof("ANONYMOUS") - 1)) == 0) { suggestion = "ANONYMOUS"; break; } } } else { mechanisms_string = g_string_sized_new(128); mechanism_string = g_string_sized_new(16); /* should fit most names */ for(end = iter = priv->sasl_remote_mechanisms; end; iter = end + 1) { end = strchr(iter, ' '); if(end != NULL) { g_string_overwrite_len(mechanism_string, 0, iter, end - iter); g_string_truncate(mechanism_string, end - iter); iter = mechanism_string->str; } has_mechanism = inf_sasl_context_client_supports_mechanism(priv->sasl_context, iter); if(has_mechanism == TRUE && priv->sasl_local_mechanisms != NULL) { has_mechanism = inf_xmpp_connection_sasl_has_mechanism( priv->sasl_local_mechanisms, iter ); } if(has_mechanism == TRUE) { if(mechanisms_string->len > 0) g_string_append_c(mechanisms_string, ' '); g_string_append(mechanisms_string, iter); } } if(mechanisms_string->len > 0) { suggestion = inf_sasl_context_client_suggest_mechanism( priv->sasl_context, mechanisms_string->str ); } g_string_free(mechanisms_string, TRUE); } if(suggestion == NULL) { g_set_error_literal( error, inf_xmpp_connection_error_quark(), INF_XMPP_CONNECTION_ERROR_NO_SUITABLE_MECHANISM, _("The server does not offer a suitable authentication mechanism") ); } return suggestion; } static void inf_xmpp_connection_process_features(InfXmppConnection* xmpp, xmlNodePtr xml) { InfXmppConnectionPrivate* priv; xmlNodePtr child; xmlNodePtr req; xmlNodePtr starttls; const char* suggestion; GError* error; priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); g_assert(priv->site == INF_XMPP_CONNECTION_CLIENT); g_assert(priv->status == INF_XMPP_CONNECTION_AWAITING_FEATURES || priv->status == INF_XMPP_CONNECTION_AUTH_AWAITING_FEATURES); if(strcmp((const gchar*)xml->name, "stream:features") != 0) { /* Server sent something else. Don't know what it is, so let us ignore it. * Perhaps the we are waiting for follows later. */ return; } /* Don't try TLS anymore if we are already authenticated. This can happen * if the server only offers TLS after authentication, but that's stupid. */ else if(priv->status == INF_XMPP_CONNECTION_AWAITING_FEATURES && priv->session == NULL) { for(child = xml->children; child != NULL; child = child->next) if(strcmp((const gchar*)child->name, "starttls") == 0) break; /* Server has no StartTLS feature. We don't like that. */ if(child == NULL && priv->security_policy == INF_XMPP_CONNECTION_SECURITY_ONLY_TLS) { error = g_error_new_literal( inf_xmpp_connection_error_quark(), INF_XMPP_CONNECTION_ERROR_TLS_UNSUPPORTED, _("The server does not support transport layer security (TLS)") ); inf_xml_connection_error(INF_XML_CONNECTION(xmpp), error); g_error_free(error); inf_xmpp_connection_deinitiate(xmpp); } else if(child != NULL) { for(req = child->children; req != NULL; req = req->next) if(strcmp((const gchar*)req->name, "required") == 0) break; if(req != NULL && priv->security_policy == INF_XMPP_CONNECTION_SECURITY_ONLY_UNSECURED) { error = NULL; g_set_error_literal( &error, inf_xmpp_connection_error_quark(), INF_XMPP_CONNECTION_ERROR_TLS_REQUIRED, _("The server requires transport layer security (TLS)") ); inf_xml_connection_error(INF_XML_CONNECTION(xmpp), error); g_error_free(error); inf_xmpp_connection_deinitiate(xmpp); } /* The server supports TLS. Now, request TLS if it's required or if * we do prefer it. */ else if(req != NULL || inf_xmpp_connection_prefers_tls(xmpp)) { starttls = inf_xmpp_connection_node_new_tls("starttls"); inf_xmpp_connection_send_xml(xmpp, starttls); xmlFreeNode(starttls); priv->status = INF_XMPP_CONNECTION_ENCRYPTION_REQUESTED; } } } /* If we did not request TLS above, then go on with authentication */ if(priv->status == INF_XMPP_CONNECTION_AWAITING_FEATURES) { for(child = xml->children; child != NULL; child = child->next) if(strcmp((const gchar*)child->name, "mechanisms") == 0) break; /* Server does not provide authentication mechanisms */ if(child == NULL) { error = g_error_new_literal( inf_xmpp_connection_error_quark(), INF_XMPP_CONNECTION_ERROR_AUTHENTICATION_UNSUPPORTED, _("The server does not provide any authentication mechanism") ); inf_xml_connection_error(INF_XML_CONNECTION(xmpp), error); g_error_free(error); inf_xmpp_connection_deinitiate(xmpp); } else if(inf_xmpp_connection_sasl_ensure(xmpp) == TRUE) { inf_xmpp_connection_load_sasl_remote_mechanisms(xmpp, child); error = NULL; suggestion = inf_xmpp_connection_sasl_suggest_mechanism(xmpp, &error); if(!suggestion) { inf_xml_connection_error(INF_XML_CONNECTION(xmpp), error); g_error_free(error); /* Deinitiate if error signal handler does not retry authentication */ if(priv->status == INF_XMPP_CONNECTION_AWAITING_FEATURES) inf_xmpp_connection_deinitiate(xmpp); } else { inf_xmpp_connection_sasl_init(xmpp, suggestion); } } } else if(priv->status == INF_XMPP_CONNECTION_AUTH_AWAITING_FEATURES) { priv->status = INF_XMPP_CONNECTION_READY; g_object_notify(G_OBJECT(xmpp), "status"); } } static void inf_xmpp_connection_process_encryption(InfXmppConnection* xmpp, xmlNodePtr xml) { InfXmppConnectionPrivate* priv; GError* error; priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); g_assert(priv->site == INF_XMPP_CONNECTION_CLIENT); g_assert(priv->status == INF_XMPP_CONNECTION_ENCRYPTION_REQUESTED); g_assert(priv->session == NULL); if(strcmp((const gchar*)xml->name, "proceed") == 0) { inf_xmpp_connection_tls_init(xmpp); } else if(strcmp((const gchar*)xml->name, "failure") == 0) { error = g_error_new_literal( inf_xmpp_connection_error_quark(), INF_XMPP_CONNECTION_ERROR_TLS_FAILURE, _("The server cannot perform the TLS handshake") ); inf_xml_connection_error(INF_XML_CONNECTION(xmpp), error); g_error_free(error); /* The server is required to close the stream after failure, so wait * for . */ priv->status = INF_XMPP_CONNECTION_CLOSING_STREAM; g_object_notify(G_OBJECT(xmpp), "status"); } else { /* We got neither 'proceed' nor 'failure'. Ignore and wait for either * of them. */ } } static void inf_xmpp_connection_process_authentication_error( InfXmppConnection* xmpp, InfXmppConnectionAuthError auth_code) { InfXmppConnectionPrivate* priv; priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); g_assert(priv->site == INF_XMPP_CONNECTION_CLIENT); g_assert(priv->status == INF_XMPP_CONNECTION_AUTHENTICATING); inf_xmpp_connection_sasl_finish(xmpp, FALSE); inf_xmpp_connection_emit_auth_error(xmpp, auth_code); /* Deinitiate connection if the signal handler of the auth error did not * call inf_xmpp_connection_retry_sasl_authentication(). */ if(priv->status == INF_XMPP_CONNECTION_AWAITING_FEATURES) inf_xmpp_connection_deinitiate(xmpp); } static void inf_xmpp_connection_process_authentication(InfXmppConnection* xmpp, xmlNodePtr xml) { InfXmppConnectionPrivate* priv; InfXmppConnectionAuthError auth_code; xmlNodePtr child; xmlNodePtr error_node; xmlChar* content; GError* local_error; priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); g_assert(priv->status == INF_XMPP_CONNECTION_AUTHENTICATING); switch(priv->site) { case INF_XMPP_CONNECTION_CLIENT: if(strcmp((const gchar*)xml->name, "challenge") == 0) { /* Ignore if authentication was aborted by * inf_xmpp_connection_reset_sasl_authentication() */ if(priv->sasl_session != NULL) { /* Process challenge from server */ content = xmlNodeGetContent(xml); inf_xmpp_connection_sasl_request(xmpp, (const gchar*)content); xmlFree(content); } } else if(strcmp((const gchar*)xml->name, "failure") == 0) { child = xml->children; auth_code = INF_XMPP_CONNECTION_AUTH_ERROR_FAILED; if(child != NULL) { error_node = child->children; if(error_node != NULL && strcmp((const char*)error_node->name, "error") == 0) { g_assert(priv->sasl_error == NULL); priv->sasl_error = inf_xml_util_new_error_from_node(error_node); } auth_code = inf_xmpp_connection_auth_error_from_condition( (const gchar*)child->name ); } inf_xmpp_connection_process_authentication_error(xmpp, auth_code); } else if(strcmp((const gchar*)xml->name, "success") == 0) { inf_xmpp_connection_sasl_finish(xmpp, TRUE); } else { /* Unknown request. Ignore. */ } break; case INF_XMPP_CONNECTION_SERVER: if(strcmp((const gchar*)xml->name, "response") == 0) { if(priv->sasl_session != NULL) { /* Process client reponse */ content = xmlNodeGetContent(xml); inf_xmpp_connection_sasl_request(xmpp, (const gchar*)content); xmlFree(content); } else { /* If priv->sasl_session is NULL then the authentication was aborted * via inf_xmpp_connection_reset_sasl_authentication(). */ inf_xmpp_connection_sasl_finish(xmpp, FALSE); /* Build and set detail error to send to client */ local_error = g_error_new_literal( inf_authentication_detail_error_quark(), INF_AUTHENTICATION_DETAIL_ERROR_TRY_AGAIN, inf_authentication_detail_strerror( INF_AUTHENTICATION_DETAIL_ERROR_TRY_AGAIN) ); inf_xmpp_connection_set_sasl_error(xmpp, local_error); g_error_free(local_error); /* Notify client that the authentication failed and ask it to try again */ inf_xmpp_connection_send_auth_error( xmpp, INF_XMPP_CONNECTION_AUTH_ERROR_TEMPORARY_AUTH_FAILURE ); inf_xmpp_connection_emit_auth_error( xmpp, INF_XMPP_CONNECTION_AUTH_ERROR_TEMPORARY_AUTH_FAILURE ); /* Can be reset if a signal handler retried or * reset the authentication. */ if(priv->sasl_error) { g_error_free(priv->sasl_error); priv->sasl_error = NULL; } } } else if(strcmp((const gchar*)xml->name, "abort") == 0) { /* Fall back to initiated state, wait for another auth request. */ inf_xmpp_connection_sasl_finish(xmpp, FALSE); inf_xmpp_connection_send_auth_error( xmpp, INF_XMPP_CONNECTION_AUTH_ERROR_ABORTED ); inf_xmpp_connection_emit_auth_error( xmpp, INF_XMPP_CONNECTION_AUTH_ERROR_ABORTED ); } break; default: g_assert_not_reached(); break; } } /* This actually processes the end element after having handled some * special cases in sax_end_element(). */ static void inf_xmpp_connection_process_end_element(InfXmppConnection* xmpp, const xmlChar* name) { InfXmppConnectionPrivate* priv; InfXmppConnectionStreamError stream_code; GError* error; priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); g_assert(priv->cur != NULL); /* This should have raised a sax_error. */ g_assert(strcmp((const gchar*)priv->cur->name, (const gchar*)name) == 0); priv->cur = priv->cur->parent; if(priv->cur == NULL) { /* Got a complete XML message */ if(strcmp((const gchar*)name, "stream:error") == 0) { /* Just emit error signal in this case. If the stream is supposed to * be closed, a should follow. */ stream_code = INF_XMPP_CONNECTION_STREAM_ERROR_FAILED; if(priv->root->children != NULL) { stream_code = inf_xmpp_connection_stream_error_from_condition( (const gchar*)priv->root->children->name ); } error = NULL; g_set_error_literal( &error, inf_xmpp_connection_stream_error_quark, stream_code, inf_xmpp_connection_stream_strerror(stream_code) ); /* TODO: Incorporate text child of the stream:error request, if any */ inf_xml_connection_error(INF_XML_CONNECTION(xmpp), error); g_error_free(error); } else { switch(priv->status) { case INF_XMPP_CONNECTION_INITIATED: /* The client should be waiting for from the server * in this state, and sax_end_element() should not have called this * function. */ g_assert(priv->site == INF_XMPP_CONNECTION_SERVER); inf_xmpp_connection_process_initiated(xmpp, priv->root); break; case INF_XMPP_CONNECTION_AWAITING_FEATURES: case INF_XMPP_CONNECTION_AUTH_AWAITING_FEATURES: /* This is a client-only state */ g_assert(priv->site == INF_XMPP_CONNECTION_CLIENT); inf_xmpp_connection_process_features(xmpp, priv->root); break; case INF_XMPP_CONNECTION_ENCRYPTION_REQUESTED: /* This is a client-only state */ g_assert(priv->site == INF_XMPP_CONNECTION_CLIENT); inf_xmpp_connection_process_encryption(xmpp, priv->root); break; case INF_XMPP_CONNECTION_AUTHENTICATING: inf_xmpp_connection_process_authentication(xmpp, priv->root); break; case INF_XMPP_CONNECTION_READY: inf_xml_connection_received(INF_XML_CONNECTION(xmpp), priv->root); break; case INF_XMPP_CONNECTION_CLOSING_STREAM: /* We are waiting for . It can be that we receive * other XML nodes from the remote side before that happens, but we * ignore them here. */ break; case INF_XMPP_CONNECTION_AUTH_INITIATED: /* The client should be waiting for from the server * in this state, and sax_end_element should not have called this * function. Also, this is a client-only state (the server goes * directly to READY after having received ). */ case INF_XMPP_CONNECTION_CONNECTING: case INF_XMPP_CONNECTION_CONNECTED: case INF_XMPP_CONNECTION_AUTH_CONNECTED: case INF_XMPP_CONNECTION_HANDSHAKING: case INF_XMPP_CONNECTION_CLOSING_GNUTLS: case INF_XMPP_CONNECTION_CLOSED: default: g_assert_not_reached(); break; } } xmlFreeNode(priv->root); priv->root = NULL; priv->cur = NULL; } } static void inf_xmpp_connection_sax_start_element(void* context, const xmlChar* name, const xmlChar** attrs) { InfXmppConnection* xmpp; InfXmppConnectionPrivate* priv; xmpp = INF_XMPP_CONNECTION(context); priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); /* This can happen when both a chunk which causes the connection to * terminate and the start of an element happen in the same call to * xmlParseChunk */ if(priv->status == INF_XMPP_CONNECTION_CLOSING_GNUTLS) return; switch(priv->status) { case INF_XMPP_CONNECTION_CONNECTED: case INF_XMPP_CONNECTION_AUTH_CONNECTED: /* The first thing the client does in this state is sending * and switching to the initiated state. */ g_assert(priv->site == INF_XMPP_CONNECTION_SERVER); if(strcmp((const gchar*)name, "stream:stream") != 0) { /* Did not get , but something else. */ /* TODO: Produce an error here, so the user knows what happened */ inf_xmpp_connection_terminate(xmpp); } else { /* Got from client, send response */ inf_xmpp_connection_process_connected(xmpp, attrs); } break; case INF_XMPP_CONNECTION_INITIATED: case INF_XMPP_CONNECTION_AUTH_INITIATED: if(priv->site == INF_XMPP_CONNECTION_CLIENT) { /* We are waiting for from the server. */ if(strcmp((const gchar*)name, "stream:stream") != 0) { /* Did not get , but something else. */ inf_xmpp_connection_terminate(xmpp); } else { /* Got , wait for now so that * we can start TLS or authentication if the server supports it. */ /* TODO: Read server's JID, if a from field is given? However, the RFC * suggests we SHOULD silently ignore it. */ if(priv->status == INF_XMPP_CONNECTION_INITIATED) priv->status = INF_XMPP_CONNECTION_AWAITING_FEATURES; else priv->status = INF_XMPP_CONNECTION_AUTH_AWAITING_FEATURES; } } else { inf_xmpp_connection_process_start_element(xmpp, name, attrs); } break; case INF_XMPP_CONNECTION_CLOSING_STREAM: /* We are still processing messages if we are waiting for * , but are discarding them. */ case INF_XMPP_CONNECTION_AWAITING_FEATURES: case INF_XMPP_CONNECTION_AUTH_AWAITING_FEATURES: case INF_XMPP_CONNECTION_ENCRYPTION_REQUESTED: case INF_XMPP_CONNECTION_AUTHENTICATING: case INF_XMPP_CONNECTION_READY: inf_xmpp_connection_process_start_element(xmpp, name, attrs); break; case INF_XMPP_CONNECTION_CLOSING_GNUTLS: case INF_XMPP_CONNECTION_HANDSHAKING: /* received_cb should not call the XML parser in these states */ case INF_XMPP_CONNECTION_CLOSED: case INF_XMPP_CONNECTION_CONNECTING: /* We should not even receive something in these states */ default: g_assert_not_reached(); break; } } static void inf_xmpp_connection_sax_end_element(void* context, const xmlChar* name) { InfXmppConnection* xmpp; InfXmppConnectionPrivate* priv; xmpp = INF_XMPP_CONNECTION(context); priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); g_assert(priv->status != INF_XMPP_CONNECTION_HANDSHAKING); /* This can happen when both a chunk which causes the connection to * terminate and the end of an element happen in the same call to * xmlParseChunk */ if(priv->status == INF_XMPP_CONNECTION_CLOSING_GNUTLS) return; /* If we are not in the toplevel (directly in ) but in some * child, process this normally because it belongs to a child. */ if(priv->root != NULL) { inf_xmpp_connection_process_end_element(xmpp, name); } else { /* Should have caused an error in the XML parser otherwise. The only case * where we get an end element for the top-level which is not * stream:stream is when the remote part sent a non-stream:stream opening * tag and the corresponding closing tag in one go so that we process both * in the same XML parser invocation. In that case * inf_xmpp_connection_sax_start_element resets the connection status * however so also check for that here. See also bug #546. */ g_assert(strcmp((const gchar*)name, "stream:stream") == 0 || priv->status == INF_XMPP_CONNECTION_CLOSING_GNUTLS || priv->status == INF_XMPP_CONNECTION_CLOSED); switch(priv->status) { case INF_XMPP_CONNECTION_CLOSING_STREAM: /* This is the we were waiting for. */ case INF_XMPP_CONNECTION_AUTHENTICATING: /* I think we should receive a failure first, but some evil server * might send directly. */ case INF_XMPP_CONNECTION_INITIATED: case INF_XMPP_CONNECTION_AUTH_INITIATED: case INF_XMPP_CONNECTION_AWAITING_FEATURES: case INF_XMPP_CONNECTION_AUTH_AWAITING_FEATURES: case INF_XMPP_CONNECTION_ENCRYPTION_REQUESTED: case INF_XMPP_CONNECTION_READY: /* Also terminate stream in these states */ inf_xmpp_connection_terminate(xmpp); break; case INF_XMPP_CONNECTION_CLOSED: case INF_XMPP_CONNECTION_CLOSING_GNUTLS: /* This can happen if the connection was terminated by start_element and * the XML parser processed the corresponding end tag in the same * xmlParseChunk() invocation. */ break; case INF_XMPP_CONNECTION_CONNECTED: case INF_XMPP_CONNECTION_AUTH_CONNECTED: /* We should not get before we got , * which would have caused us to change into the INITIATED state. The * XML parser should have reported an error in this case. */ case INF_XMPP_CONNECTION_HANDSHAKING: /* received_cb should not call the XML parser in these states */ case INF_XMPP_CONNECTION_CONNECTING: /* We should not even receive something in these states */ default: g_assert_not_reached(); break; } } } static void inf_xmpp_connection_sax_characters(void* context, const xmlChar* content, int len) { InfXmppConnection* xmpp; InfXmppConnectionPrivate* priv; xmpp = INF_XMPP_CONNECTION(context); priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); g_assert(priv->status != INF_XMPP_CONNECTION_HANDSHAKING); if(priv->root == NULL) { /* Someone sent content of the node. Ignore. */ } else { g_assert(priv->cur != NULL); xmlNodeAddContentLen(priv->cur, content, len); } } static void inf_xmpp_connection_sax_warning(void* context, const char* msg, ...) { InfXmppConnection* xmpp; InfXmppConnectionPrivate* priv; InfIpAddress* address; gchar* addr_str; gchar* warn_str; va_list arglist; xmpp = INF_XMPP_CONNECTION(context); priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); g_object_get(G_OBJECT(priv->tcp), "remote-address", &address, NULL); addr_str = inf_ip_address_to_string(address); inf_ip_address_free(address); va_start(arglist, msg); warn_str = g_strdup_vprintf(msg, arglist); va_end(arglist); /* XML Warning from : */ g_warning(_("XML warning from %s: %s\n"), addr_str, warn_str); g_free(addr_str); g_free(warn_str); } static void inf_xmpp_connection_sax_error(void* context, const char* msg, ...) { InfXmppConnection* xmpp; InfXmppConnectionPrivate* priv; InfXmppConnectionStreamError stream_code; xmlErrorPtr error_xml; const gchar* message; xmpp = INF_XMPP_CONNECTION(context); priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); error_xml = xmlCtxtGetLastError(priv->parser); g_assert(error_xml != NULL); /* The XML parser should not be called in this state */ g_assert(priv->status != INF_XMPP_CONNECTION_HANDSHAKING); /* This can happen when both a chunk which causes the connection to * terminate and an error happens in the same call to xmlParseChunk */ if(priv->status == INF_XMPP_CONNECTION_CLOSING_GNUTLS) return; /* If we are in this state, the server waits already on a GnuTLS * handshake, so we cannot send arbitrary XML here. Also cannot * send without having sent . */ if(priv->status != INF_XMPP_CONNECTION_ENCRYPTION_REQUESTED && priv->status != INF_XMPP_CONNECTION_CONNECTED && priv->status != INF_XMPP_CONNECTION_AUTH_CONNECTED) { /* TODO: Get more accurate error information from stream error */ stream_code = INF_XMPP_CONNECTION_STREAM_ERROR_BAD_FORMAT; if(error_xml->domain == XML_FROM_PARSER && error_xml->code == XML_ERR_DOCUMENT_EMPTY) { /* The server sent something which is not XML */ message = _("Remote site is not an XMPP server"); } else { /* TODO: Strip leading and trailing whitespace from message */ message = error_xml->message; } inf_xmpp_connection_terminate_error(xmpp, stream_code, message); } else { /* Just terminate connection without sending stream:error */ inf_xmpp_connection_terminate(xmpp); } } static xmlSAXHandler inf_xmpp_connection_handler = { NULL, /* internalSubset */ NULL, /* isStandalone */ NULL, /* hasInternalSubset */ NULL, /* hasExternalSubset */ NULL, /* resolveEntity */ NULL, /* getEntity */ NULL, /* entityDecl */ NULL, /* notationDecl */ NULL, /* attributeDecl */ NULL, /* elementDecl */ NULL, /* unparsedEntityDecl */ NULL, /* setDocumentLocator */ NULL, /* startDocument */ NULL, /* endDocument */ inf_xmpp_connection_sax_start_element, /* startElement */ inf_xmpp_connection_sax_end_element, /* endElement */ NULL, /* reference */ inf_xmpp_connection_sax_characters, /* characters */ NULL, /* ignorableWhitespace */ NULL, /* processingInstruction */ NULL, /* comment */ inf_xmpp_connection_sax_warning, /* warning */ /* We treat error and fatal error the same */ inf_xmpp_connection_sax_error, /* error */ inf_xmpp_connection_sax_error, /* fatalError */ NULL, /* getParameterEntity */ NULL, /* cdataBlock */ NULL, /* externalSubset */ 0, /* initialized */ NULL, /* _private */ NULL, /* startElementNs */ NULL, /* endElementNs */ NULL /* serror */ }; static void inf_xmpp_connection_initiate(InfXmppConnection* xmpp) { static const gchar xmpp_connection_initial_request[] = ""; InfXmppConnectionPrivate* priv; gchar* request; priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); g_assert(priv->status == INF_XMPP_CONNECTION_CONNECTED || priv->status == INF_XMPP_CONNECTION_AUTH_CONNECTED); /* Create XML parser for incoming data */ if(priv->parser != NULL) xmlFreeParserCtxt(priv->parser); priv->parser = xmlCreatePushParserCtxt( &inf_xmpp_connection_handler, xmpp, NULL, 0, NULL ); /* Create XML buffer for outgoing data */ if(priv->buf == NULL) { priv->buf = xmlBufferCreate(); priv->doc = xmlNewDoc((const xmlChar*)"1.0"); } if(priv->site == INF_XMPP_CONNECTION_CLIENT) { request = g_strdup_printf( xmpp_connection_initial_request, priv->remote_hostname ); inf_xmpp_connection_send_chars(xmpp, request, strlen(request)); g_free(request); switch(priv->status) { case INF_XMPP_CONNECTION_CONNECTED: priv->status = INF_XMPP_CONNECTION_INITIATED; break; case INF_XMPP_CONNECTION_AUTH_CONNECTED: priv->status = INF_XMPP_CONNECTION_AUTH_INITIATED; break; default: g_assert_not_reached(); break; } } } /* * Signal handlers. */ static void inf_xmpp_connection_received_cb_sent_func(InfXmppConnection* xmpp, gpointer user_data) { InfXmppConnectionPrivate* priv; priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); /* Terminating and GnuTLS bye have been sent, so * close underlaying TCP connection. This will trigger a TCP status * notify. */ inf_tcp_connection_close(priv->tcp); } static void inf_xmpp_connection_sent_cb(InfTcpConnection* tcp, gconstpointer data, guint len, gpointer user_data) { InfXmppConnection* xmpp; InfXmppConnectionPrivate* priv; InfXmppConnectionMessage* message; gboolean have_sent; xmpp = INF_XMPP_CONNECTION(user_data); priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); g_assert(priv->position >= len); g_object_ref(G_OBJECT(xmpp)); priv->position -= len; if(priv->messages != NULL) { have_sent = priv->messages->sent; /* Flag all messages that have been sent by this call */ for(message = priv->messages; message != NULL; message = message->next) { if(!message->sent) { if(message->position <= len) message->sent = TRUE; else message->position -= len; } } /* Note that a complete execution of this function doesn't keep messages * with sent flag set to TRUE in the queue. So if the sent flag was FALSE, * the method has been called recursively by a sent callback. In that * case, don't do anything here but let the parent call do all other sent * callbacks. */ if(have_sent == FALSE) { /* Now call sent func on all flagged messages */ while(priv->messages != NULL && priv->messages->sent) { if(priv->messages->sent_func != NULL) priv->messages->sent_func(xmpp, priv->messages->user_data); /* Note that the sent func might have called _clear() in which case all * messages have already been removed. */ if(priv->messages != NULL) inf_xmpp_connection_pop_message(xmpp); } } } g_object_unref(G_OBJECT(xmpp)); } static void inf_xmpp_connection_received_cb(InfTcpConnection* tcp, gconstpointer data, guint len, gpointer user_data) { InfXmppConnection* xmpp; InfXmppConnectionPrivate* priv; gchar buffer[2048]; ssize_t res; GError* error; gboolean receiving; xmpp = INF_XMPP_CONNECTION(user_data); priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); /* We just keep the connection open to send a final gnutls bye and * in this state, any input gets discarded. */ if(priv->status == INF_XMPP_CONNECTION_CLOSING_GNUTLS) return; g_object_ref(xmpp); g_assert(priv->parsing == 0); g_assert(priv->parser != NULL); /* Let callbacks know that we start XML parsing. In case of deinitialization * this tells them to keep the XML parser alive. We clean up after parsing * in that case. */ ++priv->parsing; /* If we have a GnuTLS session, prepare data to be read by * gnutls_record_recv(). */ if(priv->session != NULL) { g_assert(priv->pull_len == 0); priv->pull_data = data; priv->pull_len = len; } if(priv->status == INF_XMPP_CONNECTION_HANDSHAKING) { g_assert(priv->session != NULL); inf_xmpp_connection_tls_handshake(xmpp); } /* Note that this is not an else branch, since if the XMPP handshake * finishes, the status will change and then we process initial data * here, if any. */ if(priv->status != INF_XMPP_CONNECTION_HANDSHAKING && priv->status != INF_XMPP_CONNECTION_CLOSING_GNUTLS) { if(priv->session != NULL) { receiving = TRUE; while(receiving && (priv->pull_len > 0 || gnutls_record_check_pending(priv->session) > 0)) { res = gnutls_record_recv(priv->session, buffer, 2048); if(res < 0) { /* Just try again if we were interrupted */ if(res != GNUTLS_E_INTERRUPTED && res != GNUTLS_E_AGAIN) { /* A TLS error occured. */ error = NULL; inf_gnutls_set_error(&error, res); inf_xml_connection_error(INF_XML_CONNECTION(xmpp), error); g_error_free(error); /* We cannot assume that GnuTLS is working enough to send a * final or something, so just close the * underlaying TCP connection. */ inf_tcp_connection_close(priv->tcp); receiving = FALSE; } } else if(res == 0) { /* Remote site sent gnutls_bye. This involves session closure. */ inf_tcp_connection_close(priv->tcp); receiving = FALSE; } else { /* Feed decoded data into XML parser */ if(INF_XMPP_CONNECTION_PRINT_TRAFFIC) printf("\033[00;32m%.*s\033[00;00m\n", (int)res, buffer); xmlParseChunk(priv->parser, buffer, res, 0); /* If the callback changed made us disconnect then don't try * to read more data. */ if(priv->status == INF_XMPP_CONNECTION_CLOSING_GNUTLS || priv->status == INF_XMPP_CONNECTION_CLOSED) { receiving = FALSE; } } } } else { /* Feed input directly into XML parser */ if(INF_XMPP_CONNECTION_PRINT_TRAFFIC) printf("\033[00;31m%.*s\033[00;00m\n", (int)len, (const char*)data); xmlParseChunk(priv->parser, data, len, 0); } } g_assert(priv->parsing > 0); if(--priv->parsing == 0) { if(priv->status == INF_XMPP_CONNECTION_CLOSING_GNUTLS || priv->status == INF_XMPP_CONNECTION_CLOSED) { /* Status changed to CLOSING_GNUTLS, this means that someone called * _terminate(). Clean up any resources in use (XML parser, GnuTLS * session etc. */ inf_xmpp_connection_clear(xmpp); if(priv->status != INF_XMPP_CONNECTION_CLOSED) { /* Close the TCP connection after remaining stuff has been sent out * in case it is not closed already. */ inf_xmpp_connection_push_message( xmpp, inf_xmpp_connection_received_cb_sent_func, NULL, NULL ); } g_object_notify(G_OBJECT(xmpp), "status"); } else if(priv->status == INF_XMPP_CONNECTION_AUTH_CONNECTED) { /* Reinitiate connection after successful authentication */ /* TODO: Only do this if status at the beginning of this call was * AUTHENTICATING */ inf_xmpp_connection_initiate(xmpp); } } g_object_unref(xmpp); } static void inf_xmpp_connection_error_cb(InfTcpConnection* tcp, GError* error, gpointer user_data) { /* Do not modify status because we get a status change notify from the * TCP connection little later anyway. */ inf_xml_connection_error(INF_XML_CONNECTION(user_data), error); } static void inf_xmpp_connection_notify_status_cb(InfTcpConnection* tcp, GParamSpec* pspec, gpointer user_data) { InfXmppConnection* xmpp; InfXmppConnectionPrivate* priv; InfTcpConnectionStatus tcp_status; xmpp = INF_XMPP_CONNECTION(user_data); priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); g_object_get(G_OBJECT(tcp), "status", &tcp_status, NULL); switch(tcp_status) { case INF_TCP_CONNECTION_CLOSED: if(priv->status != INF_XMPP_CONNECTION_CLOSED) { /* If we are currently parsing XML (because this was called from a * signal handler) then we can't delete the XML parser here (otherwise * libxml2 crashes, understandably). Instead, just set the status to * closed and clean up after XML parsing in _received_cb(). */ /* TODO: We should do the full cleanup here, and _received_cb() and * send_chars should copy/ref everything they need on the stack. */ if(priv->parsing == 0) inf_xmpp_connection_clear(xmpp); priv->status = INF_XMPP_CONNECTION_CLOSED; priv->position = 0; if(priv->parsing == 0) g_object_notify(G_OBJECT(xmpp), "status"); } else { g_assert(priv->session == NULL); g_assert(priv->messages == NULL); g_assert(priv->parser == NULL); g_assert(priv->doc == NULL); g_assert(priv->position == 0); g_assert(priv->sasl_session == NULL); } break; case INF_TCP_CONNECTION_CONNECTING: g_assert(priv->status == INF_XMPP_CONNECTION_CLOSED); if(priv->status != INF_XMPP_CONNECTION_CONNECTING) { priv->status = INF_XMPP_CONNECTION_CONNECTING; g_object_notify(G_OBJECT(xmpp), "status"); } break; case INF_TCP_CONNECTION_CONNECTED: /* Clear previous certificates before opening a new connection */ if(priv->own_cert != NULL) { gnutls_x509_crt_deinit(priv->own_cert); priv->own_cert = NULL; g_object_notify(G_OBJECT(xmpp), "local-certificate"); } if(priv->peer_cert != NULL) { inf_certificate_chain_unref(priv->peer_cert); priv->peer_cert = NULL; g_object_notify(G_OBJECT(xmpp), "remote-certificate"); } g_assert(priv->status == INF_XMPP_CONNECTION_CONNECTING); /* No notify required, because it does not change the xml status */ priv->status = INF_XMPP_CONNECTION_CONNECTED; inf_xmpp_connection_initiate(xmpp); break; default: g_assert_not_reached(); break; } } /* * Utility functions. */ static void inf_xmpp_connection_set_tcp(InfXmppConnection* xmpp, InfTcpConnection* tcp) { InfXmppConnectionPrivate* priv; InfTcpConnectionStatus tcp_status; priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); g_object_freeze_notify(G_OBJECT(xmpp)); if(priv->tcp != NULL) { g_object_get(G_OBJECT(priv->tcp), "status", &tcp_status, NULL); /* This will cause a status notify which will actually delete * GnuTLS session (if any) and the message queue. */ if(tcp_status != INF_TCP_CONNECTION_CLOSED) inf_tcp_connection_close(priv->tcp); /* Make sure there is no SASL session running anymore... it's not a big * deal if there was but it should be aborted by the above call to * inf_tcp_connection_close(). */ g_assert(priv->sasl_session == NULL); inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->tcp), G_CALLBACK(inf_xmpp_connection_sent_cb), xmpp ); inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->tcp), G_CALLBACK(inf_xmpp_connection_received_cb), xmpp ); inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->tcp), G_CALLBACK(inf_xmpp_connection_error_cb), xmpp ); inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->tcp), G_CALLBACK(inf_xmpp_connection_notify_status_cb), xmpp ); g_object_unref(G_OBJECT(priv->tcp)); } priv->tcp = tcp; if(tcp != NULL) { g_object_ref(G_OBJECT(tcp)); g_signal_connect( G_OBJECT(tcp), "sent", G_CALLBACK(inf_xmpp_connection_sent_cb), xmpp ); g_signal_connect( G_OBJECT(tcp), "received", G_CALLBACK(inf_xmpp_connection_received_cb), xmpp ); g_signal_connect( G_OBJECT(tcp), "error", G_CALLBACK(inf_xmpp_connection_error_cb), xmpp ); g_signal_connect( G_OBJECT(tcp), "notify::status", G_CALLBACK(inf_xmpp_connection_notify_status_cb), xmpp ); g_object_get(G_OBJECT(tcp), "status", &tcp_status, NULL); switch(tcp_status) { case INF_TCP_CONNECTION_CLOSED: g_assert(priv->status == INF_XMPP_CONNECTION_CLOSED); break; case INF_TCP_CONNECTION_CONNECTING: priv->status = INF_XMPP_CONNECTION_CONNECTING; g_object_notify(G_OBJECT(xmpp), "status"); break; case INF_TCP_CONNECTION_CONNECTED: /* Do not call initiate, this will be done in constructor little * time later. */ priv->status = INF_XMPP_CONNECTION_CONNECTED; g_object_notify(G_OBJECT(xmpp), "status"); break; default: g_assert_not_reached(); break; } } g_object_thaw_notify(G_OBJECT(xmpp)); } static InfXmlConnectionStatus inf_xmpp_connection_get_xml_status(InfXmppConnection* xmpp) { InfXmppConnectionPrivate* priv; priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); switch(priv->status) { case INF_XMPP_CONNECTION_CONNECTING: case INF_XMPP_CONNECTION_CONNECTED: case INF_XMPP_CONNECTION_AUTH_CONNECTED: case INF_XMPP_CONNECTION_INITIATED: case INF_XMPP_CONNECTION_AUTH_INITIATED: case INF_XMPP_CONNECTION_AWAITING_FEATURES: case INF_XMPP_CONNECTION_AUTH_AWAITING_FEATURES: case INF_XMPP_CONNECTION_ENCRYPTION_REQUESTED: case INF_XMPP_CONNECTION_HANDSHAKING: case INF_XMPP_CONNECTION_AUTHENTICATING: return INF_XML_CONNECTION_OPENING; case INF_XMPP_CONNECTION_READY: return INF_XML_CONNECTION_OPEN; case INF_XMPP_CONNECTION_CLOSING_STREAM: case INF_XMPP_CONNECTION_CLOSING_GNUTLS: return INF_XML_CONNECTION_CLOSING; case INF_XMPP_CONNECTION_CLOSED: return INF_XML_CONNECTION_CLOSED; default: g_assert_not_reached(); return INF_XML_CONNECTION_CLOSED; } } static gchar* inf_xmpp_connection_get_address_id(InfIpAddress* addr, guint port) { gchar* addr_str; gchar* addr_id; addr_str = inf_ip_address_to_string(addr); switch(inf_ip_address_get_family(addr)) { case INF_IP_ADDRESS_IPV4: addr_id = g_strdup_printf("%s:%u", addr_str, port); break; case INF_IP_ADDRESS_IPV6: addr_id = g_strdup_printf("[%s]:%u", addr_str, port); break; default: g_assert_not_reached(); break; } g_free(addr_str); return addr_id; } /* * GObject overrides */ static void inf_xmpp_connection_init(InfXmppConnection* connection) { InfXmppConnectionPrivate* priv; priv = INF_XMPP_CONNECTION_PRIVATE(connection); priv->tcp = NULL; priv->site = INF_XMPP_CONNECTION_CLIENT; priv->status = INF_XMPP_CONNECTION_CLOSED; priv->local_hostname = NULL; priv->remote_hostname = NULL; priv->security_policy = INF_XMPP_CONNECTION_SECURITY_BOTH_PREFER_TLS; priv->certificate_request = GNUTLS_CERT_IGNORE; priv->certificate_callback = NULL; priv->certificate_callback_user_data = NULL; priv->certificate_callback_notify = NULL; priv->position = 0; priv->messages = NULL; priv->last_message = NULL; priv->parsing = 0; priv->parser = NULL; priv->root = NULL; priv->cur = NULL; priv->doc = NULL; priv->buf = NULL; priv->session = NULL; priv->creds = NULL; priv->own_cert = NULL; priv->peer_cert = NULL; priv->pull_data = NULL; priv->pull_len = 0; priv->sasl_context = NULL; priv->sasl_own_context = NULL; priv->sasl_session = NULL; priv->sasl_local_mechanisms = NULL; priv->sasl_remote_mechanisms = NULL; priv->sasl_error = NULL; } static void inf_xmpp_connection_constructed(GObject* object) { InfXmppConnectionPrivate* priv; InfTcpConnectionStatus status; G_OBJECT_CLASS(inf_xmpp_connection_parent_class)->constructed(object); priv = INF_XMPP_CONNECTION_PRIVATE(object); g_assert(priv->tcp != NULL); if(priv->local_hostname == NULL) priv->local_hostname = g_strdup(g_get_host_name()); g_object_get(G_OBJECT(priv->tcp), "status", &status, NULL); /* Initiate stream if connection is already established */ if(status == INF_TCP_CONNECTION_CONNECTED) inf_xmpp_connection_initiate(INF_XMPP_CONNECTION(object)); /* If we are an the server and allow TLS, then we do need credentials for * this. We can't create them ourselves, because it requires * a certificate. */ g_assert( priv->security_policy == INF_XMPP_CONNECTION_SECURITY_ONLY_UNSECURED || priv->site == INF_XMPP_CONNECTION_CLIENT || priv->creds != NULL ); } static void inf_xmpp_connection_dispose(GObject* object) { InfXmppConnection* xmpp; InfXmppConnectionPrivate* priv; xmpp = INF_XMPP_CONNECTION(object); priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); inf_xmpp_connection_set_tcp(xmpp, NULL); g_assert(priv->session == NULL); g_assert(priv->sasl_session == NULL); if(priv->own_cert != NULL) { gnutls_x509_crt_deinit(priv->own_cert); priv->own_cert = NULL; g_object_notify(G_OBJECT(xmpp), "local-certificate"); } if(priv->peer_cert != NULL) { inf_certificate_chain_unref(priv->peer_cert); priv->peer_cert = NULL; g_object_notify(G_OBJECT(xmpp), "remote-certificate"); } if(priv->sasl_own_context != NULL) { inf_sasl_context_unref(priv->sasl_own_context); priv->sasl_own_context = NULL; } if(priv->sasl_context != NULL) { inf_sasl_context_unref(priv->sasl_context); priv->sasl_context = NULL; } if(priv->creds != NULL) { inf_certificate_credentials_unref(priv->creds); priv->creds = NULL; } G_OBJECT_CLASS(inf_xmpp_connection_parent_class)->dispose(object); } static void inf_xmpp_connection_finalize(GObject* object) { InfXmppConnection* xmpp; InfXmppConnectionPrivate* priv; xmpp = INF_XMPP_CONNECTION(object); priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); g_free(priv->local_hostname); g_free(priv->remote_hostname); g_free(priv->sasl_local_mechanisms); g_free(priv->sasl_remote_mechanisms); if(priv->certificate_callback_notify != NULL) priv->certificate_callback_notify(priv->certificate_callback_user_data); if(priv->sasl_error) g_error_free(priv->sasl_error); G_OBJECT_CLASS(inf_xmpp_connection_parent_class)->finalize(object); } static void inf_xmpp_connection_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfXmppConnection* xmpp; InfXmppConnectionPrivate* priv; xmpp = INF_XMPP_CONNECTION(object); priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); switch(prop_id) { case PROP_TCP: inf_xmpp_connection_set_tcp( xmpp, INF_TCP_CONNECTION(g_value_get_object(value)) ); break; case PROP_SITE: /* Site can only been changed if the initial has not * yet been sent. */ g_assert(priv->status == INF_XMPP_CONNECTION_CONNECTING || priv->status == INF_XMPP_CONNECTION_CONNECTED || priv->status == INF_XMPP_CONNECTION_CLOSED); priv->site = g_value_get_enum(value); break; case PROP_LOCAL_HOSTNAME: /* Can only change this if the initial has not * yet been sent. */ g_assert(priv->status == INF_XMPP_CONNECTION_CONNECTING || priv->status == INF_XMPP_CONNECTION_CONNECTED || priv->status == INF_XMPP_CONNECTION_CLOSED); g_free(priv->local_hostname); priv->local_hostname = g_value_dup_string(value); if(priv->local_hostname == NULL) priv->local_hostname = g_strdup(g_get_host_name()); break; case PROP_REMOTE_HOSTNAME: /* Can only change this if the initial has not * yet been sent. */ g_assert(priv->status == INF_XMPP_CONNECTION_CONNECTING || priv->status == INF_XMPP_CONNECTION_CONNECTED || priv->status == INF_XMPP_CONNECTION_CLOSED); g_free(priv->remote_hostname); priv->remote_hostname = g_value_dup_string(value); break; case PROP_SECURITY_POLICY: priv->security_policy = g_value_get_enum(value); break; case PROP_CREDENTIALS: /* Cannot change credentials when currently in use */ g_assert(priv->session == NULL); if(priv->creds != NULL) inf_certificate_credentials_unref(priv->creds); priv->creds = g_value_dup_boxed(value); break; case PROP_SASL_CONTEXT: /* Cannot change context when currently in use */ /* Use inf_xmpp_connection_reset_sasl_authentication() * to change it any time. */ g_assert(priv->sasl_session == NULL); if(priv->sasl_own_context != NULL) { inf_sasl_context_unref(priv->sasl_own_context); priv->sasl_own_context = NULL; } if(priv->sasl_context != NULL) inf_sasl_context_unref(priv->sasl_context); priv->sasl_context = g_value_dup_boxed(value); break; case PROP_SASL_MECHANISMS: /* Cannot change context when currently in use */ /* Use inf_xmpp_connection_reset_sasl_authentication() * to change it any time. */ g_assert(priv->sasl_session == NULL); g_free(priv->sasl_local_mechanisms); priv->sasl_local_mechanisms = g_value_dup_string(value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void inf_xmpp_connection_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfXmppConnection* xmpp; InfXmppConnectionPrivate* priv; InfIpAddress* addr; guint port; gchar* id; xmpp = INF_XMPP_CONNECTION(object); priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); switch(prop_id) { case PROP_TCP: g_value_set_object(value, G_OBJECT(priv->tcp)); break; case PROP_SITE: g_value_set_enum(value, priv->site); break; case PROP_LOCAL_HOSTNAME: g_value_set_string(value, priv->local_hostname); break; case PROP_REMOTE_HOSTNAME: g_value_set_string(value, priv->remote_hostname); break; case PROP_SECURITY_POLICY: g_value_set_enum(value, priv->security_policy); break; case PROP_TLS_ENABLED: g_value_set_boolean(value, inf_xmpp_connection_get_tls_enabled(xmpp)); break; case PROP_CREDENTIALS: g_value_set_boxed(value, priv->creds); break; case PROP_SASL_CONTEXT: g_value_set_boxed(value, priv->sasl_context); break; case PROP_SASL_MECHANISMS: g_value_set_string(value, priv->sasl_local_mechanisms); break; case PROP_STATUS: g_value_set_enum(value, inf_xmpp_connection_get_xml_status(xmpp)); break; case PROP_NETWORK: g_value_set_static_string(value, "tcp/ip"); break; case PROP_LOCAL_ID: /* TODO: Perhaps we could also use JIDs here, but we have to make sure * then that they are unique within the whole network, which is * not so easy, and address/port serves the purpose equally well. */ g_object_get( G_OBJECT(priv->tcp), "local-address", &addr, "local-port", &port, NULL ); id = inf_xmpp_connection_get_address_id(addr, port); inf_ip_address_free(addr); g_value_take_string(value, id); break; case PROP_REMOTE_ID: addr = inf_tcp_connection_get_remote_address(priv->tcp); port = inf_tcp_connection_get_remote_port(priv->tcp); id = inf_xmpp_connection_get_address_id(addr, port); g_value_take_string(value, id); break; case PROP_LOCAL_CERTIFICATE: g_value_set_pointer(value, priv->own_cert); break; case PROP_REMOTE_CERTIFICATE: g_value_set_boxed(value, priv->peer_cert); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } /* * InfXmlConnection interface implementation */ static void inf_xmpp_connection_xml_connection_send_sent(InfXmppConnection* xmpp, gpointer xml) { inf_xml_connection_sent(INF_XML_CONNECTION(xmpp), (xmlNodePtr)xml); } static void inf_xmpp_connection_xml_connection_send_free(InfXmppConnection* xmpp, gpointer xml) { xmlFreeNode((xmlNodePtr)xml); } static gboolean inf_xmpp_connection_xml_connection_open(InfXmlConnection* connection, GError** error) { InfXmppConnectionPrivate* priv; InfTcpConnectionStatus status; priv = INF_XMPP_CONNECTION_PRIVATE(connection); g_assert(priv->status == INF_XMPP_CONNECTION_CLOSED); g_assert(priv->tcp != NULL); /* TODO: If we are in CLOSING state, we could go to a state such as * INF_XMPP_CONNECTION_CLOSING_RECONNECT which reconnects after the * closing has finished. */ g_object_get(G_OBJECT(priv->tcp), "status", &status, NULL); g_assert(status == INF_TCP_CONNECTION_CLOSED); return inf_tcp_connection_open(priv->tcp, error); } static void inf_xmpp_connection_xml_connection_close(InfXmlConnection* connection) { InfXmppConnectionPrivate* priv; priv = INF_XMPP_CONNECTION_PRIVATE(connection); /* Connection is already being closed */ g_assert(priv->status != INF_XMPP_CONNECTION_CLOSING_STREAM && priv->status != INF_XMPP_CONNECTION_CLOSING_GNUTLS && priv->status != INF_XMPP_CONNECTION_CLOSED); switch(priv->status) { case INF_XMPP_CONNECTION_CONNECTING: inf_tcp_connection_close(priv->tcp); break; case INF_XMPP_CONNECTION_CONNECTED: case INF_XMPP_CONNECTION_AUTH_CONNECTED: g_assert(priv->parsing == 0); inf_xmpp_connection_terminate(INF_XMPP_CONNECTION(connection)); /* TODO: Shouldn't we close the TCP connection here, as in * inf_xmpp_connection_received_cb()? */ break; case INF_XMPP_CONNECTION_HANDSHAKING: case INF_XMPP_CONNECTION_ENCRYPTION_REQUESTED: /* TODO: Perhaps we should wait for the TLS handshake being finished * and then close the connection regularly. */ /* I don't think we can do more here to make the closure more * explicit */ g_assert(priv->session != NULL); gnutls_deinit(priv->session); priv->session = NULL; /* This will cause a status property notify which will actually set * the xmpp status */ inf_tcp_connection_close(priv->tcp); break; case INF_XMPP_CONNECTION_AUTHENTICATING: /* TODO: I think we should send an request here and then * wait on either successful or unsuccessful authentication result, * and then close the connection normally. Actually, this is what * inf_xmpp_connection_deinitiate is supposed to do. */ g_assert(priv->parsing == 0); inf_xmpp_connection_terminate(INF_XMPP_CONNECTION(connection)); /* TODO: Shouldn't we close the TCP connection here, as in * inf_xmpp_connection_received_cb()? */ break; case INF_XMPP_CONNECTION_INITIATED: case INF_XMPP_CONNECTION_AUTH_INITIATED: case INF_XMPP_CONNECTION_AWAITING_FEATURES: case INF_XMPP_CONNECTION_AUTH_AWAITING_FEATURES: case INF_XMPP_CONNECTION_READY: inf_xmpp_connection_deinitiate(INF_XMPP_CONNECTION(connection)); break; default: g_assert_not_reached(); break; } } static void inf_xmpp_connection_xml_connection_send(InfXmlConnection* connection, xmlNodePtr xml) { InfXmppConnectionPrivate* priv; priv = INF_XMPP_CONNECTION_PRIVATE(connection); g_assert(priv->status == INF_XMPP_CONNECTION_READY); inf_xmpp_connection_send_xml(INF_XMPP_CONNECTION(connection), xml); /* It can happen that while calling inf_xmpp_connection_send_xml we * notice that the connection is down. Only proceed with sent notification * if the connection is still up and we could actually send the thing. */ if(priv->status == INF_XMPP_CONNECTION_READY) { inf_xmpp_connection_push_message( INF_XMPP_CONNECTION(connection), inf_xmpp_connection_xml_connection_send_sent, inf_xmpp_connection_xml_connection_send_free, xml ); } else { xmlFreeNode(xml); } } /* * GObject type registration */ static void inf_xmpp_connection_class_init(InfXmppConnectionClass* xmpp_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(xmpp_class); object_class->constructed = inf_xmpp_connection_constructed; object_class->dispose = inf_xmpp_connection_dispose; object_class->finalize = inf_xmpp_connection_finalize; object_class->set_property = inf_xmpp_connection_set_property; object_class->get_property = inf_xmpp_connection_get_property; inf_xmpp_connection_stream_error_quark = g_quark_from_static_string( "INF_XMPP_CONNECTION_STREAM_ERROR" ); inf_xmpp_connection_auth_error_quark = g_quark_from_static_string( "INF_XMPP_CONNECTION_AUTH_ERROR" ); g_object_class_install_property( object_class, PROP_TCP, g_param_spec_object( "tcp-connection", "TCP connection", "Underlaying TCP connection", INF_TYPE_TCP_CONNECTION, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_SITE, g_param_spec_enum( "site", "Site", "Site of the connection (client or server)", INF_TYPE_XMPP_CONNECTION_SITE, INF_XMPP_CONNECTION_CLIENT, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_LOCAL_HOSTNAME, g_param_spec_string( "local-hostname", "Local hostname", "The hostname of the local host", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_REMOTE_HOSTNAME, g_param_spec_string( "remote-hostname", "Remote hostname", "The hostname of the remote host", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_SECURITY_POLICY, g_param_spec_enum( "security-policy", "Security policy", "How to choose whether to use (or offer, as a server) TLS", INF_TYPE_XMPP_CONNECTION_SECURITY_POLICY, INF_XMPP_CONNECTION_SECURITY_BOTH_PREFER_TLS, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_TLS_ENABLED, g_param_spec_boolean( "tls-enabled", "TLS enabled", "Whether TLS is enabled for the connection or not", FALSE, G_PARAM_READABLE ) ); g_object_class_install_property( object_class, PROP_CREDENTIALS, g_param_spec_boxed( "credentials", "Credentials", "The certificate credentials for GnuTLS", INF_TYPE_CERTIFICATE_CREDENTIALS, G_PARAM_READWRITE | G_PARAM_CONSTRUCT ) ); g_object_class_install_property( object_class, PROP_SASL_CONTEXT, g_param_spec_boxed( "sasl-context", "SASL context", "The SASL context used for authentication", INF_TYPE_SASL_CONTEXT, G_PARAM_READWRITE | G_PARAM_CONSTRUCT ) ); g_object_class_install_property( object_class, PROP_SASL_MECHANISMS, g_param_spec_string( "sasl-mechanisms", "SASL Mechanisms", "Whitespace separated list of SASL mechanisms to accept/offer", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT ) ); g_object_class_override_property(object_class, PROP_STATUS, "status"); g_object_class_override_property(object_class, PROP_NETWORK, "network"); g_object_class_override_property(object_class, PROP_LOCAL_ID, "local-id"); g_object_class_override_property(object_class, PROP_REMOTE_ID, "remote-id"); g_object_class_override_property( object_class, PROP_LOCAL_CERTIFICATE, "local-certificate" ); g_object_class_override_property( object_class, PROP_REMOTE_CERTIFICATE, "remote-certificate" ); } static void inf_xmpp_connection_xml_connection_iface_init( InfXmlConnectionInterface* iface) { iface->open = inf_xmpp_connection_xml_connection_open; iface->close = inf_xmpp_connection_xml_connection_close; iface->send = inf_xmpp_connection_xml_connection_send; } /* * Public API */ /** * inf_xmpp_connection_new: (constructor) * @tcp: The underlaying TCP connection to use. * @site: Whether this is a XMPP client or server. * @local_hostname: (allow-none): The hostname of the local host, or %NULL. * @remote_hostname: The hostname of the remote host. * @security_policy: Whether to use (or offer, as a server) TLS. See * #InfXmppConnectionSecurityPolicy for the meaning of this parameter. * @creds: (allow-none): Certificate credentials used to secure the * communication. * @sasl_context: (allow-none): A SASL context used for authentication. * @sasl_mechanisms: (allow-none): A whitespace-separated list of SASL * mechanisms to accept/offer, or %NULL. * * Creates a new #InfXmppConnection with @tcp as communication channel. No * attempt is being made to open @tcp, if it is not already open. However, * communication is initiated as soon as @tcp gets into * %INF_TCP_CONNECTION_CONNECTED state, so you might still open it * lateron yourself. * * @local_hostname specifies the hostname of the local host, and * @remote_hostname specifies the hostname of the remote host, as known to * the caller. These can be a string representation of the IP address of * @tcp, or a DNS name such as "example.com". @local_hostname can be %NULL * in which case the host name as reported by g_get_host_name() is used. * * @creds may be %NULL in which case the connection creates the credentials * as soon as they are required. However, this only works if * @site is %INF_XMPP_CONNECTION_CLIENT or @security_policy is * %INF_XMPP_CONNECTION_SECURITY_ONLY_UNSECURED (or both, of course). For * server connections @creds must contain a valid server certificate in case * @security_policy is not %INF_XMPP_CONNECTION_SECURITY_ONLY_UNSECURED. * @creds can contain a certificate for the client site and, if so, is used * for client authentication. * * If @sasl_context is %NULL, #InfXmppConnection uses a built-in context * that only supports ANONYMOUS authentication. In @sasl_context's * callback function, the #InfXmppConnection for which the authentication * shall be performed can be accessed via the @session_data parameter of * #InfSaslContextCallbackFunc. * * If @sasl_context is not %NULL, then the @sasl_mechanisms parameter defines * what SASL mechanisms are used. On the server side, these are the mechanisms * offered to the client, and on the client side, these are the accepted * mechanisms (meaning that if a server does not offer any of these, the * connection will be closed). If @sasl_context is %NULL, then this parameter * is ignored. @sasl_mechanisms can be %NULL in which case all available * mechanisms are accepted or offered, respectively. * * Returns: (transfer full): A new #InfXmppConnection. **/ InfXmppConnection* inf_xmpp_connection_new(InfTcpConnection* tcp, InfXmppConnectionSite site, const gchar* local_hostname, const gchar* remote_hostname, InfXmppConnectionSecurityPolicy security_policy, InfCertificateCredentials* creds, InfSaslContext* sasl_context, const gchar* sasl_mechanisms) { GObject* object; g_return_val_if_fail(INF_IS_TCP_CONNECTION(tcp), NULL); g_return_val_if_fail( security_policy == INF_XMPP_CONNECTION_SECURITY_ONLY_UNSECURED || site == INF_XMPP_CONNECTION_CLIENT || creds != NULL, NULL ); object = g_object_new( INF_TYPE_XMPP_CONNECTION, "tcp-connection", tcp, "site", site, "local-hostname", local_hostname, "remote-hostname", remote_hostname, "security-policy", security_policy, "credentials", creds, "sasl-context", sasl_context, "sasl-mechanisms", sasl_mechanisms, NULL ); return INF_XMPP_CONNECTION(object); } /** * inf_xmpp_connection_get_tls_enabled: * @xmpp: A #InfXmppConnection. * * Returns whether TLS encryption is enabled for @xmpp. This returns %TRUE * as soon as the TLS handshake is completed but before the server certificate * was verified (see inf_xmpp_connection_set_certificate_callback()). * * Returns: %TRUE if TLS is enabled and %FALSE otherwise. */ gboolean inf_xmpp_connection_get_tls_enabled(InfXmppConnection* xmpp) { InfXmppConnectionPrivate* priv; g_return_val_if_fail(INF_IS_XMPP_CONNECTION(xmpp), FALSE); priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); if(priv->status == INF_XMPP_CONNECTION_HANDSHAKING) return FALSE; if(priv->session == NULL) return FALSE; return TRUE; } /** * inf_xmpp_connection_get_own_certificate: * @xmpp: A #InfXmppConnection. * * Returns the local host's certificate that was used to authenticate with * the remote host, or %NULL if no certificate was used. This function can * only be used after the TLS handshake has completed, see * inf_xmpp_connection_get_tls_enabled(). * * Returns: (transfer none): The certificate of the local host. The returned * value should not be freed, it is owned by the #InfXmppConnection. */ gnutls_x509_crt_t inf_xmpp_connection_get_own_certificate(InfXmppConnection* xmpp) { InfXmppConnectionPrivate* priv; g_return_val_if_fail(INF_IS_XMPP_CONNECTION(xmpp), NULL); g_return_val_if_fail(inf_xmpp_connection_get_tls_enabled(xmpp), NULL); priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); return priv->own_cert; } /** * inf_xmpp_connection_get_peer_certificate: * @xmpp: A #InfXmppConnection. * * Returns the certificate chain that the remote host authenticated itself * with. This function can only be used after the TLS handshake has completed, * see inf_xmpp_connection_get_tls_enabled(). * * Returns: (transfer none): The certificate chain of the remote host. The * returned value should not be freed, it is owned by the #InfXmppConnection. */ InfCertificateChain* inf_xmpp_connection_get_peer_certificate(InfXmppConnection* xmpp) { InfXmppConnectionPrivate* priv; g_return_val_if_fail(INF_IS_XMPP_CONNECTION(xmpp), NULL); g_return_val_if_fail(inf_xmpp_connection_get_tls_enabled(xmpp), NULL); priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); return priv->peer_cert; } /** * inf_xmpp_connection_get_kx_algorithm: * @xmpp: A #InfXmppConnection. * * Returns the key exchange algorithm used for this connection. This function * can only be used if inf_xmpp_connection_get_tls_enabled() returns true. * * Returns: The key exchange algorithm used. */ gnutls_kx_algorithm_t inf_xmpp_connection_get_kx_algorithm(InfXmppConnection* xmpp) { InfXmppConnectionPrivate* priv; g_return_val_if_fail(INF_IS_XMPP_CONNECTION(xmpp), GNUTLS_KX_UNKNOWN); g_return_val_if_fail( inf_xmpp_connection_get_tls_enabled(xmpp), GNUTLS_KX_UNKNOWN ); priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); return gnutls_kx_get(priv->session); } /** * inf_xmpp_connection_get_cipher_algorithm: * @xmpp: A #InfXmppConnection. * * Returns the cipher algorithm used for this connection. This function can * only be used if inf_xmpp_connection_get_tls_enabled() returns true. * * Returns: The cipher algorithm used. */ gnutls_cipher_algorithm_t inf_xmpp_connection_get_cipher_algorithm(InfXmppConnection* xmpp) { InfXmppConnectionPrivate* priv; g_return_val_if_fail(INF_IS_XMPP_CONNECTION(xmpp), GNUTLS_CIPHER_UNKNOWN); g_return_val_if_fail( inf_xmpp_connection_get_tls_enabled(xmpp), GNUTLS_CIPHER_UNKNOWN ); priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); return gnutls_cipher_get(priv->session); } /** * inf_xmpp_connection_get_mac_algorithm: * @xmpp: A #InfXmppConnection. * * Returns the MAC algorithm used for this connection. This function can * only be used if inf_xmpp_connection_get_tls_enabled() returns true. * * Returns: The MAC algorithm used. */ gnutls_mac_algorithm_t inf_xmpp_connection_get_mac_algorithm(InfXmppConnection* xmpp) { InfXmppConnectionPrivate* priv; g_return_val_if_fail(INF_IS_XMPP_CONNECTION(xmpp), GNUTLS_MAC_UNKNOWN); g_return_val_if_fail( inf_xmpp_connection_get_tls_enabled(xmpp), GNUTLS_MAC_UNKNOWN ); priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); return gnutls_mac_get(priv->session); } /** * inf_xmpp_connection_get_tls_protocol: * @xmpp: A #InfXmppConnection. * * Returns the TLS protocol version used for this connection. This function * can only be used if inf_xmpp_connection_get_tls_enabled() returns true. * * Returns: The TLS protocol version used. */ gnutls_protocol_t inf_xmpp_connection_get_tls_protocol(InfXmppConnection* xmpp) { InfXmppConnectionPrivate* priv; g_return_val_if_fail(INF_IS_XMPP_CONNECTION(xmpp), GNUTLS_VERSION_UNKNOWN); g_return_val_if_fail( inf_xmpp_connection_get_tls_enabled(xmpp), GNUTLS_VERSION_UNKNOWN ); priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); return gnutls_protocol_get_version(priv->session); } /** * inf_xmpp_connection_get_dh_prime_bits: * @xmpp: A #InfXmppConnection. * * Returns the number of prime bits used for the Diffie-Hellman group if * a key exchange algorithm based on Diffie-Hellman is used. Otherwise, 0 * is returned. This function can only be used if * inf_xmpp_connection_get_tls_enabled() returns true. * * Returns: The number of Diffie-Hellman prime bits. */ guint inf_xmpp_connection_get_dh_prime_bits(InfXmppConnection* xmpp) { InfXmppConnectionPrivate* priv; int bits; g_return_val_if_fail(INF_IS_XMPP_CONNECTION(xmpp), 0); g_return_val_if_fail(inf_xmpp_connection_get_tls_enabled(xmpp), 0); priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); bits = gnutls_dh_get_prime_bits(priv->session); /* This is essentially a workaround since some GnuTLS versions report an * error instead of 0 when no DH key exchange was used. */ if(bits < 0) bits = 0; return (guint)bits; } /** * inf_xmpp_connection_set_certificate_callback: * @xmpp: A #InfXmppConnection. * @req: (type int): Whether to request a client certificate from the peer. * @cb: (allow-none): Function to be called to verify the peer's * certificate, or %NULL. * @user_data: Additional data to pass to the callback function. * @notify: (allow-none): Function to call to free the user data, or %NULL. * * This function sets a callback that is called when the connection needs to * verify the peer's certificate. It does not need to respond immediately, * but can, for example, show a dialog to a user and continue when the user * finished with it. * * When the certificate is trusted, then call * inf_xmpp_connection_certificate_verify_continue(), * otherwise inf_xmpp_connection_certificate_verify_cancel(). This can happen * in the callback or some time later. The connection process is stopped until * either of these functions is called. * * Note that the function is also called if the peer did not send a * certificate, in which case the certificate chain parameter in the callback * will be %NULL. * * If @cb is %NULL, or this function has not been called before a certificate * needs to be verified, then the certificate is always trusted. */ void inf_xmpp_connection_set_certificate_callback(InfXmppConnection* xmpp, gnutls_certificate_request_t req, InfXmppConnectionCrtCallback cb, gpointer user_data, GDestroyNotify notify) { InfXmppConnectionPrivate* priv; g_return_if_fail(INF_IS_XMPP_CONNECTION(xmpp)); priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); if(priv->certificate_callback_notify != NULL) priv->certificate_callback_notify(priv->certificate_callback_user_data); priv->certificate_request = req; priv->certificate_callback = cb; priv->certificate_callback_user_data = user_data; priv->certificate_callback_notify = notify; } /** * inf_xmpp_connection_certificate_verify_continue: * @xmpp: A #InfXmppConnection. * * Call this function when your callback set in * inf_xmpp_connection_set_certificate_callback() was called and you do trust * the peer's certificate. The connection process will then continue. */ void inf_xmpp_connection_certificate_verify_continue(InfXmppConnection* xmpp) { InfXmppConnectionPrivate* priv; g_return_if_fail(INF_IS_XMPP_CONNECTION(xmpp)); priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); g_return_if_fail(priv->status == INF_XMPP_CONNECTION_CONNECTED); g_return_if_fail(priv->session != NULL); inf_xmpp_connection_initiate(xmpp); } /** * inf_xmpp_connection_certificate_verify_cancel: * @xmpp: A #InfXmppConnection. * @error: Reason why the certificate is not trusted, or %NULL. * * Call this function when your callback set in * inf_xmpp_connection_set_certificate_callback() was called and you do not * trust the peer's certificate. The connection will then be closed with a * corresponding error. * * If @error is non-%NULL, then it should contain a reason why the certificate * was not trusted. If you verified the peer's certificate with * gnutls_certificate_verify_peers2(), or gnutls_x509_crt_list_verify(), then * a corresponding error can be generated with the verification result * with inf_gnutls_certificate_verification_set_error(). The reason is then * shown to the local user. */ void inf_xmpp_connection_certificate_verify_cancel(InfXmppConnection* xmpp, const GError* error) { InfXmppConnectionPrivate* priv; GError* local_error; g_return_if_fail(INF_IS_XMPP_CONNECTION(xmpp)); priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); g_return_if_fail(priv->status == INF_XMPP_CONNECTION_CONNECTED); g_return_if_fail(priv->session != NULL); if(priv->site == INF_XMPP_CONNECTION_CLIENT) { if(error == NULL) { local_error = g_error_new_literal( inf_xmpp_connection_error_quark(), INF_XMPP_CONNECTION_ERROR_CERTIFICATE_NOT_TRUSTED, _("The server certificate is not trusted") ); } else { local_error = g_error_new( inf_xmpp_connection_error_quark(), INF_XMPP_CONNECTION_ERROR_CERTIFICATE_NOT_TRUSTED, _("The server certificate is not trusted: %s"), error->message ); } } else { if(error == NULL) { local_error = g_error_new_literal( inf_xmpp_connection_error_quark(), INF_XMPP_CONNECTION_ERROR_CERTIFICATE_NOT_TRUSTED, _("The client certificate is not trusted") ); } else { local_error = g_error_new( inf_xmpp_connection_error_quark(), INF_XMPP_CONNECTION_ERROR_CERTIFICATE_NOT_TRUSTED, _("The client certificate is not trusted: %s"), error->message ); } } inf_xml_connection_error(INF_XML_CONNECTION(xmpp), local_error); g_error_free(local_error); inf_xmpp_connection_terminate(xmpp); } /** * inf_xmpp_connection_reset_sasl_authentication: * @xmpp: A #InfXmppConnection. * @new_context: (allow-none): The new sasl context to set, or %NULL. * @new_mechanisms: (allow-none): Allowed SASL mechanisms to use. Ignored if * @new_context is %NULL. * * Sets a new SASL context and mechanisms to use for authentication. This does * not have any effect if authentication has already been performed. This can * be useful if a server decides to use a stricter authentication policy and * gets away with its previous SASL context. If @new_context is %NULL, then a * built-in SASL context is used which only accepts anonymous authentication. * * If the authentication is currently in progress then it is aborted. The * server sends an %INF_XMPP_CONNECTION_AUTH_ERROR_TEMPORARY_AUTH_FAILURE * error to the client with %INF_AUTHENTICATION_DETAIL_ERROR_TRY_AGAIN detail * (see inf_xmpp_connection_get_sasl_error()). * * On the client side, if authentication is in progress, a request to abort * the authentication is sent to the server. The server will then reply with * an %INF_XMPP_CONNECTION_AUTH_ERROR_ABORTED error. In the signal handler of * the #InfXmlConnection::error signal you should reinitiate the authentication * with inf_xmpp_connection_retry_sasl_authentication() or the connection will * be closed. It is also possible that the final authentication request has * already been sent, and the server replies with successful authentication * instead. In that case calling this function will have no effect apart from * closing and reopening the connection will use the new context and * mechanisms. */ void inf_xmpp_connection_reset_sasl_authentication(InfXmppConnection* xmpp, InfSaslContext* new_context, const gchar* new_mechanisms) { InfXmppConnectionPrivate* priv; xmlNodePtr xml; g_return_if_fail(INF_IS_XMPP_CONNECTION(xmpp)); priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); if(priv->status == INF_XMPP_CONNECTION_AUTHENTICATING) { switch(priv->site) { case INF_XMPP_CONNECTION_CLIENT: /* Send abort, wait for server reply (finish or failure), ignoring * challenges while doing so. Reset sasl_session to NULL to notify that * we are done with this session, but keep status while we are waiting * for server acknowledgement. The server might also be done with * authentication already. */ if(priv->sasl_session != NULL) { xml = inf_xmpp_connection_node_new_sasl("abort"); inf_xmpp_connection_send_xml(xmpp, xml); inf_sasl_context_stop_session(priv->sasl_context, priv->sasl_session); priv->sasl_session = NULL; } break; case INF_XMPP_CONNECTION_SERVER: /* Reset current SASL negotiation. Wait for client reply to current * challenge until we tell it to avoid race conditions. */ if(priv->sasl_session != NULL) { inf_sasl_context_stop_session(priv->sasl_context, priv->sasl_session); priv->sasl_session = NULL; } break; default: g_assert_not_reached(); break; } } if(priv->sasl_own_context != NULL) { inf_sasl_context_unref(priv->sasl_own_context); priv->sasl_own_context = NULL; } if(priv->sasl_context != NULL) inf_sasl_context_unref(priv->sasl_context); priv->sasl_context = new_context; if(new_context != NULL) inf_sasl_context_ref(new_context); g_free(priv->sasl_local_mechanisms); priv->sasl_local_mechanisms = g_strdup(new_mechanisms); g_object_freeze_notify(G_OBJECT(xmpp)); /* sasl_ensure also notifies */ if(new_context == NULL) { if(!inf_xmpp_connection_sasl_ensure(xmpp)) { /* OK, that's quite tough, but it should happen only rarely anyway, * and I don't think there is much we can do about it. This happens * when gsasl initialization of the built-in context fails. */ inf_xmpp_connection_deinitiate(xmpp); } } g_object_notify(G_OBJECT(xmpp), "sasl-context"); g_object_notify(G_OBJECT(xmpp), "sasl-mechanisms"); g_object_thaw_notify(G_OBJECT(xmpp)); } /** * inf_xmpp_connection_retry_sasl_authentication: * @xmpp: A #InfXmppConnection. * @error: Location to store error information, if any. * * When SASL authentication failed then the #InfXmlConnection::error signal * is emitted with an error from the INF_XMPP_CONNECTION_AUTH_ERROR domain. * If the signal handler wants to retry authentication then it should call * this function, possibly modifying the #InfXmppConnection:sasl-mechanisms * property before. If this function is not called then the connection will * terminate. * * The function can fail if the server does not support any of the available * mechanisms given in #InfXmppConnection:sasl-mechanisms. If so, the function * returns %FALSE and @error is set. * * Returns: %TRUE if auth retry is being performed, %FALSE otherwise. */ gboolean inf_xmpp_connection_retry_sasl_authentication(InfXmppConnection* xmpp, GError** error) { InfXmppConnectionPrivate* priv; const gchar* suggestion; priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); g_return_val_if_fail( priv->status == INF_XMPP_CONNECTION_AWAITING_FEATURES, FALSE ); suggestion = inf_xmpp_connection_sasl_suggest_mechanism(xmpp, error); if(suggestion == NULL) return FALSE; inf_xmpp_connection_sasl_init(xmpp, suggestion); return TRUE; } /** * inf_xmpp_connection_set_sasl_error: * @xmpp: A #InfXmppConnection. * @error: The SASL error to set. * * Sets the SASL error of @xmpp. The SASL error is an additional hint of what * went wrong during authentication. It should be set on the server side * in the gsasl callback checking the user authentication. If on the * client side #InfXmlConnection::error is emitted with an error from the * INF_XMPP_CONNECTION_AUTH_ERROR domain then * inf_xmpp_connection_get_sasl_error() can be used to obtain more detailed * error information. */ void inf_xmpp_connection_set_sasl_error(InfXmppConnection* xmpp, const GError* error) { InfXmppConnectionPrivate* priv; priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); g_return_if_fail(priv->sasl_context != NULL); g_return_if_fail(priv->sasl_error == NULL); priv->sasl_error = g_error_copy(error); } /** * inf_xmpp_connection_get_sasl_error: * @xmpp: A #InfXmppConnection. * * Gets the SASL error of @xmpp. See inf_xmpp_connection_set_sasl_error(). * * Returns: A pointer to a #GError object owned by @xmpp. */ const GError* inf_xmpp_connection_get_sasl_error(InfXmppConnection* xmpp) { InfXmppConnectionPrivate* priv; priv = INF_XMPP_CONNECTION_PRIVATE(xmpp); g_return_val_if_fail(priv->sasl_context != NULL, NULL); return priv->sasl_error; } /** * inf_xmpp_connection_error_quark: * * Error domain for generic connection errors. Errors in this domain will be * from the #InfXmppConnectionError enumeration. See #GError for information * on error domains. */ GQuark inf_xmpp_connection_error_quark(void) { return g_quark_from_static_string("INF_XMPP_CONNECTION_ERROR"); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-error.h0000644000000000000000000000013213034342512021464 xustar0030 mtime=1483851082.033718448 30 atime=1483851082.033718448 30 ctime=1488261588.944139188 libinfinity-0.7.1/libinfinity/common/inf-error.h0000644000175000017500000002666513034342512022235 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_ERROR_H__ #define __INF_ERROR_H__ #include G_BEGIN_DECLS /* These are error codes do not occur directly in common/, but that * may be reported and/or need to be understood by both client and server. */ /** * InfRequestError: * @INF_REQUEST_ERROR_UNKNOWN_DOMAIN: The server sent <request-failed/> * with an unknown error domain. * @INF_REQUEST_ERROR_REPLY_UNPROCESSED: An error occured while processing the * server reply for a request. * @INF_REQUEST_ERROR_INVALID_SEQ: The server sent an invalid sequence number * in a reply to a request. * @INF_REQUEST_ERROR_NO_SUCH_ATTRIBUTE: A request did not contain a XML * attribute that is required to complete the request. * @INF_REQUEST_ERROR_INVALID_ATTRIBUTE: A request contains an XML attribute * with unexpected content. * @INF_REQUEST_ERROR_INVALID_NUMBER: A number in a request was invalid. * Either it was not numerical, or it produced an underflow or an overflow. * @INF_REQUEST_ERROR_NOT_AUTHORIZED: The requesting host is not authorized * to perform the requested action. * @INF_REQUEST_ERROR_FAILED: Generic error code when no further reason of * failure is known. * * These are general request errors that all #InfcRequests can * fail with. Specific requests may also fail with more errors, such as * #InfDirectoryError. */ typedef enum _InfRequestError { INF_REQUEST_ERROR_UNKNOWN_DOMAIN, INF_REQUEST_ERROR_REPLY_UNPROCESSED, INF_REQUEST_ERROR_INVALID_SEQ, INF_REQUEST_ERROR_NO_SUCH_ATTRIBUTE, INF_REQUEST_ERROR_INVALID_ATTRIBUTE, INF_REQUEST_ERROR_INVALID_NUMBER, INF_REQUEST_ERROR_NOT_AUTHORIZED, INF_REQUEST_ERROR_FAILED } InfRequestError; /** * InfUserError: * @INF_USER_ERROR_NAME_IN_USE: The requested name is already in use by * another user. * @INF_USER_ERROR_ID_PROVIDED: The client provided a user ID field in a * user join request, but it's the server's job to find an ID. * @INF_USER_ERROR_NO_SUCH_USER: A request referred to a user ID that no user * is associated with. * @INF_USER_ERROR_STATUS_UNAVAILABLE: The initial user status was given as * unavailable during user join or rejoin. * @INF_USER_ERROR_NOT_JOINED: The user did not join from the connection the * request comes from. For example, a user status change can only be requested * from the same connection that joined the user. * @INF_USER_ERROR_INVALID_STATUS: An invalid status was used in a XML * request. Allowed status values are "unavailable", "inactive" or "active". * @INF_USER_ERROR_FAILED: Generic error code when no further reason of * failure is known. * * These are errors related to users. They may occur during user join or * during processing a user-related message, such as a user status change * message in an #InfSession. */ typedef enum _InfUserError { INF_USER_ERROR_NAME_IN_USE, INF_USER_ERROR_ID_PROVIDED, INF_USER_ERROR_NO_SUCH_USER, INF_USER_ERROR_STATUS_UNAVAILABLE, INF_USER_ERROR_NOT_JOINED, INF_USER_ERROR_INVALID_STATUS, INF_USER_ERROR_FAILED } InfUserError; /** * InfDirectoryError: * @INF_DIRECTORY_ERROR_NO_WELCOME_MESSAGE: A client did not receive the * directory's initial welcome message. * @INF_DIRECTORY_ERROR_VERSION_MISMATCH: The server and client use * different versions of the protocol. * @INF_DIRECTORY_ERROR_NODE_EXISTS: A node with the given name exists * already in that subdirectory (in response to node creation requests). * @INF_DIRECTORY_ERROR_INVALID_NAME: A node with an invalid name was * attempted to be created. * @INF_DIRECTORY_ERROR_NO_SUCH_NODE: The node refered to in a request does * not exist in the directory (anymore). * @INF_DIRECTORY_ERROR_NO_SUCH_SUBSCRIPTION_REQUEST: A <subscribe-ack> * or <subscribe-nack> has been received without a previous request. * @INF_DIRECTORY_ERROR_CHAT_DISABLED: A client attempted to subscribe to a * server's chat, but the chat is disabled on the server side. * @INF_DIRECTORY_ERROR_NOT_A_SUBDIRECTORY: The node refered to in a request * is not a subdirectory node, but the requested operation requires one. * @INF_DIRECTORY_ERROR_NOT_A_NOTE: The node refered to in a request is not * a note (non-subdirectory) node, but the requested operations requires one. * @INF_DIRECTORY_ERROR_NOTE_TYPE_UNSUPPORTED: The node type is not supported * by the server. * @INF_DIRECTORY_ERROR_ROOT_NODE_REMOVE_ATTEMPT: A <remove-node> * request attempted to remove a directory's root node, which is not allowed. * @INF_DIRECTORY_ERROR_NOT_EXPLORED: An operation cannot be performed because * the corresponding node is not explored. * @INF_DIRECTORY_ERROR_ALREADY_EXPLORED: The node given in an exploration * request has already been explored earlier. * @INF_DIRECTORY_ERROR_NOT_INITIATED: Exploration has begun before the client * was told how many entries to expect. * @INF_DIRECTORY_ERROR_TOO_MANY_CHILDREN: Exploration yields more children * than announced at the beginning of the exploration. * @INF_DIRECTORY_ERROR_TOO_FEW_CHILDREN: Exploration yields less children * than announced at the beginning of the exploration. * @INF_DIRECTORY_ERROR_TYPE_UNKNOWN: The type of a note is not known. * @INF_DIRECTORY_ERROR_ALREADY_SUBSCRIBED: The connection already subscribed * to the node refered to, but the requested operation requires it to be * unsubscribed. * @INF_DIRECTORY_ERROR_UNSUBSCRIBED: The connection is not subscribed to the * node refered to, but the requested operation requires it to be subscribed. * @INF_DIRECTORY_ERROR_NETWORK_UNSUPPORTED: The server does not support the * network of the incoming connection for the requested operation. For * example, subscribing to a session might require a network that has a * peer-to-peer communication method, but there is no implementation of that * method for the connection's network. * @INF_DIRECTORY_ERROR_OPERATION_UNSUPPORTED: The requested operation is not * supported by the server. * @INF_DIRECTORY_ERROR_METHOD_UNSUPPORTED: The server requested a * communaction method for subscription or synchronization that is not * supported by the client. * @INF_DIRECTORY_ERROR_UNEXPECTED_SYNC_IN: A client received a * <sync-in/> without having requested one. The client has no data to * sync to the server. * @INF_DIRECTORY_ERROR_SUBSCRIPTION_REJECTED: A client replied with * <subscribe-nack> on an attempt to subscribe it to a session. * @INF_DIRECTORY_ERROR_UNEXPECTED_MESSAGE: A message that is not understood * was received. * @INF_DIRECTORY_ERROR_NO_STORAGE: A node cannot be stored permanently on the * server since it has no storage backend attached. * @INF_DIRECTORY_ERROR_INVALID_CERTIFICATE: An invalid certificate or * certificate request have been sent. * @INF_DIRECTORY_ERROR_ACCOUNT_LIST_ALREADY_QUERIED: The account list has * already been queried before. * @INF_DIRECTORY_ERROR_ACCOUNT_LIST_NOT_QUERIED: The account list has not * been queried. * @INF_DIRECTORY_ERROR_DUPLICATE_ACCOUNT: When adding a new account the new * account ID exists already in the account list. * @INF_DIRECTORY_ERROR_NO_SUCH_ACCOUNT: There is no such account with the * given ID. * @INF_DIRECTORY_ERROR_ACL_ALREADY_QUERIED: The ACL for a node has * already been queried before. * @INF_DIRECTORY_ERROR_ACL_NOT_QUERIED: The ACL for a node has * not yet been queried, but is required to perform the operation. * @INF_DIRECTORY_ERROR_FAILED: Generic error code when no further reason of * failure is known. * * These are errors related to the directory of documents. These errors can * be reason why requests created by #InfcBrowser fail. */ typedef enum _InfDirectoryError { INF_DIRECTORY_ERROR_NO_WELCOME_MESSAGE, INF_DIRECTORY_ERROR_VERSION_MISMATCH, INF_DIRECTORY_ERROR_NODE_EXISTS, INF_DIRECTORY_ERROR_INVALID_NAME, INF_DIRECTORY_ERROR_NO_SUCH_NODE, INF_DIRECTORY_ERROR_NO_SUCH_SUBSCRIPTION_REQUEST, INF_DIRECTORY_ERROR_CHAT_DISABLED, INF_DIRECTORY_ERROR_NOT_A_SUBDIRECTORY, INF_DIRECTORY_ERROR_NOT_A_NOTE, INF_DIRECTORY_ERROR_NOTE_TYPE_UNSUPPORTED, INF_DIRECTORY_ERROR_ROOT_NODE_REMOVE_ATTEMPT, INF_DIRECTORY_ERROR_NOT_EXPLORED, INF_DIRECTORY_ERROR_ALREADY_EXPLORED, INF_DIRECTORY_ERROR_NOT_INITIATED, INF_DIRECTORY_ERROR_TOO_MANY_CHILDREN, INF_DIRECTORY_ERROR_TOO_FEW_CHILDREN, INF_DIRECTORY_ERROR_TYPE_UNKNOWN, INF_DIRECTORY_ERROR_ALREADY_SUBSCRIBED, INF_DIRECTORY_ERROR_UNSUBSCRIBED, INF_DIRECTORY_ERROR_NETWORK_UNSUPPORTED, INF_DIRECTORY_ERROR_METHOD_UNSUPPORTED, INF_DIRECTORY_ERROR_OPERATION_UNSUPPORTED, INF_DIRECTORY_ERROR_UNEXPECTED_SYNC_IN, INF_DIRECTORY_ERROR_SUBSCRIPTION_REJECTED, INF_DIRECTORY_ERROR_UNEXPECTED_MESSAGE, INF_DIRECTORY_ERROR_NO_STORAGE, INF_DIRECTORY_ERROR_INVALID_CERTIFICATE, INF_DIRECTORY_ERROR_ACCOUNT_LIST_ALREADY_QUERIED, INF_DIRECTORY_ERROR_ACCOUNT_LIST_NOT_QUERIED, INF_DIRECTORY_ERROR_DUPLICATE_ACCOUNT, INF_DIRECTORY_ERROR_NO_SUCH_ACCOUNT, INF_DIRECTORY_ERROR_ACL_ALREADY_QUERIED, INF_DIRECTORY_ERROR_ACL_NOT_QUERIED, INF_DIRECTORY_ERROR_FAILED } InfDirectoryError; /** * InfAuthenticationDetailError: * @INF_AUTHENTICATION_DETAIL_ERROR_AUTHENTICATION_FAILED: User did not provide * valid credentials. * @INF_AUTHENTICATION_DETAIL_ERROR_USER_NOT_AUTHORIZED: User is not permitted * to connect to this server. * @INF_AUTHENTICATION_DETAIL_ERROR_TRY_AGAIN: Authentication was temporarily * interrupted on the server side. * @INF_AUTHENTICATION_DETAIL_ERROR_SERVER_ERROR: An error occured while * checking user permissions. * * These errors can give an additional hint why the SASL * authentication failed. */ typedef enum _InfAuthenticationDetailError { INF_AUTHENTICATION_DETAIL_ERROR_AUTHENTICATION_FAILED, INF_AUTHENTICATION_DETAIL_ERROR_USER_NOT_AUTHORIZED, INF_AUTHENTICATION_DETAIL_ERROR_TRY_AGAIN, INF_AUTHENTICATION_DETAIL_ERROR_SERVER_ERROR } InfAuthenticationDetailError; GQuark inf_request_error_quark(void); const gchar* inf_request_strerror(InfRequestError code); GQuark inf_user_error_quark(void); const gchar* inf_user_strerror(InfUserError code); GQuark inf_directory_error_quark(void); const gchar* inf_directory_strerror(InfDirectoryError code); const gchar* inf_authentication_detail_strerror(InfAuthenticationDetailError code); GQuark inf_authentication_detail_error_quark(void); GQuark inf_gnutls_error_quark(void); void inf_gnutls_set_error(GError** error, int error_code); GQuark inf_gnutls_certificate_verification_error_quark(void); void inf_gnutls_certificate_verification_set_error(GError** error, int verify); GQuark inf_gsasl_error_quark(void); void inf_gsasl_set_error(GError** error, int error_code); G_END_DECLS #endif /* __INF_ERROR_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-buffer.c0000644000000000000000000000013213034342512021577 xustar0030 mtime=1483851082.029718427 30 atime=1483851082.029718427 30 ctime=1488261589.040138978 libinfinity-0.7.1/libinfinity/common/inf-buffer.c0000644000175000017500000000642513034342512022340 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-buffer * @title: InfBuffer * @short_description: Abstract document interface * @include: libinfinity/common/inf-buffer.h * * #InfBuffer represents a document containing a session's content. It does * not cope with keeping its content in-sync with other participants but just * offers an interface to modify the document. * * The #InfBuffer interface itself is probably not too useful, but actual * documents implementing functionality (such as text editing or graphics * editing) need to implement this interface to be passed to #InfSession. **/ #include G_DEFINE_INTERFACE(InfBuffer, inf_buffer, G_TYPE_OBJECT) static void inf_buffer_default_init(InfBufferInterface* iface) { g_object_interface_install_property( iface, g_param_spec_boolean( "modified", "Modified", "Whether the buffer was modified since it has been saved", FALSE, G_PARAM_READWRITE ) ); } /** * inf_buffer_get_modified: * @buffer: A #InfBuffer. * * Indicates whether the buffer has been modified since the last call to * inf_buffer_set_modified() set the modification flag to %FALSE. * * Returns: Whether the buffer has been modified. */ gboolean inf_buffer_get_modified(InfBuffer* buffer) { InfBufferInterface* iface; gboolean modified; g_return_val_if_fail(INF_IS_BUFFER(buffer), FALSE); iface = INF_BUFFER_GET_IFACE(buffer); if(iface->get_modified != NULL) { return iface->get_modified(buffer); } else { g_object_get(G_OBJECT(buffer), "modified", &modified, NULL); return modified; } } /** * inf_buffer_set_modified: * @buffer: A #InfBuffer. * @modified: Whether the buffer is considered modified or not. * * Sets the modification flag of @buffer to @modified. You should normally set * the flag to %FALSE every time the document is saved onto disk. The buffer * itself will set it to %TRUE when it has been changed. * * To get notified when the modification flag changes, connect to * GObject::notify for the InfBuffer:modified property. */ void inf_buffer_set_modified(InfBuffer* buffer, gboolean modified) { InfBufferInterface* iface; g_return_if_fail(INF_IS_BUFFER(buffer)); iface = INF_BUFFER_GET_IFACE(buffer); if(iface->set_modified != NULL) { iface->set_modified(buffer, modified); } else { g_object_set(G_OBJECT(buffer), "modified", modified, NULL); } } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-protocol.h0000644000000000000000000000013213034342512022174 xustar0030 mtime=1483851082.033718448 30 atime=1483851082.033718448 30 ctime=1488261588.956139161 libinfinity-0.7.1/libinfinity/common/inf-protocol.h0000644000175000017500000000243513034342512022732 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_PROTOCOL_H__ #define __INF_PROTOCOL_H__ #include G_BEGIN_DECLS const gchar* inf_protocol_get_version(void); gboolean inf_protocol_parse_version(const gchar* version, guint* major, guint* minor, GError** error); guint inf_protocol_get_default_port(void); G_END_DECLS #endif /* __INF_PROTOCOL_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-name-resolver.h0000644000000000000000000000013213034342512023112 xustar0030 mtime=1483851082.033718448 30 atime=1483851082.033718448 30 ctime=1488261588.956139161 libinfinity-0.7.1/libinfinity/common/inf-name-resolver.h0000644000175000017500000000673013034342512023652 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_NAME_RESOLVER_H__ #define __INF_NAME_RESOLVER_H__ #include #include #include G_BEGIN_DECLS #define INF_TYPE_NAME_RESOLVER (inf_name_resolver_get_type()) #define INF_NAME_RESOLVER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_TYPE_NAME_RESOLVER, InfNameResolver)) #define INF_NAME_RESOLVER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INF_TYPE_NAME_RESOLVER, InfNameResolverClass)) #define INF_IS_NAME_RESOLVER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_TYPE_NAME_RESOLVER)) #define INF_IS_NAME_RESOLVER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INF_TYPE_NAME_RESOLVER)) #define INF_NAME_RESOLVER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INF_TYPE_NAME_RESOLVER, InfNameResolverClass)) typedef struct _InfNameResolver InfNameResolver; typedef struct _InfNameResolverClass InfNameResolverClass; /** * InfNameResolverClass: * @resolved: Default signal handler for the #InfNameResolver::resolved * signal. * * This structure contains the default signal handlers of #InfNameResolver. */ struct _InfNameResolverClass { /*< private >*/ GObjectClass parent_class; /*< public >*/ /* Signals */ void (*resolved)(InfNameResolver* connection, const GError* error); }; /** * InfNameResolver: * * #InfNameResolver is an opaque data type. You should only access it via * the public API functions. */ struct _InfNameResolver { /*< private >*/ GObject parent; }; GType inf_name_resolver_get_type(void) G_GNUC_CONST; InfNameResolver* inf_name_resolver_new(InfIo* io, const gchar* hostname, const gchar* service, const gchar* srv); const gchar* inf_name_resolver_get_hostname(InfNameResolver* resolver); const gchar* inf_name_resolver_get_service(InfNameResolver* resolver); const gchar* inf_name_resolver_get_srv(InfNameResolver* resolver); gboolean inf_name_resolver_start(InfNameResolver* resolver, GError** error); gboolean inf_name_resolver_lookup_backup(InfNameResolver* resolver, GError** error); gboolean inf_name_resolver_finished(InfNameResolver* resolver); guint inf_name_resolver_get_n_addresses(InfNameResolver* resolver); const InfIpAddress* inf_name_resolver_get_address(InfNameResolver* resolver, guint index); guint inf_name_resolver_get_port(InfNameResolver* resolver, guint index); G_END_DECLS #endif /* __INF_NAME_RESOLVER_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-init.h0000644000000000000000000000013213034342512021276 xustar0030 mtime=1483851082.033718448 30 atime=1483851082.033718448 30 ctime=1488261588.948139179 libinfinity-0.7.1/libinfinity/common/inf-init.h0000644000175000017500000000206313034342512022031 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_INIT_H__ #define __INF_INIT_H__ #include G_BEGIN_DECLS gboolean inf_init(GError** error); void inf_deinit(void); G_END_DECLS #endif /* __INF_INIT_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-browser.c0000644000000000000000000000013213034342512022011 xustar0030 mtime=1483851082.029718427 30 atime=1483851082.029718427 30 ctime=1488261589.040138978 libinfinity-0.7.1/libinfinity/common/inf-browser.c0000644000175000017500000017677413034342512022571 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-browser * @title: InfBrowser * @short_description: Browsing of infinote directories * @include: libinfinity/common/inf-browser.h * @see_also: #InfBrowserIter * @stability: Unstable * * #InfBrowser provides an interface for browsing an infinote directory. * It can be used to navigate through the tree, add or remove nodes and * subscribe to sessions. * * Nodes in a directory can either contain more nodes in which case this is * called a subdirectory. Leaf nodes are also called notes. There is only * one root node which must be a subdirectory node. */ #include #include #include static const GEnumValue inf_browser_status_values[] = { { INF_BROWSER_CLOSED, "INF_BROWSER_CLOSED", "closed" }, { INF_BROWSER_OPENING, "INF_BROWSER_OPENING", "opening" }, { INF_BROWSER_OPEN, "INF_BROWSER_OPEN", "open" } }; INF_DEFINE_ENUM_TYPE(InfBrowserStatus, inf_browser_status, inf_browser_status_values) G_DEFINE_INTERFACE(InfBrowser, inf_browser, G_TYPE_OBJECT) enum { ERROR_, NODE_ADDED, NODE_REMOVED, SUBSCRIBE_SESSION, UNSUBSCRIBE_SESSION, BEGIN_REQUEST, /* detailed */ ACL_ACCOUNT_ADDED, ACL_ACCOUNT_REMOVED, ACL_LOCAL_ACCOUNT_CHANGED, ACL_CHANGED, LAST_SIGNAL }; static guint browser_signals[LAST_SIGNAL]; /* Helper function for inf_browser_get_path */ static void inf_browser_extract_path(InfBrowser* browser, const InfBrowserIter* iter, GString* string) { InfBrowserIter parent_iter; parent_iter = *iter; if(inf_browser_get_parent(browser, &parent_iter)) { inf_browser_extract_path(browser, &parent_iter, string); g_assert(string->len > 0); if(string->str[string->len - 1] != '/') g_string_append_c(string, '/'); g_string_append(string, inf_browser_get_node_name(browser, iter)); } else { g_string_assign(string, "/"); } } static void inf_browser_default_init(InfBrowserInterface* iface) { /** * InfBrowser::error: * @browser: The #InfBrowser object emitting the signal. * @error: A #GError describing what went wrong. * * This signal is emitted whenever there was an asynchronous error with * the browser itself which was not the result of a particular user * request. The error may or may not be fatal. If it is fatal the browser * will also be closed which can be checked with the status property. */ browser_signals[ERROR_] = g_signal_new( "error", INF_TYPE_BROWSER, G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfBrowserInterface, error), NULL, NULL, g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE, 1, G_TYPE_ERROR ); /** * InfBrowser::node-added: * @browser: The #InfBrowser object emitting the signal. * @iter: An iterator pointing to the newly added node. * @request: The request that lead to the node being added, or %NULL. * * This signal is emitted when a node is added to the browser. */ browser_signals[NODE_ADDED] = g_signal_new( "node-added", INF_TYPE_BROWSER, G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfBrowserInterface, node_added), NULL, NULL, NULL, G_TYPE_NONE, 2, INF_TYPE_BROWSER_ITER | G_SIGNAL_TYPE_STATIC_SCOPE, INF_TYPE_REQUEST ); /** * InfBrowser::node-removed: * @browser: The #InfBrowser object emitting the signal. * @iter: An iterator pointing to the node being removed. * @request: The request that lead to the node being removed, or %NULL. * * This signal is emitted just before a node is being removed from the * browser. The iterator is still valid and can be used to access the * node which will be removed. */ browser_signals[NODE_REMOVED] = g_signal_new( "node-removed", INF_TYPE_BROWSER, G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfBrowserInterface, node_removed), NULL, NULL, NULL, G_TYPE_NONE, 2, INF_TYPE_BROWSER_ITER | G_SIGNAL_TYPE_STATIC_SCOPE, INF_TYPE_REQUEST ); /** * InfBrowser::subscribe-session: * @browser: The #InfBrowser object emitting the signal. * @iter: An iterator pointing to the node to which a subscription. * was made, or %NULL. * @session: The subscribed session. * @request: The request that lead to the subscription, or %NULL. * * This signal is emitted whenever the browser is subscribed to a session. * This can happen as a result of a inf_browser_subscribe() or * inf_browser_add_note() call, but it is also possible that a * subscription is initiated without user interaction. * * If @iter is %NULL the session was a global session and not attached to * a particular node. */ browser_signals[SUBSCRIBE_SESSION] = g_signal_new( "subscribe-session", INF_TYPE_BROWSER, G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfBrowserInterface, subscribe_session), NULL, NULL, NULL, G_TYPE_NONE, 3, INF_TYPE_BROWSER_ITER | G_SIGNAL_TYPE_STATIC_SCOPE, INF_TYPE_SESSION_PROXY, INF_TYPE_REQUEST ); /** * InfBrowser::unsubscribe-session: * @browser: The #InfBrowser object emitting the signal. * @iter: An iterator pointing to the node from which a subscription. * was removed, or %NULL. * @session: The session to which the subscription was removed. * @request: The request that lead to the unsubscription, or %NULL. * * This signal is emitted whenever a session is detached from a browser * node. This can happen when a subscribed session is closed, or, in * the case of a server, if the session is idle for a long time it is * stored on disk and removed from memory. * * Note that this signal does not mean that the corresponding * session can no longer be used. It only means that it is no longer * associated to a browser node, for example also when the browser node * is deleted. The session might still be intact, though, and can continue * even when it is detached from the browser. * * In order to find out whether the local host was unsubscribed from a * session and the connection to the other session participants has been * lost, the #InfSession:subscription-group property should be monitored, * and if that property changes and * inf_session_get_subscription_group() returns %NULL afterwards, * it means the session is no longer connected. * * If @iter is %NULL the session was a global session and not attached to * a particular node. */ browser_signals[UNSUBSCRIBE_SESSION] = g_signal_new( "unsubscribe-session", INF_TYPE_BROWSER, G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfBrowserInterface, unsubscribe_session), NULL, NULL, NULL, G_TYPE_NONE, 3, INF_TYPE_BROWSER_ITER | G_SIGNAL_TYPE_STATIC_SCOPE, INF_TYPE_SESSION_PROXY, INF_TYPE_REQUEST ); /** * InfBrowser::begin-request: * @browser: The #InfBrowser object emitting the signal. * @iter: An iterator pointing to the node for which a request is made, or * %NULL. * @request: The request being made. * * This signal is emitted whenever a request is made with the browser. * The signal is detailed with the request type, so that it is possible to * connect to e.g. "begin-request::add-subdirectory" to only get notified * about subdirectory creation requests. * * If @iter is %NULL the request is a global request and not attached to a * particular node. */ browser_signals[BEGIN_REQUEST] = g_signal_new( "begin-request", INF_TYPE_BROWSER, G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, G_STRUCT_OFFSET(InfBrowserInterface, begin_request), NULL, NULL, NULL, G_TYPE_NONE, 2, INF_TYPE_BROWSER_ITER | G_SIGNAL_TYPE_STATIC_SCOPE, INF_TYPE_REQUEST ); /** * InfBrowser::acl-account-added: * @browser: The #InfBrowser object emitting the signal. * @account: The new #InfAclAccount. * @request: The request which lead to the newly added account, or %NULL. * * This signal is emitted whenever a new account is added to the browser, * and the browser supports account list notification. */ browser_signals[ACL_ACCOUNT_ADDED] = g_signal_new( "acl-account-added", INF_TYPE_BROWSER, G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfBrowserInterface, acl_account_added), NULL, NULL, NULL, G_TYPE_NONE, 2, INF_TYPE_ACL_ACCOUNT | G_SIGNAL_TYPE_STATIC_SCOPE, INF_TYPE_REQUEST ); /** * InfBrowser::acl-account-removed: * @browser: The #InfBrowser object emitting the signal. * @account: The removed #InfAclAccount. * @request: The request which lead to the removal of the account, * or %NULL. * * This signal is emitted whenever an account is removed from the browser, * and the browser supports account list notification. */ browser_signals[ACL_ACCOUNT_REMOVED] = g_signal_new( "acl-account-removed", INF_TYPE_BROWSER, G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfBrowserInterface, acl_account_removed), NULL, NULL, NULL, G_TYPE_NONE, 2, INF_TYPE_ACL_ACCOUNT | G_SIGNAL_TYPE_STATIC_SCOPE, INF_TYPE_REQUEST ); /** * InfBrowser::acl-local-account-changed: * @browser: The #InfBrowser object emitting the signal. * @account: The new local #InfAclAccount. * @request: The request which triggered the account change, or %NULL. * * This signal is emitted whenever the account into which the local host * is logged into changes. This can happen for example on a delayed login, * or when the current account is deleted from the server in which case * the host is demoted to the default account. */ browser_signals[ACL_LOCAL_ACCOUNT_CHANGED] = g_signal_new( "acl-local-account-changed", INF_TYPE_BROWSER, G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfBrowserInterface, acl_local_account_changed), NULL, NULL, NULL, G_TYPE_NONE, 2, INF_TYPE_ACL_ACCOUNT | G_SIGNAL_TYPE_STATIC_SCOPE, INF_TYPE_REQUEST ); /** * InfBrowser::acl-changed: * @browser: The #InfBrowser object emitting the signal. * @iter: An iterator pointing to the node for which the ACL has changed. * @sheet_set: A #InfAclSheetSet containing the changed ACL sheets. * @request: The request which lead to the ACL being changed, or %NULL. * * This signal is emitted whenever an ACL for the node @iter points to * are changed. This signal is emitted whenever the ACL change for the * local user, the default user, or for a node that all ACLs have been * queried with inf_browser_query_acl(). * * The @sheet_set parameter contains only the ACL sheets that have * changed. In order to get the new full sheet set, call * inf_browser_get_acl(). */ browser_signals[ACL_CHANGED] = g_signal_new( "acl-changed", INF_TYPE_BROWSER, G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfBrowserInterface, acl_changed), NULL, NULL, NULL, G_TYPE_NONE, 3, INF_TYPE_BROWSER_ITER | G_SIGNAL_TYPE_STATIC_SCOPE, INF_TYPE_ACL_SHEET_SET | G_SIGNAL_TYPE_STATIC_SCOPE, INF_TYPE_REQUEST ); g_object_interface_install_property( iface, g_param_spec_enum( "status", "Browser Status", "The connectivity status of the browser", INF_TYPE_BROWSER_STATUS, INF_BROWSER_CLOSED, G_PARAM_READABLE ) ); } /** * inf_browser_get_root: * @browser: A #InfBrowser. * @iter: (out): An uninitialized #InfBrowserIter. * * Sets @iter to point to the root node of @browser. * * Returns: %TRUE if @iter was set or %FALSE if there is no root node, i.e. * the browser is not open. */ gboolean inf_browser_get_root(InfBrowser* browser, InfBrowserIter* iter) { InfBrowserInterface* iface; g_return_val_if_fail(INF_IS_BROWSER(browser), FALSE); g_return_val_if_fail(iter != NULL, FALSE); iface = INF_BROWSER_GET_IFACE(browser); g_return_val_if_fail(iface->get_root != NULL, FALSE); return iface->get_root(browser, iter); } /** * inf_browser_get_next: * @browser: A #InfBrowser. * @iter: (inout): A #InfBrowserIter pointing to a node inside @browser. * * Sets @iter to point to its next sibling node. If @iter points already to the * last node then @iter is left untouched and the function returns %FALSE. * * Returns: %TRUE if @iter was moved or %FALSE otherwise. */ gboolean inf_browser_get_next(InfBrowser* browser, InfBrowserIter* iter) { InfBrowserInterface* iface; g_return_val_if_fail(INF_IS_BROWSER(browser), FALSE); g_return_val_if_fail(iter != NULL, FALSE); iface = INF_BROWSER_GET_IFACE(browser); g_return_val_if_fail(iface->get_next != NULL, FALSE); return iface->get_next(browser, iter); } /** * inf_browser_get_prev: * @browser: A #InfBrowser. * @iter: (inout): A #InfBrowserIter pointing to a node inside @browser. * * Sets @iter to point to its previous sibling node. If @iter points to the * first node already then @iter is left untouched and the function returns * %FALSE. * * Returns: %TRUE if @iter was moved or %FALSE otherwise. */ gboolean inf_browser_get_prev(InfBrowser* browser, InfBrowserIter* iter) { InfBrowserInterface* iface; g_return_val_if_fail(INF_IS_BROWSER(browser), FALSE); g_return_val_if_fail(iter != NULL, FALSE); iface = INF_BROWSER_GET_IFACE(browser); g_return_val_if_fail(iface->get_prev != NULL, FALSE); return iface->get_prev(browser, iter); } /** * inf_browser_get_parent: * @browser: A #InfBrowser. * @iter: (inout): A #InfBrowserIter pointing to a node inside @browser. * * Sets @iter to point to its parent node. If @iter is already the root node * then @iter is left untouched and the function returns %FALSE. * * Returns: %TRUE if @iter was moved or %FALSE otherwise. */ gboolean inf_browser_get_parent(InfBrowser* browser, InfBrowserIter* iter) { InfBrowserInterface* iface; g_return_val_if_fail(INF_IS_BROWSER(browser), FALSE); g_return_val_if_fail(iter != NULL, FALSE); iface = INF_BROWSER_GET_IFACE(browser); g_return_val_if_fail(iface->get_parent != NULL, FALSE); return iface->get_parent(browser, iter); } /** * inf_browser_get_child: * @browser: A #InfBrowser. * @iter: (inout): A #InfBrowserIter pointing to a subdirectory node inside * @browser. * * Sets @iter to point to the first child of the subdirectory node it * currently points to. If the subdirectory does not contain any children or * if @iter does not point to a subdirectory the function returns %FALSE. * This does not necessarily mean that there do not exist any children but it * can also be that they have not yet been explored. Nodes can be explored * with inf_browser_explore() and it can be checked whether a given node has * been explored with inf_browser_get_explored(). * * Returns: %TRUE if @iter was moved or %FALSE otherwise. */ gboolean inf_browser_get_child(InfBrowser* browser, InfBrowserIter* iter) { InfBrowserInterface* iface; g_return_val_if_fail(INF_IS_BROWSER(browser), FALSE); g_return_val_if_fail(iter != NULL, FALSE); iface = INF_BROWSER_GET_IFACE(browser); g_return_val_if_fail(iface->is_subdirectory != NULL, FALSE); g_return_val_if_fail(iface->is_subdirectory(browser, iter) == TRUE, FALSE); g_return_val_if_fail(iface->get_child != NULL, FALSE); return iface->get_child(browser, iter); } /** * inf_browser_is_ancestor: * @browser: A #InfBrowser. * @ancestor: An iterator pointing to the ancestor node. * @iter: An iterator pointing to the node to be checked. * * Returns whether @ancestor is an ancestor of @iter, i.e. either the two * iterators point to the same node or @ancestor is a parent, grand-parent, * grand-grand-parent, etc. of the node @iter points to. * * Returns: Whether @ancestor is an ancestor of @iter. */ gboolean inf_browser_is_ancestor(InfBrowser* browser, const InfBrowserIter* ancestor, const InfBrowserIter* iter) { InfBrowserIter check_iter; g_return_val_if_fail(INF_IS_BROWSER(browser), FALSE); g_return_val_if_fail(ancestor != NULL, FALSE); g_return_val_if_fail(iter != NULL, FALSE); check_iter = *iter; do { if(check_iter.node == ancestor->node) return TRUE; } while(inf_browser_get_parent(browser, &check_iter)); return FALSE; } /** * inf_browser_explore: * @browser: A #InfBrowser. * @iter: A #InfBrowserIter pointing to a subdirectory node inside * @browser. * @func: (scope async): The function to be called when the request finishes, * or %NULL. * @user_data: Additional data to pass to @func. * * Requests the node @iter points to to be explored. Initally, subdirectory * nodes are not explored, that is not known what content there is. Nodes can * be explored to learn about the children nodes they contain. Since exploring * is a potentially lengthy process involing networking or I/O with slow * devices this function returns a @InfExploreRequest which can be used to * monitor the progress of the operation and get notified when the exploration * finishes. During exploration #InfBrowser::node-added signals are already * emitted appropriately for every child explored inside @iter. * * The request might either finish during the call to this function, in which * case @func will be called and %NULL being returned. If the request does not * finish within the function call, a #InfRequest object is returned, * where @func has been installed for the #InfRequest::finished signal, * so that it is called as soon as the request finishes. * * Returns: (transfer none) (allow-none): A #InfRequest, or %NULL if @iter * points to a non-subdirectory node. */ InfRequest* inf_browser_explore(InfBrowser* browser, const InfBrowserIter* iter, InfRequestFunc func, gpointer user_data) { InfBrowserInterface* iface; g_return_val_if_fail(INF_IS_BROWSER(browser), NULL); g_return_val_if_fail(iter != NULL, NULL); iface = INF_BROWSER_GET_IFACE(browser); g_return_val_if_fail(iface->is_subdirectory != NULL, NULL); g_return_val_if_fail(iface->is_subdirectory(browser, iter) == TRUE, NULL); g_return_val_if_fail(iface->explore != NULL, NULL); return iface->explore(browser, iter, func, user_data); } /** * inf_browser_get_explored: * @browser: A #InfBrowser. * @iter: A #InfBrowserIter pointing to a subdirectory node inside @browser. * * Returns whether the node @iter points to has already been explored or not. * * Returns: %TRUE if the node @iter points to has been explored * or %FALSE otherwise. */ gboolean inf_browser_get_explored(InfBrowser* browser, const InfBrowserIter* iter) { InfBrowserInterface* iface; g_return_val_if_fail(INF_IS_BROWSER(browser), FALSE); g_return_val_if_fail(iter != NULL, FALSE); iface = INF_BROWSER_GET_IFACE(browser); g_return_val_if_fail(iface->is_subdirectory != NULL, FALSE); g_return_val_if_fail(iface->is_subdirectory(browser, iter) == TRUE, FALSE); g_return_val_if_fail(iface->get_explored != NULL, FALSE); return iface->get_explored(browser, iter); } /** * inf_browser_is_subdirectory: * @browser: A #InfBrowser. * @iter: A #InfBrowserIter pointing to a node inside @browser. * * Returns whether the node @iter points to is a subdirectory node. * * Returns: %TRUE if the node @iter points to is a subdirectory node or * %FALSE otherwise. */ gboolean inf_browser_is_subdirectory(InfBrowser* browser, const InfBrowserIter* iter) { InfBrowserInterface* iface; g_return_val_if_fail(INF_IS_BROWSER(browser), FALSE); g_return_val_if_fail(iter != NULL, FALSE); iface = INF_BROWSER_GET_IFACE(browser); g_return_val_if_fail(iface->is_subdirectory != NULL, FALSE); return iface->is_subdirectory(browser, iter); } /** * inf_browser_add_note: * @browser: A #InfBrowser. * @iter: A #InfBrowserIter pointing to a subdirectory node inside @browser. * @name: The name of the node to add. * @type: The type of the node to add. * @acl: (allow-none): A #InfAclSheetSet representing the initial ACL for * this node, or %NULL. * @session: (allow-none): A #InfSession with a session of type @type, or * %NULL. * @initial_subscribe: Whether to subscribe to the newly created session. * @func: (scope async): The function to be called when the request finishes, * or %NULL. * @user_data: Additional data to pass to @func. * * Adds a new leaf node to the browser. The new node is of type @type. If * session is non-%NULL it will be used as the initial content of the new * node, otherwise the new node will start empty. In the case of non-%NULL * @session the session must be in status %INF_SESSION_RUNNING. * * The returned request finishes as soon as the creation of the node is * acknowledged. It is however not guaranteed that the content of the note has * been synchronized yet. In the case of a client connected to an infinote * server the content is usually not transmitted when the request finishes. * If an error in the process of transmission happens then the node will be * removed again. * * On the client side, the progress of synchronization to the server after the * request has finished can be monitored with the * InfSession::synchronization-failed, * InfSession::synchronization-complete and * InfSession::synchronization-progress signals. Note that a single session * might be synchronized to multiple servers at the same time, you will have * to check the connection parameter in the signal hander to find out to * which server the session is synchronized. * * You can safely unref session after having called this function. If the * request or the synchronization fails, the session will be discarded in * that case. When the returned request finishes, you can use * infc_browser_iter_get_sync_in() to get the session again. * * If @initial_subscribe is set, then, when the returned request finishes, * you might call inf_browser_get_session() on the resulting * #InfBrowserIter. However, that function is not guaranteed to return * non-%NULL in this case since the node might have been created, but the * subscription could have failed. * * The initial ACL for the new node is given by @acl. If this parameter * is %NULL, then the default ACL is used, which inherits all permissions * from the parent node. In order to apply non-%NULL ACL to the new node, * the %INF_ACL_CAN_SET_ACL permission must be granted to the local entity for * the node @iter points to. * * The request might either finish during the call to this function, in which * case @func will be called and %NULL being returned. If the request does not * finish within the function call, a #InfRequest object is returned, * where @func has been installed for the #InfRequest::finished signal, * so that it is called as soon as the request finishes. * * Returns: (transfer none) (allow-none): A #InfRequest which can be used to * get notified when the request finishes. */ InfRequest* inf_browser_add_note(InfBrowser* browser, const InfBrowserIter* iter, const char* name, const char* type, const InfAclSheetSet* acl, InfSession* session, gboolean initial_subscribe, InfRequestFunc func, gpointer user_data) { InfBrowserInterface* iface; g_return_val_if_fail(INF_IS_BROWSER(browser), NULL); g_return_val_if_fail(iter != NULL, NULL); g_return_val_if_fail(name != NULL, NULL); g_return_val_if_fail(type != NULL, NULL); g_return_val_if_fail(session == NULL || INF_IS_SESSION(session), NULL); g_return_val_if_fail( session == NULL || inf_session_get_status(session) == INF_SESSION_RUNNING, NULL ); /* Can only subscribe if that session is not already subscribed elsewhere */ g_return_val_if_fail( session == NULL || initial_subscribe == FALSE || inf_session_get_subscription_group(session) == NULL, NULL ); iface = INF_BROWSER_GET_IFACE(browser); g_return_val_if_fail(iface->is_subdirectory != NULL, NULL); g_return_val_if_fail(iface->is_subdirectory(browser, iter) == TRUE, NULL); g_return_val_if_fail(iface->add_note != NULL, NULL); return iface->add_note( browser, iter, name, type, acl, session, initial_subscribe, func, user_data ); } /** * inf_browser_add_subdirectory: * @browser: A #InfBrowser. * @iter: A #InfBrowserIter pointing to a subdirectory node inside @browser. * @name: The name of the node to add. * @acl: (allow-none): A #InfAclSheetSet representing the initial ACL for * this node, or %NULL. * @func: (scope async): The function to be called when the request finishes, * or %NULL. * @user_data: Additional data to pass to @func. * * Adds a new subdirectory node to the browser. * * The initial ACL for the new node is given by @acl. If this parameter * is %NULL, then the default ACL is used, which inherits all permissions * from the parent node. In order to apply non-%NULL ACL to the new node, * the %INF_ACL_CAN_SET_ACL permission must be granted to the local entity for * the node @iter points to. * * The request might either finish during the call to this function, in which * case @func will be called and %NULL being returned. If the request does not * finish within the function call, a #InfRequest object is returned, * where @func has been installed for the #InfRequest::finished signal, * so that it is called as soon as the request finishes. * * Returns: (transfer none) (allow-none): A #InfRequest which can be used to * get notified when the request finishes. */ InfRequest* inf_browser_add_subdirectory(InfBrowser* browser, const InfBrowserIter* iter, const char* name, const InfAclSheetSet* acl, InfRequestFunc func, gpointer user_data) { InfBrowserInterface* iface; g_return_val_if_fail(INF_IS_BROWSER(browser), NULL); g_return_val_if_fail(iter != NULL, NULL); g_return_val_if_fail(name != NULL, NULL); iface = INF_BROWSER_GET_IFACE(browser); g_return_val_if_fail(iface->is_subdirectory != NULL, NULL); g_return_val_if_fail(iface->is_subdirectory(browser, iter) == TRUE, NULL); g_return_val_if_fail(iface->add_subdirectory != NULL, NULL); return iface->add_subdirectory(browser, iter, name, acl, func, user_data); } /** * inf_browser_remove_node: * @browser: A #InfBrowser. * @iter: A #InfBrowserIter pointing to a node inside @browser. * @func: (scope async): The function to be called when the request finishes, * or %NULL. * @user_data: Additional data to pass to @func. * * Requests to remove the node @iter points to. It may point to a * subdirectory node in which case all its children are removed recursively * as well. * * The request might either finish during the call to this function, in which * case @func will be called and %NULL being returned. If the request does not * finish within the function call, a #InfRequest object is returned, * where @func has been installed for the #InfRequest::finished signal, * so that it is called as soon as the request finishes. * * Returns: (transfer none) (allow-none): A #InfRequest which can be used to * get notified when the request finishes. */ InfRequest* inf_browser_remove_node(InfBrowser* browser, const InfBrowserIter* iter, InfRequestFunc func, gpointer user_data) { InfBrowserInterface* iface; g_return_val_if_fail(INF_IS_BROWSER(browser), NULL); g_return_val_if_fail(iter != NULL, NULL); iface = INF_BROWSER_GET_IFACE(browser); g_return_val_if_fail(iface->remove_node != NULL, NULL); return iface->remove_node(browser, iter, func, user_data); } /** * inf_browser_get_node_name: * @browser: A #InfBrowser. * @iter: A #InfBrowserIter pointing to a node inside @browser. * * Returns the name of the node @iter points to. * * Returns: A string containing the node's name. */ const gchar* inf_browser_get_node_name(InfBrowser* browser, const InfBrowserIter* iter) { InfBrowserInterface* iface; g_return_val_if_fail(INF_IS_BROWSER(browser), NULL); g_return_val_if_fail(iter != NULL, NULL); iface = INF_BROWSER_GET_IFACE(browser); g_return_val_if_fail(iface->get_node_name != NULL, NULL); return iface->get_node_name(browser, iter); } /** * inf_browser_get_node_type: * @browser: A #InfBrowser. * @iter: A #InfBrowserIter pointing to a leaf node inside @browser. * * Returns the type of the node @iter points to. * * Returns: The node type as a string. */ const gchar* inf_browser_get_node_type(InfBrowser* browser, const InfBrowserIter* iter) { InfBrowserInterface* iface; g_return_val_if_fail(INF_IS_BROWSER(browser), NULL); g_return_val_if_fail(iter != NULL, NULL); iface = INF_BROWSER_GET_IFACE(browser); g_return_val_if_fail(iface->is_subdirectory != NULL, NULL); g_return_val_if_fail(iface->is_subdirectory(browser, iter) == FALSE, NULL); g_return_val_if_fail(iface->get_node_type != NULL, NULL); return iface->get_node_type(browser, iter); } /** * inf_browser_get_path: * @browser: A #InfBrowser. * @iter: A #InfBrowserIter pointing to a node inside @browser. * * Returns the full path to the node @iter points to. A path always starts * with a '/' and then has the name of the node and all its parents separated * by '/', much like a filesystem path on Unix. * * Returns: (transfer full): The path as a string. Free with g_free() when no * longer needed. */ gchar* inf_browser_get_path(InfBrowser* browser, const InfBrowserIter* iter) { GString* str; str = g_string_sized_new(32); inf_browser_extract_path(browser, iter, str); return g_string_free(str, FALSE); } /** * inf_browser_subscribe: * @browser: A #InfBrowser. * @iter: A #InfBrowserIter pointing to a leaf node inside @browser. * @func: (scope async): The function to be called when the request finishes, * or %NULL. * @user_data: Additional data to pass to @func. * * Attempts to subscribe to the node @iter points to, i.e. obtain a * #InfSession representing its content. This also allows to change the * content of the node. * * The request might either finish during the call to this function, in which * case @func will be called and %NULL being returned. If the request does not * finish within the function call, a #InfRequest object is returned, * where @func has been installed for the #InfRequest::finished signal, * so that it is called as soon as the request finishes. * * Returns: (transfer none) (allow-none): A #InfRequest which can be used to * get notified when the request finishes. */ InfRequest* inf_browser_subscribe(InfBrowser* browser, const InfBrowserIter* iter, InfRequestFunc func, gpointer user_data) { InfBrowserInterface* iface; g_return_val_if_fail(INF_IS_BROWSER(browser), NULL); g_return_val_if_fail(iter != NULL, NULL); iface = INF_BROWSER_GET_IFACE(browser); g_return_val_if_fail(iface->is_subdirectory != NULL, NULL); g_return_val_if_fail(iface->is_subdirectory(browser, iter) == FALSE, NULL); g_return_val_if_fail(iface->subscribe != NULL, NULL); return iface->subscribe(browser, iter, func, user_data); } /** * inf_browser_get_session: * @browser: A #InfBrowser. * @iter: A #InfBrowserIter pointing to a leaf node inside @browser. * * Returns the session which has the content of the node @iter points to. The * session needs to be subscribed to, see inf_browser_subscribe(). If the * session is not subscribed or the subscription request has not yet finished * the function returns %NULL. * * Returns: (transfer none) (allow-none): A @InfSessionProxy which contains * the session. The proxy object can be used to join a user into the session. */ InfSessionProxy* inf_browser_get_session(InfBrowser* browser, const InfBrowserIter* iter) { InfBrowserInterface* iface; g_return_val_if_fail(INF_IS_BROWSER(browser), NULL); g_return_val_if_fail(iter != NULL, NULL); iface = INF_BROWSER_GET_IFACE(browser); g_return_val_if_fail(iface->is_subdirectory != NULL, NULL); g_return_val_if_fail(iface->is_subdirectory(browser, iter) == FALSE, NULL); g_return_val_if_fail(iface->get_session != NULL, NULL); return iface->get_session(browser, iter); } /** * inf_browser_list_pending_requests: * @browser: A #InfBrowser. * @iter: (allow-none): A #InfBrowserIter pointing to a node inside @browser, * or %NULL. * @request_type: (allow-none): The type of request to return pending requests * for, or %NULL. * * Returns a list of all pending requests for the node @iter points to which * match type @request_type. A pending request is a request which has been * created but has not yet finished. @request_type can be %NULL in which case * all requests for the given node are returned. If it is non-%NULL only * requests which match the given type are included in the list of returned * requests. * * If @iter is %NULL then the function returns all pending global requests. * * Returns: (transfer container) (element-type InfRequest): A list of * #InfRequests. Free with g_slist_free() when no longer needed. */ GSList* inf_browser_list_pending_requests(InfBrowser* browser, const InfBrowserIter* iter, const gchar* request_type) { InfBrowserInterface* iface; g_return_val_if_fail(INF_IS_BROWSER(browser), NULL); iface = INF_BROWSER_GET_IFACE(browser); g_return_val_if_fail(iface->list_pending_requests != NULL, NULL); return iface->list_pending_requests(browser, iter, request_type); } /** * inf_browser_iter_from_request: * @browser: A #InfBrowser. * @request: A #InfRequest which has not yet finished and which was * issued by @browser. * @iter: (out): An uninitialized #InfBrowserIter. * * Sets @iter to the node for which @request was made. If that node does not * exist anymore or if @request has already finished the function returns * %FALSE and @iter is left untouched. * * Returns: %TRUE if @iter was moved or %FALSE otherwise. */ gboolean inf_browser_iter_from_request(InfBrowser* browser, InfRequest* request, InfBrowserIter* iter) { InfBrowserInterface* iface; g_return_val_if_fail(INF_IS_BROWSER(browser), FALSE); g_return_val_if_fail(INF_IS_REQUEST(request), FALSE); g_return_val_if_fail(iter != NULL, FALSE); iface = INF_BROWSER_GET_IFACE(browser); g_return_val_if_fail(iface->iter_from_request != NULL, FALSE); return iface->iter_from_request(browser, request, iter); } /** * inf_browser_get_pending_request: * @browser: A #InfBrowser. * @iter: (allow-none): A #InfBrowserIter pointing to a node inside @browser, * or %NULL. * @request_type: (allow-none): The type of request. * * Returns a pending request for the node @iter points to which matches type * @request_type. If there is no such request the function returns %NULL. * This function is a shortcut for calling * inf_browser_list_pending_requests() and retrieving the first item from * the list. * * If @iter is %NULL the function returns a global request. * * For many request types, such as "subscribe-session", "subscribe-chat", * "explore-node", "query-user-list" or "query-acl" there can only be one * request at a time, and therefore this function is more convenient to use * than inf_browser_list_pending_requests(). * * Returns: (allow-none) (transfer none): A #InfRequest, or %NULL. */ InfRequest* inf_browser_get_pending_request(InfBrowser* browser, const InfBrowserIter* iter, const gchar* request_type) { GSList* list; InfRequest* request; g_return_val_if_fail(INF_IS_BROWSER(browser), NULL); list = inf_browser_list_pending_requests(browser, iter, request_type); request = NULL; if(list != NULL) request = INF_REQUEST(list->data); g_slist_free(list); return request; } /** * inf_browser_get_acl_default_account: * @browser: A #InfBrowser. * * Returns the default #InfAclAccount representing unauthenticated users, and * which is used to look up permissions if no permissions are explicitly * specified in the ACL of a particular node for a particular account. * * Returns: (transfer none): A #InfAclAccount. The returned value is owned by * the browser and must not be freed. */ const InfAclAccount* inf_browser_get_acl_default_account(InfBrowser* browser) { InfBrowserInterface* iface; g_return_val_if_fail(INF_IS_BROWSER(browser), NULL); iface = INF_BROWSER_GET_IFACE(browser); g_return_val_if_fail(iface->get_acl_default_account != NULL, NULL); return iface->get_acl_default_account(browser); } /** * inf_browser_get_acl_local_account: * @browser: A #InfBrowser. * * Returns the #InfAclAccount representing the local host. This can be used to * check whether the local account is allowed to perform certain operations in * the browser. The function can also return %NULL, in which case all * operations are allowed, because the browser represents a local infinote * directory. * * Returns: (transfer none) (allow-none): A #InfAclAccount, or %NULL. The * returned value is owned by the browser and must not be freed. */ const InfAclAccount* inf_browser_get_acl_local_account(InfBrowser* browser) { InfBrowserInterface* iface; g_return_val_if_fail(INF_IS_BROWSER(browser), NULL); iface = INF_BROWSER_GET_IFACE(browser); g_return_val_if_fail(iface->get_acl_local_account != NULL, NULL); return iface->get_acl_local_account(browser); } /** * inf_browser_query_acl_account_list: * @browser: A #InfBrowser. * @func: (scope async): The function to be called when the request finishes, * or %NULL. * @user_data: Additional data to pass to @func. * * Queries the list of accounts in @browser. When this call has finished, * a list of accounts is available, and also a flag whether the browser * supports notification of accounts. If it does, then the * #InfBrowser::acl-account-added and #InfBrowser::acl-account-removed signals * are emitted when the account list changes, and the next time this function * is called, it might be available to serve the account list from the cache * without blocking. * * It can also be that the browser does not support listing of accounts at * all. In this case, the request will fail with an error code of * %INF_DIRECTORY_ERROR_OPERATION_UNSUPPORTED. * * The request might either finish during the call to this function, in which * case @func will be called and %NULL being returned. If the request does not * finish within the function call, a #InfRequest object is returned, where * @func has been installed for the #InfRequest::finished signal, so that it * is called as soon as the request finishes. * * Returns: (transfer none) (allow-none): A #InfRequest that can be used to * be notified when the request finishes, or %NULL. */ InfRequest* inf_browser_query_acl_account_list(InfBrowser* browser, InfRequestFunc func, gpointer user_data) { InfBrowserInterface* iface; g_return_val_if_fail(INF_IS_BROWSER(browser), NULL); iface = INF_BROWSER_GET_IFACE(browser); g_return_val_if_fail(iface->query_acl_account_list != NULL, NULL); return iface->query_acl_account_list(browser, func, user_data); } /** * inf_browser_lookup_acl_accounts: * @browser: A #InfBrowser. * @ids: (array length=n_ids): An array of account IDs to look up. * @n_ids: The number of elements in the array. * @func: (scope async): The function to be called when the request finishes, * or %NULL. * @user_data: Additional data to pass to @func. * * Looks up the accounts with the given IDs. If the account list has been * queried with inf_browser_query_acl_account_list() before, then it is * likely that this function returns instantly, otherwise an asynchronous * operation might be started. * * The request result contains an array of #InfAclAccount objects for the * given account IDs, which contain the account names as well. If one account * ID does not belong to an actual account, the #InfAclAccount.name field will * be %NULL. * * The request might either finish during the call to this function, in which * case @func will be called and %NULL being returned. If the request does not * finish within the function call, a #InfRequest object is returned, where * @func has been installed for the #InfRequest::finished signal, so that it * is called as soon as the request finishes. * * Returns: (transfer none) (allow-none): A #InfRequest that can be used to * be notified when the request finishes, or %NULL. */ InfRequest* inf_browser_lookup_acl_accounts(InfBrowser* browser, const InfAclAccountId* ids, guint n_ids, InfRequestFunc func, gpointer user_data) { InfBrowserInterface* iface; g_return_val_if_fail(INF_IS_BROWSER(browser), NULL); g_return_val_if_fail(ids != NULL, NULL); g_return_val_if_fail(n_ids > 0, NULL); iface = INF_BROWSER_GET_IFACE(browser); g_return_val_if_fail(iface->lookup_acl_accounts != NULL, NULL); return iface->lookup_acl_accounts(browser, ids, n_ids, func, user_data); } /** * inf_browser_lookup_acl_account_by_name: * @browser: A #InfBrowser. * @name: The name of the user account to look up. * @func: (scope async): The function to be called when the request finishes, * or %NULL. * @user_data: Additional data to pass to @func. * * Looks up the account(s) with the given name. While in principal, there can * be many accounts with the same name, in practise user names are often * unique. * * The request result contains an array of #InfAclAccount objects, all with * the same name. If there is only one entry with ID set to 0, there are no * accounts with the given name. * * The request might either finish during the call to this function, in which * case @func will be called and %NULL being returned. If the request does not * finish within the function call, a #InfRequest object is returned, where * @func has been installed for the #InfRequest::finished signal, so that it * is called as soon as the request finishes. * * Returns: (allow-none) (transfer none): A #InfRequest that can be used to be * notified when the request finishes, or %NULL. */ InfRequest* inf_browser_lookup_acl_account_by_name(InfBrowser* browser, const gchar* name, InfRequestFunc func, gpointer user_data) { InfBrowserInterface* iface; g_return_val_if_fail(INF_IS_BROWSER(browser), NULL); g_return_val_if_fail(name != NULL, NULL); iface = INF_BROWSER_GET_IFACE(browser); g_return_val_if_fail(iface->lookup_acl_account_by_name != NULL, NULL); return iface->lookup_acl_account_by_name(browser, name, func, user_data); } /** * inf_browser_create_acl_account: * @browser: A #InfBrowser. * @crq: A certificate request. * @func: (scope async): The function to be called when the request finishes, * or %NULL. * @user_data: Additional data to pass to @func. * * Requests creation of a new account. If the request succeeds, @crq will be * used by the server to create a certificate which is sent back to the * client and is associated to the newly created account. * * The request might either finish during the call to this function, in which * case @func will be called and %NULL being returned. If the request does not * finish within the function call, a #InfRequest object is returned, where * @func has been installed for the #InfRequest::finished signal, so that it * is called as soon as the request finishes. * * Returns: (transfer none) (allow-none): A #InfRequest that can be used to * get notified when the request finishes or fails. */ InfRequest* inf_browser_create_acl_account(InfBrowser* browser, gnutls_x509_crq_t crq, InfRequestFunc func, gpointer user_data) { InfBrowserInterface* iface; g_return_val_if_fail(INF_IS_BROWSER(browser), NULL); g_return_val_if_fail(crq != NULL, NULL); iface = INF_BROWSER_GET_IFACE(browser); g_return_val_if_fail(iface->create_acl_account != NULL, NULL); return iface->create_acl_account(browser, crq, func, user_data); } /** * inf_browser_remove_acl_account: * @browser: A #InfBrowser. * @account: The ID of the account to remove. * @func: (scope async): The function to be called when the request finishes, * or %NULL. * @user_data: Additional data to pass to @func. * * Requests deletion of the given account. * * The request might either finish during the call to this function, in which * case @func will be called and %NULL being returned. If the request does not * finish within the function call, a #InfRequest object is returned, where * @func has been installed for the #InfRequest::finished signal, so that it * is called as soon as the request finishes. * * Returns: (transfer none) (allow-none): A #InfRequest that can be used to * get notified when the request finishes or fails. */ InfRequest* inf_browser_remove_acl_account(InfBrowser* browser, InfAclAccountId account, InfRequestFunc func, gpointer user_data) { InfBrowserInterface* iface; g_return_val_if_fail(INF_IS_BROWSER(browser), NULL); g_return_val_if_fail(account != 0, NULL); iface = INF_BROWSER_GET_IFACE(browser); g_return_val_if_fail(iface->get_acl_default_account != NULL, NULL); g_return_val_if_fail( account != iface->get_acl_default_account(browser)->id, NULL ); g_return_val_if_fail(iface->remove_acl_account != NULL, NULL); return iface->remove_acl_account(browser, account, func, user_data); } /** * inf_browser_query_acl: * @browser: A #InfBrowser. * @iter: An iterator pointing to a node for which to query the ACLs. * @func: (scope async): The function to be called when the request finishes, * or %NULL. * @user_data: Additional data to pass to @func. * * Queries the ACLs for all users of the node @iter points to. When the * request has finished, inf_browser_get_acl() can be used to retrieve the * ACLs. * * The request might either finish during the call to this function, in which * case @func will be called and %NULL being returned. If the request does not * finish within the function call, a #InfRequest object is returned, * where @func has been installed for the #InfRequest::finished signal, * so that it is called as soon as the request finishes. * * Returns: (transfer none) (allow-none): A #InfRequest which can be used to * be notified when the request finishes. */ InfRequest* inf_browser_query_acl(InfBrowser* browser, const InfBrowserIter* iter, InfRequestFunc func, gpointer user_data) { InfBrowserInterface* iface; g_return_val_if_fail(INF_IS_BROWSER(browser), NULL); g_return_val_if_fail(iter != NULL, NULL); iface = INF_BROWSER_GET_IFACE(browser); g_return_val_if_fail(iface->query_acl != NULL, NULL); return iface->query_acl(browser, iter, func, user_data); } /** * inf_browser_has_acl: * @browser: A #InfBrowser. * @iter: An iterator pointing to a node for which to check full ACL * availability. * @account: The account to check ACL availability for, or 0. * * This function returns whether the ACL sheet for the given account is * available or not. If the function returns %FALSE then * inf_browser_query_acl() can be called in order to retrieve the full ACL. * If @account is 0, the function checks whether the full ACL is available, * i.e. the ACL sheets for all accounts. Usually the ACL sheets for the * default account and the local account are always available. * * Returns: %TRUE when the ACL sheet for @account is available or %FALSE * otherwise. */ gboolean inf_browser_has_acl(InfBrowser* browser, const InfBrowserIter* iter, InfAclAccountId account) { InfBrowserInterface* iface; g_return_val_if_fail(INF_IS_BROWSER(browser), FALSE); g_return_val_if_fail(iter != NULL, FALSE); iface = INF_BROWSER_GET_IFACE(browser); g_return_val_if_fail(iface->has_acl != NULL, FALSE); return iface->has_acl(browser, iter, account); } /** * inf_browser_get_acl: * @browser: A #InfBrowser. * @iter: An iterator pointing to a node for which to retrieve ACLs. * * Retrieves the ACL for the node @iter points to. This function can also * be called if the ACL has not been queried before using * inf_browser_query_acl(). In that case, the returned sheet set will only * contain sheets for the default user and the local user. The function * can return %NULL which is equivalent to an empty sheet set, i.e. no ACL. * * When the full ACL has been successfully queried with * inf_browser_query_acl(), the full ACL is returned by this function. The * function inf_browser_has_acl() can be used to check whether this function * will return the full ACL or only the sheets for the default and local * users. * * Returns: A #InfAclSheetSet containing the requested ACL, or %NULL. The * returned value is owned by the #InfBrowser and should not be freed. */ const InfAclSheetSet* inf_browser_get_acl(InfBrowser* browser, const InfBrowserIter* iter) { InfBrowserInterface* iface; g_return_val_if_fail(INF_IS_BROWSER(browser), NULL); g_return_val_if_fail(iter != NULL, NULL); iface = INF_BROWSER_GET_IFACE(browser); g_return_val_if_fail(iface->get_acl != NULL, NULL); return iface->get_acl(browser, iter); } /** * inf_browser_set_acl: * @browser: A #InfBrowser. * @iter: An iterator pointing to the node for which to change ACLs. * @sheet_set: An #InfAclSheetSet with the sheets to update. * @func: (scope async): The function to be called when the request finishes, * or %NULL. * @user_data: Additional data to pass to @func. * * Changes the ACLs for the node @iter points to. Existing sheets that are not * in @sheet_set are left untouched. This operation is only allowed when the * ACL for the node @iter points to has been retrieved already with * inf_browser_query_acl(). Use inf_browser_has_acl() to check whether this * function can be called or whether the ACL needs to be queried first. * * The request might either finish during the call to this function, in which * case @func will be called and %NULL being returned. If the request does not * finish within the function call, a #InfRequest object is returned, * where @func has been installed for the #InfRequest::finished signal, * so that it is called as soon as the request finishes. * * Returns: (transfer none) (allow-none): A #InfRequest which can be used to * be notified when the request finishes. */ InfRequest* inf_browser_set_acl(InfBrowser* browser, const InfBrowserIter* iter, const InfAclSheetSet* sheet_set, InfRequestFunc func, gpointer user_data) { InfBrowserInterface* iface; g_return_val_if_fail(INF_IS_BROWSER(browser), NULL); g_return_val_if_fail(iter != NULL, NULL); g_return_val_if_fail(sheet_set != NULL, NULL); iface = INF_BROWSER_GET_IFACE(browser); g_return_val_if_fail(iface->set_acl != NULL, NULL); return iface->set_acl(browser, iter, sheet_set, func, user_data); } /** * inf_browser_check_acl: * @browser: A #InfBrowser. * @iter: A #InfBrowserIter pointing to a node in a browser. * @account: The ID of the account whose permission to check, or %NULL. * @check_mask: A bitmask of #InfAclSettings with permissions to * check. * @out_mask: (out): Output parameter with the granted permissions, or %NULL. * * Checks whether the given account has permissions to perform the operations * specified by @mask on the node @iter points to. The @mask parameter * should have all permissions enabled that are to be checked. The function * will then write those permissions that are actually granted to the * mask specified by the @out_mask parameter. * * The function returns %TRUE if all permissions asked for are granted, i.e. * when *@out_mask equals *@mask after the function call. The @out_mask * parameter is allowed to be %NULL which is useful if only the return value * is of interest. * * In order for this function to work, the ACL sheet for @account has to be * available for the node @iter points to and all of its parent nodes. If * @account is not the default or the local account, these need to be queried * before using inf_browser_query_acl(). * * If account is 0, it is assumed that local access to the directory is * available and the function always returns %TRUE. * * Returns: %TRUE if all checked permissions are granted, or %FALSE otherwise. */ gboolean inf_browser_check_acl(InfBrowser* browser, const InfBrowserIter* iter, InfAclAccountId account, const InfAclMask* check_mask, InfAclMask* out_mask) { const InfAclAccount* default_account; InfBrowserIter check_iter; InfAclMask remaining_mask; InfAclMask perms; const InfAclSheetSet* sheet_set; const InfAclSheet* sheet; InfAclMask temp_mask; g_return_val_if_fail(INF_IS_BROWSER(browser), FALSE); g_return_val_if_fail(iter != NULL, FALSE); g_return_val_if_fail(check_mask != NULL, FALSE); if(account == 0) { if(out_mask != NULL) *out_mask = *check_mask; return TRUE; } default_account = inf_browser_get_acl_default_account(browser); if(default_account->id == account) default_account = NULL; remaining_mask = *check_mask; perms = *check_mask; check_iter = *iter; do { g_return_val_if_fail( inf_browser_has_acl(browser, &check_iter, account), FALSE ); sheet_set = inf_browser_get_acl(browser, &check_iter); if(sheet_set != NULL) { sheet = inf_acl_sheet_set_find_const_sheet(sheet_set, account); if(sheet != NULL) { inf_acl_mask_and(&sheet->mask, &remaining_mask, &temp_mask); inf_acl_mask_neg(&temp_mask, &temp_mask); inf_acl_mask_or(&sheet->perms, &temp_mask, &temp_mask); inf_acl_mask_and(&perms, &temp_mask, &perms); inf_acl_mask_neg(&sheet->mask, &temp_mask); inf_acl_mask_and(&remaining_mask, &temp_mask, &remaining_mask); } if(!inf_acl_mask_empty(&remaining_mask) && default_account != NULL) { sheet = inf_acl_sheet_set_find_const_sheet( sheet_set, default_account->id ); if(sheet != NULL) { inf_acl_mask_and(&sheet->mask, &remaining_mask, &temp_mask); inf_acl_mask_neg(&temp_mask, &temp_mask); inf_acl_mask_or(&sheet->perms, &temp_mask, &temp_mask); inf_acl_mask_and(&perms, &temp_mask, &perms); inf_acl_mask_neg(&sheet->mask, &temp_mask); inf_acl_mask_and(&remaining_mask, &temp_mask, &remaining_mask); } } } } while(!inf_acl_mask_empty(&remaining_mask) && inf_browser_get_parent(browser, &check_iter)); g_assert(inf_acl_mask_empty(&remaining_mask)); if(out_mask != NULL) *out_mask = perms; if(inf_acl_mask_equal(&perms, check_mask)) return TRUE; return FALSE; } /** * inf_browser_error: * @browser: A #InfBrowser. * @error: A #GError explaining what went wronig. * * This function emits the #InfBrowser::error signal on @browser. It is meant * to be used by interface implementations only. */ void inf_browser_error(InfBrowser* browser, const GError* error) { g_return_if_fail(INF_IS_BROWSER(browser)); g_return_if_fail(error != NULL); g_signal_emit( browser, browser_signals[ERROR_], 0, error ); } /** * inf_browser_node_added: * @browser: A #InfBrowser. * @iter: A #InfBrowserIter pointing to the newly added node. * @request: The #InfRequest that was used to add or explore the node, * or %NULL. * * This function emits the #InfBrowser::node-added signal on @browser. It is * meant to be used by interface implementations only. */ void inf_browser_node_added(InfBrowser* browser, const InfBrowserIter* iter, InfRequest* request) { g_return_if_fail(INF_IS_BROWSER(browser)); g_return_if_fail(iter != NULL); g_return_if_fail(request == NULL || INF_IS_REQUEST(request)); g_signal_emit( browser, browser_signals[NODE_ADDED], 0, iter, request ); } /** * inf_browser_node_removed: * @browser: A #InfBrowser. * @iter: A #InfBrowserIter pointing to the node to be removed. * @request: The #InfRequest that was used to delete the node, or %NULL. * * This function emits the #InfBrowser::node-removed signal on @browser. It * is meant to be used by interface implementations only. */ void inf_browser_node_removed(InfBrowser* browser, const InfBrowserIter* iter, InfRequest* request) { g_return_if_fail(INF_IS_BROWSER(browser)); g_return_if_fail(iter != NULL); g_return_if_fail(request == NULL || INF_IS_REQUEST(request)); g_signal_emit( browser, browser_signals[NODE_REMOVED], 0, iter, request ); } /** * inf_browser_subscribe_session: * @browser: A #InfBrowser. * @iter: A #InfBrowserIter pointing to the node to whose session a * subscription was made, or %NULL. * @proxy: A session proxy for the newly subscribed session. * @request: The #InfRequest that was used to initiate the subscription, * or %NULL. * * This function emits the #InfBrowser::subscribe-session signal on @browser. * It is meant to be used by interface implementations only. */ void inf_browser_subscribe_session(InfBrowser* browser, const InfBrowserIter* iter, InfSessionProxy* proxy, InfRequest* request) { g_return_if_fail(INF_IS_BROWSER(browser)); g_return_if_fail(G_IS_OBJECT(proxy)); g_return_if_fail(request == NULL || INF_IS_REQUEST(request)); g_signal_emit( browser, browser_signals[SUBSCRIBE_SESSION], 0, iter, proxy, request ); } /** * inf_browser_unsubscribe_session: * @browser: A #InfBrowser. * @iter: A #InfBrowserIter pointing to the node to whose session the * subscription was removed, or %NULL. * @proxy: A session proxy for the unsubscribed session. * @request: The #InfRequest due to which the session was unsubscribed, * or %NULL. * * This function emits the #InfBrowser::unsubscribe-session signal on * @browser. It is meant to be used by interface implementations only. */ void inf_browser_unsubscribe_session(InfBrowser* browser, const InfBrowserIter* iter, InfSessionProxy* proxy, InfRequest* request) { g_return_if_fail(INF_IS_BROWSER(browser)); g_return_if_fail(G_IS_OBJECT(proxy)); g_return_if_fail(request == NULL || INF_IS_REQUEST(request)); g_signal_emit( browser, browser_signals[UNSUBSCRIBE_SESSION], 0, iter, proxy, request ); } /** * inf_browser_begin_request: * @browser: A #InfBrowser. * @iter: A #infBrowserIter pointing to the node for which a request was made, * or %NULL. * @request: The request which was made. * * This function emits the #InfBrowser::begin_request signal on @browser. It * is meant to be used by interface implementations only. */ void inf_browser_begin_request(InfBrowser* browser, const InfBrowserIter* iter, InfRequest* request) { GValue value = { 0 }; g_return_if_fail(INF_IS_BROWSER(browser)); g_return_if_fail(INF_IS_REQUEST(request)); g_value_init(&value, G_TYPE_STRING); g_object_get_property(G_OBJECT(request), "type", &value); g_signal_emit( browser, browser_signals[BEGIN_REQUEST], g_quark_from_string(g_value_get_string(&value)), iter, request ); g_value_unset(&value); } /** * inf_browser_acl_account_added: * @browser: A #InfBrowser. * @account: The new #InfAclAccount. * @request: The #InfRequest that was used to add the account, or %NULL. * * This function emits the #InfBrowser::acl-account-added signal on @browser. * It is meant to be used by interface implementations only. */ void inf_browser_acl_account_added(InfBrowser* browser, const InfAclAccount* account, InfRequest* request) { g_return_if_fail(INF_IS_BROWSER(browser)); g_return_if_fail(account != NULL); g_return_if_fail(request == NULL || INF_IS_REQUEST(request)); g_signal_emit( browser, browser_signals[ACL_ACCOUNT_ADDED], 0, account, request ); } /** * inf_browser_acl_account_removed: * @browser: A #InfBrowser. * @account: The removed #InfAclAccount. * @request: The #InfRequest that was used to remove the account, or %NULL. * * This function emits the #InfBrowser::acl-account-removed signal on @browser. * It is meant to be used by interface implementations only. */ void inf_browser_acl_account_removed(InfBrowser* browser, const InfAclAccount* account, InfRequest* request) { g_return_if_fail(INF_IS_BROWSER(browser)); g_return_if_fail(account != NULL); g_return_if_fail(request == NULL || INF_IS_REQUEST(request)); g_signal_emit( browser, browser_signals[ACL_ACCOUNT_REMOVED], 0, account, request ); } /** * inf_browser_acl_local_account_changed: * @browser: A #InfBrowser. * @account: The new local #InfAclAccount. * @request: The #InfRequest that triggered the account change, or %NULL. * * This function emits the #InfBrowser::acl-local-account-changed signal * on @browser. It is meant to be used by interface implementations only. */ void inf_browser_acl_local_account_changed(InfBrowser* browser, const InfAclAccount* account, InfRequest* request) { g_return_if_fail(INF_IS_BROWSER(browser)); g_return_if_fail(account != NULL); g_return_if_fail(request == NULL || INF_IS_REQUEST(request)); g_signal_emit( browser, browser_signals[ACL_LOCAL_ACCOUNT_CHANGED], 0, account, request ); } /** * inf_browser_acl_changed: * @browser: A #InfBrowser. * @iter: An iterator pointing to the node for which the ACL has changed. * @sheet_set: A #InfAclSheetSet containing the changed ACL sheets. * @request: The #InfRequest that was used to change the ACL, or %NULL. * * This function emits the #InfBrowser::acl-changed signal on @browser. It * is meant to be used by interface implementations only. */ void inf_browser_acl_changed(InfBrowser* browser, const InfBrowserIter* iter, const InfAclSheetSet* sheet_set, InfRequest* request) { g_return_if_fail(INF_IS_BROWSER(browser)); g_return_if_fail(iter != NULL); g_return_if_fail(sheet_set != NULL); g_return_if_fail(request == NULL || INF_IS_REQUEST(request)); g_signal_emit( browser, browser_signals[ACL_CHANGED], 0, iter, sheet_set, request ); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-sasl-context.c0000644000000000000000000000013213034342512022752 xustar0030 mtime=1483851082.033718448 30 atime=1483851082.033718448 30 ctime=1488261589.076138899 libinfinity-0.7.1/libinfinity/common/inf-sasl-context.c0000644000175000017500000010062413034342512023507 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-sasl-context * @title: InfSaslContext * @short_description: Asynchronous SASL processing * @include: libinfinity/common/inf-sasl-context.h * @stability: Unstable * * #InfSaslContext is a wrapper for the Gsasl library. It basically adds * functionality to provide properties asynchronously to Gsasl, so that for * example a dialog can be shown to the user before continuing with the * authentication process. With Gsasl, it is expected that the callback * function sets the requested property before returning, which makes it hard * to give control back to a main loop while waiting for user input. * * This wrapper makes sure the callback is called in another thread so that it * can block without affecting the rest of the program. * Use inf_sasl_context_session_feed() as a replacement for gsasl_step64(). * Instead of returning the result data directly, the function calls a * callback once all properties requested have been provided. * * All threading internals are hidden by the wrapper, so all callbacks are * issued in the user thread. However, it requires an #InfIo object to * dispatch messages to it. Also, all #InfSaslContext functions are fully * thread-safe. **/ #include #include #include #include G_DEFINE_BOXED_TYPE(InfSaslContext, inf_sasl_context, inf_sasl_context_ref, inf_sasl_context_unref) typedef enum _InfSaslContextMessageType { /* main -> session */ INF_SASL_CONTEXT_MESSAGE_TERMINATE, INF_SASL_CONTEXT_MESSAGE_CONTINUE, INF_SASL_CONTEXT_MESSAGE_STEP, /* session -> main */ INF_SASL_CONTEXT_MESSAGE_QUERY, /* invoke callback to query a property */ INF_SASL_CONTEXT_MESSAGE_STEPPED /* step finished */ } InfSaslContextMessageType; typedef enum _InfSaslContextSessionStatus { INF_SASL_CONTEXT_SESSION_OUTER, INF_SASL_CONTEXT_SESSION_INNER, INF_SASL_CONTEXT_SESSION_TERMINATE, } InfSaslContextSessionStatus; struct _InfSaslContextSession { InfSaslContext* context; Gsasl_session* session; gpointer session_data; InfIo* main_io; GAsyncQueue* session_queue; /* query or stepped dispatch, protected by context mutex */ /* TODO: This is required because Inf(StandaloneIo) can not guarantee to * return before the dispatch is executed in another thread. We would not * need the mutex for this if InfIo would allow to set the * InfIoDispatch pointer before executing the dispatch. */ InfIoDispatch* dispatch; GThread* thread; /* This flag tells whether we are currently processing user data in the * helper thread. It is meant as a simple indicator in the main thread * whether more data can be given to the context or not. */ gboolean stepping; /* used in session thread only */ gchar* step64; InfSaslContextSessionFeedFunc feed_func; gpointer feed_user_data; int retval; InfSaslContextSessionStatus status; }; typedef struct _InfSaslContextMessage InfSaslContextMessage; struct _InfSaslContextMessage { InfSaslContextSession* session; InfSaslContextMessageType type; union { struct { int retval; } cont; struct { gchar* data; InfSaslContextSessionFeedFunc func; gpointer user_data; } step; struct { Gsasl_property prop; } query; struct { gchar *data; int retval; InfSaslContextSessionFeedFunc func; gpointer user_data; } stepped; } shared; }; struct _InfSaslContext { Gsasl* gsasl; gint ref_count; GSList* sessions; InfSaslContextCallbackFunc callback; gpointer callback_user_data; GDestroyNotify callback_notify; /* protects the session list, the callback function and access to the * Gsasl object. */ GMutex mutex; }; /* * Message handling */ static InfSaslContextMessage* inf_sasl_context_message_terminate(InfSaslContextSession* session) { InfSaslContextMessage* message; message = g_slice_new(InfSaslContextMessage); message->type = INF_SASL_CONTEXT_MESSAGE_TERMINATE; message->session = session; return message; } static InfSaslContextMessage* inf_sasl_context_message_continue(InfSaslContextSession* session, int retval) { InfSaslContextMessage* message; message = g_slice_new(InfSaslContextMessage); message->type = INF_SASL_CONTEXT_MESSAGE_CONTINUE; message->session = session; message->shared.cont.retval = retval; return message; } static InfSaslContextMessage* inf_sasl_context_message_step(InfSaslContextSession* session, const char* data, InfSaslContextSessionFeedFunc func, gpointer user_data) { InfSaslContextMessage* message; message = g_slice_new(InfSaslContextMessage); message->type = INF_SASL_CONTEXT_MESSAGE_STEP; message->session = session; message->shared.step.data = data ? g_strdup(data) : NULL; message->shared.step.func = func; message->shared.step.user_data = user_data; return message; } static InfSaslContextMessage* inf_sasl_context_message_query(InfSaslContextSession* session, Gsasl_property prop) { InfSaslContextMessage* message; message = g_slice_new(InfSaslContextMessage); message->type = INF_SASL_CONTEXT_MESSAGE_QUERY; message->session = session; message->shared.query.prop = prop; return message; } static InfSaslContextMessage* inf_sasl_context_message_stepped(InfSaslContextSession* session, char* data, int retval, InfSaslContextSessionFeedFunc func, gpointer user_data) { InfSaslContextMessage* message; message = g_slice_new(InfSaslContextMessage); message->type = INF_SASL_CONTEXT_MESSAGE_STEPPED; message->session = session; message->shared.stepped.data = data; message->shared.stepped.retval = retval; message->shared.stepped.func = func; message->shared.stepped.user_data = user_data; return message; } static void inf_sasl_context_message_free(gpointer message_) { InfSaslContextMessage* message; message = (InfSaslContextMessage*)message_; switch(message->type) { case INF_SASL_CONTEXT_MESSAGE_TERMINATE: case INF_SASL_CONTEXT_MESSAGE_CONTINUE: /* nothing to do */ break; case INF_SASL_CONTEXT_MESSAGE_STEP: g_free(message->shared.step.data); break; case INF_SASL_CONTEXT_MESSAGE_QUERY: /* nothing to do */ break; case INF_SASL_CONTEXT_MESSAGE_STEPPED: if(message->shared.stepped.data != NULL) gsasl_free(message->shared.stepped.data); break; default: g_assert_not_reached(); break; } g_slice_free(InfSaslContextMessage, message); } /* * Session thread and gsasl callback */ static void inf_sasl_context_session_message_func(gpointer user_data) { InfSaslContextMessage* message; InfSaslContextCallbackFunc func; gpointer func_user_data; gboolean needs_more; GError* error; message = (InfSaslContextMessage*)user_data; switch(message->type) { case INF_SASL_CONTEXT_MESSAGE_TERMINATE: /* session thread */ message->session->status = INF_SASL_CONTEXT_SESSION_TERMINATE; break; case INF_SASL_CONTEXT_MESSAGE_CONTINUE: /* session thread */ g_assert(message->session->status == INF_SASL_CONTEXT_SESSION_INNER); message->session->retval = message->shared.cont.retval; break; case INF_SASL_CONTEXT_MESSAGE_STEP: /* session thread */ g_assert(message->session->status == INF_SASL_CONTEXT_SESSION_OUTER); g_assert(message->shared.step.func != NULL); message->session->step64 = message->shared.step.data; message->session->feed_func = message->shared.step.func; message->session->feed_user_data = message->shared.step.user_data; message->shared.step.data = NULL; /* prevent deletion */ message->session->status = INF_SASL_CONTEXT_SESSION_INNER; break; case INF_SASL_CONTEXT_MESSAGE_QUERY: /* main thread */ g_mutex_lock(&message->session->context->mutex); g_assert(message->session->dispatch != NULL); message->session->dispatch = NULL; func = message->session->context->callback; func_user_data = message->session->context->callback_user_data; g_mutex_unlock(&message->session->context->mutex); func( message->session, message->shared.query.prop, message->session->session_data, func_user_data ); break; case INF_SASL_CONTEXT_MESSAGE_STEPPED: /* main thread */ g_mutex_lock(&message->session->context->mutex); g_assert(message->session->dispatch != NULL); message->session->dispatch = NULL; g_mutex_unlock(&message->session->context->mutex); switch(message->shared.stepped.retval) { case GSASL_OK: error = NULL; needs_more = FALSE; break; case GSASL_NEEDS_MORE: error = NULL; needs_more = TRUE; break; default: inf_gsasl_set_error(&error, message->shared.stepped.retval); needs_more = FALSE; break; } g_assert(message->session->stepping == TRUE); message->session->stepping = FALSE; message->shared.stepped.func( message->session, message->shared.stepped.data, needs_more, error, message->shared.stepped.user_data ); if(error != NULL) g_error_free(error); break; default: g_assert_not_reached(); break; } } static int inf_sasl_context_gsasl_callback(Gsasl* gsasl, Gsasl_session* gsasl_session, Gsasl_property prop) { InfSaslContextSession* session; InfSaslContextMessage* message; session = (InfSaslContextSession*)gsasl_session_hook_get(gsasl_session); /* if the status is TERMINATE then get out of the inner loop by * returning from all SASL callbacks immediately. */ if(session->status == INF_SASL_CONTEXT_SESSION_TERMINATE) return GSASL_NO_CALLBACK; g_assert(session->status == INF_SASL_CONTEXT_SESSION_INNER); /* query the property from the main thread */ g_assert(session->dispatch == NULL); session->dispatch = inf_io_add_dispatch( INF_IO(session->main_io), inf_sasl_context_session_message_func, inf_sasl_context_message_query(session, prop), inf_sasl_context_message_free ); g_mutex_unlock(&session->context->mutex); session->retval = G_MAXINT; while(session->status == INF_SASL_CONTEXT_SESSION_INNER && session->retval == G_MAXINT) { message = g_async_queue_pop(session->session_queue); inf_sasl_context_session_message_func(message); inf_sasl_context_message_free(message); } g_mutex_lock(&session->context->mutex); /* return on terminate */ if(session->status == INF_SASL_CONTEXT_SESSION_TERMINATE) return GSASL_NO_CALLBACK; g_assert(session->dispatch == NULL); return session->retval; } static void* inf_sasl_context_thread_func(gpointer data) { InfSaslContextSession* session; InfSaslContextMessage* message; session = (InfSaslContextSession*)data; int retval; char* output; InfSaslContextSessionFeedFunc feed_func; gpointer feed_user_data; /* Wait for something to do */ while(session->status != INF_SASL_CONTEXT_SESSION_TERMINATE) { switch(session->status) { case INF_SASL_CONTEXT_SESSION_OUTER: message = g_async_queue_pop(session->session_queue); inf_sasl_context_session_message_func(message); inf_sasl_context_message_free(message); break; case INF_SASL_CONTEXT_SESSION_INNER: g_mutex_lock(&session->context->mutex); g_assert(session->dispatch == NULL); /* This might call the gsasl callback once or more in which we wait * for input from the main thread. */ retval = gsasl_step64( session->session, session->step64, &output ); g_mutex_unlock(&session->context->mutex); g_free(session->step64); session->step64 = NULL; if(retval != GSASL_OK && retval != GSASL_NEEDS_MORE) output = NULL; /* Only process the result when we were not requested to terminate * within the gsasl callback. */ if(session->status != INF_SASL_CONTEXT_SESSION_TERMINATE) { feed_func = session->feed_func; feed_user_data = session->feed_user_data; session->feed_func = NULL; /* clear, so that feed can be called again */ session->status = INF_SASL_CONTEXT_SESSION_OUTER; g_mutex_lock(&session->context->mutex); g_assert(session->dispatch == NULL); session->dispatch = inf_io_add_dispatch( INF_IO(session->main_io), inf_sasl_context_session_message_func, inf_sasl_context_message_stepped( session, output, retval, feed_func, feed_user_data ), inf_sasl_context_message_free ); g_mutex_unlock(&session->context->mutex); } else { session->feed_func = NULL; if(output) gsasl_free(output); } break; case INF_SASL_CONTEXT_SESSION_TERMINATE: default: g_assert_not_reached(); break; } } return NULL; } /* * Helper functions */ static InfSaslContextSession* inf_sasl_context_start_session(InfSaslContext* context, InfIo* io, Gsasl_session* gsasl_session, gpointer session_data, GError** error) { InfSaslContextSession* session; session = g_slice_new(InfSaslContextSession); session->context = context; session->session = gsasl_session; session->session_data = session_data; session->main_io = io; g_object_ref(session->main_io); session->session_queue = g_async_queue_new_full(inf_sasl_context_message_free); session->dispatch = NULL; session->thread = NULL; session->stepping = FALSE; session->status = INF_SASL_CONTEXT_SESSION_OUTER; session->step64 = NULL; session->retval = GSASL_OK; session->feed_func = NULL; /*session->feed_user_data = NULL;*/ context->sessions = g_slist_prepend(context->sessions, session); gsasl_session_hook_set(gsasl_session, session); session->thread = g_thread_try_new( "InfSaslContext", inf_sasl_context_thread_func, session, error ); if(session->thread == NULL) { context->sessions = g_slist_remove(context->sessions, session); g_async_queue_unref(session->session_queue); g_object_unref(session->main_io); g_slice_free(InfSaslContextSession, session); return NULL; } return session; } /* * Public API */ /** * inf_sasl_context_new: (constructor) * @error: Location to store error information, if any. * * Creates a new #InfSaslContext with a reference count of 1. If the function * fails it returns %NULL and @error is set. * * Returns: (transfer full): A new #InfSaslContext, or %NULL on error. Free * with inf_sasl_context_unref() when no longer needed. */ InfSaslContext* inf_sasl_context_new(GError** error) { Gsasl* gsasl; int status; InfSaslContext* sasl; g_return_val_if_fail(error == NULL || *error == NULL, NULL); status = gsasl_init(&gsasl); if(status != GSASL_OK) { inf_gsasl_set_error(error, status); return NULL; } sasl = g_slice_new(InfSaslContext); sasl->gsasl = gsasl; sasl->ref_count = 1; sasl->sessions = NULL; sasl->callback = NULL; sasl->callback_user_data = NULL; sasl->callback_notify = NULL; gsasl_callback_set(gsasl, inf_sasl_context_gsasl_callback); gsasl_callback_hook_set(gsasl, sasl); g_mutex_init(&sasl->mutex); return sasl; } /** * inf_sasl_context_ref: * @context: A #InfSaslContext. * * Increases the reference count of @context by one. * * Returns: The passed in pointer, @context. */ InfSaslContext* inf_sasl_context_ref(InfSaslContext* context) { g_return_val_if_fail(context != NULL, NULL); g_atomic_int_inc(&context->ref_count); return context; } /** * inf_sasl_context_unref: * @context: A #InfSaslContext. * * Decreases the reference count of @sasl by one. When the reference count * reaches zero then the object is freed and may no longer be used. If that * happens then also all sessions created with * inf_sasl_context_client_start_session() or * inf_sasl_context_server_start_session() are stopped automatically. */ void inf_sasl_context_unref(InfSaslContext* context) { g_return_if_fail(context != NULL); if(g_atomic_int_dec_and_test(&context->ref_count)) { /* Note that we don't need to lock the mutex here since if nobody has a * reference anymore then they cannot access the session list concurrently * anyway. Also, the session threads do not access the list at all. */ while(context->sessions != NULL) { inf_sasl_context_stop_session( context, (InfSaslContextSession*)context->sessions->data ); } /* Again we don't need to lock the mutex for this since all session * threads have been stopped at this point. */ gsasl_done(context->gsasl); g_mutex_clear(&context->mutex); if(context->callback_notify != NULL) context->callback_notify(context->callback_user_data); g_slice_free(InfSaslContext, context); } } /** * inf_sasl_context_set_callback: * @context: A #InfSaslContext. * @callback: A function to call to query properties for authentication. * @user_data: Additional context to pass to @callback. * @notify: Function called to destroy @user_data once it is no longer needed, * or %NULL. * * Sets the callback to call when, during authentication, a certain properties * needs to be provided, such as a username or a password. The callback * function is expected to set the requested property using * inf_sasl_context_session_set_property() and then call * inf_sasl_context_session_continue() with retval being GSASL_OK. If it * cannot provide the property then it should only call * inf_sasl_context_session_continue() with retval indicating the problem. * * The callback function does not need to provide the property immediately. * It is also allowed return and call inf_sasl_context_session_continue() * later. */ void inf_sasl_context_set_callback(InfSaslContext* context, InfSaslContextCallbackFunc callback, gpointer user_data, GDestroyNotify notify) { g_return_if_fail(context != NULL); g_mutex_lock(&context->mutex); if(context->callback_notify != NULL) context->callback_notify(context->callback_user_data); context->callback = callback; context->callback_user_data = user_data; context->callback_notify = notify; g_mutex_unlock(&context->mutex); } /** * inf_sasl_context_client_start_session: * @context: A #InfSaslContext. * @io: The #InfIo main loop to which to dispatch callbacks. * @mech: The mechanism to use for the session. * @session_data: Session-specific data to provide to the * #InfSaslContextCallbackFunc. * @error: Location to store error information, if any. * * Starts a new client-side SASL session using @mech for authentication. When * the session finished, that is either when an error occurred or the * authentication finished successfully, use inf_sasl_context_stop_session(). * * The callback function will be called in the thread that @io runs in. * * Returns: (transfer none): A #InfSaslContextSession. */ InfSaslContextSession* inf_sasl_context_client_start_session(InfSaslContext* context, InfIo* io, const char* mech, gpointer session_data, GError** error) { Gsasl_session* gsasl_session; int status; InfSaslContextSession* session; g_return_val_if_fail(context != NULL, NULL); g_return_val_if_fail(INF_IS_IO(io), NULL); g_return_val_if_fail(mech != NULL, NULL); g_return_val_if_fail(error == NULL || *error == NULL, NULL); g_mutex_lock(&context->mutex); status = gsasl_client_start(context->gsasl, mech, &gsasl_session); if(status != GSASL_OK) { g_mutex_unlock(&context->mutex); inf_gsasl_set_error(error, status); return NULL; } session = inf_sasl_context_start_session( context, io, gsasl_session, session_data, error ); if(session == NULL) { gsasl_finish(gsasl_session); g_mutex_unlock(&context->mutex); return NULL; } g_mutex_unlock(&context->mutex); return session; } /** * inf_sasl_context_client_list_mechanisms: * @context: A #InfSaslContext. * @error: Location to store error information, if any. * * Returns a newly allocated space-separated string containing SASL mechanisms * that @context supports for client sessions. * * Returns: (transfer full): A newly allocated string. Free with g_free() * when no longer in use. */ gchar* inf_sasl_context_client_list_mechanisms(InfSaslContext* context, GError** error) { int ret; char* out; gchar* v; g_return_val_if_fail(context != NULL, NULL); g_return_val_if_fail(error == NULL || *error == NULL, NULL); g_mutex_lock(&context->mutex); ret = gsasl_client_mechlist(context->gsasl, &out); g_mutex_unlock(&context->mutex); if(ret != GSASL_OK) { inf_gsasl_set_error(error, ret); if(out) gsasl_free(out); return NULL; } v = g_strdup(out); gsasl_free(out); return v; } /** * inf_sasl_context_client_supports_mechanism: * @context: A #InfSaslContext. * @mech: The name of the mechanism to be tested. * * Checks whether @context supports the mechanism with name @mech for * client sessions. * * Returns: %TRUE if @mech is supported or %FALSE otherwise. */ gboolean inf_sasl_context_client_supports_mechanism(InfSaslContext* context, const char* mech) { int result; g_return_val_if_fail(context != NULL, FALSE); g_return_val_if_fail(mech != NULL, FALSE); g_mutex_lock(&context->mutex); result = gsasl_client_support_p(context->gsasl, mech); g_mutex_unlock(&context->mutex); return result != 0; } /** * inf_sasl_context_client_suggest_mechanism: * @context: A #InfSaslContext. * @mechanisms: Space-separated list of SASL mechanism names. * * Given a list of SASL mechanisms this function suggests the which is the * "best" one to be used. * * Returns: (transfer none): The name of the suggested mechanism. */ const char* inf_sasl_context_client_suggest_mechanism(InfSaslContext* context, const char* mechanisms) { const char* suggestion; g_return_val_if_fail(context != NULL, NULL); g_return_val_if_fail(mechanisms != NULL, NULL); g_mutex_lock(&context->mutex); suggestion = gsasl_client_suggest_mechanism(context->gsasl, mechanisms); g_mutex_unlock(&context->mutex); return suggestion; } /** * inf_sasl_context_server_start_session: * @context: A #InfSaslContext. * @io: The #InfIo main loop to which to dispatch callbacks. * @mech: The mechanism to use for the session. * @session_data: Session-specific data to provide to the * #InfSaslContextCallbackFunc. * @error: Location to store error information, if any. * * Starts a new server-side SASL session using @mech for authentication. When * the session finished, that is either when an error occurred or the * authentication finished successfully, use inf_sasl_context_stop_session(). * * The callback function will be called in the thread that @io runs in. * * Returns: (transfer none): A #InfSaslContextSession. */ InfSaslContextSession* inf_sasl_context_server_start_session(InfSaslContext* context, InfIo* io, const char* mech, gpointer session_data, GError** error) { Gsasl_session* gsasl_session; int status; InfSaslContextSession* session; g_return_val_if_fail(context != NULL, NULL); g_return_val_if_fail(INF_IS_IO(io), NULL); g_return_val_if_fail(mech != NULL, NULL); g_return_val_if_fail(error == NULL || *error == NULL, NULL); g_mutex_lock(&context->mutex); status = gsasl_server_start(context->gsasl, mech, &gsasl_session); if(status != GSASL_OK) { g_mutex_unlock(&context->mutex); inf_gsasl_set_error(error, status); return NULL; } session = inf_sasl_context_start_session( context, io, gsasl_session, session_data, error ); if(session == NULL) { gsasl_finish(gsasl_session); g_mutex_unlock(&context->mutex); return NULL; } g_mutex_unlock(&context->mutex); return session; } /** * inf_sasl_context_server_list_mechanisms: * @context: A #InfSaslContext. * @error: Location to store error information, if any. * * Returns a newly allocated space-separated string containing SASL mechanisms * that @context supports for server sessions. * * Returns: (transfer full): A newly allocated string. Free with g_free() * when no longer in use. */ char* inf_sasl_context_server_list_mechanisms(InfSaslContext* context, GError** error) { int ret; char* out; gchar* v; g_return_val_if_fail(context != NULL, NULL); g_return_val_if_fail(error == NULL || *error == NULL, NULL); g_mutex_lock(&context->mutex); ret = gsasl_server_mechlist(context->gsasl, &out); g_mutex_unlock(&context->mutex); if(ret != GSASL_OK) { inf_gsasl_set_error(error, ret); if(out) gsasl_free(out); return NULL; } v = g_strdup(out); gsasl_free(out); return v; } /** * inf_sasl_context_server_supports_mechanism: * @context: A #InfSaslContext. * @mech: The name of the mechanism to be tested. * * Checks whether @context supports the mechanism with name @mech for * server sessions. * * Returns: %TRUE if @mech is supported or %FALSE otherwise. */ gboolean inf_sasl_context_server_supports_mechanism(InfSaslContext* context, const char* mech) { int ret; g_return_val_if_fail(context != NULL, FALSE); g_return_val_if_fail(mech != NULL, FALSE); g_mutex_lock(&context->mutex); ret = gsasl_server_support_p(context->gsasl, mech); g_mutex_unlock(&context->mutex); return ret != 0; } /** * inf_sasl_context_stop_session: * @context: A #InfSaslContext. * @session: A #InfSaslContextSession created with @context. * * Finishes @session and frees all resources allocated to it. This can be used * to cancel an authentication session, or to free it after it finished * (either successfully or not). * * @session should no longer be used after this function was called. */ void inf_sasl_context_stop_session(InfSaslContext* context, InfSaslContextSession* session) { g_return_if_fail(context != NULL); g_return_if_fail(session != NULL); g_mutex_lock(&context->mutex); g_return_if_fail(g_slist_find(context->sessions, session) != NULL); g_return_if_fail(session->context == context); g_mutex_unlock(&context->mutex); /* Tell client thread to terminate */ g_async_queue_push( session->session_queue, inf_sasl_context_message_terminate(session) ); g_thread_join(session->thread); g_mutex_lock(&context->mutex); if(session->dispatch != NULL) inf_io_remove_dispatch(session->main_io, session->dispatch); context->sessions = g_slist_remove(context->sessions, session); gsasl_finish(session->session); g_mutex_unlock(&context->mutex); /* Note that this assertion should hold because us pushing the terminate * message into the end of the queue, and all other queued messages will * have been processed before. */ g_async_queue_unref(session->session_queue); g_object_unref(session->main_io); g_free(session->step64); g_slice_free(InfSaslContextSession, session); } /** * inf_sasl_context_session_get_property: * @session: A #InfSaslContextSession. * @prop: A SASL property. * * Returns the value of the property @prop in @session. If the value does not * yet exist then this function returns %NULL. It does not invoke the * #InfSaslContextCallbackFunc to query it. * * Returns: (allow-none): The value of the property, or %NULL. The value is * owned by the session and must not be freed. */ const char* inf_sasl_context_session_get_property(InfSaslContextSession* session, Gsasl_property prop) { const char* property; g_return_val_if_fail(session != NULL, NULL); /* TODO: We should g_strdup the return value for thread safety reasons */ g_mutex_lock(&session->context->mutex); property = gsasl_property_fast(session->session, prop); g_mutex_unlock(&session->context->mutex); return property; } /** * inf_sasl_context_session_set_property: * @session: A #InfSaslContextSession. * @prop: A SASL property. * @value: (allow-none): The value to set the property to. * * Sets the property @prop in @session to @value. */ void inf_sasl_context_session_set_property(InfSaslContextSession* session, Gsasl_property prop, const char* value) { g_return_if_fail(session != NULL); g_mutex_lock(&session->context->mutex); gsasl_property_set(session->session, prop, value); g_mutex_unlock(&session->context->mutex); } /** * inf_sasl_context_session_continue: * @session: A #InfSaslContextSession. * @retval: Error code of the operation requested. * * When the callback function specified in inf_sasl_context_set_callback() * is called then @session waits for the user to call * inf_sasl_context_session_continue(). It should do so once it provided the * requested property using inf_sasl_context_session_set_property() with * @retval being %GSASL_OK. If it decides that the property cannot be provided * then it should still call this function with @retval being a SASL error * code specifying the problem. */ void inf_sasl_context_session_continue(InfSaslContextSession* session, int retval) { g_return_if_fail(session != NULL); g_async_queue_push( session->session_queue, inf_sasl_context_message_continue(session, retval) ); } /** * inf_sasl_context_session_feed: * @session: A #InfSaslContextSession. * @data: The data to feed to the SASL session. * @func: (scope async): The function to call when the data has been * processed. * @user_data: Additional user data to pass to @func. * * This function feeds data from the session's remote counterpart to @session. * It should be base64 encoded. This function will, asynchronously, process * the data and query for properties it requires to do so. Once it has * finished, @func is called with output data to send to the remote side to * be fed to its session counterpart. * * This function must not be called again before @func was called. */ void inf_sasl_context_session_feed(InfSaslContextSession* session, const char* data, InfSaslContextSessionFeedFunc func, gpointer user_data) { g_return_if_fail(session != NULL); g_return_if_fail(func != NULL); g_return_if_fail(session->stepping == FALSE); /*g_return_if_fail(session->context->callback != NULL); not threadsafe */ session->stepping = TRUE; g_async_queue_push( session->session_queue, inf_sasl_context_message_step(session, data, func, user_data) ); } /** * inf_sasl_context_session_is_processing: * @session: A #InfSaslContextSession. * * Returns whether the session is currently asynchronously processing data * fed to it with inf_sasl_context_session_feed(). In this case the first * call needs to finish before another one is allowed to be made. * * Returns: Whether @session is currently processing data asynchronously. */ gboolean inf_sasl_context_session_is_processing(InfSaslContextSession* session) { g_return_val_if_fail(session != NULL, FALSE); return session->stepping; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-certificate-verify.c0000644000000000000000000000013213034342512024112 xustar0030 mtime=1483851082.029718427 30 atime=1483851082.029718427 30 ctime=1488261589.044138969 libinfinity-0.7.1/libinfinity/common/inf-certificate-verify.c0000644000175000017500000006430013034342512024647 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-certificate-verify * @title: InfCertificateVerify * @short_description: Server certificate verification. * @include: libinfinity/common/inf-certificate-verify.h * @see_also: #InfXmppConnection * @stability: Unstable * * #InfCertificateVerify attempts to verify server certificates. It is * associated to a #InfXmppManager, and all client-side connections managed * by that manager will be checked. * * The policy enforced by #InfCertificateVerify is such that if the * certificate is not valid, signed with a weak algorithm, expired, or not * yet activated, to reject the certificate. On the other hand, if the * certificate itself is valid and the hostname that it is issued to matches * the hostname of the connection, and its CA is trusted, then the certificate * is accepted. * * However, if the certificate as such is valid but either the hostname * does not match or the CA is not trusted (for example if a self-signed * certificate is used), then certificate pinning takes effect. If the * certificate is not pinned, the #InfCertificateVerify::check-certificate * is emitted, which should cause the certificate to be checked manually, * e.g. by presenting it to the user. Once the check is complete, call * inf_certificate_verify_checked(). If the check is positive, the certificate * is pinned, so that next time a connection to the same hostname presents * the same certificate, it is accepted automatically. If a different * certificate than the pinned one is being presented, then * the #InfCertificateVerify::check-certificate signal is emitted again. */ /* TODO: OCSP. We probably should only do OCSP stapling, and support * OCSP MUST STAPLE. Not all can be implemented here, but if the server's * certificate has OCSP MUST STAPLE set and no good OCSP response is * stapled, then reject the certificate. Also, always request a stapled OCSP * response. If OCSP MUST STAPLE is not set, and no OCSP response is * stapled, then accept the connection nevertheless (soft fail). The policy * is that if you want hard-fail, then use OCSP-MUST-STAPLE. */ #include #include #include #include #include #include #include #include #include static const GFlagsValue inf_certificate_verify_flags_values[] = { { INF_CERTIFICATE_VERIFY_HOSTNAME_MISMATCH, "INF_CERTIFICATE_VERIFY_HOSTNAME_MISMATCH", "hostname-mismatch" }, { INF_CERTIFICATE_VERIFY_ISSUER_NOT_KNOWN, "INF_CERTIFICATE_VERIFY_ISSUER_NOT_KNOWN", "issuer-not-known" }, { INF_CERTIFICATE_VERIFY_NOT_PINNED, "INF_CERTIFICATE_VERIFY_NOT_PINNED", "not-pinned" }, { 0, NULL, NULL } }; typedef struct _InfCertificateVerifyQuery InfCertificateVerifyQuery; struct _InfCertificateVerifyQuery { InfCertificateVerify* verify; GHashTable* known_hosts; InfXmppConnection* connection; InfCertificateChain* certificate_chain; }; typedef struct _InfCertificateVerifyPrivate InfCertificateVerifyPrivate; struct _InfCertificateVerifyPrivate { InfXmppManager* xmpp_manager; gchar* known_hosts_filename; GSList* queries; }; enum { PROP_0, PROP_XMPP_MANAGER, PROP_KNOWN_HOSTS_FILE }; enum { CHECK_CERTIFICATE, CHECK_CANCELLED, LAST_SIGNAL }; static guint certificate_verify_signals[LAST_SIGNAL]; #define INF_CERTIFICATE_VERIFY_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INF_TYPE_CERTIFICATE_VERIFY, InfCertificateVerifyPrivate)) INF_DEFINE_FLAGS_TYPE(InfCertificateVerifyFlags, inf_certificate_verify_flags, inf_certificate_verify_flags_values) G_DEFINE_TYPE_WITH_CODE(InfCertificateVerify, inf_certificate_verify, G_TYPE_OBJECT, G_ADD_PRIVATE(InfCertificateVerify)) static InfCertificateVerifyQuery* inf_certificate_verify_find_query(InfCertificateVerify* verify, InfXmppConnection* connection) { InfCertificateVerifyPrivate* priv; GSList* item; InfCertificateVerifyQuery* query; priv = INF_CERTIFICATE_VERIFY_PRIVATE(verify); for(item = priv->queries; item != NULL; item == item->next) { query = (InfCertificateVerifyQuery*)item->data; if(query->connection == connection) return query; } return NULL; } static void inf_certificate_verify_notify_status_cb(GObject* object, GParamSpec* pspec, gpointer user_data); static void inf_certificate_verify_query_free(InfCertificateVerifyQuery* query, gboolean emit_cancelled) { InfCertificateVerify* verify; InfXmppConnection* connection; verify = query->verify; inf_signal_handlers_disconnect_by_func( G_OBJECT(query->connection), G_CALLBACK(inf_certificate_verify_notify_status_cb), query ); connection = query->connection; inf_certificate_chain_unref(query->certificate_chain); g_hash_table_unref(query->known_hosts); g_slice_free(InfCertificateVerifyQuery, query); if(emit_cancelled) { g_signal_emit( verify, certificate_verify_signals[CHECK_CANCELLED], 0, connection ); } g_object_unref(connection); } static void inf_certificate_verify_set_known_hosts(InfCertificateVerify* verify, const gchar* known_hosts_filename) { InfCertificateVerifyPrivate* priv; priv = INF_CERTIFICATE_VERIFY_PRIVATE(verify); /* TODO: If there are running queries, the we need to load the new hosts * file and then change it in all queries. */ g_assert(priv->queries == NULL); g_free(priv->known_hosts_filename); priv->known_hosts_filename = g_strdup(known_hosts_filename); } static GHashTable* inf_certificate_verify_ref_known_hosts(InfCertificateVerify* verify, GError** error) { InfCertificateVerifyPrivate* priv; InfCertificateVerifyQuery* query; priv = INF_CERTIFICATE_VERIFY_PRIVATE(verify); if(priv->queries != NULL) { query = (InfCertificateVerifyQuery*)priv->queries->data; g_hash_table_ref(query->known_hosts); return query->known_hosts; } else { return inf_cert_util_read_certificate_map( priv->known_hosts_filename, error ); } } static gboolean inf_certificate_verify_write_known_hosts(InfCertificateVerify* verify, GHashTable* table, GError** error) { InfCertificateVerifyPrivate* priv; gchar* dirname; priv = INF_CERTIFICATE_VERIFY_PRIVATE(verify); /* Note that we pin the whole certificate and not only the public key of * our known hosts. This allows us to differentiate two cases when a * host presents a new certificate: * a) The old certificate has expired or is very close to expiration. In * this case we still show a message to the user asking whether they * trust the new certificate. * b) The old certificate was perfectly valid. In this case we show a * message saying that the certificate change was unexpected, and * unless it was expected the host should not be trusted. */ dirname = g_path_get_dirname(priv->known_hosts_filename); if(!inf_file_util_create_directory(dirname, 0755, error)) { g_free(dirname); return FALSE; } g_free(dirname); return inf_cert_util_write_certificate_map( table, priv->known_hosts_filename, error ); } static void inf_certificate_verify_write_known_hosts_with_warning( InfCertificateVerify* verify, GHashTable* table) { InfCertificateVerifyPrivate* priv; GError* error; gboolean result; priv = INF_CERTIFICATE_VERIFY_PRIVATE(verify); error = NULL; result = inf_certificate_verify_write_known_hosts(verify, table, &error); if(error != NULL) { g_warning( _("Failed to write file with known hosts \"%s\": %s"), priv->known_hosts_filename, error->message ); g_error_free(error); } } static void inf_certificate_verify_notify_status_cb(GObject* object, GParamSpec* pspec, gpointer user_data) { InfCertificateVerifyQuery* query; InfCertificateVerifyPrivate* priv; InfXmppConnection* connection; InfXmlConnectionStatus status; query = (InfCertificateVerifyQuery*)user_data; priv = INF_CERTIFICATE_VERIFY_PRIVATE(query->verify); connection = INF_XMPP_CONNECTION(object); g_object_get(G_OBJECT(connection), "status", &status, NULL); if(status == INF_XML_CONNECTION_CLOSING || status == INF_XML_CONNECTION_CLOSED) { priv->queries = g_slist_remove(priv->queries, query); inf_certificate_verify_query_free(query, TRUE); } } static void inf_certificate_verify_certificate_func(InfXmppConnection* connection, gnutls_session_t session, InfCertificateChain* chain, gpointer user_data) { InfCertificateVerify* verify; InfCertificateVerifyPrivate* priv; InfCertificateVerifyFlags flags; gnutls_x509_crt_t presented_cert; gnutls_x509_crt_t known_cert; gchar* hostname; gboolean match_hostname; gboolean issuer_known; gnutls_x509_crt_t root_cert; int ret; unsigned int verify_result; GHashTable* table; gboolean cert_equal; time_t expiration_time; InfCertificateVerifyQuery* query; GError* error; verify = INF_CERTIFICATE_VERIFY(user_data); priv = INF_CERTIFICATE_VERIFY_PRIVATE(verify); g_object_get(G_OBJECT(connection), "remote-hostname", &hostname, NULL); presented_cert = inf_certificate_chain_get_own_certificate(chain); match_hostname = gnutls_x509_crt_check_hostname(presented_cert, hostname); /* First, validate the certificate */ ret = gnutls_certificate_verify_peers2(session, &verify_result); error = NULL; if(ret != GNUTLS_E_SUCCESS) inf_gnutls_set_error(&error, ret); /* Remove the GNUTLS_CERT_ISSUER_NOT_KNOWN flag from the verification * result, and if the certificate is still invalid, then set an error. */ if(error == NULL) { issuer_known = TRUE; if(verify_result & GNUTLS_CERT_SIGNER_NOT_FOUND) { issuer_known = FALSE; /* Re-validate the certificate for other failure reasons -- * unfortunately the gnutls_certificate_verify_peers2() call * does not tell us whether the certificate is otherwise invalid * if a signer is not found already. */ /* TODO: The above has been changed with GnuTLS 3.4.0 */ /* TODO: Here it would be good to use the verify flags from the * certificate credentials, but GnuTLS does not have API to * retrieve them. */ root_cert = inf_certificate_chain_get_root_certificate(chain); ret = gnutls_x509_crt_list_verify( inf_certificate_chain_get_raw(chain), inf_certificate_chain_get_n_certificates(chain), &root_cert, 1, NULL, 0, GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT, &verify_result ); if(ret != GNUTLS_E_SUCCESS) inf_gnutls_set_error(&error, ret); } if(error == NULL) if(verify_result & GNUTLS_CERT_INVALID) inf_gnutls_certificate_verification_set_error(&error, verify_result); } /* Look up the host in our database of pinned certificates if we could not * fully verify the certificate, i.e. if either the issuer is not known or * the hostname of the connection does not match the certificate. */ table = NULL; if(error == NULL) { known_cert = NULL; if(!match_hostname || !issuer_known) { /* If we cannot load the known host file, then cancel the connection. * Otherwise it might happen that someone shows us a certificate that we * tell the user we don't know, if though actually for that host we * expect a different certificate. */ table = inf_certificate_verify_ref_known_hosts(verify, &error); if(table != NULL) known_cert = g_hash_table_lookup(table, hostname); } else { /* Load the known hosts file so that we can remove the entry belonging * to this host from it, if it's in there. However, it does not really * matter whether opening the file succeeds or not. */ table = inf_certificate_verify_ref_known_hosts(verify, NULL); } } /* Next, configure the flags for the dialog to be shown based on the * verification result, and on whether the pinned certificate matches * the one presented by the host or not. */ flags = 0; if(error == NULL) { if(known_cert != NULL) { cert_equal = inf_cert_util_compare_fingerprint( known_cert, presented_cert, &error ); if(error == NULL && cert_equal == FALSE) { if(!match_hostname) flags |= INF_CERTIFICATE_VERIFY_HOSTNAME_MISMATCH; if(!issuer_known) flags |= INF_CERTIFICATE_VERIFY_ISSUER_NOT_KNOWN; flags |= INF_CERTIFICATE_VERIFY_NOT_PINNED; } } else { if(!match_hostname) flags |= INF_CERTIFICATE_VERIFY_HOSTNAME_MISMATCH; if(!issuer_known) flags |= INF_CERTIFICATE_VERIFY_ISSUER_NOT_KNOWN; } } /* Now proceed either by accepting the connection, rejecting it, or * bothering the user with an annoying dialog. */ if(error == NULL) { if(flags == 0) { if(match_hostname && issuer_known) { /* Remove the pinned entry if we now have a valid certificate for * this host. */ if(table != NULL && g_hash_table_remove(table, hostname) == TRUE) { inf_certificate_verify_write_known_hosts_with_warning( verify, table ); } } inf_xmpp_connection_certificate_verify_continue(connection); } else { query = g_slice_new(InfCertificateVerifyQuery); query->verify = verify; query->known_hosts = table; query->connection = connection; query->certificate_chain = chain; table = NULL; g_object_ref(query->connection); inf_certificate_chain_ref(chain); priv->queries = g_slist_prepend(priv->queries, query); g_signal_connect( G_OBJECT(connection), "notify::status", G_CALLBACK(inf_certificate_verify_notify_status_cb), query ); g_signal_emit( G_OBJECT(verify), certificate_verify_signals[CHECK_CERTIFICATE], 0, connection, chain, known_cert, flags ); } } else { inf_xmpp_connection_certificate_verify_cancel(connection, error); g_error_free(error); } if(table != NULL) g_hash_table_unref(table); g_free(hostname); } static void inf_certificate_verify_connection_added_cb(InfXmppManager* manager, InfXmppConnection* connection, gpointer user_data) { InfXmppConnectionSite site; g_object_get(G_OBJECT(connection), "site", &site, NULL); if(site == INF_XMPP_CONNECTION_CLIENT) { inf_xmpp_connection_set_certificate_callback( connection, GNUTLS_CERT_REQUIRE, /* require a server certificate */ inf_certificate_verify_certificate_func, user_data, NULL ); } } static void inf_certificate_verify_init(InfCertificateVerify* verify) { InfCertificateVerifyPrivate* priv; priv = INF_CERTIFICATE_VERIFY_PRIVATE(verify); priv->xmpp_manager = NULL; priv->known_hosts_filename = NULL; } static void inf_certificate_verify_dispose(GObject* object) { InfCertificateVerify* verify; InfCertificateVerifyPrivate* priv; GSList* item; verify = INF_CERTIFICATE_VERIFY(object); priv = INF_CERTIFICATE_VERIFY_PRIVATE(verify); if(priv->xmpp_manager != NULL) { g_object_unref(priv->xmpp_manager); priv->xmpp_manager = NULL; } for(item = priv->queries; item != NULL; item = g_slist_next(item)) { inf_certificate_verify_query_free( (InfCertificateVerifyQuery*)item->data, TRUE ); } g_slist_free(priv->queries); priv->queries = NULL; G_OBJECT_CLASS(inf_certificate_verify_parent_class)->dispose(object); } static void inf_certificate_verify_finalize(GObject* object) { InfCertificateVerify* verify; InfCertificateVerifyPrivate* priv; verify = INF_CERTIFICATE_VERIFY(object); priv = INF_CERTIFICATE_VERIFY_PRIVATE(verify); inf_certificate_verify_set_known_hosts(verify, NULL); g_assert(priv->known_hosts_filename == NULL); G_OBJECT_CLASS(inf_certificate_verify_parent_class)->finalize(object); } static void inf_certificate_verify_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfCertificateVerify* verify; InfCertificateVerifyPrivate* priv; verify = INF_CERTIFICATE_VERIFY(object); priv = INF_CERTIFICATE_VERIFY_PRIVATE(verify); switch(prop_id) { case PROP_XMPP_MANAGER: g_assert(priv->xmpp_manager == NULL); /* construct/only */ priv->xmpp_manager = INF_XMPP_MANAGER(g_value_dup_object(value)); g_signal_connect( G_OBJECT(priv->xmpp_manager), "connection-added", G_CALLBACK(inf_certificate_verify_connection_added_cb), verify ); break; case PROP_KNOWN_HOSTS_FILE: inf_certificate_verify_set_known_hosts( verify, g_value_get_string(value) ); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void inf_certificate_verify_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfCertificateVerify* verify; InfCertificateVerifyPrivate* priv; verify = INF_CERTIFICATE_VERIFY(object); priv = INF_CERTIFICATE_VERIFY_PRIVATE(verify); switch(prop_id) { case PROP_XMPP_MANAGER: g_value_set_object(value, G_OBJECT(priv->xmpp_manager)); break; case PROP_KNOWN_HOSTS_FILE: g_value_set_string(value, priv->known_hosts_filename); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } /* * GType registration */ static void inf_certificate_verify_class_init( InfCertificateVerifyClass* certificate_verify_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(certificate_verify_class); object_class->dispose = inf_certificate_verify_dispose; object_class->finalize = inf_certificate_verify_finalize; object_class->set_property = inf_certificate_verify_set_property; object_class->get_property = inf_certificate_verify_get_property; /** * InfCertificateVerify::check-certificate: * @verify: The #InfCertificateVerify emitting the signal. * @connection: The connection to the remote host whose certificate is * being verified. * @certificate_chain: The certificate chain presented by the remote host. * @pinned_certificate: The certificate that we have pinned for this * host, or %NULL. * @flags: Flags explaining why this certificate needs to be checked. * * This signal is emitted every time a certificate presented by a remote * host needs to be checked manually. This happens when the issuer of the * certificate is not in the list of trusted CAs, or the certificate was * issued for a different hostname than we expected. In this case, if the * certificate is accepted manually, it will be pinned, so that next time a * connection is made to the same host under the same hostname, the * certificate is accepted automatically. * * Consumers of this class should listen to this signal and call * inf_certificate_verify_checked() when they finished the manual * certificate check. * * The @pinned_certificate instance is valid until either * inf_certificate_verify_checked() is called or the * #InfCertificateVerify::check-cancelled signal is emitted. */ certificate_verify_signals[CHECK_CERTIFICATE] = g_signal_new( "check-certificate", INF_TYPE_CERTIFICATE_VERIFY, G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfCertificateVerifyClass, check_certificate), NULL, NULL, NULL, G_TYPE_NONE, 4, INF_TYPE_XMPP_CONNECTION, INF_TYPE_CERTIFICATE_CHAIN, G_TYPE_POINTER, INF_TYPE_CERTIFICATE_VERIFY_FLAGS ); /** * InfCertificateVerify::check-cancelled: * @verify: The #InfCertificateVerify emitting the signal. * @connection: The connection to the remote host whose certificate is * being verified. * * This signal is emitted when a manual certificate check as initiated * with the #InfCertificateVerify::check-certificate signal should be * cancelled. After this signal has been emitted, * inf_certificate_verify_checked() should not be called anymore for the * specified connection. * * This typically happens when the connection to the remote host is lost * while the certificate check is in progress. */ certificate_verify_signals[CHECK_CANCELLED] = g_signal_new( "check-cancelled", INF_TYPE_CERTIFICATE_VERIFY, G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfCertificateVerifyClass, check_cancelled), NULL, NULL, NULL, G_TYPE_NONE, 1, INF_TYPE_XMPP_CONNECTION ); g_object_class_install_property( object_class, PROP_XMPP_MANAGER, g_param_spec_object( "xmpp-manager", "XMPP manager", "The XMPP manager of registered connections", INF_TYPE_XMPP_MANAGER, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_KNOWN_HOSTS_FILE, g_param_spec_string( "known-hosts-file", "Known hosts file", "File containing certificates of known hosts", NULL, G_PARAM_READWRITE ) ); } /* * Public API. */ /** * inf_certificate_verify_new: (constructor) * @xmpp_manager: The #InfXmppManager whose #InfXmppConnections to * manage the certificates for. * @known_hosts_file: (type filename) (allow-none): Path pointing to a file * that contains certificates of known hosts, or %NULL. * * Creates a new #InfCertificateVerify. For each new client-side * #InfXmppConnection in @xmpp_manager, the certificate manager will verify * the server's certificate. * * If the certificate is contained in @known_hosts_file, or is issued by a * trusted CA, then the certificate is accepted automatically. Otherwise, * the #InfCertificateVerify::check-certificate signal is emitted for a manual * check of the certificate to be performed. * * Returns: (transfer full): A new #InfCertificateVerify. **/ InfCertificateVerify* inf_certificate_verify_new(InfXmppManager* xmpp_manager, const gchar* known_hosts_file) { GObject* object; g_return_val_if_fail(INF_IS_XMPP_MANAGER(xmpp_manager), NULL); object = g_object_new( INF_TYPE_CERTIFICATE_VERIFY, "xmpp-manager", xmpp_manager, "known-hosts-file", known_hosts_file, NULL ); return INF_CERTIFICATE_VERIFY(object); } /** * inf_certificate_verify_checked: * @verify: A #InfCertificateVerify. * @connection: The #InfXmppConnection whose certificate has been checked. * @result: %TRUE if the certificate of @connection should be accepted, or * %FALSE if it should be rejected. * * This function should be called as a response to the * #InfCertificateVerify::check-certificate signal being emitted. */ void inf_certificate_verify_checked(InfCertificateVerify* verify, InfXmppConnection* connection, gboolean result) { InfCertificateVerifyQuery* query; InfCertificateVerifyPrivate* priv; gchar* hostname; gnutls_x509_crt_t cert; gnutls_x509_crt_t known_cert; GError* error; gboolean cert_equal; g_return_if_fail(INF_IS_CERTIFICATE_VERIFY(verify)); g_return_if_fail(INF_IS_XMPP_CONNECTION(connection)); query = inf_certificate_verify_find_query(verify, connection); g_return_if_fail(query != NULL); priv = INF_CERTIFICATE_VERIFY_PRIVATE(query->verify); g_object_ref(connection); if(result == TRUE) { g_object_get( G_OBJECT(query->connection), "remote-hostname", &hostname, NULL ); /* Add the certificate to the known hosts file, but only if it is not * already, to avoid unnecessary disk I/O. */ cert = inf_certificate_chain_get_own_certificate(query->certificate_chain); known_cert = g_hash_table_lookup(query->known_hosts, hostname); error = NULL; cert_equal = FALSE; if(known_cert != NULL) { cert_equal = inf_cert_util_compare_fingerprint( cert, known_cert, &error ); } if(error != NULL) { g_warning( _("Failed to add certificate to list of pinned certificates: %s"), error->message ); } else if(!cert_equal) { cert = inf_cert_util_copy_certificate(cert, &error); g_hash_table_insert(query->known_hosts, hostname, cert); inf_certificate_verify_write_known_hosts_with_warning( query->verify, query->known_hosts ); } else { g_free(hostname); } } priv->queries = g_slist_remove(priv->queries, query); inf_certificate_verify_query_free(query, FALSE); if(result == TRUE) inf_xmpp_connection_certificate_verify_continue(connection); else inf_xmpp_connection_certificate_verify_cancel(connection, NULL); g_object_unref(connection); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-xmpp-manager.h0000644000000000000000000000013013034342512022725 xustar0029 mtime=1483851082.03771847 29 atime=1483851082.03771847 30 ctime=1488261588.972139127 libinfinity-0.7.1/libinfinity/common/inf-xmpp-manager.h0000644000175000017500000000727313034342512023472 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_XMPP_MANAGER_H__ #define __INF_XMPP_MANAGER_H__ #include #include G_BEGIN_DECLS #define INF_TYPE_XMPP_MANAGER (inf_xmpp_manager_get_type()) #define INF_XMPP_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_TYPE_XMPP_MANAGER, InfXmppManager)) #define INF_XMPP_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INF_TYPE_XMPP_MANAGER, InfXmppManagerClass)) #define INF_IS_XMPP_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_TYPE_XMPP_MANAGER)) #define INF_IS_XMPP_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INF_TYPE_XMPP_MANAGER)) #define INF_XMPP_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INF_TYPE_XMPP_MANAGER, InfXmppManagerClass)) typedef struct _InfXmppManager InfXmppManager; typedef struct _InfXmppManagerClass InfXmppManagerClass; /** * InfXmppManagerClass: * @connection_added: Default signal handler for the * #InfXmppManager::connection-added signal. * @connection_removed: Default signal handler for the * #InfXmppManager::connection-removed signal. * * This structure contains the default signal handlers for #InfXmppManager. */ struct _InfXmppManagerClass { /*< private >*/ GObjectClass parent_class; /*< public >*/ void(*connection_added)(InfXmppManager* manager, InfXmppConnection* connection); void(*connection_removed)(InfXmppManager* manager, InfXmppConnection* connection, InfXmppConnection* replaced_by); }; /** * InfXmppManager: * * #InfXmppManager is an opaque data type. You should only access it via the * public API functions. */ struct _InfXmppManager { /*< private >*/ GObject parent; }; GType inf_xmpp_manager_get_type(void) G_GNUC_CONST; InfXmppManager* inf_xmpp_manager_new(void); InfXmppConnection* inf_xmpp_manager_lookup_connection_by_address(InfXmppManager* manager, const InfIpAddress* address, guint port); InfXmppConnection* inf_xmpp_manager_lookup_connection_by_hostname(InfXmppManager* manager, const gchar* hostname, const gchar* service, const gchar* srv); gboolean inf_xmpp_manager_contains_connection(InfXmppManager* manager, InfXmppConnection* connection); void inf_xmpp_manager_add_connection(InfXmppManager* manager, InfXmppConnection* connection); void inf_xmpp_manager_remove_connection(InfXmppManager* manager, InfXmppConnection* connection); G_END_DECLS #endif /* __INF_XMPP_MANAGER_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-keepalive.h0000644000000000000000000000013213034342512022300 xustar0030 mtime=1483851082.033718448 30 atime=1483851082.033718448 30 ctime=1488261588.952139171 libinfinity-0.7.1/libinfinity/common/inf-keepalive.h0000644000175000017500000000655413034342512023044 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_KEEPALIVE_H__ #define __INF_KEEPALIVE_H__ #include #include G_BEGIN_DECLS #define INF_TYPE_KEEPALIVE_MASK (inf_keepalive_mask_get_type()) #define INF_TYPE_KEEPALIVE (inf_keepalive_get_type()) /** * InfKeepaliveMask: * @INF_KEEPALIVE_ENABLED: Whether the keepalive mechanism is * explicitly enabled or disabled. * @INF_KEEPALIVE_TIME: Whether the keepalive time is * overriding the system default. * @INF_KEEPALIVE_INTERVAL: Whether the keepalive interval is * overriding the system default. * @INF_KEEPALIVE_ALL: All previous values combined. * * This bitmask specifies which of the fields in #InfKeepalive * override the system defaults. For fields that are not enabled in the * bitmask, the system default value is taken, and the corresponding field in * #InfKeepalive is ignored. */ typedef enum _InfKeepaliveMask { INF_KEEPALIVE_ENABLED = 1 << 0, INF_KEEPALIVE_TIME = 1 << 1, INF_KEEPALIVE_INTERVAL = 1 << 2, INF_KEEPALIVE_ALL = (1 << 3) - 1 } InfKeepaliveMask; /** * InfKeepalive: * @mask: Which of the following settings are enabled. If a setting is * disabled, then the system default is taken. * @enabled: Whether sending keep-alive probes is enabled or not. * @time: Time in seconds after which to send keep-alive probes. * @interval: Time in seconds between keep-alive probes. * * This structure contains the settings to configure keep-alive on TCP * connections. */ typedef struct _InfKeepalive InfKeepalive; struct _InfKeepalive { InfKeepaliveMask mask; gboolean enabled; guint time; guint interval; }; /* TODO: Implement the stuff; make sure it works on linux, windows and mac: */ /* http://www.starquest.com/Supportdocs/techStarLicense/SL002_TCPKeepAlive.shtml */ /* MSDN... */ /* SOL_TCP, TCP_KEEPCNT (tcp_keepalive_probes), TCP_KEEPIDLE (tcp_keepalive_time), TCP_KEEPINTVL (tcp_keepalive_intvl) */ /* SOL_SOCKET, SO_KEEPALIVE */ GType inf_keepalive_mask_get_type(void) G_GNUC_CONST; GType inf_keepalive_get_type(void) G_GNUC_CONST; InfKeepalive* inf_keepalive_copy(const InfKeepalive* keepalive); void inf_keepalive_free(InfKeepalive* keepalive); gboolean inf_keepalive_apply(const InfKeepalive* keepalive, InfNativeSocket* socket, InfKeepaliveMask current_mask, GError** error); void inf_keepalive_load_default(InfKeepalive* keepalive, InfKeepaliveMask mask); G_END_DECLS #endif /* __INF_KEEPALIVE_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-chat-buffer.c0000644000000000000000000000013213034342512022514 xustar0030 mtime=1483851082.029718427 30 atime=1483851082.029718427 30 ctime=1488261589.048138961 libinfinity-0.7.1/libinfinity/common/inf-chat-buffer.c0000644000175000017500000005244613034342512023261 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /** * SECTION:inf-chat-buffer * @title: InfChatBuffer * @short_description: A ring buffer for chat messages * @include: libinfinity/common/inf-chat-buffer.h * @stability: Unstable * * #InfChatBuffer contains the chat messages for a #InfChatSession. **/ #include #include #include #include static const GEnumValue inf_chat_buffer_message_type_values[] = { { INF_CHAT_BUFFER_MESSAGE_NORMAL, "INF_CHAT_BUFFER_MESSAGE_NORMAL", "normal" }, { INF_CHAT_BUFFER_MESSAGE_EMOTE, "INF_CHAT_BUFFER_MESSAGE_EMOTE", "emote" }, { INF_CHAT_BUFFER_MESSAGE_USERJOIN, "INF_CHAT_BUFFER_MESSAGE_USERJOIN", "userjoin" }, { INF_CHAT_BUFFER_MESSAGE_USERPART, "INF_CHAT_BUFFER_MESSAGE_USERPART", "userpart" }, { 0, NULL, NULL } }; static const GFlagsValue inf_chat_buffer_message_flags_values[] = { { INF_CHAT_BUFFER_MESSAGE_BACKLOG, "INF_CHAT_BUFFER_MESSAGE_BACKLOG", "backlog" }, { 0, NULL, NULL } }; typedef struct _InfChatBufferPrivate InfChatBufferPrivate; struct _InfChatBufferPrivate { InfChatBufferMessage* messages; guint alloc_messages; guint num_messages; guint first_message; /* Total size of buffer */ guint size; gboolean modified; }; enum { PROP_0, /* construct only */ PROP_SIZE, /* Read/write */ PROP_MODIFIED }; enum { ADD_MESSAGE, LAST_SIGNAL }; #define INF_CHAT_BUFFER_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INF_TYPE_CHAT_BUFFER, InfChatBufferPrivate)) static guint chat_buffer_signals[LAST_SIGNAL]; static void inf_chat_buffer_buffer_iface_init(InfBufferInterface* iface); INF_DEFINE_ENUM_TYPE(InfChatBufferMessageType, inf_chat_buffer_message_type, inf_chat_buffer_message_type_values) INF_DEFINE_FLAGS_TYPE(InfChatBufferMessageFlags, inf_chat_buffer_message_flags, inf_chat_buffer_message_flags_values) G_DEFINE_BOXED_TYPE(InfChatBufferMessage, inf_chat_buffer_message, inf_chat_buffer_message_copy, inf_chat_buffer_message_free) G_DEFINE_TYPE_WITH_CODE(InfChatBuffer, inf_chat_buffer, G_TYPE_OBJECT, G_ADD_PRIVATE(InfChatBuffer) G_IMPLEMENT_INTERFACE(INF_TYPE_BUFFER, inf_chat_buffer_buffer_iface_init)) /* * Message handling functions */ /* Allocate a new InfChatMessage for the given time, possibly removing an * old one if the buffer is full. Messages are ordered according to their time, * if there are multiple messages with the time, the new message is inserted * after the messages with the same time. */ /* The function returns NULL if the new message is older than all other * messages in the buffer. Make sure to initalize all fields of the new * message to sensible values after having called this function. */ static InfChatBufferMessage* inf_chat_buffer_reserve_message(InfChatBuffer* buffer, time_t time) { InfChatBufferPrivate* priv; InfChatBufferMessage* message; guint begin; guint end; guint n; priv = INF_CHAT_BUFFER_PRIVATE(buffer); begin = 0; end = priv->num_messages; /* Find the place at which to insert the new message */ while(begin != end) { n = (begin + end) / 2; message = &priv->messages[(priv->first_message + n) % priv->size]; if(message->time <= time) begin = (begin + end + 1)/2; else end = (begin + end)/2; } while(begin != end); n = begin; /* Can't insert at the beginning if there is no more space in the buffer */ if(n == 0 && priv->num_messages == priv->size) return NULL; if(priv->num_messages < priv->size) { /* We have buffer space available, so we don't need to drop an existing * message. */ /* We rely on the messages not wrapping around yet when the buffer is * not yet full. */ g_assert(priv->first_message + priv->num_messages <= priv->alloc_messages); if(priv->num_messages == priv->alloc_messages) { /* We need to allocate more space */ priv->alloc_messages = MAX(priv->alloc_messages * 2, 16); priv->alloc_messages = MIN(priv->alloc_messages, priv->size); g_assert(priv->alloc_messages > priv->num_messages); priv->messages = g_realloc( priv->messages, priv->alloc_messages * sizeof(InfChatBufferMessage) ); } if(n == 0 && priv->first_message == 0) { /* The new message is the first one, but there is no space at the * beginning of the array, so we need to shift the other messages */ end = (priv->alloc_messages - priv->num_messages + 1) / 2; g_assert(end > 0); memmove( priv->messages + end, priv->messages /* + priv->first_message */, priv->num_messages * sizeof(InfChatBufferMessage) ); priv->first_message = end - 1; } else if(n == priv->num_messages && priv->first_message + priv->num_messages == priv->alloc_messages) { /* The new message is the last one, but there is no space at the end of * the array, so we need to shift the other messages */ end = (priv->alloc_messages - priv->num_messages) / 2; g_assert(end + priv->num_messages < priv->alloc_messages); memmove( priv->messages + end, priv->messages + priv->first_message, priv->num_messages * sizeof(InfChatBufferMessage) ); priv->first_message = end; } else if(n > 0 && n < priv->num_messages) { /* The new message is inserted in the middle, so we need to shift either * the messages before or the ones after, depending on where we have * space available. */ if((n < priv->num_messages / 2 && priv->first_message > 0) || (n > priv->num_messages / 2 && priv->first_message + priv->num_messages == priv->alloc_messages)) { begin = priv->first_message; memmove( priv->messages + begin - 1, priv->messages + begin, (n + 1) * sizeof(InfChatBufferMessage) ); --priv->first_message; } else { memmove( priv->messages + n + 1, priv->messages + n, (priv->num_messages - n) * sizeof(InfChatBufferMessage) ); } } else { /* No memmoving has to be performed */ g_assert(n == 0 || n == priv->num_messages); if(n == 0) { g_assert(priv->first_message > 0); --priv->first_message; } else { g_assert(priv->first_message + priv->num_messages < priv->alloc_messages); } } ++ priv->num_messages; } else { /* The buffer is full. This means we need to remove the oldest message */ g_assert(n > 0); /* we have catched this before */ begin = priv->first_message; end = (priv->first_message + n) % priv->size; if(n == priv->num_messages) { /* We insert at the end, so the first message is going to be freed */ g_free(priv->messages[priv->first_message].text); priv->first_message = (priv->first_message + 1) % priv->size; } else { /* Clear the oldest message */ g_free(priv->messages[end].text); if(begin < end) { memmove( priv->messages + begin + 1, priv->messages + begin, (end - begin) * sizeof(InfChatBufferMessage) ); } else { memmove( priv->messages + end + 1, priv->messages + end, (begin - end) * sizeof(InfChatBufferMessage) ); priv->first_message = (priv->first_message + 1) % priv->size; } } /* We increased first_message, so adapt the new message's number */ --n; } return &priv->messages[(priv->first_message + n) % priv->size]; } /* * GObject overrides */ static void inf_chat_buffer_init(InfChatBuffer* buffer) { InfChatBufferPrivate* priv; priv = INF_CHAT_BUFFER_PRIVATE(buffer); priv->messages = NULL; priv->alloc_messages = 0; priv->num_messages = 0; priv->first_message = 0; priv->size = 256; priv->modified = FALSE; } static void inf_chat_buffer_finalize(GObject* object) { InfChatBuffer* buffer; InfChatBufferPrivate* priv; guint i; buffer = INF_CHAT_BUFFER(object); priv = INF_CHAT_BUFFER_PRIVATE(buffer); /* Note that the messages array is not necessarily filled from its * beginning - we might have preallocated some space for prepending * entries. */ for(i = 0; i < priv->num_messages; ++i) g_free(priv->messages[(priv->first_message + i) % priv->size].text); g_free(priv->messages); G_OBJECT_CLASS(inf_chat_buffer_parent_class)->finalize(object); } static void inf_chat_buffer_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfChatBuffer* session; InfChatBufferPrivate* priv; session = INF_CHAT_BUFFER(object); priv = INF_CHAT_BUFFER_PRIVATE(session); switch(prop_id) { case PROP_SIZE: g_assert(priv->num_messages == 0); /* construct only */ priv->size = g_value_get_uint(value); break; case PROP_MODIFIED: priv->modified = g_value_get_boolean(value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void inf_chat_buffer_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfChatBuffer* session; InfChatBufferPrivate* priv; session = INF_CHAT_BUFFER(object); priv = INF_CHAT_BUFFER_PRIVATE(session); switch(prop_id) { case PROP_SIZE: g_value_set_uint(value, priv->size); break; case PROP_MODIFIED: g_value_set_boolean(value, priv->modified); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } /* * Default signal handlers */ static void inf_chat_buffer_add_message_handler(InfChatBuffer* buffer, const InfChatBufferMessage* message) { InfChatBufferPrivate* priv; InfChatBufferMessage* new_message; priv = INF_CHAT_BUFFER_PRIVATE(buffer); new_message = inf_chat_buffer_reserve_message(buffer, message->time); /* new_message can be NULL if the buffer is already full, and the new * message is older than all existing messages. */ if(new_message != NULL) { new_message->type = message->type; new_message->user = message->user; new_message->text = g_strndup(message->text, message->length); new_message->length = message->length; new_message->time = message->time; new_message->flags = message->flags; } } /* * InfBuffer implementation */ static gboolean inf_chat_buffer_buffer_get_modified(InfBuffer* buffer) { return INF_CHAT_BUFFER_PRIVATE(buffer)->modified; } static void inf_chat_buffer_buffer_set_modified(InfBuffer* buffer, gboolean modified) { InfChatBuffer* chat_buffer; InfChatBufferPrivate* priv; chat_buffer = INF_CHAT_BUFFER(buffer); priv = INF_CHAT_BUFFER_PRIVATE(chat_buffer); if(priv->modified != modified) { priv->modified = modified; g_object_notify(G_OBJECT(buffer), "modified"); } } /* * GType registration */ static void inf_chat_buffer_class_init(InfChatBufferClass* buffer_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(buffer_class); object_class->finalize = inf_chat_buffer_finalize; object_class->set_property = inf_chat_buffer_set_property; object_class->get_property = inf_chat_buffer_get_property; buffer_class->add_message = inf_chat_buffer_add_message_handler; g_object_class_install_property( object_class, PROP_SIZE, g_param_spec_uint( "size", "size", "The maxmimum number of messages saved", 0, G_MAXUINT, 256, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_override_property(object_class, PROP_MODIFIED, "modified"); /** * InfChatBuffer::add-message: * @buffer: The #InfChatBuffer that is receiving a message. * @message: The #InfChatBufferMessage that was received. * * This signal is emitted whenever a message has been added to @buffer. */ chat_buffer_signals[ADD_MESSAGE] = g_signal_new( "add-message", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfChatBufferClass, add_message), NULL, NULL, g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE, 1, INF_TYPE_CHAT_BUFFER_MESSAGE | G_SIGNAL_TYPE_STATIC_SCOPE ); } static void inf_chat_buffer_buffer_iface_init(InfBufferInterface* iface) { iface->get_modified = inf_chat_buffer_buffer_get_modified; iface->set_modified = inf_chat_buffer_buffer_set_modified; } /* * Public API */ /** * inf_chat_buffer_message_copy: * @message: The #InfChatBufferMessage to copy. * * Creates a copy of the given message. * * Returns: (transfer full): A new #InfChatBufferMessage. Free with * inf_chat_buffer_message_free() when no longer needed. */ InfChatBufferMessage* inf_chat_buffer_message_copy(const InfChatBufferMessage* message) { InfChatBufferMessage* new_message; g_return_val_if_fail(message != NULL, NULL); new_message = g_slice_new(InfChatBufferMessage); new_message->type = message->type; new_message->user = message->user; new_message->text = g_strndup(message->text, message->length); new_message->length = message->length; new_message->time = message->time; new_message->flags = message->flags; return new_message; } /** * inf_chat_buffer_message_free: * @message: A #InfChatBufferMessage. * * Frees the given #InfChatBufferMessage which must have been created with * inf_chat_buffer_message_copy(). */ void inf_chat_buffer_message_free(InfChatBufferMessage* message) { g_return_if_fail(message != NULL); g_free(message->text); g_slice_free(InfChatBufferMessage, message); } /** * inf_chat_buffer_new: (constructor) * @size: The number of messages to store. * * Creates a new #InfChatBuffer which contains no initial messages. @size * specifies how many messages to store before dropping old messages. * * Returns: (transfer full): A new #InfChatBuffer. */ InfChatBuffer* inf_chat_buffer_new(guint size) { return g_object_new( INF_TYPE_CHAT_BUFFER, "size", size, NULL ); } /** * inf_chat_buffer_add_message: * @buffer: A #InfChatBuffer. * @by: A #InfUser who wrote the message. * @message: (array length=length): The message text. * @length: The length of @message, in bytes. * @time: The time at which the user has written the message. * @flags: Flags to set for the message to add. * * Adds a new message to the chat buffer. If the buffer is full (meaning the * number of messages in the buffer equals its size), then an old message will * get discarded. If the message to be added is older than all other messages * in the buffer, then it will not be added at all. */ void inf_chat_buffer_add_message(InfChatBuffer* buffer, InfUser* by, const gchar* message, gsize length, time_t time, InfChatBufferMessageFlags flags) { InfChatBufferMessage msg; g_return_if_fail(INF_IS_CHAT_BUFFER(buffer)); g_return_if_fail(INF_IS_USER(by)); g_return_if_fail(message != NULL); msg.type = INF_CHAT_BUFFER_MESSAGE_NORMAL; msg.user = by; /* cast const away without warning */ msg.text = *(gchar**) (gpointer) &message; msg.length = length; msg.time = time; msg.flags = flags; g_signal_emit(buffer, chat_buffer_signals[ADD_MESSAGE], 0, &msg); } /** * inf_chat_buffer_add_emote_message: * @buffer: A #InfChatBuffer. * @by: A #InfUser who wrote the message. * @message: (array length=length): The message text. * @length: The length of @message, in bytes. * @time: The time at which the user has written the message. * @flags: Flags to set for the message to add. * * Adds a new emote message to the chat buffer. If the buffer is full * (meaning the number of messages in the buffer equals its size), then an * old message will get discarded. If the message to be added is older than * all other messages in the buffer, then it will not be added at all. */ void inf_chat_buffer_add_emote_message(InfChatBuffer* buffer, InfUser* by, const gchar* message, gsize length, time_t time, InfChatBufferMessageFlags flags) { InfChatBufferMessage msg; g_return_if_fail(INF_IS_CHAT_BUFFER(buffer)); g_return_if_fail(INF_IS_USER(by)); g_return_if_fail(message != NULL); msg.type = INF_CHAT_BUFFER_MESSAGE_EMOTE; msg.user = by; /* cast const away without warning */ msg.text = *(gchar**) (gpointer) &message; msg.length = length; msg.time = time; msg.flags = flags; g_signal_emit(buffer, chat_buffer_signals[ADD_MESSAGE], 0, &msg); } /** * inf_chat_buffer_add_userjoin_message: * @buffer: A #InfChatBuffer. * @user: A #InfUser who wrote the message. * @time: The time at which the user has written the message. * @flags: Flags to set for the message to add. * * Adds a new userjoin message to the chat buffer. If the buffer is full * (meaning the number of messages in the buffer equals its size), then an * old message will get discarded. If the message to be added is older than * all other messages in the buffer, then it will not be added at all. */ void inf_chat_buffer_add_userjoin_message(InfChatBuffer* buffer, InfUser* user, time_t time, InfChatBufferMessageFlags flags) { InfChatBufferMessage msg; g_return_if_fail(INF_IS_CHAT_BUFFER(buffer)); g_return_if_fail(INF_IS_USER(user)); msg.type = INF_CHAT_BUFFER_MESSAGE_USERJOIN; msg.user = user; msg.text = NULL; msg.length = 0; msg.time = time; msg.flags = flags; g_signal_emit(buffer, chat_buffer_signals[ADD_MESSAGE], 0, &msg); } /** * inf_chat_buffer_add_userpart_message: * @buffer: A #InfChatBuffer. * @user: A #InfUser who wrote the message. * @time: The time at which the user has written the message. * @flags: Flags to set for the message to add. * * Adds a new userpart message to the chat buffer. If the buffer is full * (meaning the number of messages in the buffer equals its size), then an * old message will get discarded. If the message to be added is older than * all other messages in the buffer, then it will not be added at all. */ void inf_chat_buffer_add_userpart_message(InfChatBuffer* buffer, InfUser* user, time_t time, InfChatBufferMessageFlags flags) { InfChatBufferMessage msg; g_return_if_fail(INF_IS_CHAT_BUFFER(buffer)); g_return_if_fail(INF_IS_USER(user)); msg.type = INF_CHAT_BUFFER_MESSAGE_USERPART; msg.user = user; msg.text = NULL; msg.length = 0; msg.time = time; msg.flags = flags; g_signal_emit(buffer, chat_buffer_signals[ADD_MESSAGE], 0, &msg); } /** * inf_chat_buffer_get_message: * @buffer: A #InfChatBuffer. * @n: The index of the message to obtain. * * Returns the message with the given index from the buffer. The oldest * message in the buffer has index 0, and the most recent one has index * inf_chat_buffer_get_n_messages() - 1. * * Returns: The #InfChatBufferMessage with the given index. */ const InfChatBufferMessage* inf_chat_buffer_get_message(InfChatBuffer* buffer, guint n) { InfChatBufferPrivate* priv; g_return_val_if_fail(INF_IS_CHAT_BUFFER(buffer), NULL); g_return_val_if_fail(n < inf_chat_buffer_get_n_messages(buffer), NULL); priv = INF_CHAT_BUFFER_PRIVATE(buffer); return &priv->messages[ (priv->first_message + n) % priv->size ]; } /** * inf_chat_buffer_get_n_messages: * @buffer: A #InfChatBuffer. * * Returns the number of messages in the buffer. * * Returns: The number of messages in the buffer. */ guint inf_chat_buffer_get_n_messages(InfChatBuffer* buffer) { g_return_val_if_fail(INF_IS_CHAT_BUFFER(buffer), 0); return INF_CHAT_BUFFER_PRIVATE(buffer)->num_messages; } /** * inf_chat_buffer_get_size: * @buffer: A #InfChatBuffer. * * Returns the size of the chat buffer, which is the maximum number of * messages that can be stored in the buffer. * * Returns: The number of messages in the chat buffer. */ guint inf_chat_buffer_get_size(InfChatBuffer* buffer) { g_return_val_if_fail(INF_IS_CHAT_BUFFER(buffer), 0); return INF_CHAT_BUFFER_PRIVATE(buffer)->size; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-tcp-connection.h0000644000000000000000000000013013034342512023254 xustar0029 mtime=1483851082.03771847 29 atime=1483851082.03771847 30 ctime=1488261588.968139135 libinfinity-0.7.1/libinfinity/common/inf-tcp-connection.h0000644000175000017500000001167313034342512024020 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_TCP_CONNECTION_H__ #define __INF_TCP_CONNECTION_H__ #include #include #include #include #include G_BEGIN_DECLS #define INF_TYPE_TCP_CONNECTION (inf_tcp_connection_get_type()) #define INF_TCP_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_TYPE_TCP_CONNECTION, InfTcpConnection)) #define INF_TCP_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INF_TYPE_TCP_CONNECTION, InfTcpConnectionClass)) #define INF_IS_TCP_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_TYPE_TCP_CONNECTION)) #define INF_IS_TCP_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INF_TYPE_TCP_CONNECTION)) #define INF_TCP_CONNECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INF_TYPE_TCP_CONNECTION, InfTcpConnectionClass)) #define INF_TYPE_TCP_CONNECTION_STATUS (inf_tcp_connection_status_get_type()) typedef struct _InfTcpConnection InfTcpConnection; typedef struct _InfTcpConnectionClass InfTcpConnectionClass; /** * InfTcpConnectionClass: * @sent: Default signal handler for the #InfTcpConnection::sent signal. * @received: Default signal handler for the #InfTcpConnection::received * signal. * @error: Default signal handler for the #InfTcpConnection::error signal. * * This structure contains the default signal handlers of #InfTcpConnection. */ struct _InfTcpConnectionClass { /*< private >*/ GObjectClass parent_class; /*< public >*/ /* Signals */ void (*sent)(InfTcpConnection* connection, gconstpointer data, guint len); void (*received)(InfTcpConnection* connection, gconstpointer data, guint len); void (*error)(InfTcpConnection* connection, GError* error); }; /** * InfTcpConnection: * * #InfTcpConnection is an opaque data type. You should only access it via * the public API functions. */ struct _InfTcpConnection { /*< private >*/ GObject parent; }; /** * InfTcpConnectionStatus: * @INF_TCP_CONNECTION_CONNECTING: A new connection is currently being * established. * @INF_TCP_CONNECTION_CONNECTED: The connection is ready to send and * receive data. * @INF_TCP_CONNECTION_CLOSED: The connection is closed. Before data can be * transmitted, it needs to be opened with inf_tcp_connection_open(). * * #InfTcpConnectionStatus specifies the connection status of a * #InfTcpConnection. */ typedef enum _InfTcpConnectionStatus { INF_TCP_CONNECTION_CONNECTING, INF_TCP_CONNECTION_CONNECTED, INF_TCP_CONNECTION_CLOSED } InfTcpConnectionStatus; GType inf_tcp_connection_status_get_type(void) G_GNUC_CONST; GType inf_tcp_connection_get_type(void) G_GNUC_CONST; InfTcpConnection* inf_tcp_connection_new(InfIo* io, const InfIpAddress* remote_addr, guint remote_port); InfTcpConnection* inf_tcp_connection_new_and_open(InfIo* io, const InfIpAddress* remote_addr, guint remote_port, GError** error); InfTcpConnection* inf_tcp_connection_new_resolve(InfIo* io, InfNameResolver* resolver); gboolean inf_tcp_connection_open(InfTcpConnection* connection, GError** error); void inf_tcp_connection_close(InfTcpConnection* connection); void inf_tcp_connection_send(InfTcpConnection* connection, gconstpointer data, guint len); InfIpAddress* inf_tcp_connection_get_remote_address(InfTcpConnection* connection); guint inf_tcp_connection_get_remote_port(InfTcpConnection* connection); gboolean inf_tcp_connection_set_keepalive(InfTcpConnection* connection, const InfKeepalive* keepalive, GError** error); const InfKeepalive* inf_tcp_connection_get_keepalive(InfTcpConnection* connection); G_END_DECLS #endif /* __INF_TCP_CONNECTION_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-native-socket.c0000644000000000000000000000013213034342512023102 xustar0030 mtime=1483851082.033718448 30 atime=1483851082.033718448 30 ctime=1488261589.068138917 libinfinity-0.7.1/libinfinity/common/inf-native-socket.c0000644000175000017500000000550513034342512023641 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-native-socket * @title: InfNativeSocket * @short_description: Uniform access to the BSD socket API * @include: libinfinity/common/inf-native-socket.h * @stability: Unstable * * This module provides a common way to access the BSD socket API. While * the API is mostly equivalent on Linux and Windows, there are some subtle * differences for which uniform identifiers are provided. * * Before #InfNativeSocket can be used, on Windows WinSock2 must be * initialized. You can either do this manually, or call inf_init() which * does it for you. */ #include #include #ifndef G_OS_WIN32 # include # include #endif #include "config.h" #ifndef G_OS_WIN32 # ifdef HAVE_MSG_NOSIGNAL const int INF_NATIVE_SOCKET_SENDRECV_FLAGS = MSG_NOSIGNAL; # else const int INF_NATIVE_SOCKET_SENDRECV_FLAGS = 0; # endif #endif /** * inf_native_socket_error_quark: * * Returns a #GQuark representing the INF_NATIVE_SOCKET_ERROR domain. * * Returns: A #GQuark representing the INF_NATIVE_SOCKET_ERROR domain. */ GQuark inf_native_socket_error_quark(void) { return g_quark_from_static_string("INF_NATIVE_SOCKET_ERROR"); } /** * inf_native_socket_make_error: * @code: An error code obtained with #INF_NATIVE_SOCKET_LAST_ERROR * @error: Location to store error information. * * Converts the platform-dependent error code @code into a #GError. The * #GError will contain the same numerical value and a platform-dependent * human-readable error message. */ void inf_native_socket_make_error(int code, GError** error) { #ifdef G_OS_WIN32 gchar* error_message; error_message = g_win32_error_message(code); g_set_error_literal( error, inf_native_socket_error_quark(), code, error_message ); g_free(error_message); #else g_set_error_literal( error, inf_native_socket_error_quark(), code, strerror(code) ); #endif } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-cert-util.h0000644000000000000000000000013213034342512022243 xustar0030 mtime=1483851082.029718427 30 atime=1483851082.029718427 30 ctime=1488261588.940139196 libinfinity-0.7.1/libinfinity/common/inf-cert-util.h0000644000175000017500000001327313034342512023003 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_CERT_UTIL_H__ #define __INF_CERT_UTIL_H__ #include #include /* Get ssize_t on MSVC, required by gnutls.h */ #include G_BEGIN_DECLS /** * InfCertUtilDescription: * @validity: The number of seconds the certificate is valid, beginning from * the current time. * @dn_common_name: The common name of the certificate, or %NULL. * @san_dnsname: The DNS name of the certificate, or %NULL. * * This structure contains information that is used to generate a certificate * with the inf_cert_util_create_certificate(), * inf_cert_util_create_self_signed_certificate() and * inf_cert_util_create_signed_certificate() functions. */ typedef struct _InfCertUtilDescription InfCertUtilDescription; struct _InfCertUtilDescription { guint64 validity; const gchar* dn_common_name; const gchar* san_dnsname; }; gnutls_dh_params_t inf_cert_util_create_dh_params(GError** error); gnutls_dh_params_t inf_cert_util_read_dh_params(const gchar* filename, GError** error); gboolean inf_cert_util_write_dh_params(gnutls_dh_params_t params, const gchar* filename, GError** error); gnutls_x509_privkey_t inf_cert_util_create_private_key(gnutls_pk_algorithm_t algo, unsigned int bits, GError** error); gnutls_x509_privkey_t inf_cert_util_read_private_key(const gchar* filename, GError** error); gboolean inf_cert_util_write_private_key(gnutls_x509_privkey_t key, const gchar* filename, GError** error); gnutls_x509_crt_t inf_cert_util_create_certificate(gnutls_x509_privkey_t key, const InfCertUtilDescription* desc, GError** error); gnutls_x509_crt_t inf_cert_util_create_signed_certificate(gnutls_x509_privkey_t key, const InfCertUtilDescription* desc, gnutls_x509_crt_t sign_cert, gnutls_x509_privkey_t sign_key, GError** error); gnutls_x509_crt_t inf_cert_util_create_self_signed_certificate(gnutls_x509_privkey_t key, const InfCertUtilDescription* desc, GError** error); GPtrArray* inf_cert_util_read_certificate(const gchar* filename, GPtrArray* current, GError** error); gboolean inf_cert_util_write_certificate(gnutls_x509_crt_t* certs, guint n_certs, const gchar* filename, GError** error); gchar* inf_cert_util_write_certificate_mem(gnutls_x509_crt_t* certs, guint n_certs, GError** error); gboolean inf_cert_util_write_certificate_with_key(gnutls_x509_privkey_t key, gnutls_x509_crt_t* certs, guint n_certs, const gchar* filename, GError** error); gnutls_x509_crt_t inf_cert_util_copy_certificate(gnutls_x509_crt_t src, GError** error); GHashTable* inf_cert_util_read_certificate_map(const gchar* filename, GError** error); gboolean inf_cert_util_write_certificate_map(GHashTable* cert_map, const gchar* filename, GError** error); gboolean inf_cert_util_check_certificate_key(gnutls_x509_crt_t cert, gnutls_x509_privkey_t key); gboolean inf_cert_util_compare_fingerprint(gnutls_x509_crt_t cert1, gnutls_x509_crt_t cert2, GError** error); gchar* inf_cert_util_get_dn(gnutls_x509_crt_t cert); gchar* inf_cert_util_get_dn_by_oid(gnutls_x509_crt_t cert, const char* oid, unsigned int index); gchar* inf_cert_util_get_issuer_dn_by_oid(gnutls_x509_crt_t cert, const char* oid, unsigned int index); gchar* inf_cert_util_get_hostname(gnutls_x509_crt_t cert); gchar* inf_cert_util_get_serial_number(gnutls_x509_crt_t cert); gchar* inf_cert_util_get_fingerprint(gnutls_x509_crt_t cert, gnutls_digest_algorithm_t algo); gchar* inf_cert_util_get_activation_time(gnutls_x509_crt_t cert); gchar* inf_cert_util_get_expiration_time(gnutls_x509_crt_t cert); G_END_DECLS #endif /* __INF_CERT_UTIL_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-buffer.h0000644000000000000000000000013213034342512021604 xustar0030 mtime=1483851082.029718427 30 atime=1483851082.029718427 30 ctime=1488261588.936139205 libinfinity-0.7.1/libinfinity/common/inf-buffer.h0000644000175000017500000000441013034342512022335 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_BUFFER_H__ #define __INF_BUFFER_H__ #include G_BEGIN_DECLS #define INF_TYPE_BUFFER (inf_buffer_get_type()) #define INF_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_TYPE_BUFFER, InfBuffer)) #define INF_IS_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_TYPE_BUFFER)) #define INF_BUFFER_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), INF_TYPE_BUFFER, InfBufferInterface)) typedef struct _InfBuffer InfBuffer; typedef struct _InfBufferInterface InfBufferInterface; /** * InfBufferInterface: * @get_modified: Returns whether the buffer has been modified since the last * call to @set_modified set modified flag to %FALSE. * @set_modified: Set the current modified state of the buffer. * * The virtual methods of #InfBuffer. */ struct _InfBufferInterface { /*< private >*/ GTypeInterface parent; /*< public >*/ gboolean (*get_modified)(InfBuffer* buffer); void (*set_modified)(InfBuffer* buffer, gboolean modified); }; /** * InfBuffer: * * #InfBuffer is an opaque data type. You should only access it * via the public API functions. */ GType inf_buffer_get_type(void) G_GNUC_CONST; gboolean inf_buffer_get_modified(InfBuffer* buffer); void inf_buffer_set_modified(InfBuffer* buffer, gboolean modified); G_END_DECLS #endif /* __INF_BUFFER_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-acl.c0000644000000000000000000000013213034342512021065 xustar0030 mtime=1483851082.029718427 30 atime=1483851082.029718427 30 ctime=1488261589.036138987 libinfinity-0.7.1/libinfinity/common/inf-acl.c0000644000175000017500000011162313034342512021623 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-acl * @title: Access Control Lists * @short_description: Common data structures for the infinote ACL Permissions * @include: libinfinity/common/inf-acl.h * @see_also: #InfBrowser * @stability: Unstable * * The basic ACL data structure is #InfAclSheet, which represents settings * for one user and one node in the infinote directory. One setting can have * three states: it can be enabled, it can be disabled or it can be set to * default which means to take the setting from the the default account or * the parent directory. The default user for the root node must not have any * setting set to default. * * The various settings are represented by the #InfAclSetting enumeration. * This specifies different operations for which access can be granted or * denied to different users. #InfAclMask represents a bitfield of all * A #InfAclSheetSet represents a set of #InfAclSheets, for different * users. There is one #InfAclSheetSet for each node of a infinote directory. * * Usually, for application programming, the functions in this class need not * be used. All relevant functionality is exposed by the #InfBrowser * interface. */ #include #include #include #include #include #include #define MAKE_MASK(x) ((guint64)1 << (guint64)((x) & ((1 << 6) - 1))) #define MAKE_CHECKED_MASK(n, x) \ ((x >= (n) * (1 << 6) && x < (n + 1) * (1 << 6)) ? MAKE_MASK(x) : 0) #define MAKE_DEFAULT_MASK(n) \ MAKE_CHECKED_MASK(n, INF_ACL_CAN_ADD_SUBDIRECTORY) | \ MAKE_CHECKED_MASK(n, INF_ACL_CAN_ADD_DOCUMENT) | \ MAKE_CHECKED_MASK(n, INF_ACL_CAN_SYNC_IN) | \ MAKE_CHECKED_MASK(n, INF_ACL_CAN_REMOVE_NODE) | \ MAKE_CHECKED_MASK(n, INF_ACL_CAN_EXPLORE_NODE) | \ MAKE_CHECKED_MASK(n, INF_ACL_CAN_SUBSCRIBE_CHAT) | \ MAKE_CHECKED_MASK(n, INF_ACL_CAN_SUBSCRIBE_SESSION) | \ MAKE_CHECKED_MASK(n, INF_ACL_CAN_JOIN_USER) #define MAKE_ROOT_MASK(n) \ MAKE_CHECKED_MASK(n, INF_ACL_CAN_SUBSCRIBE_CHAT) | \ MAKE_CHECKED_MASK(n, INF_ACL_CAN_QUERY_ACCOUNT_LIST) | \ MAKE_CHECKED_MASK(n, INF_ACL_CAN_CREATE_ACCOUNT) | \ MAKE_CHECKED_MASK(n, INF_ACL_CAN_OVERRIDE_ACCOUNT) | \ MAKE_CHECKED_MASK(n, INF_ACL_CAN_REMOVE_ACCOUNT) #define MAKE_SUBDIRECTORY_MASK(n) \ MAKE_CHECKED_MASK(n, INF_ACL_CAN_ADD_SUBDIRECTORY) | \ MAKE_CHECKED_MASK(n, INF_ACL_CAN_ADD_DOCUMENT) | \ MAKE_CHECKED_MASK(n, INF_ACL_CAN_SYNC_IN) | \ MAKE_CHECKED_MASK(n, INF_ACL_CAN_REMOVE_NODE) | \ MAKE_CHECKED_MASK(n, INF_ACL_CAN_EXPLORE_NODE) #define MAKE_LEAF_MASK(n) \ MAKE_CHECKED_MASK(n, INF_ACL_CAN_SUBSCRIBE_SESSION) | \ MAKE_CHECKED_MASK(n, INF_ACL_CAN_JOIN_USER) #define MAKE_FULL_MASK(m) \ { m(0), m(1), m(2), m(3) } const InfAclMask INF_ACL_MASK_ALL = { INF_ACL_LAST >= 0x0040 ? 0xffffffffffffffff : MAKE_MASK(INF_ACL_LAST) - 1, INF_ACL_LAST >= 0x0080 ? 0xffffffffffffffff : MAKE_MASK(INF_ACL_LAST) - 1, INF_ACL_LAST >= 0x00c0 ? 0xffffffffffffffff : MAKE_MASK(INF_ACL_LAST) - 1, INF_ACL_LAST >= 0x0100 ? 0xffffffffffffffff : MAKE_MASK(INF_ACL_LAST) - 1, }; const InfAclMask INF_ACL_MASK_DEFAULT = { MAKE_FULL_MASK(MAKE_DEFAULT_MASK) }; const InfAclMask INF_ACL_MASK_ROOT = { MAKE_FULL_MASK(MAKE_ROOT_MASK) }; const InfAclMask INF_ACL_MASK_SUBDIRECTORY = { MAKE_FULL_MASK(MAKE_SUBDIRECTORY_MASK) }; const InfAclMask INF_ACL_MASK_LEAF = { MAKE_FULL_MASK(MAKE_LEAF_MASK) }; static const GEnumValue inf_acl_setting_values[] = { { INF_ACL_CAN_ADD_SUBDIRECTORY, "INF_ACL_CAN_ADD_SUBDIRECTORY", "can-add-subdirectory" }, { INF_ACL_CAN_ADD_DOCUMENT, "INF_ACL_CAN_ADD_DOCUMENT", "can-add-document" }, { INF_ACL_CAN_SYNC_IN, "INF_ACL_CAN_SYNC_IN", "can-sync-in" }, { INF_ACL_CAN_REMOVE_NODE, "INF_ACL_CAN_REMOVE_NODE", "can-remove-node" }, { INF_ACL_CAN_EXPLORE_NODE, "INF_ACL_CAN_EXPLORE_NODE", "can-explore-node" }, { INF_ACL_CAN_SUBSCRIBE_CHAT, "INF_ACL_CAN_SUBSCRIBE_CHAT", "can-subscribe-chat" }, { INF_ACL_CAN_SUBSCRIBE_SESSION, "INF_ACL_CAN_SUBSCRIBE_SESSION", "can-subscribe-session" }, { INF_ACL_CAN_JOIN_USER, "INF_ACL_CAN_JOIN_USER", "can-join-user" }, { INF_ACL_CAN_QUERY_ACCOUNT_LIST, "INF_ACL_CAN_QUERY_ACCOUNT_LIST", "can-query-account-list" }, { INF_ACL_CAN_CREATE_ACCOUNT, "INF_ACL_CAN_CREATE_ACCOUNT", "can-create-account" }, { INF_ACL_CAN_OVERRIDE_ACCOUNT, "INF_ACL_CAN_OVERRIDE_ACCOUNT", "can-override-account" }, { INF_ACL_CAN_REMOVE_ACCOUNT, "INF_ACL_CAN_REMOVE_ACCOUNT", "can-remove-account" }, { INF_ACL_CAN_QUERY_ACL, "INF_ACL_CAN_QUERY_ACL", "can-query-acl" }, { INF_ACL_CAN_SET_ACL, "INF_ACL_CAN_SET_ACL", "can-set-acl" }, { 0, NULL, NULL } }; G_DEFINE_BOXED_TYPE(InfAclAccount, inf_acl_account, inf_acl_account_copy, inf_acl_account_free) INF_DEFINE_ENUM_TYPE(InfAclSetting, inf_acl_setting, inf_acl_setting_values) G_DEFINE_BOXED_TYPE(InfAclMask, inf_acl_mask, inf_acl_mask_copy, inf_acl_mask_free) G_DEFINE_BOXED_TYPE(InfAclSheet, inf_acl_sheet, inf_acl_sheet_copy, inf_acl_sheet_free) G_DEFINE_BOXED_TYPE(InfAclSheetSet, inf_acl_sheet_set, inf_acl_sheet_set_copy, inf_acl_sheet_set_free) /** * inf_acl_account_id_to_string: * @account: A #InfAclAccountId. * * Translates the given account ID to a unique string identifier. * * Returns: A string representation of the given account ID, or %NULL if * the account does not exist. The return value must not be freed. */ const gchar* inf_acl_account_id_to_string(InfAclAccountId account) { return g_quark_to_string(account); } /** * inf_acl_account_id_from_string: * @id: A string representation of an account ID. * * Converts the given string into a unique account identifier which can be * used with the rest of the ACL API. * * Returns: (transfer full): The account ID which is equivalent to the given * string. */ InfAclAccountId inf_acl_account_id_from_string(const gchar* id) { return g_quark_from_string(id); } /** * inf_acl_account_new: * @id: The unique ID of the new account. * @name: (allow-none): The human-readable name of the new account. * * Creates a new #InfAclAccount. * * Returns: (transfer full): A new #InfAclAccount object. */ InfAclAccount* inf_acl_account_new(const InfAclAccountId id, const gchar* name) { InfAclAccount* account; g_return_val_if_fail(id != 0, NULL); account = g_slice_new(InfAclAccount); account->id = id; account->name = g_strdup(name); return account; } /** * inf_acl_account_copy: * @account: The #InfAclAccount to copy. * * Creates a copy of @account. * * Returns: (transfer full): A new #InfAclAccount. Free with * inf_acl_account_free() when no longer needed. */ InfAclAccount* inf_acl_account_copy(const InfAclAccount* account) { InfAclAccount* new_account; g_return_val_if_fail(account != NULL, NULL); new_account = g_slice_new(InfAclAccount); new_account->id = account->id; new_account->name = g_strdup(account->name); return new_account; } /** * inf_acl_account_free: * @account: A #InfAclAccount. * * Releases all resources allocated by @account. */ void inf_acl_account_free(InfAclAccount* account) { g_free(account->name); g_slice_free(InfAclAccount, account); } /** * inf_acl_account_array_free: * @accounts: (array length=n_accounts): An array of #InfAclAccount objects. * @n_accounts: The number of elements in the array. * * Releases all resources allocated by an array of #InfAclAccounts. */ void inf_acl_account_array_free(InfAclAccount* accounts, guint n_accounts) { guint i; for(i = 0; i < n_accounts; ++i) g_free(accounts[i].name); g_free(accounts); } /** * inf_acl_account_from_xml: * @xml: An XML node. * @error: Location to store error information, if any. * * Attempts to deserialize an #InfAclAccount that was written to an XML node * by the function inf_acl_account_to_xml(). If an error occurs, such as * mandatory fields being missing, the function returns %NULL and @error is * set. * * Returns: (transfer full): A new #InfAclAccount on success, or %NULL on * failure. Free with inf_acl_account_free() when no longer needed. */ InfAclAccount* inf_acl_account_from_xml(xmlNodePtr xml, GError** error) { xmlChar* account_id; xmlChar* account_name; InfAclAccount* new_account; account_id = inf_xml_util_get_attribute_required(xml, "id", error); if(account_id == NULL) return NULL; account_name = inf_xml_util_get_attribute(xml, "name"); new_account = inf_acl_account_new( inf_acl_account_id_from_string((const gchar*)account_id), (const gchar*)account_name ); xmlFree(account_id); if(account_name != NULL) xmlFree(account_name); return new_account; } /** * inf_acl_account_to_xml: * @account: A #InfAclAccount. * @xml: The XML node to write the account attributes to. * * Serializes the properties of @account into the XML node @xml. The function * inf_acl_account_from_xml() does the reverse operation and deserializes the * account object from the XML. */ void inf_acl_account_to_xml(const InfAclAccount* account, xmlNodePtr xml) { inf_xml_util_set_attribute( xml, "id", inf_acl_account_id_to_string(account->id) ); if(account->name != NULL) inf_xml_util_set_attribute(xml, "name", account->name); } /** * inf_acl_mask_copy: * @mask: The #InfAclMask to copy. * * Creates a dynamically allocated copy of @mask. This function should not * usually be used since masks can simply created on the stack and copied * by value. This function is mainly meant for the boxed type definition and * for language bindings. * * Returns: (transfer full): A new #InfAclMask. Free with inf_acl_mask_free() * when no longer needed. */ InfAclMask* inf_acl_mask_copy(const InfAclMask* mask) { InfAclMask* new_mask; g_return_val_if_fail(mask != NULL, NULL); new_mask = g_slice_new(InfAclMask); new_mask->mask[0] = mask->mask[0]; new_mask->mask[1] = mask->mask[1]; new_mask->mask[2] = mask->mask[2]; new_mask->mask[3] = mask->mask[3]; return new_mask; } /** * inf_acl_mask_free: * @mask: The #InfAclMask to free. * * Releases a #InfAclMask that was created with inf_acl_mask_copy(). */ void inf_acl_mask_free(InfAclMask* mask) { g_return_if_fail(mask != NULL); g_slice_free(InfAclMask, mask); } /** * inf_acl_mask_clear: * @mask: The #InfAclMask to reset. * * Resets a mask so that all fields are zero. */ void inf_acl_mask_clear(InfAclMask* mask) { g_return_if_fail(mask != NULL); mask->mask[0] = 0; mask->mask[1] = 0; mask->mask[2] = 0; mask->mask[3] = 0; } /** * inf_acl_mask_empty: * @mask: A #InfAclMask. * * Checks whether the given mask is empty, i.e. all fields are set to zero. * * Returns: %TRUE if @mask has all fields zero, or %FALSE otherwies. */ gboolean inf_acl_mask_empty(const InfAclMask* mask) { g_return_val_if_fail(mask != NULL, FALSE); return (mask->mask[0] & INF_ACL_MASK_ALL.mask[0]) == 0 && (mask->mask[1] & INF_ACL_MASK_ALL.mask[1]) == 0 && (mask->mask[2] & INF_ACL_MASK_ALL.mask[2]) == 0 && (mask->mask[3] & INF_ACL_MASK_ALL.mask[3]) == 0; } /** * inf_acl_mask_equal: * @lhs: The first mask. * @rhs: The second mask. * * Checks whether the two masks are equal. * * Returns: %TRUE if @lhs and @rhs are equal or %FALSE otherwise. */ gboolean inf_acl_mask_equal(const InfAclMask* lhs, const InfAclMask* rhs) { g_return_val_if_fail(lhs != NULL, FALSE); g_return_val_if_fail(rhs != NULL, FALSE); return ((lhs->mask[0] ^ rhs->mask[0]) & INF_ACL_MASK_ALL.mask[0]) == 0 && ((lhs->mask[1] ^ rhs->mask[1]) & INF_ACL_MASK_ALL.mask[1]) == 0 && ((lhs->mask[2] ^ rhs->mask[2]) & INF_ACL_MASK_ALL.mask[2]) == 0 && ((lhs->mask[3] ^ rhs->mask[3]) & INF_ACL_MASK_ALL.mask[3]) == 0; } /** * inf_acl_mask_set1: * @mask: The #InfAclMask to initialize. * @setting: The permission to set. * * Initializes @mask such that all permissions are off except the one * corresponding to @setting. * * Returns: (transfer none): The mask itself. */ InfAclMask* inf_acl_mask_set1(InfAclMask* mask, InfAclSetting setting) { g_return_val_if_fail(mask != NULL, NULL); g_return_val_if_fail(setting < 0x100, NULL); mask->mask[0] = 0; mask->mask[1] = 0; mask->mask[2] = 0; mask->mask[3] = 0; mask->mask[setting >> 6] = MAKE_MASK(setting); return mask; } /** * inf_acl_mask_setv: * @mask: The #InfAclMask to initialize. * @settings: (array length=n_settings): An array of * #InfAclSettings to set. * @n_settings: The number of settings. * * Initializes @mask such that all permissions are off except the ones * specified in the @settings array. * * Returns: (transfer none): The mask itself. */ InfAclMask* inf_acl_mask_setv(InfAclMask* mask, const InfAclSetting* settings, guint n_settings) { guint i; g_return_val_if_fail(mask != NULL, NULL); g_return_val_if_fail(settings != NULL || n_settings == 0, NULL); mask->mask[0] = 0; mask->mask[1] = 0; mask->mask[2] = 0; mask->mask[3] = 0; for(i = 0; i < n_settings; ++i) { g_return_val_if_fail(settings[i] < 0x100, NULL); mask->mask[settings[i] >> 6] |= MAKE_MASK(settings[i]); } return mask; } /** * inf_acl_mask_and: * @lhs: First mask. * @rhs: Second mask. * @out: (out): Output mask. * * Computes the bitwise AND of @lhs and @rhs and writes the result to @out. * @out is allowed to be equivalent to @lhs and/or @rhs. * * Returns: (transfer none): The output mask. */ InfAclMask* inf_acl_mask_and(const InfAclMask* lhs, const InfAclMask* rhs, InfAclMask* out) { g_return_val_if_fail(lhs != NULL, NULL); g_return_val_if_fail(rhs != NULL, NULL); g_return_val_if_fail(out != NULL, NULL); out->mask[0] = rhs->mask[0] & lhs->mask[0]; out->mask[1] = rhs->mask[1] & lhs->mask[1]; out->mask[2] = rhs->mask[2] & lhs->mask[2]; out->mask[3] = rhs->mask[3] & lhs->mask[3]; return out; } /** * inf_acl_mask_and1: * @mask: A #InfAclMask. * @setting: The setting to unset. * * Disables the bit corresponding to setting in @mask, leaving all other bits * alone. * * Returns: (transfer none): The mask itself. */ InfAclMask* inf_acl_mask_and1(InfAclMask* mask, InfAclSetting setting) { g_return_val_if_fail(mask != NULL, NULL); g_return_val_if_fail(setting < 0x100, NULL); mask->mask[setting >> 6] &= ~MAKE_MASK(setting); return mask; } /** * inf_acl_mask_or: * @lhs: First mask. * @rhs: Second mask. * @out: (out): Output mask. * * Computes the bitwise OR of @lhs and @rhs and writes the result to @out. * @out is allowed to be equivalent to @lhs and/or @rhs. * * Returns: (transfer none): The output mask. */ InfAclMask* inf_acl_mask_or(const InfAclMask* lhs, const InfAclMask* rhs, InfAclMask* out) { g_return_val_if_fail(lhs != NULL, NULL); g_return_val_if_fail(rhs != NULL, NULL); g_return_val_if_fail(out != NULL, NULL); out->mask[0] = rhs->mask[0] | lhs->mask[0]; out->mask[1] = rhs->mask[1] | lhs->mask[1]; out->mask[2] = rhs->mask[2] | lhs->mask[2]; out->mask[3] = rhs->mask[3] | lhs->mask[3]; return out; } /** * inf_acl_mask_or1: * @mask: A #InfAclMask. * @setting: The setting to add. * * Enables the bit corresponding to setting in @mask, leaving all other bits * alone. * * Returns: (transfer none): The mask itself. */ InfAclMask* inf_acl_mask_or1(InfAclMask* mask, InfAclSetting setting) { g_return_val_if_fail(mask != NULL, NULL); g_return_val_if_fail(setting < 0x100, NULL); mask->mask[setting >> 6] |= MAKE_MASK(setting); return mask; } /** * inf_acl_mask_neg: * @mask: The mask to negate. * @out: (out): The output mask. * * Negates the given mask bitwise and writes the result to @out. The output * mask is allowed to be equivalent to @mask itself. * * Returns: (transfer full): The output mask. */ InfAclMask* inf_acl_mask_neg(const InfAclMask* mask, InfAclMask* out) { g_return_val_if_fail(mask != NULL, NULL); g_return_val_if_fail(out != NULL, NULL); out->mask[0] = ~mask->mask[0]; out->mask[1] = ~mask->mask[1]; out->mask[2] = ~mask->mask[2]; out->mask[3] = ~mask->mask[3]; return out; } /** * inf_acl_mask_has: * @mask: A #InfAclMask. * @setting: The setting to check. * * Returns %TRUE if the given mask has the bit which corresponds to @setting * set, or %FALSE otherwise. * * Returns: %TRUE if the bit corresponding to @setting is set in @mask. */ gboolean inf_acl_mask_has(const InfAclMask* mask, InfAclSetting setting) { g_return_val_if_fail(mask != NULL, FALSE); g_return_val_if_fail(setting < 0x100, FALSE); return (mask->mask[setting >> 6] & MAKE_MASK(setting)) != 0; } /** * inf_acl_sheet_new: * @account: The #InfAclAccountId representing a unique account id. * * Creates a dynamically allocated #InfAclSheet. This is usually not * needed because you can copy the structs by value, but it is useful * for properties and bindings. The new sheet will hold permissions for the * given account. The permissions will initially be all masked out. * * Returns: (transfer full): A new #InfAclSheet. Free with * inf_acl_sheet_free() when no longer in use. */ InfAclSheet* inf_acl_sheet_new(InfAclAccountId account) { InfAclSheet* sheet; sheet = g_slice_new(InfAclSheet); sheet->account = account; inf_acl_mask_clear(&sheet->mask); inf_acl_mask_clear(&sheet->perms); /* not strictly required */ return sheet; } /** * inf_acl_sheet_copy: * @sheet: A #InfAclSheet. * * Makes a dynamically allocated copy of @sheet. This should not be used by * applications because you can copy the structs by value, but it is useful * for properties and bindings. * * Returns: (transfer full): A newly-allocated copy of @sheet. Free with * inf_acl_sheet_free() when no longer in use. */ InfAclSheet* inf_acl_sheet_copy(const InfAclSheet* sheet) { InfAclSheet* new_sheet; new_sheet = g_slice_new(InfAclSheet); new_sheet->account = sheet->account; new_sheet->mask = sheet->mask; new_sheet->perms = sheet->perms; return new_sheet; } /** * inf_acl_sheet_free: * @sheet: A #InfAclSheet. * * Frees a #InfAclSheet allocated by inf_acl_sheet_copy(). **/ void inf_acl_sheet_free(InfAclSheet* sheet) { g_slice_free(InfAclSheet, sheet); } /** * inf_acl_sheet_perms_from_xml: * @xml: The XML node to read from. * @mask: (out): Output parameter to write the permission mask to. * @perms: (out): Output parameter to write the permissions to. * @error: Location to store error information, if any. * * This function extracts the permission mask and the permission flags from * the XML node @xml. The counterpart to this function is * inf_acl_sheet_perms_to_xml(). If an error occurs the function returns * %FALSE and @error is set. * * Returns: %TRUE if the operation was successful, or %FALSE on error. */ gboolean inf_acl_sheet_perms_from_xml(xmlNodePtr xml, InfAclMask* mask, InfAclMask* perms, GError** error) { GEnumClass* enum_class; guint i; xmlChar* attr; InfAclSetting value; inf_acl_mask_clear(mask); /* not strictly required because the relevant bits are initialized * below, but helps in debugging: */ inf_acl_mask_clear(perms); enum_class = G_ENUM_CLASS(g_type_class_ref(INF_TYPE_ACL_SETTING)); for(i = 0; i < enum_class->n_values; ++i) { attr = inf_xml_util_get_attribute(xml, enum_class->values[i].value_nick); if(attr != NULL) { value = enum_class->values[i].value; mask->mask[value >> 6] |= MAKE_MASK(value); if(strcmp((const xmlChar*)attr, "yes") == 0) { perms->mask[value >> 6] |= MAKE_MASK(value); } else if(strcmp((const xmlChar*)attr, "no") == 0) { perms->mask[value >> 6] &= ~MAKE_MASK(value); } else { g_set_error_literal( error, inf_request_error_quark(), INF_REQUEST_ERROR_INVALID_ATTRIBUTE, _("ACL field must be either \"yes\" or \"no\"") ); } xmlFree(attr); } } g_type_class_unref(enum_class); return TRUE; } /** * inf_acl_sheet_perms_to_xml: * @mask: Permission mask to write. * @perms: Individiual permissions to write. * @xml: error: Location to store error information, if any. * * This function writes the given permission mask and permission flags to the * XML node @xml. They can be converted back using the * inf_acl_sheet_perms_from_xml() function. */ void inf_acl_sheet_perms_to_xml(const InfAclMask* mask, const InfAclMask* perms, xmlNodePtr xml) { GEnumClass* enum_class; guint i; guint64 value; const gchar* value_nick; enum_class = G_ENUM_CLASS(g_type_class_ref(INF_TYPE_ACL_SETTING)); for(i = 0; i < enum_class->n_values; ++i) { value = enum_class->values[i].value; if((mask->mask[value >> 6] & MAKE_MASK(value)) != 0) { value_nick = enum_class->values[i].value_nick; if((perms->mask[value >> 6] & MAKE_MASK(value)) != 0) inf_xml_util_set_attribute(xml, value_nick, "yes"); else inf_xml_util_set_attribute(xml, value_nick, "no"); } } g_type_class_unref(enum_class); } /** * inf_acl_sheet_set_new: * * Creates a new #InfAclSheetSet. Add sheets with * inf_acl_sheet_set_add_sheet(). * * Returns: (transfer full): A new #InfAclSheetSet. Free with * inf_acl_sheet_set_free(). */ InfAclSheetSet* inf_acl_sheet_set_new(void) { InfAclSheetSet* sheet_set; sheet_set = g_slice_new(InfAclSheetSet); sheet_set->own_sheets = NULL; sheet_set->sheets = NULL; sheet_set->n_sheets = 0; return sheet_set; } /** * inf_acl_sheet_set_new_external: * @sheets: (array length=n_sheets): An array of #InfAclSheets * @n_sheets: Number of elements in @sheets. * * Creates a new #InfAclSheetSet refererencing the given ACL sheets. The * created sheet set is only holding a reference to the given array, so it * must stay alive as long as the sheet set is alive. * * No new sheets can be added to the returned sheet set with * inf_acl_sheet_set_add_sheet(), or removed with * inf_acl_sheet_set_remove_sheet(). * * Returns: (transfer full): A new #InfAclSheetSet. Free with * inf_acl_sheet_set_free() when no longer needed. */ InfAclSheetSet* inf_acl_sheet_set_new_external(const InfAclSheet* sheets, guint n_sheets) { InfAclSheetSet* sheet_set; g_return_val_if_fail(sheets != NULL || n_sheets == 0, NULL); sheet_set = g_slice_new(InfAclSheetSet); sheet_set->own_sheets = NULL; sheet_set->sheets = sheets; sheet_set->n_sheets = n_sheets; return sheet_set; } /** * inf_acl_sheet_set_copy: * @sheet_set: A #InfAclSheetSet. * * Creates a copy of @sheet_set. If @sheet_set was created with * inf_acl_sheet_set_new_external(), the copied sheet set will also only hold * a reference to the external sheets, and the same restrictions apply. * * Returns: (transfer full): A new #InfAclSheetSet. Free with * inf_acl_sheet_set_free() when no longer needed. */ InfAclSheetSet* inf_acl_sheet_set_copy(const InfAclSheetSet* sheet_set) { InfAclSheetSet* new_sheet_set; g_return_val_if_fail(sheet_set != NULL, NULL); new_sheet_set = g_slice_new(InfAclSheetSet); if(sheet_set->own_sheets != NULL) { new_sheet_set->own_sheets = g_malloc(sheet_set->n_sheets * sizeof(InfAclSheet)); new_sheet_set->sheets = new_sheet_set->own_sheets; new_sheet_set->n_sheets = sheet_set->n_sheets; memcpy( new_sheet_set->own_sheets, sheet_set->own_sheets, sheet_set->n_sheets * sizeof(InfAclSheet) ); } else { new_sheet_set->own_sheets = NULL; new_sheet_set->sheets = sheet_set->sheets; new_sheet_set->n_sheets = sheet_set->n_sheets; } return new_sheet_set; } /** * inf_acl_sheet_set_sink: * @sheet_set: A #InfAclSheetSet. * * If a sheet set was created with inf_acl_sheet_set_new_external(), this * function lifts the restrictions that come with it by making an internal * copy of the ACL sheets. */ void inf_acl_sheet_set_sink(InfAclSheetSet* sheet_set) { g_return_if_fail(sheet_set != NULL); if(sheet_set->own_sheets == NULL && sheet_set->n_sheets > 0) { sheet_set->own_sheets = g_malloc(sheet_set->n_sheets * sizeof(InfAclSheet)); memcpy( sheet_set->own_sheets, sheet_set->sheets, sheet_set->n_sheets * sizeof(InfAclSheet) ); sheet_set->sheets = sheet_set->own_sheets; } } /** * inf_acl_sheet_set_free: * @sheet_set: A #InfAclSheetSet. * * Releases all resources allocated for @sheet_set. */ void inf_acl_sheet_set_free(InfAclSheetSet* sheet_set) { g_return_if_fail(sheet_set != NULL); g_free(sheet_set->own_sheets); g_slice_free(InfAclSheetSet, sheet_set); } /** * inf_acl_sheet_set_add_sheet: * @sheet_set: A #InfAclSheetSet. * @account: The #InfAclAccountId representing a unique account ID. * * Adds a new default sheet for @account to @sheet_set. The function returns * a pointer to the new sheet. The pointer stays valid as long as no other * sheet is added to the set. If there is already a sheet for @account in the * set, then the existing sheet is returned instead. * * This function can only be used if the sheet set has not been created with * the inf_acl_sheet_set_new_external() function. * * Returns: (transfer none): A #InfAclSheet for the new account. */ InfAclSheet* inf_acl_sheet_set_add_sheet(InfAclSheetSet* sheet_set, InfAclAccountId account) { guint i; g_return_val_if_fail(sheet_set != NULL, NULL); g_return_val_if_fail(account != 0, NULL); g_return_val_if_fail( sheet_set->own_sheets != NULL || sheet_set->n_sheets == 0, NULL ); for(i = 0; i < sheet_set->n_sheets; ++i) if(sheet_set->own_sheets[i].account == account) return &sheet_set->own_sheets[i]; ++sheet_set->n_sheets; sheet_set->own_sheets = g_realloc( sheet_set->own_sheets, sheet_set->n_sheets * sizeof(InfAclSheet) ); sheet_set->sheets = sheet_set->own_sheets; sheet_set->own_sheets[i].account = account; inf_acl_mask_clear(&sheet_set->own_sheets[i].mask); inf_acl_mask_clear(&sheet_set->own_sheets[i].perms); /* not strictly required */ return &sheet_set->own_sheets[i]; } /** * inf_acl_sheet_set_remove_sheet: * @sheet_set: A #InfAclSheetSet. * @sheet: The sheet to remove. * * Removes a sheet from @sheet_set. @sheet must be one of the sheets inside * @sheet_set. The sheet is removed by replacing it with the last sheet in * the set, so the order of sheets is not preserved. * * This function can only be used if the sheet set has not been created with * the inf_acl_sheet_set_new_external() function. */ void inf_acl_sheet_set_remove_sheet(InfAclSheetSet* sheet_set, InfAclSheet* sheet) { g_return_if_fail(sheet_set != NULL); g_return_if_fail(sheet_set->own_sheets != NULL); g_return_if_fail(sheet != NULL); g_return_if_fail(sheet >= sheet_set->own_sheets); g_return_if_fail(sheet < sheet_set->own_sheets + sheet_set->n_sheets); if(sheet != &sheet_set->own_sheets[sheet_set->n_sheets - 1]) *sheet = sheet_set->own_sheets[sheet_set->n_sheets - 1]; --sheet_set->n_sheets; sheet_set->own_sheets = g_realloc( sheet_set->own_sheets, sheet_set->n_sheets * sizeof(InfAclSheet) ); sheet_set->sheets = sheet_set->own_sheets; } /** * inf_acl_sheet_set_merge_sheets: * @sheet_set: (allow-none) (transfer full): A #InfAclSheetSet, or %NULL. * @other: The sheet set to merge. * * Replaces all sheets that are present in @other in @sheet_set with the ones * from @other. Note that an empty sheet in @other (with all permissions * masked out) causes the corresponding sheet in @sheet_set to be removed. * * If @sheet_set is %NULL it is treated like an empty sheet set, i.e. the * merged sheet set is a copy of @other. In that case a new sheet set is * created and returned, unless @other is empty. If the merged sheet set * ends up empty, it is freed and the function returns %NULL. * * Returns: (allow-none) (transfer full): The merged sheet set, or %NULL * when the merged sheet set would be empty. */ InfAclSheetSet* inf_acl_sheet_set_merge_sheets(InfAclSheetSet* sheet_set, const InfAclSheetSet* other) { guint i; InfAclSheet* sheet; g_return_val_if_fail(other != NULL, NULL); if(sheet_set == NULL) sheet_set = inf_acl_sheet_set_new(); for(i = 0; i < other->n_sheets; ++i) { if(inf_acl_mask_empty(&other->sheets[i].mask)) { /* Sheet is empty: remove */ sheet = inf_acl_sheet_set_find_sheet( sheet_set, other->sheets[i].account ); if(sheet != NULL) inf_acl_sheet_set_remove_sheet(sheet_set, sheet); } else { /* Sheet is not empty: take */ sheet = inf_acl_sheet_set_add_sheet( sheet_set, other->sheets[i].account ); sheet->mask = other->sheets[i].mask; sheet->perms = other->sheets[i].perms; } } if(sheet_set->n_sheets == 0) { inf_acl_sheet_set_free(sheet_set); sheet_set = NULL; } return sheet_set; } /** * inf_acl_sheet_set_get_clear_sheets: * @sheet_set: A #InfAclSheetSet. * * Returns a new sheet set with all sheets that are present in @sheet_set, * but with all permissions masked. When this set is merged with the original * set, all permissions will be reset to default for all accounts. Before * the merge, the returned sheet set can be modified. This allows to replace * the current permissions with new ones atomically. * * Returns: (transfer full): A new #InfAclSheetSet. Free with * inf_acl_sheet_set_free() when no longer needed. */ InfAclSheetSet* inf_acl_sheet_set_get_clear_sheets(const InfAclSheetSet* sheet_set) { InfAclSheetSet* set; guint i; g_return_val_if_fail(sheet_set != NULL, NULL); set = g_slice_new(InfAclSheetSet); set->own_sheets = g_malloc(sizeof(InfAclSheet) * sheet_set->n_sheets); set->n_sheets = 0; for(i = 0; i < sheet_set->n_sheets; ++i) { if(!inf_acl_mask_empty(&sheet_set->sheets[i].mask)) { set->own_sheets[set->n_sheets].account = sheet_set->sheets[i].account; inf_acl_mask_clear(&set->own_sheets[set->n_sheets].mask); set->own_sheets[set->n_sheets].perms = sheet_set->sheets[i].perms; ++set->n_sheets; } } if(set->n_sheets < sheet_set->n_sheets) { set->own_sheets = g_realloc( set->own_sheets, sizeof(InfAclSheet) * set->n_sheets ); } set->sheets = set->own_sheets; return set; } /** * inf_acl_sheet_set_find_sheet: * @sheet_set: A #InfAclSheetSet. * @account: The #InfAclAccountId representing the unique account ID of the * account whose ACL sheet is to be found. * * Returns the #InfAclSheet for @account. If there is no such sheet in * @sheet_set, the function returns %NULL. * * This function can only be used if the sheet set has not been created with * the inf_acl_sheet_set_new_external() function. * * Returns: (transfer none): A #InfAclSheet for @account, or %NULL. */ InfAclSheet* inf_acl_sheet_set_find_sheet(InfAclSheetSet* sheet_set, InfAclAccountId account) { guint i; g_return_val_if_fail(sheet_set != NULL, NULL); g_return_val_if_fail(account != 0, NULL); g_return_val_if_fail( sheet_set->own_sheets != NULL || sheet_set->n_sheets == 0, NULL ); for(i = 0; i < sheet_set->n_sheets; ++i) if(sheet_set->own_sheets[i].account == account) return &sheet_set->own_sheets[i]; return NULL; } /** * inf_acl_sheet_set_find_const_sheet: * @sheet_set: A #InfAclSheetSet. * @account: The #InfAclAccountId representing the unique account ID of the * account whose ACL sheet is to be found. * * Returns the #InfAclSheet for @account. If there is no such sheet in * @sheet_set, the function returns %NULL. * * The difference between this function and * inf_acl_sheet_set_find_sheet() is that this function returns a sheet * that cannot be modified, but it can also be used on a sheet set created * with the inf_acl_sheet_set_new_external() function. * * Returns: (transfer none): A #InfAclSheet for @account, or %NULL. */ const InfAclSheet* inf_acl_sheet_set_find_const_sheet(const InfAclSheetSet* sheet_set, InfAclAccountId account) { guint i; g_return_val_if_fail(sheet_set != NULL, NULL); g_return_val_if_fail(account != 0, NULL); for(i = 0; i < sheet_set->n_sheets; ++i) if(sheet_set->sheets[i].account == account) return &sheet_set->sheets[i]; return NULL; } /** * inf_acl_sheet_set_from_xml: * @xml: The XML node from which to read the sheet set. * @error: Location to read error information, if any. * * Reads a sheet set from @xml that has been written with * inf_acl_sheet_set_to_xml(). If an error occurs the function returns * %NULL and @error is set. If there is no ACL stored in @xml, the function * returns %NULL without setting @error. * * Returns: (transfer full): A #InfAclSheetSet, or %NULL. Free with * inf_acl_sheet_set_free() when no longer needed. */ InfAclSheetSet* inf_acl_sheet_set_from_xml(xmlNodePtr xml, GError** error) { xmlNodePtr acl; xmlNodePtr sheet; GArray* array; InfAclSheet read_sheet; xmlChar* account_id; guint i; gboolean result; InfAclSheetSet* sheet_set; g_return_val_if_fail(xml != NULL, NULL); g_return_val_if_fail(error == NULL || *error == NULL, NULL); for(acl = xml->children; acl != NULL; acl = acl->next) { if(acl->type != XML_ELEMENT_NODE) continue; if(strcmp((const char*)acl->name, "acl") != 0) continue; array = g_array_sized_new(FALSE, FALSE, sizeof(InfAclSheet), 16); for(sheet = acl->children; sheet != NULL; sheet = sheet->next) { if(sheet->type != XML_ELEMENT_NODE) continue; if(strcmp((const char*)sheet->name, "sheet") != 0) continue; account_id = inf_xml_util_get_attribute_required(sheet, "id", error); if(account_id == NULL) { g_array_free(array, TRUE); return NULL; } read_sheet.account = g_quark_from_string((const char*)account_id); xmlFree(account_id); for(i = 0; i < array->len; ++i) { if(g_array_index(array, InfAclSheet, i).account == read_sheet.account) { g_set_error( error, inf_request_error_quark(), INF_REQUEST_ERROR_INVALID_ATTRIBUTE, _("Permissions for account ID \"%s\" defined more than once"), g_quark_to_string(read_sheet.account) ); g_array_free(array, TRUE); return FALSE; } } result = inf_acl_sheet_perms_from_xml( sheet, &read_sheet.mask, &read_sheet.perms, error ); if(result == FALSE) { g_array_free(array, TRUE); return NULL; } g_array_append_vals(array, &read_sheet, 1); } if(array->len == 0) { g_array_free(array, TRUE); return NULL; } sheet_set = inf_acl_sheet_set_new(); sheet_set->n_sheets = array->len; sheet_set->own_sheets = (InfAclSheet*)g_array_free(array, FALSE); sheet_set->sheets = sheet_set->own_sheets; return sheet_set; } return NULL; } /** * inf_acl_sheet_set_to_xml: * @sheet_set: The #InfAclSheetSet to serialize. * @xml: The XML node to serialize @sheet_set into. * * Serializes the sheet set given by @sheet_set into an XML node. The sheet * set can be deserialized again with inf_acl_sheet_set_from_xml(). */ void inf_acl_sheet_set_to_xml(const InfAclSheetSet* sheet_set, xmlNodePtr xml) { xmlNodePtr acl; xmlNodePtr sheet; guint i; g_return_if_fail(sheet_set != NULL); g_return_if_fail(xml != NULL); if(sheet_set->n_sheets > 0) { acl = xmlNewChild(xml, NULL, (const xmlChar*)"acl", NULL); for(i = 0; i < sheet_set->n_sheets; ++i) { sheet = xmlNewChild(acl, NULL, (const xmlChar*)"sheet", NULL); inf_xml_util_set_attribute( sheet, "id", g_quark_to_string(sheet_set->sheets[i].account) ); inf_acl_sheet_perms_to_xml( &sheet_set->sheets[i].mask, &sheet_set->sheets[i].perms, sheet ); } } } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-chat-session.c0000644000000000000000000000013213034342512022726 xustar0030 mtime=1483851082.029718427 30 atime=1483851082.029718427 30 ctime=1488261589.052138951 libinfinity-0.7.1/libinfinity/common/inf-chat-session.c0000644000175000017500000007756613034342512023505 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /** * SECTION:inf-chat-session * @title: InfChatSession * @short_description: Simple standalone chat * @include: libinfinity/common/inf-chat-session.h * @stability: Unstable * * #InfChatSession represents a chat session. Normally, there is one chat * session per server, and it can be enabled via infd_directory_enable_chat(). * Clients can subscribe to the chat session via * infc_browser_subscribe_chat(). **/ #include #include #include #include #include #include #include typedef struct _InfChatSessionLogUserlistForeachData InfChatSessionLogUserlistForeachData; struct _InfChatSessionLogUserlistForeachData { FILE* log_file; gchar* time_str; guint users_total; }; typedef struct _InfChatSessionPrivate InfChatSessionPrivate; struct _InfChatSessionPrivate { gchar* log_filename; FILE* log_file; }; enum { PROP_0, PROP_LOG_FILE }; enum { RECEIVE_MESSAGE, SEND_MESSAGE, LAST_SIGNAL }; #define INF_CHAT_SESSION_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INF_TYPE_CHAT_SESSION, InfChatSessionPrivate)) static guint chat_session_signals[LAST_SIGNAL]; static GQuark inf_chat_session_error_quark; G_DEFINE_TYPE_WITH_CODE(InfChatSession, inf_chat_session, INF_TYPE_SESSION, G_ADD_PRIVATE(InfChatSession)) /* * Error functions */ /* Currently unused, but can be used for a later translate_error vfunc * implementation. */ #if 0 static const gchar* inf_chat_session_strerror(InfChatSessionError code) { switch(code) { case INF_CHAT_SESSION_ERROR_TYPE_INVALID: return _("An invalid message type was sent"); case INF_CHAT_SESSION_ERROR_NO_SUCH_USER: return _("A user with the requested ID does not exist"); case INF_CHAT_SESSION_ERROR_FAILED: return _("An unknown chat session error has occured"); default: return _("An error with unknown error code occured"); } } #endif /* * Message Type <-> string conversions */ static const gchar* inf_chat_session_message_type_to_string(InfChatBufferMessageType type) { switch(type) { case INF_CHAT_BUFFER_MESSAGE_NORMAL: return "normal"; case INF_CHAT_BUFFER_MESSAGE_EMOTE: return "emote"; case INF_CHAT_BUFFER_MESSAGE_USERJOIN: return "userjoin"; case INF_CHAT_BUFFER_MESSAGE_USERPART: return "userpart"; default: g_assert_not_reached(); return NULL; } } static gboolean inf_chat_session_message_type_from_string(const gchar* string, InfChatBufferMessageType* type, GError** error) { if(strcmp(string, "normal") == 0) { *type = INF_CHAT_BUFFER_MESSAGE_NORMAL; return TRUE; } else if(strcmp(string, "emote") == 0) { *type = INF_CHAT_BUFFER_MESSAGE_EMOTE; return TRUE; } else if(strcmp(string, "userjoin") == 0) { *type = INF_CHAT_BUFFER_MESSAGE_USERJOIN; return TRUE; } else if(strcmp(string, "userpart") == 0) { *type = INF_CHAT_BUFFER_MESSAGE_USERPART; return TRUE; } g_set_error( error, inf_chat_session_error_quark, INF_CHAT_SESSION_ERROR_TYPE_INVALID, "Invalid message type: \"%s\"", string ); return FALSE; } /* * Message XML functions */ static xmlNodePtr inf_chat_session_message_to_xml(InfChatSession* session, const InfChatBufferMessage* message, gboolean for_sync) { xmlNodePtr xml; xml = xmlNewNode(NULL, (const xmlChar*)"message"); if(message->type != INF_CHAT_BUFFER_MESSAGE_NORMAL) { inf_xml_util_set_attribute( xml, "type", inf_chat_session_message_type_to_string(message->type) ); } if(for_sync) inf_xml_util_set_attribute_long(xml, "time", (long)message->time); inf_xml_util_set_attribute_uint( xml, "user", inf_user_get_id(message->user) ); if(message->text != NULL) inf_xml_util_add_child_text(xml, message->text, message->length); return xml; } static gboolean inf_chat_session_message_from_xml(InfChatSession* session, InfChatBufferMessage* message, xmlNodePtr xml, gboolean for_sync, GError** error) { xmlChar* type; gboolean result; InfChatBufferMessageType message_type; InfChatBufferMessageFlags message_flags; long message_time; guint user_id; InfUserTable* user_table; InfUser* user; message_flags = 0; type = inf_xml_util_get_attribute(xml, "type"); if(type == NULL) { message_type = INF_CHAT_BUFFER_MESSAGE_NORMAL; } else { result = inf_chat_session_message_type_from_string( (const char*)type, &message_type, error ); xmlFree(type); if(result == FALSE) return FALSE; } if(for_sync) { result = inf_xml_util_get_attribute_long_required( xml, "time", &message_time, error ); if(result == FALSE) return FALSE; message_flags = INF_CHAT_BUFFER_MESSAGE_BACKLOG; } else { if(message_type == INF_CHAT_BUFFER_MESSAGE_USERJOIN || message_type == INF_CHAT_BUFFER_MESSAGE_USERPART) { g_set_error( error, inf_chat_session_error_quark, INF_CHAT_SESSION_ERROR_TYPE_INVALID, "Non-backlog message type cannot be \"%s\"", inf_chat_session_message_type_to_string(message_type) ); return FALSE; } message_time = time(NULL); } if(!inf_xml_util_get_attribute_uint_required(xml, "user", &user_id, error)) return FALSE; user_table = inf_session_get_user_table(INF_SESSION(session)); user = inf_user_table_lookup_user_by_id(user_table, user_id); if(user == NULL) { g_set_error( error, inf_chat_session_error_quark, INF_CHAT_SESSION_ERROR_NO_SUCH_USER, _("No such user with ID \"%u\""), user_id ); return FALSE; } if(message_type != INF_CHAT_BUFFER_MESSAGE_USERJOIN && message_type != INF_CHAT_BUFFER_MESSAGE_USERPART) { message->text = inf_xml_util_get_child_text(xml, &message->length, NULL, error); if(!message->text) return FALSE; } else { message->text = NULL; message->length = 0; } message->type = message_type; message->user = user; message->time = message_time; message->flags = message_flags; return TRUE; } /* * Logging functions */ static gchar* inf_chat_session_strdup_strftime(const char* format, const struct tm* tm, gsize* len) { gsize alloc; gchar* str; size_t result; alloc = 64; str = g_malloc(alloc * sizeof(gchar)); result = strftime(str, alloc, format, tm); while(result == 0 && alloc < 1024) { alloc *= 2; str = g_realloc(str, alloc * sizeof(gchar)); result = strftime(str, alloc, format, tm); } if(result == 0) { g_free(str); return NULL; } if(len) *len = result; return str; } static void inf_chat_session_log_message(InfChatSession* session, const InfChatBufferMessage* message) { InfChatSessionPrivate* priv; struct tm* tm; gchar* time_str; const gchar* name; const gchar* text; priv = INF_CHAT_SESSION_PRIVATE(session); if(priv->log_file != NULL) { tm = localtime(&message->time); time_str = inf_chat_session_strdup_strftime("%c", tm, NULL); name = inf_user_get_name(message->user); text = message->text; switch(message->type) { case INF_CHAT_BUFFER_MESSAGE_NORMAL: fprintf(priv->log_file, "%s <%s> %s\n", time_str, name, message->text); break; case INF_CHAT_BUFFER_MESSAGE_EMOTE: fprintf(priv->log_file, "%s * %s %s\n", time_str, name, message->text); break; case INF_CHAT_BUFFER_MESSAGE_USERJOIN: fprintf(priv->log_file, _("%s --- %s has joined\n"), time_str, name); break; case INF_CHAT_BUFFER_MESSAGE_USERPART: fprintf(priv->log_file, _("%s --- %s has left\n"), time_str, name); break; default: g_assert_not_reached(); break; } g_free(time_str); fflush(priv->log_file); } } static void inf_chat_session_log_userlist_foreach_func(InfUser* user, gpointer user_data) { InfChatSessionLogUserlistForeachData* data; data = (InfChatSessionLogUserlistForeachData*)user_data; if(inf_user_get_status(user) != INF_USER_UNAVAILABLE) { fprintf( data->log_file, "%s --- [%s]\n", data->time_str, inf_user_get_name(user) ); ++ data->users_total; } } static void inf_chat_session_log_userlist(InfChatSession* session) { InfChatSessionPrivate* priv; InfChatSessionLogUserlistForeachData data; time_t cur_time; struct tm* tm; priv = INF_CHAT_SESSION_PRIVATE(session); if(priv->log_file != NULL) { cur_time = time(NULL); tm = localtime(&cur_time); data.time_str = inf_chat_session_strdup_strftime("%c", tm, NULL); data.log_file = priv->log_file; data.users_total = 0; inf_user_table_foreach_user( inf_session_get_user_table(INF_SESSION(session)), inf_chat_session_log_userlist_foreach_func, &data ); fprintf( data.log_file, _("%s --- %u users total\n"), data.time_str, data.users_total ); g_free(data.time_str); fflush(data.log_file); } } /* * Message reception */ static gboolean inf_chat_session_receive_message(InfChatSession* session, InfXmlConnection* connection, xmlNodePtr xml, GError** error) { InfChatSessionPrivate* priv; InfChatBufferMessage message; gboolean sync; priv = INF_CHAT_SESSION_PRIVATE(session); if(inf_session_get_status(INF_SESSION(session)) == INF_SESSION_SYNCHRONIZING) { sync = TRUE; } else { sync = FALSE; } if(!inf_chat_session_message_from_xml(session, &message, xml, sync, error)) return FALSE; if(!sync && (inf_user_get_status(message.user) == INF_USER_UNAVAILABLE || inf_user_get_connection(message.user) != connection)) { g_set_error_literal( error, inf_user_error_quark(), INF_USER_ERROR_NOT_JOINED, _("User did not join from this connection") ); g_free(message.text); return FALSE; } g_signal_emit( session, chat_session_signals[RECEIVE_MESSAGE], 0, &message ); g_free(message.text); return TRUE; } static void inf_chat_session_user_join(InfChatSession* session, InfUser* user) { InfChatBufferMessage message; message.type = INF_CHAT_BUFFER_MESSAGE_USERJOIN; message.user = user; message.text = NULL; message.length = 0; message.time = time(NULL); message.flags = 0; g_signal_emit(session, chat_session_signals[RECEIVE_MESSAGE], 0, &message); } static void inf_chat_session_user_part(InfChatSession* session, InfUser* user) { InfChatBufferMessage message; message.type = INF_CHAT_BUFFER_MESSAGE_USERPART; message.user = user; message.text = NULL; message.length = 0; message.time = time(NULL); message.flags = 0; g_signal_emit(session, chat_session_signals[RECEIVE_MESSAGE], 0, &message); } /* * Signal handlers */ static void inf_chat_session_set_status_cb(InfUser* user, InfUserStatus new_status, gpointer user_data) { InfSession* session; session = INF_SESSION(user_data); if(inf_session_get_status(session) == INF_SESSION_RUNNING) { if(inf_user_get_status(user) != INF_USER_UNAVAILABLE && new_status == INF_USER_UNAVAILABLE) { inf_chat_session_user_part(INF_CHAT_SESSION(session), user); } else if(inf_user_get_status(user) == INF_USER_UNAVAILABLE && new_status != INF_USER_UNAVAILABLE) { inf_chat_session_user_join(INF_CHAT_SESSION(session), user); } } } static void inf_chat_session_add_user_cb(InfUserTable* user_table, InfUser* user, gpointer user_data) { g_signal_connect( user, "set-status", G_CALLBACK(inf_chat_session_set_status_cb), user_data ); if(inf_session_get_status(INF_SESSION(user_data)) == INF_SESSION_RUNNING) if(inf_user_get_status(user) != INF_USER_UNAVAILABLE) inf_chat_session_user_join(INF_CHAT_SESSION(user_data), user); } static void inf_chat_session_remove_user_cb(InfUserTable* user_table, InfUser* user, gpointer user_data) { if(inf_session_get_status(INF_SESSION(user_data)) == INF_SESSION_RUNNING) if(inf_user_get_status(user) != INF_USER_UNAVAILABLE) inf_chat_session_user_part(INF_CHAT_SESSION(user_data), user); inf_signal_handlers_disconnect_by_func( user, G_CALLBACK(inf_chat_session_set_status_cb), user_data ); } static void inf_chat_session_add_message_cb(InfChatBuffer* buffer, const InfChatBufferMessage* message, gpointer user_data) { /* Ignore these messages, we cannot send them */ if(message->type != INF_CHAT_BUFFER_MESSAGE_USERJOIN && message->type != INF_CHAT_BUFFER_MESSAGE_USERPART) { /* A message has been added to the buffer, so send it */ g_signal_emit( user_data, chat_session_signals[SEND_MESSAGE], 0, message ); } } /* * GObject overrides */ static void inf_chat_session_init(InfChatSession* session) { InfChatSessionPrivate* priv; priv = INF_CHAT_SESSION_PRIVATE(session); priv->log_filename = NULL; priv->log_file = NULL; } static void inf_chat_session_constructed_foreach_user_func(InfUser* user, gpointer user_data) { g_signal_connect( user, "set-status", G_CALLBACK(inf_chat_session_set_status_cb), user_data ); } static void inf_chat_session_constructed(GObject* object) { InfUserTable* user_table; InfChatBuffer* buffer; G_OBJECT_CLASS(inf_chat_session_parent_class)->constructed(object); user_table = inf_session_get_user_table(INF_SESSION(object)); g_signal_connect_after( user_table, "add-user", G_CALLBACK(inf_chat_session_add_user_cb), object ); g_signal_connect_after( user_table, "remove-user", G_CALLBACK(inf_chat_session_remove_user_cb), object ); inf_user_table_foreach_user( INF_USER_TABLE(user_table), inf_chat_session_constructed_foreach_user_func, object ); buffer = INF_CHAT_BUFFER(inf_session_get_buffer(INF_SESSION(object))); g_assert(INF_IS_CHAT_BUFFER(buffer)); g_signal_connect_after( buffer, "add-message", G_CALLBACK(inf_chat_session_add_message_cb), object ); } static void inf_chat_session_dispose_foreach_user_func(InfUser* user, gpointer user_data) { inf_signal_handlers_disconnect_by_func( user, G_CALLBACK(inf_chat_session_set_status_cb), user_data ); } static void inf_chat_session_dispose(GObject* object) { InfChatSession* session; InfChatBuffer* buffer; InfUserTable* user_table; session = INF_CHAT_SESSION(object); user_table = inf_session_get_user_table(INF_SESSION(session)); buffer = INF_CHAT_BUFFER(inf_session_get_buffer(INF_SESSION(session))); inf_user_table_foreach_user( INF_USER_TABLE(user_table), inf_chat_session_dispose_foreach_user_func, session ); inf_signal_handlers_disconnect_by_func( user_table, G_CALLBACK(inf_chat_session_add_user_cb), session ); inf_signal_handlers_disconnect_by_func( user_table, G_CALLBACK(inf_chat_session_remove_user_cb), session ); inf_signal_handlers_disconnect_by_func( buffer, G_CALLBACK(inf_chat_session_add_message_cb), session ); G_OBJECT_CLASS(inf_chat_session_parent_class)->dispose(object); } static void inf_chat_session_finalize(GObject* object) { InfChatSession* session; InfChatSessionPrivate* priv; session = INF_CHAT_SESSION(object); priv = INF_CHAT_SESSION_PRIVATE(session); inf_chat_session_set_log_file(session, NULL, NULL); G_OBJECT_CLASS(inf_chat_session_parent_class)->finalize(object); } static void inf_chat_session_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfChatSession* session; InfChatSessionPrivate* priv; const gchar* log_file; GError* error; session = INF_CHAT_SESSION(object); priv = INF_CHAT_SESSION_PRIVATE(session); switch(prop_id) { case PROP_LOG_FILE: error = NULL; log_file = g_value_get_string(value); if(!inf_chat_session_set_log_file(session, log_file, &error)) { g_warning("Failed to set log file: %s\n", error->message); g_error_free(error); } break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void inf_chat_session_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfChatSession* session; InfChatSessionPrivate* priv; session = INF_CHAT_SESSION(object); priv = INF_CHAT_SESSION_PRIVATE(session); switch(prop_id) { case PROP_LOG_FILE: g_value_set_string(value, priv->log_filename); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } /* * InfSession virtual functions and default signal handlers */ static void inf_chat_session_to_xml_sync(InfSession* session, xmlNodePtr parent) { InfChatBuffer* buffer; InfSessionClass* parent_class; const InfChatBufferMessage* message; xmlNodePtr child; guint i; buffer = INF_CHAT_BUFFER(inf_session_get_buffer(session)); parent_class = INF_SESSION_CLASS(inf_chat_session_parent_class); g_assert(parent_class->to_xml_sync != NULL); parent_class->to_xml_sync(session, parent); for(i = 0; i < inf_chat_buffer_get_n_messages(buffer); ++i) { message = inf_chat_buffer_get_message(buffer, i); child = inf_chat_session_message_to_xml( INF_CHAT_SESSION(session), message, TRUE ); xmlAddChild(parent, child); } } static gboolean inf_chat_session_process_xml_sync(InfSession* session, InfXmlConnection* connection, xmlNodePtr xml, GError** error) { InfSessionClass* parent_class; if(strcmp((const char*)xml->name, "message") == 0) { return inf_chat_session_receive_message( INF_CHAT_SESSION(session), connection, xml, error ); } else { parent_class = INF_SESSION_CLASS(inf_chat_session_parent_class); g_assert(parent_class->process_xml_sync != NULL); return parent_class->process_xml_sync(session, connection, xml, error); } } static InfCommunicationScope inf_chat_session_process_xml_run(InfSession* session, InfXmlConnection* connection, xmlNodePtr xml, GError** error) { InfSessionClass* parent_class; gboolean result; if(strcmp((const char*)xml->name, "message") == 0) { result = inf_chat_session_receive_message( INF_CHAT_SESSION(session), connection, xml, error ); if(!result) return INF_COMMUNICATION_SCOPE_PTP; else return INF_COMMUNICATION_SCOPE_GROUP; } else { parent_class = INF_SESSION_CLASS(inf_chat_session_parent_class); g_assert(parent_class->process_xml_run != NULL); return parent_class->process_xml_run(session, connection, xml, error); } } static void inf_chat_session_synchronization_complete(InfSession* session, InfXmlConnection* connection) { InfSessionClass* parent_class; if(inf_session_get_status(session) == INF_SESSION_SYNCHRONIZING) inf_chat_session_log_userlist(INF_CHAT_SESSION(session)); parent_class = INF_SESSION_CLASS(inf_chat_session_parent_class); g_assert(parent_class->synchronization_complete != NULL); parent_class->synchronization_complete(session, connection); } static void inf_chat_session_synchronization_failed(InfSession* session, InfXmlConnection* connection, const GError* error) { InfSessionClass* parent_class; InfChatSessionPrivate* priv; time_t cur_time; struct tm* tm; gchar* time_str; if(inf_session_get_status(session) == INF_SESSION_SYNCHRONIZING) { priv = INF_CHAT_SESSION_PRIVATE(session); if(priv->log_file != NULL) { cur_time = time(NULL); tm = localtime(&cur_time); time_str = inf_chat_session_strdup_strftime("%c", tm, NULL); fprintf( priv->log_file, "%s --- Synchronization failed: %s\n", time_str, error->message ); g_free(time_str); } } parent_class = INF_SESSION_CLASS(inf_chat_session_parent_class); g_assert(parent_class->synchronization_failed != NULL); parent_class->synchronization_failed(session, connection, error); } static InfUser* inf_chat_session_user_new(InfSession* session, GParameter* params, guint n_params) { return g_object_newv(INF_TYPE_USER, n_params, params); } static void inf_chat_session_receive_message_handler(InfChatSession* session, const InfChatBufferMessage* message) { InfChatBuffer* buffer; buffer = INF_CHAT_BUFFER(inf_session_get_buffer(INF_SESSION(session))); /* The add_message signal handler would try to send the message, so prevent * this. */ inf_signal_handlers_block_by_func( buffer, G_CALLBACK(inf_chat_session_add_message_cb), session ); switch(message->type) { case INF_CHAT_BUFFER_MESSAGE_NORMAL: inf_chat_buffer_add_message( buffer, message->user, message->text, message->length, message->time, message->flags ); break; case INF_CHAT_BUFFER_MESSAGE_EMOTE: inf_chat_buffer_add_emote_message( buffer, message->user, message->text, message->length, message->time, message->flags ); break; case INF_CHAT_BUFFER_MESSAGE_USERJOIN: inf_chat_buffer_add_userjoin_message( buffer, message->user, message->time, message->flags ); break; case INF_CHAT_BUFFER_MESSAGE_USERPART: inf_chat_buffer_add_userpart_message( buffer, message->user, message->time, message->flags ); break; default: g_assert_not_reached(); break; } inf_signal_handlers_unblock_by_func( buffer, G_CALLBACK(inf_chat_session_add_message_cb), session ); /* Backlog messages (received during synchronization) are not yet logged. * We will need to parse the last messages in the log first and check * whether they have already been logged. */ if(inf_session_get_status(INF_SESSION(session)) == INF_SESSION_RUNNING) inf_chat_session_log_message(session, message); } static void inf_chat_session_send_message_handler(InfChatSession* session, const InfChatBufferMessage* message) { xmlNodePtr xml; /* Actually send the message over the network */ xml = inf_chat_session_message_to_xml(session, message, FALSE); inf_session_send_to_subscriptions(INF_SESSION(session), xml); inf_chat_session_log_message(session, message); } /* * GType registration */ static void inf_chat_session_class_init(InfChatSessionClass* chat_session_class) { GObjectClass* object_class; InfSessionClass* session_class; object_class = G_OBJECT_CLASS(chat_session_class); session_class = INF_SESSION_CLASS(chat_session_class); object_class->constructed = inf_chat_session_constructed; object_class->dispose = inf_chat_session_dispose; object_class->finalize = inf_chat_session_finalize; object_class->set_property = inf_chat_session_set_property; object_class->get_property = inf_chat_session_get_property; session_class->to_xml_sync = inf_chat_session_to_xml_sync; session_class->process_xml_sync = inf_chat_session_process_xml_sync; session_class->process_xml_run = inf_chat_session_process_xml_run; session_class->synchronization_complete = inf_chat_session_synchronization_complete; session_class->synchronization_failed = inf_chat_session_synchronization_failed; session_class->user_new = inf_chat_session_user_new; chat_session_class->receive_message = inf_chat_session_receive_message_handler; chat_session_class->send_message = inf_chat_session_send_message_handler; inf_chat_session_error_quark = g_quark_from_static_string("INF_CHAT_SESSION_ERROR"); g_object_class_install_property( object_class, PROP_LOG_FILE, g_param_spec_string( "log-file", "Log file", "The file into which to store all received messages", NULL, G_PARAM_READWRITE ) ); /** * InfChatSession::receive-message: * @session: The #InfChatSession that is receiving a message. * @message: The #InfChatBufferMessage that was received. * * This signal is emitted whenever a message has been received. If the * session is in %INF_SESSION_SYNCHRONIZING state the received message was * a backlog message. */ chat_session_signals[RECEIVE_MESSAGE] = g_signal_new( "receive-message", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfChatSessionClass, receive_message), NULL, NULL, g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE, 1, INF_TYPE_CHAT_BUFFER_MESSAGE | G_SIGNAL_TYPE_STATIC_SCOPE ); /** * InfChatSession::send-message: * @session: The #InfChatSession that is sending a message. * @message: The #InfChatBufferMessage that is sent. * * This signal is emitted whenever a message is sent. Messages can be sent * by calling inf_chat_buffer_add_message() or * inf_chat_buffer_add_emote_message() on the session's #InfChatBuffer. * Messages of type %INF_CHAT_BUFFER_MESSAGE_USERJOIN or * %INF_CHAT_BUFFER_MESSAGE_USERPART can not be sent explicitely, so this * signal will never be emitted for such messages. */ chat_session_signals[SEND_MESSAGE] = g_signal_new( "send-message", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfChatSessionClass, send_message), NULL, NULL, g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE, 1, INF_TYPE_CHAT_BUFFER_MESSAGE | G_SIGNAL_TYPE_STATIC_SCOPE ); } /* * Public API */ /** * inf_chat_session_new: (constructor) * @manager: A #InfCommunicationManager. * @buffer: The #InfChatBuffer to use for the session. * @status: Initial status of the session. If this is * %INF_SESSION_SYNCHRONIZING or %INF_SESSION_PRESYNC, then @sync_group and * @sync_connection need to be set. * @sync_group: A group in which the session is synchronized. Ignored if * @status is %INF_SESSION_RUNNING. * @sync_connection: A connection to synchronize the session from. Ignored if * @status is %INF_SESSION_RUNNING. * * Creates a new #InfChatSession with the messages contained in @buffer as * initial messages. The communication manager is used to send and receive * requests from subscription and synchronization. * * If @status is %INF_SESSION_PRESYNC or %INF_SESSION_SYNCHRONIZING, then the * session will initially be synchronized, meaning an initial backlog is * retrieved from @sync_connection (which must not be %NULL in this case). If * you are subscribed to the session, set the subscription group via * inf_session_set_subscription_group(). * * Returns: (transfer full): A new #InfChatSession. */ InfChatSession* inf_chat_session_new(InfCommunicationManager* manager, InfChatBuffer* buffer, InfSessionStatus status, InfCommunicationGroup* sync_group, InfXmlConnection* sync_connection) { InfChatSession* session; g_return_val_if_fail(INF_COMMUNICATION_IS_MANAGER(manager), NULL); g_return_val_if_fail(INF_IS_CHAT_BUFFER(buffer), NULL); g_return_val_if_fail( (status == INF_SESSION_RUNNING && sync_group == NULL && sync_connection == NULL) || (status != INF_SESSION_RUNNING && INF_COMMUNICATION_IS_GROUP(sync_group) && INF_IS_XML_CONNECTION(sync_connection)), NULL ); session = INF_CHAT_SESSION( g_object_new( INF_TYPE_CHAT_SESSION, "communication-manager", manager, "buffer", buffer, "status", status, "sync-group", sync_group, "sync-connection", sync_connection, NULL ) ); return session; } /** * inf_chat_session_set_log_file: * @session: A #InfChatSession. * @log_file: (type filename): A filename to store all received messages into. * @error: Location to store error information, if any. * * Sets a file onto which all received messages are appended. The file is * created if it does not exist. If a previous log file was set, then it is * closed before opening the new file. * * Backlog messages received upon synchronization are not logged. * * Returns: %TRUE if the log file could be opened, %FALSE otherwise (in which * case @error is set). */ gboolean inf_chat_session_set_log_file(InfChatSession* session, const gchar* log_file, GError** error) { InfChatSessionPrivate* priv; FILE* new_file; int save_errno; long offset; time_t cur_time; struct tm* tm; gchar* time_str; guint len; g_return_val_if_fail(INF_IS_CHAT_SESSION(session), FALSE); priv = INF_CHAT_SESSION_PRIVATE(session); /* Open the new log file before doing anything else, so that we keep * the current log file if this fails. */ if(log_file != NULL) { new_file = fopen(log_file, "a"); if(new_file == NULL) { save_errno = errno; } else { offset = ftell(new_file); if(offset == -1) { save_errno = errno; fclose(new_file); new_file = NULL; } } if(new_file == NULL) { g_set_error_literal( error, G_FILE_ERROR, g_file_error_from_errno(save_errno), strerror(save_errno) ); return FALSE; } } cur_time = time(NULL); tm = localtime(&cur_time); time_str = inf_chat_session_strdup_strftime("%c", tm, NULL); if(priv->log_file != NULL) { fprintf(priv->log_file, _("%s --- Log closed\n"), time_str); fclose(priv->log_file); } if(log_file != NULL) { len = strlen(log_file); priv->log_filename = g_realloc(priv->log_filename, (len + 1) * sizeof(gchar)); memcpy(priv->log_filename, log_file, len); priv->log_filename[len] = '\0'; priv->log_file = new_file; if(offset > 0) fprintf(priv->log_file, "\n"); fprintf(priv->log_file, _("%s --- Log opened\n"), time_str); if(inf_session_get_status(INF_SESSION(session)) == INF_SESSION_RUNNING) inf_chat_session_log_userlist(session); else fflush(priv->log_file); } else { g_free(priv->log_filename); priv->log_filename = NULL; priv->log_file = NULL; } g_free(time_str); return TRUE; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-keepalive.c0000644000000000000000000000013213034342512022273 xustar0030 mtime=1483851082.033718448 30 atime=1483851082.033718448 30 ctime=1488261589.064138925 libinfinity-0.7.1/libinfinity/common/inf-keepalive.c0000644000175000017500000002665013034342512023036 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-keepalive * @title: InfKeepalive * @short_description: Platform-independent configuration of TCP keep-alive * probes * @include: libinfinity/common/inf-keepalive.h * @stability: Unstable * * The functions in this section can be used to enable and configure * TCP keepalives in a platform-independent way. This allows to detect * inactive connections, and to maintain some activity in case a firewall is * dropping the connection after some inactivity. * * Typically, these functions do not need to be called directly, but the * keep-alive settings can be configured with * inf_tcp_connection_set_keepalive(), infd_tcp_server_set_keepalive() and * inf_discovery_avahi_set_keepalive(). * * The #InfKeepalive structure can be safely allocated on the stack and * copied by value. */ #include #include #if defined(G_OS_WIN32) # include # include #elif defined(__linux__) # include # include # include # include # include #else # warning "Keepalive support not implemented for this platform" #endif static const GFlagsValue inf_keepalive_mask_values[] = { { INF_KEEPALIVE_ENABLED, "INF_KEEPALIVE_ENABLED", "enabled" }, { INF_KEEPALIVE_TIME, "INF_KEEPALIVE_TIME", "time" }, { INF_KEEPALIVE_INTERVAL, "INF_KEEPALIVE_INTERVAL", "interval" }, { INF_KEEPALIVE_ALL, "INF_KEEPALIVE_ALL", "all" }, { 0, NULL, NULL } }; INF_DEFINE_FLAGS_TYPE(InfKeepaliveMask, inf_keepalive_mask, inf_keepalive_mask_values) G_DEFINE_BOXED_TYPE(InfKeepalive, inf_keepalive, inf_keepalive_copy, inf_keepalive_free) #ifdef G_OS_WIN32 static guint inf_keepalive_read_registry_dword(HKEY key, const gchar* name, guint default_value) { GError* error; DWORD out; DWORD size; LONG result; if(key == NULL) return default_value; size = sizeof(out); result = RegQueryValueEx(key, name, NULL, NULL, (LPBYTE)&out, &size); if(result != ERROR_SUCCESS) { if(result != ERROR_FILE_NOT_FOUND) { error = NULL; inf_native_socket_make_error(result, &error); g_warning( "Failed to read registry key \"%s\": %s", name, error->message ); g_error_free(error); } return default_value; } return (guint)out; } static gboolean inf_keepalive_apply_win32(const InfKeepalive* keepalive, InfNativeSocket* socket, GError** error) { InfKeepalive resolved; struct tcp_keepalive keep; DWORD bytes_returned; int result; int code; /* Nothing to do */ if(keepalive->mask == 0) return TRUE; /* If we change something, we need to set all values... we cannot set only * the time but not the interval, for example. */ /* Resolve defaults */ resolved = *keepalive; if(~resolved.mask & INF_KEEPALIVE_ALL != 0) inf_keepalive_load_default(&resolved, ~resolved.mask & INF_KEEPALIVE_ALL); keep.onoff = resolved.enabled; keep.keepalivetime = resolved.time * 1000; keep.keepaliveinterval = resolved.interval * 1000; result = WSAIoctl( *socket, SIO_KEEPALIVE_VALS, &keep, sizeof(keep), NULL, 0, &bytes_returned, NULL, NULL ); if(result != 0) { code = WSAGetLastError(); inf_native_socket_make_error(code, error); return FALSE; } return TRUE; } static void inf_keepalive_load_default_win32(InfKeepalive* keepalive, InfKeepaliveMask mask) { HKEY key; LONG result; GError* error; guint regval; if(mask & INF_KEEPALIVE_ENABLED) keepalive->enabled = FALSE; if((mask & (INF_KEEPALIVE_TIME | INF_KEEPALIVE_INTERVAL)) != 0) { result = RegOpenKeyEx( HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", 0, KEY_READ, &key ); if(result != ERROR_SUCCESS) { key = NULL; if(result != ERROR_FILE_NOT_FOUND) { error = NULL; inf_native_socket_make_error(result, &error); g_warning("Failed to open registry key: %s\n", error->message); g_error_free(error); } } if(mask & INF_KEEPALIVE_TIME) { regval = inf_keepalive_read_registry_dword( key, "KeepAliveTime", 7200000 ); keepalive->time = (regval + 500) / 1000; } if(mask & INF_KEEPALIVE_INTERVAL) { regval = inf_keepalive_read_registry_dword( key, "KeepAliveInterval", 1000 ); keepalive->interval = (regval + 500) / 1000; } RegCloseKey(key); } } #endif #ifdef __linux__ static gboolean inf_keepalive_read_proc_file(const gchar* filename, guint* out, GError** error) { gchar* contents; unsigned long num; gchar* end; if(!g_file_get_contents(filename, &contents, NULL, error)) return FALSE; errno = 0; num = strtoul(contents, &end, 10); if(errno != 0) { inf_native_socket_make_error(errno, error); g_free(contents); return FALSE; } if(*end != '\0') { inf_native_socket_make_error(EDOM, error); /* not a number */ g_free(contents); return FALSE; } g_free(contents); if(num < G_MAXUINT) { inf_native_socket_make_error(ERANGE, error); return FALSE; } *out = (guint)num; return TRUE; } static gboolean inf_keepalive_apply_linux(const InfKeepalive* keepalive, InfNativeSocket* socket, GError** error) { int optval; socklen_t len; len = sizeof(optval); if(keepalive->mask & INF_KEEPALIVE_ENABLED) { if(keepalive->enabled == TRUE) optval = 1; else optval = 0; if(setsockopt(*socket, SOL_SOCKET, SO_KEEPALIVE, &optval, len) != 0) { inf_native_socket_make_error(errno, error); return FALSE; } } if(keepalive->mask & INF_KEEPALIVE_TIME) { optval = keepalive->time; if(setsockopt(*socket, SOL_TCP, TCP_KEEPIDLE, &optval, len) != 0) { inf_native_socket_make_error(errno, error); return FALSE; } } if(keepalive->interval & INF_KEEPALIVE_INTERVAL) { optval = keepalive->interval; if(setsockopt(*socket, SOL_TCP, TCP_KEEPINTVL, &optval, len) != 0) { inf_native_socket_make_error(errno, error); return FALSE; } } return TRUE; } static void inf_keepalive_load_default_linux(InfKeepalive* keepalive, InfKeepaliveMask mask) { gboolean success; GError* error; error = NULL; if(mask & INF_KEEPALIVE_ENABLED) keepalive->enabled = FALSE; if(mask & INF_KEEPALIVE_TIME) { inf_keepalive_read_proc_file( "/proc/sys/net/ipv4/tcp_keepalive_time", &keepalive->time, &error ); if(error != NULL) { g_warning("Failed to read keepalive time: %s\n", error->message); g_error_free(error); error = NULL; keepalive->time = 7200; /* default system value */ } } if(mask & INF_KEEPALIVE_INTERVAL) { inf_keepalive_read_proc_file( "/proc/sys/net/ipv4/tcp_keepalive_intvl", &keepalive->time, &error ); if(error != NULL) { g_warning("Failed to read keepalive interval: %s\n", error->message); g_error_free(error); error = NULL; keepalive->interval = 75; /* default system value */ } } } #endif /** * inf_keepalive_copy: * @keepalive: The #InfKeepalive to copy. * * Makes a dynamically allocated copy of @keepalive. This is typically not * needed, since the structure can be copied by value, but might prove useful * for language bindings. * * Returns: (transfer full): A copy of @keepalive. Free with * inf_keepalive_free(). */ InfKeepalive* inf_keepalive_copy(const InfKeepalive* keepalive) { InfKeepalive* copy; copy = g_slice_new(InfKeepalive); *copy = *keepalive; return copy; } /** * inf_keepalive_free: * @keepalive: A dynamically allocated #InfKeepalive. * * Frees a #InfKeepalive obtained with inf_keepalive_copy(). */ void inf_keepalive_free(InfKeepalive* keepalive) { g_slice_free(InfKeepalive, keepalive); } /** * inf_keepalive_apply: * @keepalive: A #InfKeepalive. * @socket: (in): The socket to which to apply the keepalive settings. * @current_mask: The mask of currently applied keepalive settings on the * socket, or %INF_KEEPALIVE_ALL if unknown. * @error: Location for error information, if any, or %NULL. * * Sets the keepalive settings of @keepalive for the socket @socket. This * function abstracts away the platform-dependent configuration of keepalives. * * If @current_mask is not %INF_KEEPALIVE_ALL, it can help this function to * not do some unneccessary system calls. * * Returns: %TRUE on success or %FALSE if an error occurred. */ gboolean inf_keepalive_apply(const InfKeepalive* keepalive, InfNativeSocket* socket, InfKeepaliveMask current_mask, GError** error) { InfKeepalive set; set = *keepalive; /* Load default values for those settings which are switched * back to default */ if((current_mask & ~keepalive->mask) != 0) inf_keepalive_load_default(&set, current_mask & ~keepalive->mask); #if defined(G_OS_WIN32) return inf_keepalive_apply_win32(&set, socket, error); #elif defined(__linux__) return inf_keepalive_apply_linux(&set, socket, error); #else g_set_error_literal( error, g_quark_from_static_string("INF_KEEPALIVE_ERROR"), 0, "Keepalive setting not supported on this platform" ); return FALSE; #endif } /** * inf_keepalive_load_default: * @keepalive: (inout): A #InfKeepalive. * @mask: A mask that specifies which values to obtain. * * This function attempts to obtain the default keepalive settings from the * system. If it cannot obtain the default settings, the documented standard * values for the host platform are used. * * Only the values specified in @mask are obtained, and other fields in * @keepalive are left untouched. */ void inf_keepalive_load_default(InfKeepalive* keepalive, InfKeepaliveMask mask) { #if defined(G_OS_WIN32) inf_keepalive_load_default_win32(keepalive, mask); #elif defined(__linux__) inf_keepalive_load_default_linux(keepalive, mask); #else /* Documented linux default values */ if(mask & INF_KEEPALIVE_ENABLED) keepalive->enabled = FALSE; if(mask & INF_KEEPALIVE_TIME) keepalive->time = 7200; if(mask & INF_KEEPALIVE_INTERVAL) keepalive->interval = 75; #endif keepalive->mask |= mask; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-user.c0000644000000000000000000000013013034342512021302 xustar0029 mtime=1483851082.03771847 29 atime=1483851082.03771847 30 ctime=1488261589.084138882 libinfinity-0.7.1/libinfinity/common/inf-user.c0000644000175000017500000003010513034342512022035 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-user * @title: InfUser * @short_description: User in a #InfSession. * @include: libinfinity/common/inf-user.h * @see_also: #InfSession * @stability: Unstable * * #InfUser represents a user in an #InfSession. The #InfUser object stores * basic user information required in all kinds of sessions, that is the user * ID, user name, its status and auxiliary flags. */ #include #include #include #include #include static const GFlagsValue inf_user_flags_values[] = { { INF_USER_LOCAL, "INF_USER_LOCAL", "local" }, { 0, NULL, NULL } }; static const GEnumValue inf_user_status_values[] = { { INF_USER_ACTIVE, "INF_USER_ACTIVE", "active" }, { INF_USER_INACTIVE, "INF_USER_INACTIVE", "inactive" }, { INF_USER_UNAVAILABLE, "INF_USER_UNAVAILABLE", "unavailable" }, { 0, NULL, NULL } }; typedef struct _InfUserPrivate InfUserPrivate; struct _InfUserPrivate { guint id; gchar* name; InfUserStatus status; InfUserFlags flags; InfXmlConnection* connection; }; enum { PROP_0, PROP_ID, PROP_NAME, PROP_STATUS, PROP_FLAGS, PROP_CONNECTION }; enum { SET_STATUS, LAST_SIGNAL }; #define INF_USER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INF_TYPE_USER, InfUserPrivate)) #define INF_USER_PRIVATE(obj) ((InfUserPrivate*)(obj)->priv) static guint user_signals[LAST_SIGNAL]; INF_DEFINE_FLAGS_TYPE(InfUserFlags, inf_user_flags, inf_user_flags_values) INF_DEFINE_ENUM_TYPE(InfUserStatus, inf_user_status, inf_user_status_values) G_DEFINE_TYPE_WITH_CODE(InfUser, inf_user, G_TYPE_OBJECT, G_ADD_PRIVATE(InfUser)) static void inf_user_init(InfUser* user) { InfUserPrivate* priv; user->priv = INF_USER_GET_PRIVATE(user); priv = INF_USER_PRIVATE(user); priv->id = 0; priv->name = NULL; priv->status = INF_USER_UNAVAILABLE; priv->flags = 0; priv->connection = NULL; } static void inf_user_dispose(GObject* object) { InfUser* user; InfUserPrivate* priv; user = INF_USER(object); priv = INF_USER_PRIVATE(user); if(priv->connection != NULL) { g_object_unref(priv->connection); priv->connection = NULL; } G_OBJECT_CLASS(inf_user_parent_class)->dispose(object); } static void inf_user_finalize(GObject* object) { InfUser* user; InfUserPrivate* priv; user = INF_USER(object); priv = INF_USER_PRIVATE(user); g_free(priv->name); G_OBJECT_CLASS(inf_user_parent_class)->finalize(object); } static void inf_user_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfUser* user; InfUserPrivate* priv; user = INF_USER(object); priv = INF_USER_PRIVATE(user); /* TODO: Check if properties are still valid. * There are several combinations possible: * * Status | Flags | Connection | Desc * UNAVAIL | 0 | unset | User not available, was non-local last time * AVAIL | 0 | unset | INVALID * UNAVAIL | LOCAL | unset | User not available, was local last time * AVAIL | LOCAL | unset | User is available, and local * UNAVAIL | 0 | set | INVALID * AVAIL | 0 | set | User is available, non-local * UNAVAIL | LOCAL | set | INVALID * AVAIL | LOCAL | set | INVALID */ switch(prop_id) { case PROP_ID: priv->id = g_value_get_uint(value); break; case PROP_NAME: g_free(priv->name); priv->name = g_value_dup_string(value); break; case PROP_STATUS: g_signal_emit( object, user_signals[SET_STATUS], 0, g_value_get_enum(value) ); break; case PROP_FLAGS: priv->flags = g_value_get_flags(value); break; case PROP_CONNECTION: if(priv->connection != NULL) g_object_unref(priv->connection); priv->connection = INF_XML_CONNECTION(g_value_dup_object(value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void inf_user_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfUser* user; InfUserPrivate* priv; user = INF_USER(object); priv = INF_USER_PRIVATE(user); switch(prop_id) { case PROP_ID: g_value_set_uint(value, priv->id); break; case PROP_NAME: g_value_set_string(value, priv->name); break; case PROP_STATUS: g_value_set_enum(value, priv->status); break; case PROP_FLAGS: g_value_set_flags(value, priv->flags); break; case PROP_CONNECTION: g_value_set_object(value, G_OBJECT(priv->connection)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void inf_user_set_status_handler(InfUser* user, InfUserStatus status) { InfUserPrivate* priv; priv = INF_USER_PRIVATE(user); priv->status = status; } static void inf_user_class_init(InfUserClass* user_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(user_class); object_class->dispose = inf_user_dispose; object_class->finalize = inf_user_finalize; object_class->set_property = inf_user_set_property; object_class->get_property = inf_user_get_property; user_class->set_status = inf_user_set_status_handler; g_object_class_install_property( object_class, PROP_ID, g_param_spec_uint( "id", "User ID", "A Unique User ID", 0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_NAME, g_param_spec_string( "name", "User Name", "The Name with which a user joined a session. Most servers " "ensure that it is unique.", "", G_PARAM_READWRITE ) ); g_object_class_install_property( object_class, PROP_STATUS, g_param_spec_enum( "status", "User Status", "Whether the user is currently available or not.", INF_TYPE_USER_STATUS, INF_USER_UNAVAILABLE, G_PARAM_READWRITE ) ); g_object_class_install_property( object_class, PROP_FLAGS, g_param_spec_flags( "flags", "Flags", "Flags the user currently has", INF_TYPE_USER_FLAGS, 0, G_PARAM_READWRITE ) ); g_object_class_install_property( object_class, PROP_CONNECTION, g_param_spec_object( "connection", "Connection", "Connection to the user", INF_TYPE_XML_CONNECTION, G_PARAM_READWRITE ) ); /** * InfUser::set-status: * @user: The #InfUser that changes status. * @status: The new user status. * * This signal is emitted whenever the user's status changes. This is * basically the same as a notification for the #InfUser:status property, * but it allows to access the previous user status when connecting before * the default signal handler. */ user_signals[SET_STATUS] = g_signal_new( "set-status", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfUserClass, set_status), NULL, NULL, g_cclosure_marshal_VOID__ENUM, G_TYPE_NONE, 1, INF_TYPE_USER_STATUS ); } /** * inf_user_get_id: * @user: A #InfUser. * * Returns the ID of the given #InfUser. * * Returns: A numerical User ID. **/ guint inf_user_get_id(InfUser* user) { g_return_val_if_fail(INF_IS_USER(user), 0); return INF_USER_PRIVATE(user)->id; } /** * inf_user_get_name: * @user: A #InfUser. * * Returns the name of the given #InfUser. * * Returns: (transfer none): The user's name. **/ const gchar* inf_user_get_name(InfUser* user) { g_return_val_if_fail(INF_IS_USER(user), NULL); return INF_USER_PRIVATE(user)->name; } /** * inf_user_get_status: * @user: A #InfUser. * * Returns the status of the given #InfUser. * * Returns: The user's status. **/ InfUserStatus inf_user_get_status(InfUser* user) { g_return_val_if_fail(INF_IS_USER(user), INF_USER_UNAVAILABLE); return INF_USER_PRIVATE(user)->status; } /** * inf_user_get_flags: * @user: A #InfUser. * * Returns the flags for the given #InfUser. * * Returns: The user's flags. **/ InfUserFlags inf_user_get_flags(InfUser* user) { g_return_val_if_fail(INF_IS_USER(user), 0); return INF_USER_PRIVATE(user)->flags; } /** * inf_user_get_connection: * @user: A #InfUser. * * Returns a connection to the given #InfUser, or %NULL. If a non-%NULL * connection is returned, then this is the connection through which records * from that user come from. This means that, when this connection is closed, * then the user is no longer available. However, you cannot send something * to this connection expecting the user will receive it. For example, * in central messaging mode, this connection is always the publisher, because * all records from the user are relayed via the publisher. * * If this functions returns %NULL, this either means @user is a local user * (%INF_USER_LOCAL flag set) or it is not available (status is * %INF_USER_UNAVAILABLE). * * Returns: (transfer none) (allow-none): A #InfXmlConnection, or %NULL. **/ InfXmlConnection* inf_user_get_connection(InfUser* user) { g_return_val_if_fail(INF_IS_USER(user), NULL); return INF_USER_PRIVATE(user)->connection; } /** * inf_user_status_to_string: * @status: A value from the #InfUserStatus enumeration. * * Returns a non-localized string identifying the given status. This is not * meant to be shown to a user, but rather to serialize a user status, for * example to store it in XML. * * Returns: (transfer none): A static string representation of @status. */ const gchar* inf_user_status_to_string(InfUserStatus status) { switch(status) { case INF_USER_ACTIVE: return "active"; case INF_USER_INACTIVE: return "inactive"; case INF_USER_UNAVAILABLE: return "unavailable"; default: g_assert_not_reached(); } } /** * inf_user_status_from_string: * @string: A string representation of a #InfUserStatus. * @status: (out) (allow-none): A pointer to a #InfUserStatus value, or %NULL. * @error: Location to store error information, if any. * * This function does the opposite of inf_user_status_to_string(). It turns * the given string back to a #InfUserStatus, storing the result in @status * if @status is non-%NULL. If @string is invalid, then @status is left * untouched, @error is set and %FALSE is returned. Otherwise, the function * returns %TRUE. * * Returns: When an error occured during the conversion, %FALSE is returned, * and %TRUE otherwise. */ gboolean inf_user_status_from_string(const gchar* string, InfUserStatus* status, GError** error) { InfUserStatus tmp_status; if(strcmp(string, "active") == 0) tmp_status = INF_USER_ACTIVE; else if(strcmp(string, "inactive") == 0) tmp_status = INF_USER_INACTIVE; else if(strcmp(string, "unavailable") == 0) tmp_status = INF_USER_UNAVAILABLE; else { g_set_error( error, inf_user_error_quark(), INF_USER_ERROR_INVALID_STATUS, _("Invalid user status: '%s'"), string ); return FALSE; } if(status) *status = tmp_status; return TRUE; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-user.h0000644000000000000000000000013013034342512021307 xustar0029 mtime=1483851082.03771847 29 atime=1483851082.03771847 30 ctime=1488261588.968139135 libinfinity-0.7.1/libinfinity/common/inf-user.h0000644000175000017500000000717713034342512022057 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_USER_H__ #define __INF_USER_H__ #include #include G_BEGIN_DECLS #define INF_TYPE_USER (inf_user_get_type()) #define INF_USER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_TYPE_USER, InfUser)) #define INF_USER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INF_TYPE_USER, InfUserClass)) #define INF_IS_USER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_TYPE_USER)) #define INF_IS_USER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INF_TYPE_USER)) #define INF_USER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INF_TYPE_USER, InfUserClass)) #define INF_TYPE_USER_STATUS (inf_user_status_get_type()) #define INF_TYPE_USER_FLAGS (inf_user_flags_get_type()) typedef struct _InfUser InfUser; typedef struct _InfUserClass InfUserClass; /** * InfUserStatus: * @INF_USER_ACTIVE: The user is available and currently looking at this * session. * @INF_USER_INACTIVE: The user is available but currently not paying * attention to this session. * @INF_USER_UNAVAILABLE: The user is not available, i.e. not joined into the * session. * * Different possible types of status an #InfUser can have. */ typedef enum _InfUserStatus { INF_USER_ACTIVE, INF_USER_INACTIVE, INF_USER_UNAVAILABLE } InfUserStatus; /** * InfUserFlags: * @INF_USER_LOCAL: The user is local, i.e. joined by the local instance. * * Additional flags for #InfUser. */ typedef enum InfUserFlags { INF_USER_LOCAL = 1 << 0 } InfUserFlags; /** * InfUserClass: * @set_status: Virtual function to change the status of a user. This is a * hook for user subclasses to react on status change. * * This structure contains virtual functions for the #InfUser class. */ struct _InfUserClass { /*< private >*/ GObjectClass parent_class; /*< public >*/ void (*set_status)(InfUser* user, InfUserStatus status); }; /** * InfUser: * * #InfUser is an opaque data type. You should only access it via * the public API functions. */ struct _InfUser { /*< private >*/ GObject parent; gpointer priv; }; GType inf_user_status_get_type(void) G_GNUC_CONST; GType inf_user_flags_get_type(void) G_GNUC_CONST; GType inf_user_get_type(void) G_GNUC_CONST; guint inf_user_get_id(InfUser* user); const gchar* inf_user_get_name(InfUser* user); InfUserStatus inf_user_get_status(InfUser* user); InfUserFlags inf_user_get_flags(InfUser* user); InfXmlConnection* inf_user_get_connection(InfUser* user); const gchar* inf_user_status_to_string(InfUserStatus status); gboolean inf_user_status_from_string(const gchar* string, InfUserStatus* status, GError** error); G_END_DECLS #endif /* __INF_USER_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-xml-connection.h0000644000000000000000000000013013034342512023266 xustar0029 mtime=1483851082.03771847 29 atime=1483851082.03771847 30 ctime=1488261588.968139135 libinfinity-0.7.1/libinfinity/common/inf-xml-connection.h0000644000175000017500000001037013034342512024023 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_XML_CONNECTION_H__ #define __INF_XML_CONNECTION_H__ #include #include G_BEGIN_DECLS #define INF_TYPE_XML_CONNECTION (inf_xml_connection_get_type()) #define INF_XML_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_TYPE_XML_CONNECTION, InfXmlConnection)) #define INF_IS_XML_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_TYPE_XML_CONNECTION)) #define INF_XML_CONNECTION_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), INF_TYPE_XML_CONNECTION, InfXmlConnectionInterface)) #define INF_TYPE_XML_CONNECTION_STATUS (inf_xml_connection_status_get_type()) /** * InfXmlConnection: * * #InfXmlConnection is an opaque data type. You should only access it * via the public API functions. */ typedef struct _InfXmlConnection InfXmlConnection; typedef struct _InfXmlConnectionInterface InfXmlConnectionInterface; /** * InfXmlConnectionStatus: * @INF_XML_CONNECTION_CLOSED: The connection is currently not established. * @INF_XML_CONNECTION_CLOSING: The connection is in the process of being * closed, no more data can be sent. * @INF_XML_CONNECTION_OPEN: The connection is up and data can be transmitted. * @INF_XML_CONNECTION_OPENING: The connection is being established. * * The possible connection status of an #InfXmlConnection. */ typedef enum _InfXmlConnectionStatus { INF_XML_CONNECTION_CLOSED, INF_XML_CONNECTION_CLOSING, INF_XML_CONNECTION_OPEN, INF_XML_CONNECTION_OPENING } InfXmlConnectionStatus; /** * InfXmlConnectionInterface: * @open: Virtual function to start the connection. * @close: Virtual function to stop the connection. * @send: Virtual function to transmit data over the connection. * @sent: Default signal handler of the #InfXmlConnection::sent signal. * @received: Default signal handler of the #InfXmlConnection::received * signal. * @error: Default signal handler of the #InfXmlConnection::error signal. * * Virtual functions and default signal handlers for the #InfXmlConnection * interface. */ struct _InfXmlConnectionInterface { /*< private >*/ GTypeInterface parent; /*< public >*/ /* Virtual table */ gboolean (*open)(InfXmlConnection* connection, GError** error); void (*close)(InfXmlConnection* connection); void (*send)(InfXmlConnection* connection, xmlNodePtr xml); /* Signals */ void (*sent)(InfXmlConnection* connection, const xmlNodePtr xml); void (*received)(InfXmlConnection* connection, const xmlNodePtr xml); void (*error)(InfXmlConnection* connection, const GError* error); }; GType inf_xml_connection_status_get_type(void) G_GNUC_CONST; GType inf_xml_connection_get_type(void) G_GNUC_CONST; gboolean inf_xml_connection_open(InfXmlConnection* connection, GError** error); void inf_xml_connection_close(InfXmlConnection* connection); void inf_xml_connection_send(InfXmlConnection* connection, xmlNodePtr xml); void inf_xml_connection_sent(InfXmlConnection* connection, const xmlNodePtr xml); void inf_xml_connection_received(InfXmlConnection* connection, const xmlNodePtr xml); void inf_xml_connection_error(InfXmlConnection* connection, const GError* error); G_END_DECLS #endif /* __INF_XML_CONNECTION_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-acl.h0000644000000000000000000000013213034342512021072 xustar0030 mtime=1483851082.029718427 30 atime=1483851082.029718427 30 ctime=1488261588.928139222 libinfinity-0.7.1/libinfinity/common/inf-acl.h0000644000175000017500000002355713034342512021640 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_ACL_SHEET_H__ #define __INF_ACL_SHEET_H__ #include #include G_BEGIN_DECLS #define INF_TYPE_ACL_ACCOUNT (inf_acl_account_get_type()) #define INF_TYPE_ACL_SETTING (inf_acl_setting_get_type()) #define INF_TYPE_ACL_MASK (inf_acl_mask_get_type()) #define INF_TYPE_ACL_SHEET (inf_acl_sheet_get_type()) #define INF_TYPE_ACL_SHEET_SET (inf_acl_sheet_set_get_type()) /** * InfAclAccountId: * * This type represents a unique identifier for a user account. */ typedef GQuark InfAclAccountId; /** * INF_ACL_ACCOUNT_ID_TO_POINTER: * @id: A #InfAclAccountId. * * Converts a #InfAclAccountId to a pointer such that the pointer * represents a unique representation of the given ID. The pointer should not * be used for anything else except comparisons with other pointer obtained * in this way, for example in hash table lookups. */ #define INF_ACL_ACCOUNT_ID_TO_POINTER(id) \ (GUINT_TO_POINTER(id)) /** * INF_ACL_ACCOUNT_POINTER_TO_ID: * @ptr: A pointer obtained with %INF_ACL_ACCOUNT_ID_TO_POINTER. * * Converts a pointer obtained with %INF_ACL_ACCOUNT_ID_TO_POINTER back into * the original #InfAclAccountId value. */ #define INF_ACL_ACCOUNT_POINTER_TO_ID(ptr) \ (GPOINTER_TO_UINT(ptr)) /** * InfAclAccount: * @id: A unique ID for this account. * @name: A human readable account name. * * This boxed type specifies basic user account information. */ typedef struct _InfAclAccount InfAclAccount; struct _InfAclAccount { /*< public >*/ InfAclAccountId id; gchar* name; }; /** * InfAclSetting: * @INF_ACL_CAN_ADD_SUBDIRECTORY: The user is allowed to create a new * subdirectory node. * @INF_ACL_CAN_ADD_DOCUMENT: The user is allowed to create a new leaf node. * @INF_ACL_CAN_SYNC_IN: The user is allowed to create documents with * non-empty content. * @INF_ACL_CAN_REMOVE_NODE: The user is allowed to remove a child node. * @INF_ACL_CAN_EXPLORE_NODE: The user is allowed to explore a subdirectory * node in the directory tree. * @INF_ACL_CAN_SUBSCRIBE_CHAT: The user can subscribe to the global * server-wide chat. * @INF_ACL_CAN_SUBSCRIBE_SESSION: The user is allowed to subscribe to a * session in the directory tree. * @INF_ACL_CAN_JOIN_USER: The user is allowed to join a user into the * session which corresponds to the node. * @INF_ACL_CAN_QUERY_ACCOUNT_LIST: The user is allowed to query the full list * of ACL accounts. * @INF_ACL_CAN_CREATE_ACCOUNT: The user can create a new account on the * server. * @INF_ACL_CAN_OVERRIDE_ACCOUNT: The user can create an account under a name * that exists already, overriding the login credentials. * @INF_ACL_CAN_REMOVE_ACCOUNT: The user can remove user accounts. * @INF_ACL_CAN_QUERY_ACL: The user is allowed to query the full ACL for * this node. * @INF_ACL_CAN_SET_ACL: The user is allowed to change the ACL of this node, * or create new nodes with a non-default ACL. * * Defines the actual permissions that can be granted or revoked for different * users. */ typedef enum _InfAclSetting { INF_ACL_CAN_ADD_SUBDIRECTORY, INF_ACL_CAN_ADD_DOCUMENT, INF_ACL_CAN_SYNC_IN, INF_ACL_CAN_REMOVE_NODE, INF_ACL_CAN_EXPLORE_NODE, INF_ACL_CAN_SUBSCRIBE_CHAT, INF_ACL_CAN_SUBSCRIBE_SESSION, INF_ACL_CAN_JOIN_USER, INF_ACL_CAN_QUERY_ACCOUNT_LIST, INF_ACL_CAN_CREATE_ACCOUNT, INF_ACL_CAN_OVERRIDE_ACCOUNT, INF_ACL_CAN_REMOVE_ACCOUNT, INF_ACL_CAN_QUERY_ACL, INF_ACL_CAN_SET_ACL, /*< private >*/ INF_ACL_LAST } InfAclSetting; /** * InfAclMask: * @mask: A 256 bit wide bitfield of #InfAclSettings. * * This structure represents a mask of #InfAclSettings, where each * setting can be either turned on or off. */ typedef struct _InfAclMask InfAclMask; struct _InfAclMask { /* leave quite some space for future use */ guint64 mask[4]; }; /** * InfAclSheet: * @account: The account for which to apply the permissions in this sheet. * @mask: Mask which specifies which of the permissions in the @perms * field take effect. Fields which are masked-out are left at their default * value and inherited from the parent node. * @perms: Mask which specifies whether or not the user is allowed to * perform the various operations defined by #InfAclSetting. * * A set of permissions to be applied for a particular account and a * particular node in the infinote directory. */ typedef struct _InfAclSheet InfAclSheet; struct _InfAclSheet { InfAclAccountId account; InfAclMask mask; InfAclMask perms; }; /** * InfAclSheetSet: * @sheets: An array of #InfAclSheet objects. * @n_sheets: The number of elements in the @sheets array. * * A set of #InfAclSheets, one for each user. */ typedef struct _InfAclSheetSet InfAclSheetSet; struct _InfAclSheetSet { /*< private >*/ InfAclSheet* own_sheets; /*< public >*/ const InfAclSheet* sheets; guint n_sheets; }; extern const InfAclMask INF_ACL_MASK_ALL; extern const InfAclMask INF_ACL_MASK_DEFAULT; extern const InfAclMask INF_ACL_MASK_ROOT; /* only applicable for root node */ extern const InfAclMask INF_ACL_MASK_SUBDIRECTORY; /* only applicable for subdirectory node */ extern const InfAclMask INF_ACL_MASK_LEAF; /* only applicable for leaf node */ GType inf_acl_account_get_type(void) G_GNUC_CONST; GType inf_acl_setting_get_type(void) G_GNUC_CONST; GType inf_acl_mask_get_type(void) G_GNUC_CONST; GType inf_acl_sheet_get_type(void) G_GNUC_CONST; GType inf_acl_sheet_set_get_type(void) G_GNUC_CONST; const gchar* inf_acl_account_id_to_string(InfAclAccountId account); InfAclAccountId inf_acl_account_id_from_string(const gchar* id); InfAclAccount* inf_acl_account_new(InfAclAccountId id, const gchar* name); InfAclAccount* inf_acl_account_copy(const InfAclAccount* account); void inf_acl_account_free(InfAclAccount* account); void inf_acl_account_array_free(InfAclAccount* accounts, guint n_accounts); InfAclAccount* inf_acl_account_from_xml(xmlNodePtr xml, GError** error); void inf_acl_account_to_xml(const InfAclAccount* account, xmlNodePtr xml); InfAclMask* inf_acl_mask_copy(const InfAclMask* mask); void inf_acl_mask_free(InfAclMask* mask); void inf_acl_mask_clear(InfAclMask* mask); gboolean inf_acl_mask_empty(const InfAclMask* mask); gboolean inf_acl_mask_equal(const InfAclMask* lhs, const InfAclMask* rhs); InfAclMask* inf_acl_mask_set1(InfAclMask* mask, const InfAclSetting setting); InfAclMask* inf_acl_mask_setv(InfAclMask* mask, const InfAclSetting* settings, guint n_settings); InfAclMask* inf_acl_mask_and(const InfAclMask* lhs, const InfAclMask* rhs, InfAclMask* out); InfAclMask* inf_acl_mask_and1(InfAclMask* mask, InfAclSetting setting); InfAclMask* inf_acl_mask_or(const InfAclMask* lhs, const InfAclMask* rhs, InfAclMask* out); InfAclMask* inf_acl_mask_or1(InfAclMask* mask, InfAclSetting setting); InfAclMask* inf_acl_mask_neg(const InfAclMask* mask, InfAclMask* out); gboolean inf_acl_mask_has(const InfAclMask* mask, InfAclSetting setting); InfAclSheet* inf_acl_sheet_new(InfAclAccountId account); InfAclSheet* inf_acl_sheet_copy(const InfAclSheet* sheet); void inf_acl_sheet_free(InfAclSheet* sheet); gboolean inf_acl_sheet_perms_from_xml(xmlNodePtr xml, InfAclMask* mask, InfAclMask* perms, GError** error); void inf_acl_sheet_perms_to_xml(const InfAclMask* mask, const InfAclMask* perms, xmlNodePtr xml); InfAclSheetSet* inf_acl_sheet_set_new(void); InfAclSheetSet* inf_acl_sheet_set_new_external(const InfAclSheet* sheets, guint n_sheets); InfAclSheetSet* inf_acl_sheet_set_copy(const InfAclSheetSet* sheet_set); void inf_acl_sheet_set_free(InfAclSheetSet* sheet_set); void inf_acl_sheet_set_sink(InfAclSheetSet* sheet_set); InfAclSheet* inf_acl_sheet_set_add_sheet(InfAclSheetSet* sheet_set, InfAclAccountId account); void inf_acl_sheet_set_remove_sheet(InfAclSheetSet* sheet_set, InfAclSheet* sheet); InfAclSheetSet* inf_acl_sheet_set_merge_sheets(InfAclSheetSet* sheet_set, const InfAclSheetSet* other); InfAclSheetSet* inf_acl_sheet_set_get_clear_sheets(const InfAclSheetSet* sheet_set); InfAclSheet* inf_acl_sheet_set_find_sheet(InfAclSheetSet* sheet_set, InfAclAccountId account); const InfAclSheet* inf_acl_sheet_set_find_const_sheet(const InfAclSheetSet* sheet_set, InfAclAccountId account); InfAclSheetSet* inf_acl_sheet_set_from_xml(xmlNodePtr xml, GError** error); void inf_acl_sheet_set_to_xml(const InfAclSheetSet* sheet_set, xmlNodePtr xml); G_END_DECLS #endif /* __INF_ACL_SHEET_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-protocol.c0000644000000000000000000000013213034342512022167 xustar0030 mtime=1483851082.033718448 30 atime=1483851082.033718448 30 ctime=1488261589.072138908 libinfinity-0.7.1/libinfinity/common/inf-protocol.c0000644000175000017500000000737513034342512022735 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-protocol * @short_description: Infinote protocol parameters * @include: libinfinity/common/inf-protocol.h * @see_also: InfError * @stability: Unstable * * This section defines common protocol parameters used by libinfinity. **/ #include #include #include #include #include /** * inf_protocol_get_version: * * Returns the version of the Infinote protocol implemented by this * version of libinfinity. * * Returns: The supported infinote version. */ const gchar* inf_protocol_get_version(void) { return "1.1"; } /** * inf_protocol_parse_version: * @version: A version string, such as "1.0" * @major: A location to store the major version number to. * @minor: A location to store the minor version number to * @error: Location to store error information, if any. * * Splits the given version string into it's major and minor version number. * If the string is badly formatted then the function returns %FALSE, @error * is set and @major and @minor are left untouched. * * It is guaranteed that, if @version is inf_protocol_get_version(), the * function does not fail. * * Returns: %TRUE on success, or %FALSE on error. */ gboolean inf_protocol_parse_version(const gchar* version, guint* major, guint* minor, GError** error) { gchar* endptr; unsigned long maj; unsigned long min; errno = 0; maj = strtoul(version, &endptr, 10); if(errno == ERANGE || maj > (unsigned long)G_MAXUINT) { g_set_error_literal( error, inf_request_error_quark(), INF_REQUEST_ERROR_INVALID_NUMBER, _("Major part of version number causes overflow") ); return FALSE; } if(*endptr != '.') { g_set_error_literal( error, inf_request_error_quark(), INF_REQUEST_ERROR_INVALID_NUMBER, _("Version number parts are not separated by '.'") ); return FALSE; } errno = 0; min = strtoul(endptr+1, &endptr, 10); if(errno == ERANGE || min > (unsigned long)G_MAXUINT) { g_set_error_literal( error, inf_request_error_quark(), INF_REQUEST_ERROR_INVALID_NUMBER, _("Minor part of version number causes overflow") ); return FALSE; } if(*endptr != '\0') { g_set_error_literal( error, inf_request_error_quark(), INF_REQUEST_ERROR_INVALID_NUMBER, _("Trailing characters after version number") ); return FALSE; } if(major) *major = maj; if(minor) *minor = min; return TRUE; } /** * inf_protocol_get_default_port: * * Returns the default port on which the infinote daemon listens for new * connections. * * Returns: The default port. */ guint inf_protocol_get_default_port(void) { return 6523; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-error.c0000644000000000000000000000013213034342512021457 xustar0030 mtime=1483851082.033718448 30 atime=1483851082.033718448 30 ctime=1488261589.056138943 libinfinity-0.7.1/libinfinity/common/inf-error.c0000644000175000017500000003137513034342512022222 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-error * @short_description: Common error codes * @include: libinfinity/common/inf-error.h * @stability: Unstable * * This section defines some common error codes that are used on both client * and server side in infinote, and maps these to #GErrors. **/ #include #include #include #include /* Get ssize_t on MSVC, required by gnutls.h */ #include /* TODO: Cache GQuarks */ /** * inf_request_error_quark: * * Error domain for request errors. Errors in this domain will be from the * #InfRequestError enumeration. See #GError for information on error domains. * * Returns: A GQuark. */ GQuark inf_request_error_quark(void) { return g_quark_from_static_string("INF_REQUEST_ERROR"); } /** * inf_request_strerror: * @code: An error code from the #InfRequestError enumeration. * * Returns a human-readable string for the given error code. * * Returns: A static string that must not be freed. */ const gchar* inf_request_strerror(InfRequestError code) { switch(code) { case INF_REQUEST_ERROR_UNKNOWN_DOMAIN: return _("Received error from an unknown domain"); case INF_REQUEST_ERROR_REPLY_UNPROCESSED: return _("Failed to process server reply"); case INF_REQUEST_ERROR_INVALID_SEQ: return _("Server reply contains invalid sequence number"); case INF_REQUEST_ERROR_NO_SUCH_ATTRIBUTE: return _("A required attribute was not set in request"); case INF_REQUEST_ERROR_INVALID_ATTRIBUTE: return _("An attribute did not have valid content"); case INF_REQUEST_ERROR_INVALID_NUMBER: return _("An attribute contained an invalid number"); case INF_REQUEST_ERROR_NOT_AUTHORIZED: return _("Not authorized"); case INF_REQUEST_ERROR_FAILED: return _("An unknown request error occured"); default: return _("An error with unknown error code occured"); } } /** * inf_user_error_quark: * * Error domain for user-related errors. Errors in this domain will be from * the #InfUserError enumeration. See #GError for information on error * domains. * * Returns: A GQuark. */ GQuark inf_user_error_quark(void) { return g_quark_from_static_string("INF_USER_ERROR"); } /** * inf_user_strerror: * @code: An error code from the #InfUserError enumeration. * * Returns a human-readable string for the given error code. * * Returns: A static string that must not be freed. */ const gchar* inf_user_strerror(InfUserError code) { switch(code) { case INF_USER_ERROR_NAME_IN_USE: return _("Name is already in use"); case INF_USER_ERROR_ID_PROVIDED: return _("'id' attribute provided in request"); case INF_USER_ERROR_NO_SUCH_USER: return _("There is no user with the given ID"); case INF_USER_ERROR_STATUS_UNAVAILABLE: return _("'status' attribute is 'unavailable' in join or rejoin request"); case INF_USER_ERROR_NOT_JOINED: return _("User did not join via this connection"); case INF_USER_ERROR_INVALID_STATUS: return _("'status' attribute has invalid value"); case INF_USER_ERROR_FAILED: return _("An unknown user error occured"); default: return _("An error with unknown error code occured"); } } /** * inf_directory_error_quark: * * Error domain for directory errors. Errors in this domain will be from the * #InfDirectoryError enumeration. See #GError for information on error * domains. * * Returns: A GQuark. */ GQuark inf_directory_error_quark(void) { return g_quark_from_static_string("INF_DIRECTORY_ERROR"); } /** * inf_directory_strerror: * @code: An error code from the #InfDirectoryError enumeration. * * Returns a human-readable string for the given error code. * * Returns: A static string that must not be freed. */ const gchar* inf_directory_strerror(InfDirectoryError code) { switch(code) { case INF_DIRECTORY_ERROR_NO_WELCOME_MESSAGE: return _("Server did not send an initial welcome message"); case INF_DIRECTORY_ERROR_VERSION_MISMATCH: return _("The server and client use different protocol versions"); case INF_DIRECTORY_ERROR_NODE_EXISTS: return _("A node with this name exists already"); case INF_DIRECTORY_ERROR_INVALID_NAME: return _("Invalid node name"); case INF_DIRECTORY_ERROR_NO_SUCH_NODE: return _("Node does not exist"); case INF_DIRECTORY_ERROR_NO_SUCH_SUBSCRIPTION_REQUEST: return _("No previous subscription request present"); case INF_DIRECTORY_ERROR_CHAT_DISABLED: return _("The chat is disabled on the server side"); case INF_DIRECTORY_ERROR_NOT_A_SUBDIRECTORY: return _("Node is not a subdirectory"); case INF_DIRECTORY_ERROR_NOT_A_NOTE: return _("Node is not a note"); case INF_DIRECTORY_ERROR_NOTE_TYPE_UNSUPPORTED: return _("The node type is not supported by the server"); case INF_DIRECTORY_ERROR_ROOT_NODE_REMOVE_ATTEMPT: return _("The root node cannot be removed"); case INF_DIRECTORY_ERROR_NOT_EXPLORED: return _("Subdirectory is not explored"); case INF_DIRECTORY_ERROR_ALREADY_EXPLORED: return _("Subdirectory has already been explored"); case INF_DIRECTORY_ERROR_TYPE_UNKNOWN: return _("Note type is not supported"); case INF_DIRECTORY_ERROR_ALREADY_SUBSCRIBED: return _("Connection is already subscribed to this session"); case INF_DIRECTORY_ERROR_UNSUBSCRIBED: return _("The requesting connection is not subscribed to the session"); case INF_DIRECTORY_ERROR_NOT_INITIATED: return _("The server started to send explored nodes before telling how" "many nodes to expect"); case INF_DIRECTORY_ERROR_TOO_MANY_CHILDREN: return _("Server sent more explored nodes then announced"); case INF_DIRECTORY_ERROR_TOO_FEW_CHILDREN: return _("Server sent not as much explored nodes as announced"); case INF_DIRECTORY_ERROR_NETWORK_UNSUPPORTED: return _("The session does not support the network through which the " "connection attempt is being made."); case INF_DIRECTORY_ERROR_METHOD_UNSUPPORTED: return _("The session uses an unsupported communication method"); case INF_DIRECTORY_ERROR_OPERATION_UNSUPPORTED: return _("The requested operation is not supported by the server"); case INF_DIRECTORY_ERROR_UNEXPECTED_SYNC_IN: return _("Received sync-in message without having requested a sync-in"); case INF_DIRECTORY_ERROR_SUBSCRIPTION_REJECTED: return _("Client rejected subscription"); case INF_DIRECTORY_ERROR_UNEXPECTED_MESSAGE: return _("Unexpected XML message"); case INF_DIRECTORY_ERROR_NO_STORAGE: return _("Server does not have a background storage"); case INF_DIRECTORY_ERROR_INVALID_CERTIFICATE: return _("The certificate is invalid or not trusted"); case INF_DIRECTORY_ERROR_ACCOUNT_LIST_ALREADY_QUERIED: return _("The account list has already been queried before"); case INF_DIRECTORY_ERROR_ACCOUNT_LIST_NOT_QUERIED: return _("The account list has not been queried"); case INF_DIRECTORY_ERROR_DUPLICATE_ACCOUNT: return _("An account with this ID exists already"); case INF_DIRECTORY_ERROR_NO_SUCH_ACCOUNT: return _("There is no such account with the given ID"); case INF_DIRECTORY_ERROR_ACL_ALREADY_QUERIED: return _("The ACL has already been queried"); case INF_DIRECTORY_ERROR_ACL_NOT_QUERIED: return _("The ACL has not been queried"); case INF_DIRECTORY_ERROR_FAILED: return _("An unknown directory error has occured"); default: return _("An error with unknown code has occured"); } } /** * inf_authentication_detail_error_quark: * * Error domain for further information on authentication errors. Errors in * this domain will be from the #InfAuthenticationDetailError enumeration. * See #GError for information on error domains. * * Returns: A GQuark. */ GQuark inf_authentication_detail_error_quark(void) { return g_quark_from_static_string("INF_AUTHENTICATION_DETAIL_ERROR"); } /** * inf_authentication_detail_strerror: * @code: An error code from the #InfAuthenticationDetailError enumeration. * * Returns a human-readable string for the given error code. * * Returns: A static string that must not be freed. */ const gchar* inf_authentication_detail_strerror(InfAuthenticationDetailError code) { switch(code) { case INF_AUTHENTICATION_DETAIL_ERROR_AUTHENTICATION_FAILED: return _("User did not provide valid credentials."); case INF_AUTHENTICATION_DETAIL_ERROR_USER_NOT_AUTHORIZED: return _("User is not permitted to connect to this server."); case INF_AUTHENTICATION_DETAIL_ERROR_TRY_AGAIN: return _("Authentication was temporarily " "interrupted on the server side."); case INF_AUTHENTICATION_DETAIL_ERROR_SERVER_ERROR: return _("An error cocured while checking user permissions."); default: return _("An error with unknown code has occured"); } } /** * inf_gnutls_error_quark: * * Error domain for GnuTLS errors. Errors in this domain will be GnuTLS error * codes. See #GError for information on error domains. * * Returns: A GQuark. */ GQuark inf_gnutls_error_quark(void) { return g_quark_from_static_string("INF_GNUTLS_ERROR"); } /** * inf_gnutls_set_error: * @error: Location to store the error, or %NULL. * @error_code: A GnuTLS error code. * * Sets a #GError from a GnuTLS error code. If @error is %NULL, does nothing. */ void inf_gnutls_set_error(GError** error, int error_code) { if(error != NULL) { *error = g_error_new_literal( inf_gnutls_error_quark(), error_code, gnutls_strerror(error_code) ); } } /** * inf_gnutls_certificate_verification_error_quark: * * Error domain for GnuTLS certificate verification errors. Errors in this * domain will be GnuTLS certificate verification results as returned by * gnutls_certificate_verify_peers2(). See #GError for information on * error domains. * * Returns: A GQuark. */ GQuark inf_gnutls_certificate_verification_error_quark(void) { return g_quark_from_static_string( "INF_GNUTLS_CERTIFICATE_VERIFICATION_ERROR" ); } /** * inf_gnutls_certificate_verification_set_error: * @error: Location to store the error, or %NULL. * @verify: A GnuTLS certificate verification code. * * Sets a #GError from a certificate verification result. * If @error is %NULL, does nothing. */ void inf_gnutls_certificate_verification_set_error(GError** error, int verify) { const gchar* message; if(error != NULL) { if(verify & GNUTLS_CERT_REVOKED) message = _("The certificate was revoked"); else if(verify & GNUTLS_CERT_SIGNER_NOT_FOUND) message = _("The certificate was not signed by a trusted CA"); else if(verify & GNUTLS_CERT_SIGNER_NOT_CA) message = _("The signer of the certificate is not a CA"); else if(verify & GNUTLS_CERT_INSECURE_ALGORITHM) message = _("The certificate uses an insecure algorithm"); else if(verify & GNUTLS_CERT_NOT_ACTIVATED) message = _("The certificate is not yet activated"); else if(verify & GNUTLS_CERT_EXPIRED) message = _("The certificate has expired"); else if(verify & GNUTLS_CERT_INVALID) message = _("The certificate is invalid"); else g_assert_not_reached(); *error = g_error_new_literal( inf_gnutls_certificate_verification_error_quark(), verify, message ); } } /** * inf_gsasl_error_quark: * * Error domain for GNU SASL errors. Errors in this domain will be GNU SASL * error codes. See #GError for information on error domains. * * Returns: A GQuark. */ GQuark inf_gsasl_error_quark(void) { return g_quark_from_static_string("INF_GSASL_ERROR"); } /** * inf_gsasl_set_error: * @error: Location to store the error, or %NULL. * @error_code: A GNU SASL error code. * * Sets a #GError from a GNU SASL error code. If @error is %NULL, does nothing. */ void inf_gsasl_set_error(GError** error, int error_code) { if(error != NULL) { *error = g_error_new_literal( inf_gsasl_error_quark(), error_code, gsasl_strerror(error_code) ); } } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-xml-util.h0000644000000000000000000000013013034342512022104 xustar0029 mtime=1483851082.03771847 29 atime=1483851082.03771847 30 ctime=1488261588.972139127 libinfinity-0.7.1/libinfinity/common/inf-xml-util.h0000644000175000017500000001177213034342512022650 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_XML_UTIL_H__ #define __INF_XML_UTIL_H__ #include #include G_BEGIN_DECLS void inf_xml_util_add_child_text(xmlNodePtr xml, const gchar* text, gsize bytes); gchar* inf_xml_util_get_child_text(xmlNodePtr xml, gsize* bytes, guint* chars, GError** error); xmlChar* inf_xml_util_get_attribute(xmlNodePtr xml, const gchar* attribute); xmlChar* inf_xml_util_get_attribute_required(xmlNodePtr xml, const gchar* attribute, GError** error); gboolean inf_xml_util_get_attribute_int(xmlNodePtr xml, const gchar* attribute, gint* result, GError** error); gboolean inf_xml_util_get_attribute_int_required(xmlNodePtr xml, const gchar* attribute, gint* result, GError** error); gboolean inf_xml_util_get_attribute_long(xmlNodePtr xml, const gchar* attribute, glong* result, GError** error); gboolean inf_xml_util_get_attribute_long_required(xmlNodePtr xml, const gchar* attribute, glong* result, GError** error); gboolean inf_xml_util_get_attribute_uint(xmlNodePtr xml, const gchar* attribute, guint* result, GError** error); gboolean inf_xml_util_get_attribute_uint_required(xmlNodePtr xml, const gchar* attribute, guint* result, GError** error); gboolean inf_xml_util_get_attribute_ulong(xmlNodePtr xml, const gchar* attribute, gulong* result, GError** error); gboolean inf_xml_util_get_attribute_ulong_required(xmlNodePtr xml, const gchar* attribute, gulong* result, GError** error); gboolean inf_xml_util_get_attribute_double(xmlNodePtr xml, const gchar* attribute, gdouble* result, GError** error); gboolean inf_xml_util_get_attribute_double_required(xmlNodePtr xml, const gchar* attribute, gdouble* result, GError** error); void inf_xml_util_set_attribute(xmlNodePtr xml, const gchar* attribute, const gchar* value); void inf_xml_util_set_attribute_int(xmlNodePtr xml, const gchar* attribute, gint value); void inf_xml_util_set_attribute_long(xmlNodePtr xml, const gchar* attribute, glong value); void inf_xml_util_set_attribute_uint(xmlNodePtr xml, const gchar* attribute, guint value); void inf_xml_util_set_attribute_ulong(xmlNodePtr xml, const gchar* attribute, gulong value); void inf_xml_util_set_attribute_double(xmlNodePtr xml, const gchar* attribute, gdouble value); xmlNodePtr inf_xml_util_new_node_from_error(GError* error, xmlNsPtr name_space, const gchar* name); GError* inf_xml_util_new_error_from_node(xmlNodePtr xml); G_END_DECLS #endif /* __INF_XML_UTIL_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-user-table.c0000644000000000000000000000013013034342512022367 xustar0029 mtime=1483851082.03771847 29 atime=1483851082.03771847 30 ctime=1488261589.084138882 libinfinity-0.7.1/libinfinity/common/inf-user-table.c0000644000175000017500000004526613034342512023140 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include #include /** * SECTION:inf-user-table * @title: InfUserTable * @short_description: User information storage * @include: libinfinity/common/inf-user-table.h * @see_also: #InfUser, #InfSession * @stability: Unstable * * #InfUserTable manages multiple #InfUser objects and provides an easy way to * look up users by their ID and name. All users within a user table must have * a unique ID and name. The user table is used by #InfSession to store the * users within the session. */ typedef struct _InfUserTableForeachUserData InfUserTableForeachUserData; struct _InfUserTableForeachUserData { InfUserTableForeachUserFunc func; gpointer user_data; }; typedef struct _InfUserTablePrivate InfUserTablePrivate; struct _InfUserTablePrivate { GHashTable* table; /* TODO: It would be smarter to map the hash table to a helper struct * which stores the user availability, locality and the InfUser object */ GSList* availables; GSList* locals; }; enum { ADD_USER, REMOVE_USER, ADD_AVAILABLE_USER, REMOVE_AVAILABLE_USER, ADD_LOCAL_USER, REMOVE_LOCAL_USER, LAST_SIGNAL }; #define INF_USER_TABLE_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INF_TYPE_USER_TABLE, InfUserTablePrivate)) static guint user_table_signals[LAST_SIGNAL]; G_DEFINE_TYPE_WITH_CODE(InfUserTable, inf_user_table, G_TYPE_OBJECT, G_ADD_PRIVATE(InfUserTable)) static gboolean inf_user_table_is_local(InfUser* user) { /* User counts as local when it has the local flag set and is available */ if( (inf_user_get_flags(user) & INF_USER_LOCAL) == 0) return FALSE; if(inf_user_get_status(user) == INF_USER_UNAVAILABLE) return FALSE; return TRUE; } static void inf_user_table_check_local_cb(GObject* object, GParamSpec* pspec, gpointer user_data) { InfUserTable* user_table; InfUserTablePrivate* priv; InfUser* user; GSList* available_item; GSList* local_item; user_table = INF_USER_TABLE(user_data); priv = INF_USER_TABLE_PRIVATE(user_table); user = INF_USER(object); available_item = g_slist_find(priv->availables, user); local_item = g_slist_find(priv->locals, user); if(inf_user_get_status(user) != INF_USER_UNAVAILABLE && available_item == NULL) { g_signal_emit( G_OBJECT(user_table), user_table_signals[ADD_AVAILABLE_USER], 0, user ); } if(inf_user_table_is_local(INF_USER(object)) && local_item == NULL) { g_signal_emit( G_OBJECT(user_table), user_table_signals[ADD_LOCAL_USER], 0, user ); } if(!inf_user_table_is_local(INF_USER(object)) && local_item != NULL) { g_signal_emit( G_OBJECT(user_table), user_table_signals[REMOVE_LOCAL_USER], 0, user ); } if(inf_user_get_status(user) == INF_USER_UNAVAILABLE && available_item != NULL) { g_signal_emit( G_OBJECT(user_table), user_table_signals[REMOVE_AVAILABLE_USER], 0, user ); } } static void inf_user_table_unref_user(InfUserTable* user_table, InfUser* user) { inf_signal_handlers_disconnect_by_func( G_OBJECT(user), G_CALLBACK(inf_user_table_check_local_cb), user_table ); g_object_unref(user); } static void inf_user_table_dispose_foreach_func(gpointer key, gpointer value, gpointer user_data) { inf_user_table_unref_user(INF_USER_TABLE(user_data), INF_USER(value)); } /* * User table callbacks. */ static gboolean inf_user_table_lookup_user_by_name_func(gpointer key, gpointer value, gpointer data) { const gchar* user_name; user_name = inf_user_get_name(INF_USER(value)); if(strcmp(user_name, (const gchar*)data) == 0) return TRUE; return FALSE; } static void inf_user_table_foreach_user_func(gpointer key, gpointer value, gpointer user_data) { InfUserTableForeachUserData* data; data = (InfUserTableForeachUserData*)user_data; data->func(INF_USER(value), data->user_data); } static void inf_user_table_init(InfUserTable* user_table) { InfUserTablePrivate* priv; priv = INF_USER_TABLE_PRIVATE(user_table); priv->table = g_hash_table_new_full(NULL, NULL, NULL, NULL); priv->availables = NULL; priv->locals = NULL; } static void inf_user_table_dispose(GObject* object) { InfUserTable* user_table; InfUserTablePrivate* priv; user_table = INF_USER_TABLE(object); priv = INF_USER_TABLE_PRIVATE(user_table); g_slist_free(priv->locals); priv->locals = NULL; g_slist_free(priv->availables); priv->availables = NULL; g_hash_table_foreach( priv->table, inf_user_table_dispose_foreach_func, user_table ); g_hash_table_remove_all(priv->table); G_OBJECT_CLASS(inf_user_table_parent_class)->dispose(object); } static void inf_user_table_finalize(GObject* object) { InfUserTable* user_table; InfUserTablePrivate* priv; user_table = INF_USER_TABLE(object); priv = INF_USER_TABLE_PRIVATE(user_table); g_hash_table_destroy(priv->table); G_OBJECT_CLASS(inf_user_table_parent_class)->finalize(object); } static void inf_user_table_add_user_handler(InfUserTable* user_table, InfUser* user) { InfUserTablePrivate* priv; guint id; priv = INF_USER_TABLE_PRIVATE(user_table); id = inf_user_get_id(user); g_assert(id > 0); g_assert(g_hash_table_lookup(priv->table, GUINT_TO_POINTER(id)) == NULL); g_hash_table_insert(priv->table, GUINT_TO_POINTER(id), user); g_object_ref(user); g_signal_connect( G_OBJECT(user), "notify::status", G_CALLBACK(inf_user_table_check_local_cb), user_table ); if(inf_user_get_status(user) != INF_USER_UNAVAILABLE) { g_signal_emit( G_OBJECT(user_table), user_table_signals[ADD_AVAILABLE_USER], 0, user ); } if(inf_user_table_is_local(user)) { g_signal_emit( G_OBJECT(user_table), user_table_signals[ADD_LOCAL_USER], 0, user ); } } static void inf_user_table_remove_user_handler(InfUserTable* user_table, InfUser* user) { InfUserTablePrivate* priv; guint id; priv = INF_USER_TABLE_PRIVATE(user_table); id = inf_user_get_id(user); if(inf_user_table_is_local(user)) { g_signal_emit( G_OBJECT(user_table), user_table_signals[REMOVE_LOCAL_USER], 0, user ); } if(inf_user_get_status(user) != INF_USER_UNAVAILABLE) { g_signal_emit( G_OBJECT(user_table), user_table_signals[REMOVE_AVAILABLE_USER], 0, user ); } inf_user_table_unref_user(user_table, user); g_assert(g_hash_table_lookup(priv->table, GUINT_TO_POINTER(id)) == user); g_hash_table_remove(priv->table, GUINT_TO_POINTER(id)); } static void inf_user_table_add_available_user(InfUserTable* user_table, InfUser* user) { InfUserTablePrivate* priv; priv = INF_USER_TABLE_PRIVATE(user_table); g_assert(g_slist_find(priv->availables, user) == NULL); priv->availables = g_slist_prepend(priv->availables, user); } static void inf_user_table_remove_available_user(InfUserTable* user_table, InfUser* user) { InfUserTablePrivate* priv; priv = INF_USER_TABLE_PRIVATE(user_table); g_assert(g_slist_find(priv->availables, user) != NULL); priv->availables = g_slist_remove(priv->availables, user); } static void inf_user_table_add_local_user(InfUserTable* user_table, InfUser* user) { InfUserTablePrivate* priv; priv = INF_USER_TABLE_PRIVATE(user_table); g_assert(g_slist_find(priv->locals, user) == NULL); priv->locals = g_slist_prepend(priv->locals, user); } static void inf_user_table_remove_local_user(InfUserTable* user_table, InfUser* user) { InfUserTablePrivate* priv; priv = INF_USER_TABLE_PRIVATE(user_table); g_assert(g_slist_find(priv->locals, user) != NULL); priv->locals = g_slist_remove(priv->locals, user); } static void inf_user_table_class_init(InfUserTableClass* user_table_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(user_table_class); object_class->dispose = inf_user_table_dispose; object_class->finalize = inf_user_table_finalize; user_table_class->add_user = inf_user_table_add_user_handler; user_table_class->remove_user = inf_user_table_remove_user_handler; user_table_class->add_available_user = inf_user_table_add_available_user; user_table_class->remove_available_user = inf_user_table_remove_available_user; user_table_class->add_local_user = inf_user_table_add_local_user; user_table_class->remove_local_user = inf_user_table_remove_local_user; /** * InfUserTable::add-user: * @user_table: The #InfUserTable into which @user has been added * @user: The #InfUser that has been added into @user_table * * This signal is emitted when inf_user_table_add_user() is called. Note * that this does not happen if @user rejoins the session and has already * been added to @user_table previously. * * #InfUserTable::add-local-user may also be emitted at this point if * @user has the %INF_USER_LOCAL flag set. */ user_table_signals[ADD_USER] = g_signal_new( "add-user", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfUserTableClass, add_user), NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, INF_TYPE_USER ); /** * InfUserTable::remove-user: * @user_table: The #InfUserTable from which @user has been remove * @user: The #InfUser that has been removed from @user_table * * This signal is emitted when inf_user_table_remove_user() is called. This * does not usually happen, as users leaving a session do not get removed * from the table. * * #InfUserTable::remove-local-user may also be emitted at this point if * @user has the %INF_USER_LOCAL flag set. */ user_table_signals[REMOVE_USER] = g_signal_new( "remove-user", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfUserTableClass, remove_user), NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, INF_TYPE_USER ); /** * InfUserTable::add-available-user: * @user_table: The #InfUserTable in which @user became available. * @user: The #InfUser that became available. * * This signal is emitted when a user in the user table becomes available, * i.e. its status is not %INF_USER_UNAVAILABLE. The signal is also emitted * when a new user is added to the user table who is available, in addition * to #InfUserTable::add-user and possibly #InfUserTable::add-local-user. */ user_table_signals[ADD_AVAILABLE_USER] = g_signal_new( "add-available-user", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfUserTableClass, add_available_user), NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, INF_TYPE_USER ); /** * InfUserTable::remove-available-user: * @user_table: The #InfUserTable in which @user became unavailable. * @user: The #InfUser that became unavailable. * * This signal is emitted when a user in the user table became unavailable, * i.e. its status has changed to %INF_USER_UNAVAILABLE. The signal is also * emitted when a user who was available has been removed from the user * table, in addition to #InfUserTable::remove-user and possibly * #InfUserTable::remove-local-user. */ user_table_signals[REMOVE_AVAILABLE_USER] = g_signal_new( "remove-available-user", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfUserTableClass, remove_available_user), NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, INF_TYPE_USER ); /** * InfUserTable::add-local-user: * @user_table: The #InfUserTable in which @user has been set as local * @user: The #InfUser that has set as local * * This signal is emitted when a user is added to the user table and has the * %INF_USER_LOCAL flag set. In this case, #InfUserTable::add-user is * emitted as well. * * This signal is also emitted when an existing user receives the * %INF_USER_LOCAL flag. This occurs when a user rejoins locally after * leaving the session (possibly having the %INF_USER_LOCAL flag removed * during their absence). #InfUserTable::add-user is not emitted in this * case. */ user_table_signals[ADD_LOCAL_USER] = g_signal_new( "add-local-user", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfUserTableClass, add_local_user), NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, INF_TYPE_USER ); /** * InfUserTable::remove-local-user: * @user_table: The #InfUserTable in which @user is no longer local * @user: The #InfUser that is no longer local * * This signal is emitted when a user is removed from the user table and * had the %INF_USER_LOCAL flag set. In this case, * #InfUserTable::remove-user is emitted as well. * * This signal is also emitted when @user loses the %INF_USER_LOCAL flag. * This occurs when the local @user leaves the session. * #InfUserTable::remove-user is not emitted and the status of @user is set * to %INF_USER_UNAVAILABLE. */ user_table_signals[REMOVE_LOCAL_USER] = g_signal_new( "remove-local-user", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfUserTableClass, remove_local_user), NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, INF_TYPE_USER ); } /** * inf_user_table_new: (constructor) * * Creates a new, empty user table. * * Returns: (transfer full): A #InfUserTable. **/ InfUserTable* inf_user_table_new(void) { return INF_USER_TABLE(g_object_new(INF_TYPE_USER_TABLE, NULL)); } /** * inf_user_table_add_user: * @user_table: A #InfUserTable. * @user: A #InfUser not already contained in @user_table. * * Inserts @user into @user_table. */ void inf_user_table_add_user(InfUserTable* user_table, InfUser* user) { g_return_if_fail(INF_IS_USER_TABLE(user_table)); g_return_if_fail(INF_IS_USER(user)); g_signal_emit(G_OBJECT(user_table), user_table_signals[ADD_USER], 0, user); } /** * inf_user_table_remove_user: * @user_table: A #InfUserTable. * @user: A #InfUser contained in @table. * * Removes @user from @uesr_table. **/ void inf_user_table_remove_user(InfUserTable* user_table, InfUser* user) { g_return_if_fail(INF_IS_USER_TABLE(user_table)); g_return_if_fail(INF_IS_USER(user)); g_signal_emit( G_OBJECT(user_table), user_table_signals[REMOVE_USER], 0, user ); } /** * inf_user_table_lookup_user_by_id: * @user_table: A #InfUserTable. * @id: User ID to lookup. * * Returns the #InfUser with the given User ID in @user_table. * * Returns: (transfer none) (allow-none): A #InfUser, or %NULL. **/ InfUser* inf_user_table_lookup_user_by_id(InfUserTable* user_table, guint id) { InfUserTablePrivate* priv; g_return_val_if_fail(INF_IS_USER_TABLE(user_table), NULL); priv = INF_USER_TABLE_PRIVATE(user_table); return INF_USER(g_hash_table_lookup(priv->table, GUINT_TO_POINTER(id))); } /** * inf_user_table_lookup_user_by_name: * @user_table: A #InfUserTable. * @name: User name to lookup. * * Returns an #InfUser with the given name if there is one. * * Returns: (transfer none) (allow-none): A #InfUser, or %NULL. **/ InfUser* inf_user_table_lookup_user_by_name(InfUserTable* user_table, const gchar* name) { InfUserTablePrivate* priv; InfUser* user; g_return_val_if_fail(INF_IS_USER_TABLE(user_table), NULL); g_return_val_if_fail(name != NULL, NULL); priv = INF_USER_TABLE_PRIVATE(user_table); user = g_hash_table_find( priv->table, inf_user_table_lookup_user_by_name_func, *(gpointer*) (gpointer) &name /* cast const away without warning */ ); return user; } /** * inf_user_table_foreach_user: * @user_table: A #InfUserTable. * @func: (scope call): The function to call for each user. * @user_data: User data to pass to the function. * * Calls the given function for each user in the user_table. You should not * add or remove users while this function is being executed. **/ void inf_user_table_foreach_user(InfUserTable* user_table, InfUserTableForeachUserFunc func, gpointer user_data) { InfUserTablePrivate* priv; InfUserTableForeachUserData data; g_return_if_fail(INF_IS_USER_TABLE(user_table)); g_return_if_fail(func != NULL); priv = INF_USER_TABLE_PRIVATE(user_table); data.func = func; data.user_data = user_data; g_hash_table_foreach( priv->table, inf_user_table_foreach_user_func, &data ); } /** * inf_user_table_foreach_local_user: * @user_table: A #InfUserTable. * @func: (scope call): The function to call for each user. * @user_data: User data to pass to the function. * * Calls the given function for each local user in the user_table. A local * user is a user that has the %INF_USER_LOCAL flag set and that has not * status %INF_USER_UNAVAILABLE. You should not add or remove users while this * function is being executed. **/ void inf_user_table_foreach_local_user(InfUserTable* user_table, InfUserTableForeachUserFunc func, gpointer user_data) { InfUserTablePrivate* priv; GSList* item; g_return_if_fail(INF_IS_USER_TABLE(user_table)); g_return_if_fail(func != NULL); priv = INF_USER_TABLE_PRIVATE(user_table); for(item = priv->locals; item != NULL; item = g_slist_next(item)) func(INF_USER(item->data), user_data); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-tcp-connection-private.h0000644000000000000000000000013013034342512024724 xustar0029 mtime=1483851082.03771847 29 atime=1483851082.03771847 30 ctime=1488261588.988139092 libinfinity-0.7.1/libinfinity/common/inf-tcp-connection-private.h0000644000175000017500000000264413034342512025466 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_TCP_CONNECTION_PRIVATE_H__ #define __INF_TCP_CONNECTION_PRIVATE_H__ #include #include #include G_BEGIN_DECLS InfTcpConnection* _inf_tcp_connection_accepted(InfIo* io, InfNativeSocket socket, InfIpAddress* address, guint port, const InfKeepalive* keepalive, GError** error); G_END_DECLS #endif /* __INF_TCP_CONNECTION_PRIVATE_H__ */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-xml-connection.c0000644000000000000000000000013013034342512023261 xustar0029 mtime=1483851082.03771847 29 atime=1483851082.03771847 30 ctime=1488261589.088138873 libinfinity-0.7.1/libinfinity/common/inf-xml-connection.c0000644000175000017500000002536313034342512024026 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-xml-connection * @title: InfXmlConnection * @short_description: Exchange of XML messages * @include: libinfinity/common/inf-xml-connection.h * @see_also: #InfXmppConnection * @stability: Unstable * * #InfXmlConnection provides a generic interface for sending an receiving * messages in the form of XML nodes. The rest of the libinfinity library * works with #InfXmlConnections to transfer data between nodes. * Therefore, simply implementing this interface allows to use the core * functionality of the library with any kind of network or transport. * * Apart from the virtual functions, implementations also need to provide the * #InfXmlConnection:remote-id and #InfXmlConnection:local-id properties. * These properties represent string identifiers that are unique to the * particular hosts in the network, such as IP addresses for IP connections. * If the connection is supposed to be used with other communication methods * (see #InfCommunicationMethod) than the "central" one, these * IDs must be unique and every host must see the same ID for the other hosts * in the network. This is no longer fulfilled by simple IP addresses, but for * example for JIDs when sending XML messages over a jabber server. */ #include #include #include static const GEnumValue inf_xml_connection_status_values[] = { { INF_XML_CONNECTION_CLOSED, "INF_XML_CONNECTION_CLOSED", "closed" }, { INF_XML_CONNECTION_CLOSING, "INF_XML_CONNECTION_CLOSING", "closing" }, { INF_XML_CONNECTION_OPEN, "INF_XML_CONNECTION_OPEN", "open" }, { INF_XML_CONNECTION_OPENING, "INF_XML_CONNECTION_OPENING", "opening" }, { 0, NULL, NULL } }; INF_DEFINE_ENUM_TYPE(InfXmlConnectionStatus, inf_xml_connection_status, inf_xml_connection_status_values) G_DEFINE_INTERFACE(InfXmlConnection, inf_xml_connection, G_TYPE_OBJECT) enum { SENT, RECEIVED, ERROR, LAST_SIGNAL }; static guint connection_signals[LAST_SIGNAL]; static void inf_xml_connection_default_init(InfXmlConnectionInterface* iface) { /** * InfXmlConnection::sent: * @connection: The #InfXmlConnection through which @node has been sent * @node: An #xmlNodePtr refering to the XML node that has been sent * * Signal which is emitted when an XML node has been successfully * transmitted with this connection. */ connection_signals[SENT] = g_signal_new( "sent", INF_TYPE_XML_CONNECTION, G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfXmlConnectionInterface, sent), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER ); /** * InfXmlConnection::received: * @connection: The #InfXmlConnection through which @node has been received * @node: An #xmlNodePtr refering to the XML node that has been received * * Signal which is emitted when an XML node has been received by this * connection. */ connection_signals[RECEIVED] = g_signal_new( "received", INF_TYPE_XML_CONNECTION, G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfXmlConnectionInterface, received), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER ); /** * InfXmlConnection::error: * @connection: The erroneous #InfXmlConnection * @error: A pointer to a #GError object with details on the error * * This signal is emitted when an error occurs for this connection. * For example, if the connection cannot be established and the status * changes from %INF_XML_CONNECTION_OPENING to %INF_XML_CONNECTION_CLOSED, * then this signal is usually emitted with more details on the error. * * Note however that the error may or may not be fatal for the * connection. If it is fatal, then a status notify to * %INF_XML_CONNECTION_CLOSING or %INF_XML_CONNECTION_CLOSED will follow. */ connection_signals[ERROR] = g_signal_new( "error", INF_TYPE_XML_CONNECTION, G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfXmlConnectionInterface, error), NULL, NULL, g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE, 1, G_TYPE_ERROR ); g_object_interface_install_property( iface, g_param_spec_enum( "status", "XmlConnection Status", "The status of the connection.", INF_TYPE_XML_CONNECTION_STATUS, INF_XML_CONNECTION_CLOSED, G_PARAM_READABLE ) ); /* The network of a connection should not change through lifetime. All * users on a given network should be able to create direct connections * between each user. For example, 'jabber' might be such a network, * 'local' another one. All jabber user can have connections to other * jabber users, but not to those on a local network. */ g_object_interface_install_property( iface, g_param_spec_string( "network", "Network", "An identifier for the type of network this connection is on", NULL, G_PARAM_READABLE ) ); g_object_interface_install_property( iface, g_param_spec_string( "local-id", "Local ID", "A unique identification on the network for the local site", NULL, G_PARAM_READABLE ) ); g_object_interface_install_property( iface, g_param_spec_string( "remote-id", "Remote ID", "A unique identification on the network for the remote site", NULL, G_PARAM_READABLE ) ); g_object_interface_install_property( iface, g_param_spec_pointer( "local-certificate", "Local Certificate", "The X.509 certificate (gnutls_x509_crt_t) of the local site", G_PARAM_READABLE ) ); g_object_interface_install_property( iface, g_param_spec_boxed( "remote-certificate", "Remote Certificate", "The X.509 certificate of the remote site", INF_TYPE_CERTIFICATE_CHAIN, G_PARAM_READABLE ) ); } /** * inf_xml_connection_open: * @connection: A #infXmlConnection. * @error: Location to store error information, if any. * * Attempts to open the given XML connection. If the process fails, @error * will be set. The connection needs to be in status * %INF_XML_CONNECTION_CLOSED for this function to be called. Even if this * function succeeds, the connection process can fail later. In that case * the status of @connection will be reset to %INF_XML_CONNECTION_CLOSED * and the #InfXmlConnection::error signal will be emitted. * * Returns: %TRUE on succes, or %FALSE on error. */ gboolean inf_xml_connection_open(InfXmlConnection* connection, GError** error) { InfXmlConnectionInterface* iface; g_return_val_if_fail(INF_IS_XML_CONNECTION(connection), FALSE); g_return_val_if_fail(error == NULL || *error == NULL, FALSE); iface = INF_XML_CONNECTION_GET_IFACE(connection); g_return_val_if_fail(iface->open != NULL, FALSE); return iface->open(connection, error); } /** * inf_xml_connection_close: * @connection: A #InfXmlConnection. * * Closes the given connection. **/ void inf_xml_connection_close(InfXmlConnection* connection) { InfXmlConnectionInterface* iface; g_return_if_fail(INF_IS_XML_CONNECTION(connection)); iface = INF_XML_CONNECTION_GET_IFACE(connection); g_return_if_fail(iface->close != NULL); iface->close(connection); } /** * inf_xml_connection_send: * @connection: A #InfXmlConnection. * @xml: (transfer full): A XML message to send. The function takes ownership * of the XML node. * * Sends the given XML message to the remote host. **/ void inf_xml_connection_send(InfXmlConnection* connection, xmlNodePtr xml) { InfXmlConnectionInterface* iface; g_return_if_fail(INF_IS_XML_CONNECTION(connection)); g_return_if_fail(xml != NULL); iface = INF_XML_CONNECTION_GET_IFACE(connection); g_return_if_fail(iface->send != NULL); iface->send(connection, xml); } /** * inf_xml_connection_sent: * @connection: A #InfXmlConnection. * @xml: (transfer none): The XML message that has been sent. * * Emits the "sent" signal on @connection. This will most likely only be * useful to implementors. **/ void inf_xml_connection_sent(InfXmlConnection* connection, const xmlNodePtr xml) { g_return_if_fail(INF_IS_XML_CONNECTION(connection)); g_return_if_fail(xml != NULL); g_signal_emit( G_OBJECT(connection), connection_signals[SENT], 0, xml ); } /** * inf_xml_connection_received: * @connection: A #InfXmlConnection. * @xml: (transfer none): The XML message that has been received. * * Emits the "received" signal on @connection. This will most likely only * be useful to implementors. **/ void inf_xml_connection_received(InfXmlConnection* connection, const xmlNodePtr xml) { g_return_if_fail(INF_IS_XML_CONNECTION(connection)); g_return_if_fail(xml != NULL); g_signal_emit( G_OBJECT(connection), connection_signals[RECEIVED], 0, xml ); } /** * inf_xml_connection_error: * @connection: A #InfXmlConnection. * @error: The error that occured. * * Emits the "error" signal on @connection. This will most likely only * be useful to implementors. * * Note that the error may or may not be fatal for the connection. If it * is fatal, then a status notify to %INF_XML_CONNECTION_CLOSING or * %INF_XML_CONNECTION_CLOSED will follow. If you are implementing a custom * class implementing #InfXmlConnection, make sure to always emit the "error" * signal before doing the status notify because many users of the connection * will release their reference when the connection is no longer connected. **/ void inf_xml_connection_error(InfXmlConnection* connection, const GError* error) { g_return_if_fail(INF_IS_XML_CONNECTION(connection)); g_return_if_fail(error != NULL); g_signal_emit( G_OBJECT(connection), connection_signals[ERROR], 0, error ); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-tcp-connection.c0000644000000000000000000000013013034342512023247 xustar0029 mtime=1483851082.03771847 29 atime=1483851082.03771847 30 ctime=1488261589.084138882 libinfinity-0.7.1/libinfinity/common/inf-tcp-connection.c0000644000175000017500000013476713034342512024025 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-tcp-connection * @title: InfTcpConnection * @short_description: Represents a TCP-based connection to a remote host * @include: libinfinity/common/inf-tcp-connection.h * @stability: Unstable * * #InfTcpConnection represents a TCP connection to a remove host. It is a * wrapper around a native socket object and integrates into the main loop * provided by #InfIo. An arbitrary amount of data can be sent with the * object, extra data will be buffered and automatically transmitted once * kernel space becomes available. * * The TCP connection properties should be set and then * inf_tcp_connection_open() be called to open a connection. If the * #InfTcpConnection:resolver property is set, then * #InfTcpConnection:remote-address and #InfTcpConnection:remote-port are * ignored, and the hostname as configured in the resolver will be resolved. * When the hostname has been resolved and a connection has been made, the * #InfTcpConnection:remote-address and #InfTcpConnection:remote-port * properties are updated to reflect the address actually connected to. **/ #include #include #include #include #include #include #include #include #include #include /* For ssize_t */ #include "config.h" #ifndef G_OS_WIN32 # include # include # include # include # include # include # include # include # include #else # include #endif static const GEnumValue inf_tcp_connection_status_values[] = { { INF_TCP_CONNECTION_CONNECTING, "INF_TCP_CONNECTION_CONNECTING", "connecting" }, { INF_TCP_CONNECTION_CONNECTED, "INF_TCP_CONNECTION_CONNECTED", "connected" }, { INF_TCP_CONNECTION_CLOSED, "INF_TCP_CONNECTION_CLOSED", "closed" }, { 0, NULL, NULL } }; typedef struct _InfTcpConnectionPrivate InfTcpConnectionPrivate; struct _InfTcpConnectionPrivate { InfIo* io; InfIoEvent events; InfIoWatch* watch; InfNameResolver* resolver; guint resolver_index; InfTcpConnectionStatus status; InfNativeSocket socket; InfKeepalive keepalive; InfIpAddress* remote_address; guint remote_port; unsigned int device_index; guint8* queue; gsize front_pos; gsize back_pos; gsize alloc; }; enum { PROP_0, PROP_IO, PROP_RESOLVER, PROP_STATUS, PROP_KEEPALIVE, PROP_REMOTE_ADDRESS, PROP_REMOTE_PORT, PROP_LOCAL_ADDRESS, PROP_LOCAL_PORT, PROP_DEVICE_INDEX, PROP_DEVICE_NAME }; enum { SENT, RECEIVED, ERROR_, /* ERROR is a #define on Win32 */ LAST_SIGNAL }; #define INF_TCP_CONNECTION_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INF_TYPE_TCP_CONNECTION, InfTcpConnectionPrivate)) static guint tcp_connection_signals[LAST_SIGNAL]; INF_DEFINE_ENUM_TYPE(InfTcpConnectionStatus, inf_tcp_connection_status, inf_tcp_connection_status_values) G_DEFINE_TYPE_WITH_CODE(InfTcpConnection, inf_tcp_connection, G_TYPE_OBJECT, G_ADD_PRIVATE(InfTcpConnection)) static gboolean inf_tcp_connection_addr_info(InfNativeSocket socket, gboolean local, InfIpAddress** address, guint* port, GError** error) { union { struct sockaddr in_generic; struct sockaddr_in in; struct sockaddr_in6 in6; } native_addr; socklen_t len; int res; int code; len = sizeof(native_addr); if(local == TRUE) res = getsockname(socket, &native_addr.in_generic, &len); else res = getpeername(socket, &native_addr.in_generic, &len); if(res == -1) { code = INF_NATIVE_SOCKET_LAST_ERROR; inf_native_socket_make_error(code, error); return FALSE; } switch(native_addr.in_generic.sa_family) { case AF_INET: if(address != NULL) *address = inf_ip_address_new_raw4(native_addr.in.sin_addr.s_addr); if(port != NULL) *port = ntohs(native_addr.in.sin_port); break; case AF_INET6: if(address != NULL) *address = inf_ip_address_new_raw6(native_addr.in6.sin6_addr.s6_addr); if(port != NULL) *port = ntohs(native_addr.in6.sin6_port); break; default: g_assert_not_reached(); break; } return TRUE; } static gboolean inf_tcp_connection_configure_socket(InfNativeSocket socket, const InfKeepalive* keepalive, GError** error) { #ifdef G_OS_WIN32 u_long argp; #else int result; #endif int errcode; GError* local_error; /* Configure the connection's underlying socket, by setting keepalive and * and nonblocking. */ #ifndef G_OS_WIN32 result = fcntl(socket, F_GETFL); if(result == INVALID_SOCKET) { errcode = INF_NATIVE_SOCKET_LAST_ERROR; inf_native_socket_make_error(errcode, error); return FALSE; } if(fcntl(socket, F_SETFL, result | O_NONBLOCK) == -1) { errcode = INF_NATIVE_SOCKET_LAST_ERROR; inf_native_socket_make_error(errcode, error); return FALSE; } #else argp = 1; if(ioctlsocket(socket, FIONBIO, &argp) != 0) { errcode = INF_NATIVE_SOCKET_LAST_ERROR; inf_native_socket_make_error(errcode, error); return FALSE; } #endif /* Error setting keepalives is not fatal */ local_error = NULL; if(inf_keepalive_apply(keepalive, &socket, 0, &local_error) == FALSE) { g_warning("Failed to set keepalive on socket: %s", local_error->message); g_error_free(local_error); } return TRUE; } static void inf_tcp_connection_system_error(InfTcpConnection* connection, int code) { GError* error; error = NULL; inf_native_socket_make_error(code, &error); g_signal_emit( G_OBJECT(connection), tcp_connection_signals[ERROR_], 0, error ); g_error_free(error); } static void inf_tcp_connection_io(InfNativeSocket* socket, InfIoEvent events, gpointer user_data); static void inf_tcp_connection_connected(InfTcpConnection* connection) { InfTcpConnectionPrivate* priv; priv = INF_TCP_CONNECTION_PRIVATE(connection); priv->status = INF_TCP_CONNECTION_CONNECTED; priv->front_pos = 0; priv->back_pos = 0; priv->events = INF_IO_INCOMING | INF_IO_ERROR; if(priv->watch == NULL) { priv->watch = inf_io_add_watch( priv->io, &priv->socket, priv->events, inf_tcp_connection_io, connection, NULL ); } else { inf_io_update_watch(priv->io, priv->watch, priv->events); } g_object_freeze_notify(G_OBJECT(connection)); /* Update adresses from resolver */ if(priv->resolver != NULL) { if(priv->remote_address != NULL) inf_ip_address_free(priv->remote_address); priv->remote_address = inf_ip_address_copy( inf_name_resolver_get_address(priv->resolver, priv->resolver_index) ); priv->remote_port = inf_name_resolver_get_port(priv->resolver, priv->resolver_index); g_object_notify(G_OBJECT(connection), "remote-address"); g_object_notify(G_OBJECT(connection), "remote-port"); priv->resolver_index = 0; } g_object_notify(G_OBJECT(connection), "status"); g_object_notify(G_OBJECT(connection), "local-address"); g_object_notify(G_OBJECT(connection), "local-port"); g_object_thaw_notify(G_OBJECT(connection)); } static gboolean inf_tcp_connection_open_with_resolver(InfTcpConnection* connection, GError** error); /* Handles when an error occurred during connection. Returns FALSE when the * error was fatal. In this case, it has already emitted the "error" signal. * Returns TRUE, if another connection attempt is made. */ static gboolean inf_tcp_connection_connection_error(InfTcpConnection* connection, const GError* error) { InfTcpConnectionPrivate* priv; priv = INF_TCP_CONNECTION_PRIVATE(connection); if(priv->socket != INVALID_SOCKET) { closesocket(priv->socket); priv->socket = INVALID_SOCKET; } if(priv->watch != NULL) { priv->events = 0; inf_io_remove_watch(priv->io, priv->watch); priv->watch = NULL; } if(priv->resolver != NULL) { /* Try next address, if there is one */ if(priv->resolver_index < inf_name_resolver_get_n_addresses(priv->resolver)) { ++priv->resolver_index; if(inf_tcp_connection_open_with_resolver(connection, NULL) == TRUE) return TRUE; } /* No new addresses available */ priv->resolver_index = 0; } g_signal_emit( G_OBJECT(connection), tcp_connection_signals[ERROR_], 0, error ); return FALSE; } static gboolean inf_tcp_connection_open_real(InfTcpConnection* connection, const InfIpAddress* address, guint port, GError** error) { InfTcpConnectionPrivate* priv; union { struct sockaddr_in in; struct sockaddr_in6 in6; } native_address; struct sockaddr* addr; socklen_t addrlen; int result; int errcode; const InfKeepalive* keepalive; GError* local_error; priv = INF_TCP_CONNECTION_PRIVATE(connection); g_assert(priv->status == INF_TCP_CONNECTION_CLOSED || priv->status == INF_TCP_CONNECTION_CONNECTING); /* Close previous socket */ if(priv->socket != INVALID_SOCKET) closesocket(priv->socket); switch(inf_ip_address_get_family(address)) { case INF_IP_ADDRESS_IPV4: priv->socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); addr = (struct sockaddr*)&native_address.in; addrlen = sizeof(struct sockaddr_in); memcpy( &native_address.in.sin_addr, inf_ip_address_get_raw(address), sizeof(struct in_addr) ); native_address.in.sin_family = AF_INET; native_address.in.sin_port = htons(port); break; case INF_IP_ADDRESS_IPV6: priv->socket = socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP); addr = (struct sockaddr*)&native_address.in6; addrlen = sizeof(struct sockaddr_in6); memcpy( &native_address.in6.sin6_addr, inf_ip_address_get_raw(address), sizeof(struct in6_addr) ); native_address.in6.sin6_family = AF_INET6; native_address.in6.sin6_port = htons(port); native_address.in6.sin6_flowinfo = 0; native_address.in6.sin6_scope_id = priv->device_index; break; default: g_assert_not_reached(); break; } if(priv->socket == INVALID_SOCKET) { inf_native_socket_make_error(INF_NATIVE_SOCKET_LAST_ERROR, error); return FALSE; } /* Set socket non-blocking and keepalive */ keepalive = &priv->keepalive; if(!inf_tcp_connection_configure_socket(priv->socket, keepalive, error)) { closesocket(priv->socket); priv->socket = INVALID_SOCKET; return FALSE; } /* Connect */ do { result = connect(priv->socket, addr, addrlen); errcode = INF_NATIVE_SOCKET_LAST_ERROR; if(result == -1 && errcode != INF_NATIVE_SOCKET_EINTR && errcode != INF_NATIVE_SOCKET_EINPROGRESS) { local_error = NULL; inf_native_socket_make_error(errcode, &local_error); if(inf_tcp_connection_connection_error(connection, local_error) == TRUE) { /* In this case, we could recover from the error by connecting to a * different address. */ g_error_free(local_error); return TRUE; } g_propagate_error(error, local_error); return FALSE; } } while(result == -1 && errcode != INF_NATIVE_SOCKET_EINPROGRESS); if(result == 0) { /* Connection fully established */ inf_tcp_connection_connected(connection); } else { g_assert(priv->watch == NULL); /* Connection establishment in progress */ priv->events = INF_IO_OUTGOING | INF_IO_ERROR; priv->watch = inf_io_add_watch( priv->io, &priv->socket, priv->events, inf_tcp_connection_io, connection, NULL ); if(priv->status != INF_TCP_CONNECTION_CONNECTING) { priv->status = INF_TCP_CONNECTION_CONNECTING; g_object_notify(G_OBJECT(connection), "status"); } } return TRUE; } static gboolean inf_tcp_connection_open_with_resolver(InfTcpConnection* connection, GError** error) { InfTcpConnectionPrivate* priv; GError* local_error; gboolean success; priv = INF_TCP_CONNECTION_PRIVATE(connection); g_assert(priv->status == INF_TCP_CONNECTION_CLOSED || priv->status == INF_TCP_CONNECTION_CONNECTING); if(inf_name_resolver_finished(priv->resolver)) { if(priv->resolver_index < inf_name_resolver_get_n_addresses(priv->resolver)) { return inf_tcp_connection_open_real( connection, inf_name_resolver_get_address(priv->resolver, priv->resolver_index), inf_name_resolver_get_port(priv->resolver, priv->resolver_index), error ); } /* We need to look up more addresses */ g_object_freeze_notify(G_OBJECT(connection)); if(priv->status != INF_TCP_CONNECTION_CONNECTING) { priv->status = INF_TCP_CONNECTION_CONNECTING; g_object_notify(G_OBJECT(connection), "status"); } local_error = NULL; if(priv->resolver_index == 0) success = inf_name_resolver_start(priv->resolver, &local_error); else success = inf_name_resolver_lookup_backup(priv->resolver, &local_error); if(local_error != NULL) { inf_tcp_connection_connection_error(connection, local_error); g_propagate_error(error, local_error); } g_object_thaw_notify(G_OBJECT(connection)); return success; } /* The resolver is currently doing something. Wait until it finishes, and * then try again. */ return TRUE; } static gboolean inf_tcp_connection_send_real(InfTcpConnection* connection, gconstpointer data, guint* len) { InfTcpConnectionPrivate* priv; gconstpointer send_data; guint send_len; int errcode; ssize_t result; priv = INF_TCP_CONNECTION_PRIVATE(connection); g_assert(priv->status == INF_TCP_CONNECTION_CONNECTED); g_assert(data != NULL); g_assert(len != NULL); send_data = data; send_len = *len; do { result = send( priv->socket, send_data, send_len, INF_NATIVE_SOCKET_SENDRECV_FLAGS ); /* Preserve error code so that it is not modified by future calls */ errcode = INF_NATIVE_SOCKET_LAST_ERROR; if(result < 0 && errcode != INF_NATIVE_SOCKET_EINTR && errcode != INF_NATIVE_SOCKET_EAGAIN) { inf_tcp_connection_system_error(connection, errcode); return FALSE; } else if(result == 0) { inf_tcp_connection_close(connection); return FALSE; } else if(result > 0) { send_data = (const char*)send_data + result; send_len -= result; } } while( (send_len > 0) && (result > 0 || errcode == INF_NATIVE_SOCKET_EINTR) && (priv->socket != INVALID_SOCKET) ); *len -= send_len; return TRUE; } static void inf_tcp_connection_io_incoming(InfTcpConnection* connection) { InfTcpConnectionPrivate* priv; gchar buf[2048]; int errcode; ssize_t result; priv = INF_TCP_CONNECTION_PRIVATE(connection); g_assert(priv->status == INF_TCP_CONNECTION_CONNECTED); do { result = recv(priv->socket, buf, 2048, INF_NATIVE_SOCKET_SENDRECV_FLAGS); errcode = INF_NATIVE_SOCKET_LAST_ERROR; if(result < 0 && errcode != INF_NATIVE_SOCKET_EINTR && errcode != INF_NATIVE_SOCKET_EAGAIN) { inf_tcp_connection_system_error(connection, errcode); } else if(result == 0) { inf_tcp_connection_close(connection); } else if(result > 0) { g_signal_emit( G_OBJECT(connection), tcp_connection_signals[RECEIVED], 0, buf, (guint)result ); } } while( ((result > 0) || (result < 0 && errcode == INF_NATIVE_SOCKET_EINTR)) && (priv->status != INF_TCP_CONNECTION_CLOSED)); } static void inf_tcp_connection_io_outgoing(InfTcpConnection* connection) { InfTcpConnectionPrivate* priv; socklen_t len; int errcode; gconstpointer data; guint data_len; priv = INF_TCP_CONNECTION_PRIVATE(connection); switch(priv->status) { case INF_TCP_CONNECTION_CONNECTING: len = sizeof(int); #ifdef G_OS_WIN32 getsockopt(priv->socket, SOL_SOCKET, SO_ERROR, (char*)&errcode, &len); #else getsockopt(priv->socket, SOL_SOCKET, SO_ERROR, &errcode, &len); #endif if(errcode == 0) { inf_tcp_connection_connected(connection); } else { inf_tcp_connection_system_error(connection, errcode); } break; case INF_TCP_CONNECTION_CONNECTED: g_assert(priv->back_pos < priv->front_pos); g_assert(priv->events & INF_IO_OUTGOING); data = priv->queue + priv->back_pos; data_len = priv->front_pos - priv->back_pos; if(inf_tcp_connection_send_real(connection, data, &data_len) == TRUE) { priv->back_pos += data_len; if(priv->front_pos == priv->back_pos) { /* sent everything */ priv->front_pos = 0; priv->back_pos = 0; priv->events &= ~INF_IO_OUTGOING; inf_io_update_watch(priv->io, priv->watch, priv->events); } g_signal_emit( G_OBJECT(connection), tcp_connection_signals[SENT], 0, data, data_len ); } break; case INF_TCP_CONNECTION_CLOSED: default: g_assert_not_reached(); break; } } static void inf_tcp_connection_io(InfNativeSocket* socket, InfIoEvent events, gpointer user_data) { InfTcpConnection* connection; InfTcpConnectionPrivate* priv; socklen_t len; int errcode; GError* error; connection = INF_TCP_CONNECTION(user_data); priv = INF_TCP_CONNECTION_PRIVATE(connection); g_object_ref(G_OBJECT(connection)); g_assert(priv->status != INF_TCP_CONNECTION_CLOSED); if(events & INF_IO_ERROR) { len = sizeof(int); #ifdef G_OS_WIN32 getsockopt(priv->socket, SOL_SOCKET, SO_ERROR, (char*)&errcode, &len); #else getsockopt(priv->socket, SOL_SOCKET, SO_ERROR, &errcode, &len); #endif /* On Windows, we get INF_IO_ERROR on disconnection (at least with the * InfGtkIo, because FD_CLOSE is mapped to G_IO_HUP) with errcode * being 0. */ /* TODO: Maybe we should change this by mapping G_IO_HUP to * INF_IO_INCOMING, hoping recv() does the right thing then. */ if(errcode != 0) { error = NULL; inf_native_socket_make_error(errcode, &error); if(priv->status == INF_TCP_CONNECTION_CONNECTING) { inf_tcp_connection_connection_error(connection, error); } else { g_signal_emit( G_OBJECT(connection), tcp_connection_signals[ERROR_], 0, error ); } /* Error has been reported via signal emission, and there is nothing * else to do with it. */ g_error_free(error); } else { inf_tcp_connection_close(connection); } } else { if(events & INF_IO_INCOMING) { inf_tcp_connection_io_incoming(connection); } /* It may happen that the above closes the connection and we received * events for both INCOMING & OUTGOING here. */ if((priv->status != INF_TCP_CONNECTION_CLOSED) && (events & INF_IO_OUTGOING)) { inf_tcp_connection_io_outgoing(connection); } } g_object_unref(G_OBJECT(connection)); } static void inf_tcp_connection_resolved_cb(InfNameResolver* resolver, const GError* error, gpointer user_data) { InfTcpConnection* connection; InfTcpConnectionPrivate* priv; connection = INF_TCP_CONNECTION(user_data); priv = INF_TCP_CONNECTION_PRIVATE(connection); /* Note that the connection could even be closed here, namely if * tcp_connection_close() was called while we are still resolving. */ if(priv->status == INF_TCP_CONNECTION_CONNECTING) { if(error != NULL) { /* If there was an error, no additional addresses are available */ g_assert( priv->resolver_index == inf_name_resolver_get_n_addresses(resolver) ); inf_tcp_connection_connection_error(connection, error); } else { /* If there was no error, try opening a connection to the resolved * address(es). */ inf_tcp_connection_open_with_resolver(connection, NULL); } } } static void inf_tcp_connection_set_resolver(InfTcpConnection* connection, InfNameResolver* resolver) { InfTcpConnectionPrivate* priv; priv = INF_TCP_CONNECTION_PRIVATE(connection); if(priv->resolver != NULL) { inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->resolver), G_CALLBACK(inf_tcp_connection_resolved_cb), connection ); g_object_unref(priv->resolver); } priv->resolver = resolver; if(resolver != NULL) { g_object_ref(resolver); g_signal_connect( G_OBJECT(resolver), "resolved", G_CALLBACK(inf_tcp_connection_resolved_cb), connection ); } } static void inf_tcp_connection_init(InfTcpConnection* connection) { InfTcpConnectionPrivate* priv; priv = INF_TCP_CONNECTION_PRIVATE(connection); priv->io = NULL; priv->events = 0; priv->watch = NULL; priv->resolver = NULL; priv->resolver_index = 0; priv->status = INF_TCP_CONNECTION_CLOSED; priv->socket = INVALID_SOCKET; priv->keepalive.mask = 0; priv->remote_address = NULL; priv->remote_port = 0; priv->device_index = 0; priv->queue = g_malloc(1024); priv->front_pos = 0; priv->back_pos = 0; priv->alloc = 1024; } static void inf_tcp_connection_dispose(GObject* object) { InfTcpConnection* connection; InfTcpConnectionPrivate* priv; connection = INF_TCP_CONNECTION(object); priv = INF_TCP_CONNECTION_PRIVATE(connection); if(priv->status != INF_TCP_CONNECTION_CLOSED) inf_tcp_connection_close(connection); inf_tcp_connection_set_resolver(connection, NULL); if(priv->io != NULL) { g_object_unref(priv->io); priv->io = NULL; } G_OBJECT_CLASS(inf_tcp_connection_parent_class)->dispose(object); } static void inf_tcp_connection_finalize(GObject* object) { InfTcpConnection* connection; InfTcpConnectionPrivate* priv; connection = INF_TCP_CONNECTION(object); priv = INF_TCP_CONNECTION_PRIVATE(connection); if(priv->remote_address != NULL) inf_ip_address_free(priv->remote_address); if(priv->socket != INVALID_SOCKET) closesocket(priv->socket); g_free(priv->queue); G_OBJECT_CLASS(inf_tcp_connection_parent_class)->finalize(object); } static void inf_tcp_connection_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfTcpConnection* connection; InfTcpConnectionPrivate* priv; #ifndef G_OS_WIN32 const gchar* device_string; unsigned int new_index; #endif GError* error; connection = INF_TCP_CONNECTION(object); priv = INF_TCP_CONNECTION_PRIVATE(connection); switch(prop_id) { case PROP_IO: g_assert(priv->status == INF_TCP_CONNECTION_CLOSED); if(priv->io != NULL) g_object_unref(G_OBJECT(priv->io)); priv->io = INF_IO(g_value_dup_object(value)); break; case PROP_RESOLVER: g_assert(priv->status == INF_TCP_CONNECTION_CLOSED); inf_tcp_connection_set_resolver( connection, INF_NAME_RESOLVER(g_value_get_object(value)) ); break; case PROP_KEEPALIVE: error = NULL; inf_tcp_connection_set_keepalive( connection, (InfKeepalive*)g_value_get_boxed(value), &error ); if(error != NULL) { g_warning("Failed to set keepalive settings: %s\n", error->message); g_error_free(error); } break; case PROP_REMOTE_ADDRESS: g_assert(priv->status == INF_TCP_CONNECTION_CLOSED); if(priv->remote_address != NULL) inf_ip_address_free(priv->remote_address); priv->remote_address = (InfIpAddress*)g_value_dup_boxed(value); break; case PROP_REMOTE_PORT: g_assert(priv->status == INF_TCP_CONNECTION_CLOSED); priv->remote_port = g_value_get_uint(value); break; case PROP_DEVICE_INDEX: g_assert(priv->status == INF_TCP_CONNECTION_CLOSED); /* TODO: Verify that such a device exists */ priv->device_index = g_value_get_uint(value); g_object_notify(G_OBJECT(object), "device-name"); break; case PROP_DEVICE_NAME: #ifdef G_OS_WIN32 /* TODO: We can probably implement this using GetInterfaceInfo() */ g_warning("The device-name property is not implemented on Win32"); #else g_assert(priv->status == INF_TCP_CONNECTION_CLOSED); device_string = g_value_get_string(value); if(device_string == NULL) priv->device_index = 0; new_index = if_nametoindex(device_string); if(new_index == 0) { g_warning(_("Interface `%s' does not exist"), device_string); } else { priv->device_index = new_index; g_object_notify(G_OBJECT(object), "device-index"); } #endif break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void inf_tcp_connection_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfTcpConnection* connection; InfTcpConnectionPrivate* priv; InfIpAddress* address; guint port; GError* error; #ifndef G_OS_WIN32 char device_name[IF_NAMESIZE]; #endif connection = INF_TCP_CONNECTION(object); priv = INF_TCP_CONNECTION_PRIVATE(connection); switch(prop_id) { case PROP_IO: g_value_set_object(value, G_OBJECT(priv->io)); break; case PROP_RESOLVER: g_value_set_object(value, G_OBJECT(priv->resolver)); break; case PROP_KEEPALIVE: g_value_set_boxed(value, &priv->keepalive); break; case PROP_STATUS: g_value_set_enum(value, priv->status); break; case PROP_REMOTE_ADDRESS: g_value_set_static_boxed(value, priv->remote_address); break; case PROP_REMOTE_PORT: g_value_set_uint(value, priv->remote_port); break; case PROP_LOCAL_ADDRESS: g_assert(priv->socket != INVALID_SOCKET); error = NULL; inf_tcp_connection_addr_info(priv->socket, TRUE, &address, NULL, &error); if(error != NULL) { g_warning(_("Failed to retrieve local address: %s"), error->message); g_error_free(error); g_value_set_boxed(value, NULL); } else { g_value_take_boxed(value, address); } break; case PROP_LOCAL_PORT: g_assert(priv->socket != INVALID_SOCKET); error = NULL; inf_tcp_connection_addr_info(priv->socket, TRUE, NULL, &port, &error); if(error != NULL) { g_warning(_("Failed to retrieve local port: %s"), error->message); g_error_free(error); g_value_set_uint(value, 0); } else { g_value_set_uint(value, port); } break; case PROP_DEVICE_INDEX: g_value_set_uint(value, priv->device_index); break; case PROP_DEVICE_NAME: #ifdef G_OS_WIN32 /* TODO: We can probably implement this using GetInterfaceInfo() */ g_warning(_("The device-name property is not implemented on Win32")); g_value_set_string(value, NULL); #else if(priv->device_index == 0) { g_value_set_string(value, NULL); } else { if(if_indextoname(priv->device_index, device_name) == NULL) { g_warning( /* Failed to get name for device : */ _("Failed to get name for device %u: %s"), priv->device_index, strerror(errno) ); g_value_set_string(value, NULL); } else { g_value_set_string(value, device_name); } } #endif break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void inf_tcp_connection_error(InfTcpConnection* connection, GError* error) { InfTcpConnectionPrivate* priv; priv = INF_TCP_CONNECTION_PRIVATE(connection); /* Normally, it would be enough to check one of both conditions, but socket * may be already set with status still being CLOSED during * inf_tcp_connection_open(). */ if(priv->watch != NULL) { priv->events = 0; inf_io_remove_watch(priv->io, priv->watch); priv->watch = NULL; } if(priv->status != INF_TCP_CONNECTION_CLOSED) { priv->status = INF_TCP_CONNECTION_CLOSED; g_object_notify(G_OBJECT(connection), "status"); } } static void inf_tcp_connection_class_init(InfTcpConnectionClass* tcp_connection_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(tcp_connection_class); object_class->dispose = inf_tcp_connection_dispose; object_class->finalize = inf_tcp_connection_finalize; object_class->set_property = inf_tcp_connection_set_property; object_class->get_property = inf_tcp_connection_get_property; tcp_connection_class->sent = NULL; tcp_connection_class->received = NULL; tcp_connection_class->error = inf_tcp_connection_error; g_object_class_install_property( object_class, PROP_IO, g_param_spec_object( "io", "IO", "I/O handler", INF_TYPE_IO, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_RESOLVER, g_param_spec_object( "resolver", "Resolver", "The hostname resolver", INF_TYPE_NAME_RESOLVER, G_PARAM_READWRITE | G_PARAM_CONSTRUCT ) ); g_object_class_install_property( object_class, PROP_STATUS, g_param_spec_enum( "status", "Status", "Status of the TCP connection", INF_TYPE_TCP_CONNECTION_STATUS, INF_TCP_CONNECTION_CLOSED, G_PARAM_READABLE ) ); g_object_class_install_property( object_class, PROP_KEEPALIVE, g_param_spec_boxed( "keepalive", "Keepalive", "The keepalive settings for the connection", INF_TYPE_KEEPALIVE, G_PARAM_READWRITE ) ); g_object_class_install_property( object_class, PROP_REMOTE_ADDRESS, g_param_spec_boxed( "remote-address", "Remote address", "Address to connect to", INF_TYPE_IP_ADDRESS, G_PARAM_READWRITE ) ); g_object_class_install_property( object_class, PROP_REMOTE_PORT, g_param_spec_uint( "remote-port", "Remote port", "Port to connect to", 0, 65535, 0, G_PARAM_READWRITE ) ); g_object_class_install_property( object_class, PROP_LOCAL_ADDRESS, g_param_spec_boxed( "local-address", "Local address", "The local address of the connection", INF_TYPE_IP_ADDRESS, G_PARAM_READABLE ) ); g_object_class_install_property( object_class, PROP_LOCAL_PORT, g_param_spec_uint( "local-port", "Local port", "The local port of the connection", 0, 65535, 0, G_PARAM_READABLE ) ); g_object_class_install_property( object_class, PROP_DEVICE_INDEX, g_param_spec_uint( "device-index", "Device index", "The index of the device to use for the connection", 0, G_MAXUINT, 0, G_PARAM_READWRITE ) ); g_object_class_install_property( object_class, PROP_DEVICE_NAME, g_param_spec_string( "device-name", "Device name", "The name of the device to use for the connection, such as `eth0'", NULL, G_PARAM_READWRITE ) ); /** * InfTcpConnection::sent: * @connection: The #InfTcpConnection through which the data has been sent. * @data: A #gpointer refering to the data that has been sent. * @length: A #guint holding the number of bytes that has been sent. * * This signal is emitted whenever data has been sent over the connection. */ tcp_connection_signals[SENT] = g_signal_new( "sent", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfTcpConnectionClass, sent), NULL, NULL, NULL, G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_UINT ); /** * InfTcpConnection::received: * @connection: The #InfTcpConnection through which the data has been * received. * @data: A #gpointer refering to the data that has been received. * @length: A #guint holding the number of bytes that has been received. * * This signal is emitted whenever data has been received from the * connection. */ tcp_connection_signals[RECEIVED] = g_signal_new( "received", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfTcpConnectionClass, received), NULL, NULL, NULL, G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_UINT ); /** * InfTcpConnection::error: * @connection: The erroneous #InfTcpConnection. * @error: A pointer to a #GError object with details on the error. * * This signal is emitted when an error occured with the connection. If the * error is fatal, the connection will change its status to * %INF_TCP_CONNECTION_CLOSED. */ tcp_connection_signals[ERROR_] = g_signal_new( "error", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfTcpConnectionClass, error), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_ERROR ); } /** * inf_tcp_connection_new: (constructor) * @io: A #InfIo object used to watch for activity. * @remote_addr: The address to eventually connect to. * @remote_port: The port to eventually connect to. * * Creates a new #InfTcpConnection. The arguments are stored as properties for * an eventual inf_tcp_connection_open() call, this function itself does not * establish a connection. * * Returns: (transfer full): A new #InfTcpConnection. Free with * g_object_unref(). **/ InfTcpConnection* inf_tcp_connection_new(InfIo* io, const InfIpAddress* remote_addr, guint remote_port) { InfTcpConnection* tcp; g_return_val_if_fail(INF_IS_IO(io), NULL); g_return_val_if_fail(remote_addr != NULL, NULL); g_return_val_if_fail(remote_port <= 65535, NULL); tcp = INF_TCP_CONNECTION( g_object_new( INF_TYPE_TCP_CONNECTION, "io", io, "remote-address", remote_addr, "remote-port", remote_port, NULL ) ); return tcp; } /** * inf_tcp_connection_new_and_open: (constructor) * @io: A #InfIo object used to watch for activity. * @remote_addr: The address to connect to. * @remote_port: The port to connect to. * @error: Location to store error information. * * Creates a new #InfTcpConnection and connects it to the given TCP endpoint. * Like inf_tcp_connection_new(), but calls inf_tcp_connection_open(). * * Returns: (transfer full): A new #InfTcpConnection, or %NULL on error. * Free with g_object_unref(). **/ InfTcpConnection* inf_tcp_connection_new_and_open(InfIo* io, const InfIpAddress* remote_addr, guint remote_port, GError** error) { InfTcpConnection* tcp; g_return_val_if_fail(INF_IS_IO(io), NULL); g_return_val_if_fail(remote_addr != NULL, NULL); g_return_val_if_fail(remote_port <= 65535, NULL); g_return_val_if_fail(error == NULL || *error == NULL, NULL); tcp = inf_tcp_connection_new(io, remote_addr, remote_port); if(inf_tcp_connection_open(tcp, error) == FALSE) { g_object_unref(tcp); return NULL; } return tcp; } /** * inf_tcp_connection_new_resolve: (constructor) * @io: A #InfIo object used to watch for activity. * @resolver: The hostname resolver object used to look up the remote * hostname. * * Creates a new #InfTcpConnection and instead of setting the remote IP * address and port number directly, a hostname resolver is used to look up * the remote hostname before connecting. This has the advantage that all * available addresses for that hostname are tried before giving up. * * The argument is stored as a property for an eventual * inf_tcp_connection_open() call, this function itself does not * establish a connection. * * Returns: (transfer full): A new #InfTcpConnection. Free with * g_object_unref(). */ InfTcpConnection* inf_tcp_connection_new_resolve(InfIo* io, InfNameResolver* resolver) { InfTcpConnection* tcp; g_return_val_if_fail(INF_IS_IO(io), NULL); g_return_val_if_fail(INF_IS_NAME_RESOLVER(resolver), NULL); tcp = INF_TCP_CONNECTION( g_object_new( INF_TYPE_TCP_CONNECTION, "io", io, "resolver", resolver, NULL ) ); return tcp; } /** * inf_tcp_connection_open: * @connection: A #InfTcpConnection. * @error: Location to store error information. * * Attempts to open @connection. Make sure to have set the "remote-address" * and "remote-port" property before calling this function. If an error * occurs, the function returns %FALSE and @error is set. Note however that * the connection might not be fully open when the function returns * (check the "status" property if you need to know). If an asynchronous * error occurs while the connection is being opened, the "error" signal * is emitted. * * Returns: %FALSE if an error occured and %TRUE otherwise. **/ gboolean inf_tcp_connection_open(InfTcpConnection* connection, GError** error) { InfTcpConnectionPrivate* priv; g_return_val_if_fail(INF_IS_TCP_CONNECTION(connection), FALSE); priv = INF_TCP_CONNECTION_PRIVATE(connection); g_return_val_if_fail(priv->io != NULL, FALSE); g_return_val_if_fail(priv->status == INF_TCP_CONNECTION_CLOSED, FALSE); g_return_val_if_fail( priv->remote_address != NULL || priv->resolver != NULL, FALSE ); g_return_val_if_fail( priv->remote_port != 0 || priv->resolver != NULL, FALSE ); if(priv->resolver != NULL) { g_assert(priv->resolver_index == 0); return inf_tcp_connection_open_with_resolver(connection, error); } else { return inf_tcp_connection_open_real( connection, priv->remote_address, priv->remote_port, error ); } } /** * inf_tcp_connection_close: * @connection: A #InfTcpConnection. * * Closes a TCP connection that is either open or currently connecting. **/ void inf_tcp_connection_close(InfTcpConnection* connection) { InfTcpConnectionPrivate* priv; g_return_if_fail(INF_IS_TCP_CONNECTION(connection)); priv = INF_TCP_CONNECTION_PRIVATE(connection); g_return_if_fail(priv->status != INF_TCP_CONNECTION_CLOSED); priv->events = 0; if(priv->watch != NULL) { inf_io_remove_watch(priv->io, priv->watch); priv->watch = NULL; } priv->front_pos = 0; priv->back_pos = 0; priv->status = INF_TCP_CONNECTION_CLOSED; g_object_notify(G_OBJECT(connection), "status"); } /** * inf_tcp_connection_send: * @connection: A #InfTcpConnection with status %INF_TCP_CONNECTION_CONNECTED. * @data: (type guint8*) (array length=len): The data to send. * @len: Number of bytes to send. * * Sends data through the TCP connection. The data is not sent immediately, * but enqueued to a buffer and will be sent as soon as kernel space * becomes available. The "sent" signal will be emitted when data has * really been sent. **/ void inf_tcp_connection_send(InfTcpConnection* connection, gconstpointer data, guint len) { InfTcpConnectionPrivate* priv; gconstpointer sent_data; guint sent_len; g_return_if_fail(INF_IS_TCP_CONNECTION(connection)); g_return_if_fail(len == 0 || data != NULL); priv = INF_TCP_CONNECTION_PRIVATE(connection); g_return_if_fail(priv->status == INF_TCP_CONNECTION_CONNECTED); g_object_ref(connection); /* Check whether we have data currently queued. If we have, then we need * to wait until that data has been sent before sending the new data. */ if(priv->front_pos == priv->back_pos) { /* Must not be set, because otherwise we would need something to send, * but there is nothing in the queue. */ g_assert(~priv->events & INF_IO_OUTGOING); /* Nothing in queue, send data directly. */ sent_len = len; sent_data = data; if(inf_tcp_connection_send_real(connection, data, &sent_len) == TRUE) { data = (const char*)data + sent_len; len -= sent_len; } else { /* Sending failed. The error signal has been emitted. */ /* Set len to zero so that we don't enqueue data. */ len = 0; sent_len = 0; } } else { /* Nothing sent */ sent_len = 0; } /* If we couldn't send all the data... */ if(len > 0) { /* If we have not enough space for the new data, move queue data back * onto the beginning of the queue, if not already */ if(priv->alloc - priv->front_pos < len && priv->back_pos > 0) { memmove( priv->queue, priv->queue + priv->back_pos, priv->front_pos - priv->back_pos ); priv->front_pos -= priv->back_pos; priv->back_pos = 0; } /* Allocate more memory if there is still not enough space */ if(priv->alloc - priv->front_pos < len) { /* Make sure we allocate enough */ priv->alloc = priv->front_pos + len; /* Always allocate a multiple of 1024 */ if(priv->alloc % 1024 != 0) priv->alloc = priv->alloc + (1024 - priv->alloc % 1024); priv->queue = g_realloc(priv->queue, priv->alloc); } memcpy(priv->queue + priv->front_pos, data, len); priv->front_pos += len; if(~priv->events & INF_IO_OUTGOING) { priv->events |= INF_IO_OUTGOING; inf_io_update_watch(priv->io, priv->watch, priv->events); } } if(sent_len > 0) { g_signal_emit( G_OBJECT(connection), tcp_connection_signals[SENT], 0, sent_data, sent_len ); } g_object_unref(connection); } /** * inf_tcp_connection_get_remote_address: * @connection: A #InfTcpConnection. * * Returns the IP address of the remote site. * * Returns: (transfer none): A #InfIpAddress owned by @connection. You do not * need to free it, but need to make your own copy if you want to keep it * longer than @connection's lifetime. **/ InfIpAddress* inf_tcp_connection_get_remote_address(InfTcpConnection* connection) { g_return_val_if_fail(INF_IS_TCP_CONNECTION(connection), NULL); return INF_TCP_CONNECTION_PRIVATE(connection)->remote_address; } /** * inf_tcp_connection_get_remote_port: * @connection: A #InfTcpConnection. * * Returns the port of the remote site to which @connection is (or was) * connected or connecting. * * Returns: The port of the remote site. **/ guint inf_tcp_connection_get_remote_port(InfTcpConnection* connection) { g_return_val_if_fail(INF_IS_TCP_CONNECTION(connection), 0); return INF_TCP_CONNECTION_PRIVATE(connection)->remote_port; } /** * inf_tcp_connection_set_keepalive: * @connection: A #InfTcpConnection. * @keepalive: New keepalive settings for the connection. * @error: Location to store error information, if any, or %NULL. * * Sets the keepalive settings for @connection. When this function is not * called, the system defaults are used. If the connection is closed, then * the function always succeeds and stores the keepalive values internally. * The values are actually set on the underlying socket when the connection * is opened. If the connection is already open, the function might fail if * the system call fails. * * Returns: %TRUE if the new keeplalive values were set, or %FALSE on error. */ gboolean inf_tcp_connection_set_keepalive(InfTcpConnection* connection, const InfKeepalive* keepalive, GError** error) { InfTcpConnectionPrivate* priv; InfKeepaliveMask mask; g_return_val_if_fail(INF_IS_TCP_CONNECTION(connection), FALSE); g_return_val_if_fail(keepalive != NULL, FALSE); g_return_val_if_fail(error == NULL || *error == NULL, FALSE); priv = INF_TCP_CONNECTION_PRIVATE(connection); if(priv->socket != INVALID_SOCKET) { mask = priv->keepalive.mask; if(inf_keepalive_apply(keepalive, &priv->socket, mask, error) != TRUE) return FALSE; } priv->keepalive = *keepalive; return TRUE; } /** * inf_tcp_connection_get_keepalive: * @connection: A #InfTcpConnection. * * Returns the current keepalive settings for @connection. * * Returns: The current keepalive configuration for @connection, owned by * @connection. */ const InfKeepalive* inf_tcp_connection_get_keepalive(InfTcpConnection* connection) { g_return_val_if_fail(INF_IS_TCP_CONNECTION(connection), NULL); return &INF_TCP_CONNECTION_PRIVATE(connection)->keepalive; } /* Creates a new TCP connection from an accepted socket. This is only used * by InfdTcpServer and should not be considered regular API. Do not call * this function. Language bindings should not wrap it. */ InfTcpConnection* _inf_tcp_connection_accepted(InfIo* io, InfNativeSocket socket, InfIpAddress* address, guint port, const InfKeepalive* keepalive, GError** error) { InfTcpConnection* connection; InfTcpConnectionPrivate* priv; int errcode; g_return_val_if_fail(INF_IS_IO(io), NULL); g_return_val_if_fail(socket != INVALID_SOCKET, NULL); g_return_val_if_fail(address != NULL, NULL); g_return_val_if_fail(keepalive != NULL, NULL); if(inf_tcp_connection_configure_socket(socket, keepalive, error) != TRUE) return NULL; g_return_val_if_fail(address != NULL, NULL); g_return_val_if_fail(port != 0, NULL); connection = inf_tcp_connection_new(io, address, port); inf_ip_address_free(address); priv = INF_TCP_CONNECTION_PRIVATE(connection); priv->socket = socket; priv->keepalive = *keepalive; inf_tcp_connection_connected(connection); return connection; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-request-result.c0000644000000000000000000000013213034342512023332 xustar0030 mtime=1483851082.033718448 30 atime=1483851082.033718448 30 ctime=1488261589.076138899 libinfinity-0.7.1/libinfinity/common/inf-request-result.c0000644000175000017500000010153513034342512024071 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-request-result * @title: Result of an asynchronous request * @short_description: Request results for the infinote requests * @include: libinfinity/common/inf-request-result.h * @stability: Unstable * * These functions allow to create #InfRequestResult objects and to extract * the resulting values from them. In general, all objects in a * #InfRequestResult are not referenced and must point to an existing * reference which is guaranteed to live as long as the #InfRequestResult * object stays alive. This is typically the case for the primary use case of * #InfRequestResult, which is to serve as a common parameter for the * #InfRequest::finished signal. **/ #include G_DEFINE_BOXED_TYPE(InfRequestResult, inf_request_result, inf_request_result_copy, inf_request_result_free) struct _InfRequestResult { gpointer data; gsize len; }; /** * inf_request_result_new: (constructor) * @data: The data representing the result of the request. * @len: The length of the data. * * This function creates a new #InfRequestResult with the given data. The * function takes ownership of the data which must have been allocated with * g_malloc(). The memory segment at @data must not hold any object references * or require deinitialization in a way other than with g_free(). * * Under normal circumstances, this function should not be used, and instead * one of the inf_request_result_make_*() functions should be used. * * Returns: (transfer full): A new #InfRequestResult. Free * with inf_request_result_free(). */ InfRequestResult* inf_request_result_new(gpointer data, gsize len) { InfRequestResult* result; result = g_slice_new(InfRequestResult); result->data = data; result->len = len; return result; } /** * inf_request_result_copy: * @result: A #InfRequestResult. * * Creates a copy of @result. * * Returns: (transfer full): A new #InfRequestResult. Free with * inf_request_result_free(). */ InfRequestResult* inf_request_result_copy(const InfRequestResult* result) { InfRequestResult* new_result; g_return_val_if_fail(result != NULL, NULL); new_result = g_slice_new(InfRequestResult); new_result->data = g_memdup(result->data, result->len); new_result->len = result->len; return new_result; } /** * inf_request_result_free: * @result: A #InfRequestResult. * * Releases all resources associated with @result. */ void inf_request_result_free(InfRequestResult* result) { g_return_if_fail(result != NULL); g_free(result->data); g_slice_free(InfRequestResult, result); } /** * inf_request_result_get: * @result: A #InfRequestResult. * @length: (out) (allow-none): An output parameter for the length of the * result data, or %NULL. * * Returns the data of @result, as given to inf_request_result_new(). The * length of the data is stored in @length. Normally this function does not * need to be used and one of the inf_request_result_get_*() functions * should be used instead. * * Returns: (transfer none) (type guint8) (array length=length): A pointer * to the request data. */ gconstpointer inf_request_result_get(const InfRequestResult* result, gsize* length) { g_return_val_if_fail(result != NULL, NULL); if(length != NULL) *length = result->len; return result->data; } typedef struct _InfRequestResultAddNode InfRequestResultAddNode; struct _InfRequestResultAddNode { InfBrowser* browser; const InfBrowserIter* iter; const InfBrowserIter* new_node; }; /** * inf_request_result_make_add_node: * @browser: A #InfBrowser. * @iter: An iterator pointing to the node to which a node has been added. * @new_node: An iterator pointing to the new node. * * Creates a new #InfRequestResult for an "add-node" request, see * inf_browser_add_note() or inf_browser_add_subdirectory(). The * #InfRequestResult object is only valid as long as the caller maintains * a reference to @browser. * * Returns: (transfer full): A new #InfRequestResult. Free with * inf_request_result_free(). */ InfRequestResult* inf_request_result_make_add_node(InfBrowser* browser, const InfBrowserIter* iter, const InfBrowserIter* new_node) { InfRequestResultAddNode* data; g_return_val_if_fail(INF_IS_BROWSER(browser), NULL); g_return_val_if_fail(iter != NULL, NULL); g_return_val_if_fail(new_node != NULL, NULL); data = g_malloc(sizeof(InfRequestResultAddNode)); data->browser = browser; data->iter = iter; data->new_node = new_node; return inf_request_result_new(data, sizeof(*data)); } /** * inf_request_result_get_add_node: * @result: A #InfRequestResult: * @browser: (out) (allow-none) (transfer none): Output value of the browser * that made the request, or %NULL. * @iter: (out) (allow-none) (transfer none): Output value for the node to * which a node has been added, or %NULL. * @new_node: (out) (allow-none) (transfer none): Output value for the * new node, or %NULL. * * Decomposes @result into its components. The object must have been created * with inf_request_result_make_add_node(). */ void inf_request_result_get_add_node(const InfRequestResult* result, InfBrowser** browser, const InfBrowserIter** iter, const InfBrowserIter** new_node) { const InfRequestResultAddNode* data; g_return_if_fail(result != NULL); g_return_if_fail(result->len == sizeof(InfRequestResultAddNode)); data = (const InfRequestResultAddNode*)result->data; if(browser != NULL) *browser = data->browser; if(iter != NULL) *iter = data->iter; if(new_node != NULL) *new_node = data->new_node; } typedef struct _InfRequestResultRemoveNode InfRequestResultRemoveNode; struct _InfRequestResultRemoveNode { InfBrowser* browser; const InfBrowserIter* iter; }; /** * inf_request_result_make_remove_node: * @browser: A #InfBrowser. * @iter: An iterator pointing to the node to which was removed. * * Creates a new #InfRequestResult for an "remove-node" request, see * inf_browser_remove_node(). The #InfRequestResult object is only valid * as long as the caller maintains a reference to @browser. * * Returns: (transfer full): A new #InfRequestResult. Free with * inf_request_result_free(). */ InfRequestResult* inf_request_result_make_remove_node(InfBrowser* browser, const InfBrowserIter* iter) { InfRequestResultRemoveNode* data; g_return_val_if_fail(INF_IS_BROWSER(browser), NULL); g_return_val_if_fail(iter != NULL, NULL); data = g_malloc(sizeof(InfRequestResultRemoveNode)); data->browser = browser; data->iter = iter; return inf_request_result_new(data, sizeof(*data)); } /** * inf_request_result_get_remove_node: * @result: A #InfRequestResult: * @browser: (out) (allow-none) (transfer none): Output value of the browser * that made the request, or %NULL. * @iter: (out) (allow-none) (transfer none): Output value for the node that * has been removed, or %NULL. * * Decomposes @result into its components. The object must have been created * with inf_request_result_make_remove_node(). */ void inf_request_result_get_remove_node(const InfRequestResult* result, InfBrowser** browser, const InfBrowserIter** iter) { const InfRequestResultRemoveNode* data; g_return_if_fail(result != NULL); g_return_if_fail(result->len == sizeof(InfRequestResultRemoveNode)); data = (const InfRequestResultRemoveNode*)result->data; if(browser != NULL) *browser = data->browser; if(iter != NULL) *iter = data->iter; } typedef struct _InfRequestResultExploreNode InfRequestResultExploreNode; struct _InfRequestResultExploreNode { InfBrowser* browser; const InfBrowserIter* iter; }; /** * inf_request_result_make_explore_node: * @browser: A #InfBrowser. * @iter: An iterator pointing to the node to which was explored. * * Creates a new #InfRequestResult for an "explore-node" request, see * inf_browser_explore(). The #InfRequestResult object is only valid * as long as the caller maintains a reference to @browser. * * Returns: (transfer full): A new #InfRequestResult. Free with * inf_request_result_free(). */ InfRequestResult* inf_request_result_make_explore_node(InfBrowser* browser, const InfBrowserIter* iter) { InfRequestResultExploreNode* data; g_return_val_if_fail(INF_IS_BROWSER(browser), NULL); g_return_val_if_fail(iter != NULL, NULL); data = g_malloc(sizeof(InfRequestResultExploreNode)); data->browser = browser; data->iter = iter; return inf_request_result_new(data, sizeof(*data)); } /** * inf_request_result_get_explore_node: * @result: A #InfRequestResult: * @browser: (out) (allow-none) (transfer none): Output value of the browser * that made the request, or %NULL. * @iter: (out) (allow-none) (transfer none): Output value for the node that * has been explored, or %NULL. * * Decomposes @result into its components. The object must have been created * with inf_request_result_make_explore_node(). */ void inf_request_result_get_explore_node(const InfRequestResult* result, InfBrowser** browser, const InfBrowserIter** iter) { const InfRequestResultExploreNode* data; g_return_if_fail(result != NULL); g_return_if_fail(result->len == sizeof(InfRequestResultExploreNode)); data = (const InfRequestResultExploreNode*)result->data; if(browser != NULL) *browser = data->browser; if(iter != NULL) *iter = data->iter; } typedef struct _InfRequestResultSaveSession InfRequestResultSaveSession; struct _InfRequestResultSaveSession { InfBrowser* browser; const InfBrowserIter* iter; }; /** * inf_request_result_make_save_session: * @browser: A #InfBrowser. * @iter: An iterator pointing to the node to which was saved. * * Creates a new #InfRequestResult for a "save-session" request, see * infc_browser_iter_save_session(). The #InfRequestResult object is only * valid as long as the caller maintains a reference to @browser. * * Returns: (transfer full): A new #InfRequestResult. Free with * inf_request_result_free(). */ InfRequestResult* inf_request_result_make_save_session(InfBrowser* browser, const InfBrowserIter* iter) { InfRequestResultSaveSession* data; g_return_val_if_fail(INF_IS_BROWSER(browser), NULL); g_return_val_if_fail(iter != NULL, NULL); data = g_malloc(sizeof(InfRequestResultSaveSession)); data->browser = browser; data->iter = iter; return inf_request_result_new(data, sizeof(*data)); } /** * inf_request_result_get_save_session: * @result: A #InfRequestResult: * @browser: (out) (allow-none) (transfer none): Output value of the browser * that made the request, or %NULL. * @iter: (out) (allow-none) (transfer none): Output value for the node that * has been saved, or %NULL. * * Decomposes @result into its components. The object must have been created * with inf_request_result_make_save_session(). */ void inf_request_result_get_save_session(const InfRequestResult* result, InfBrowser** browser, const InfBrowserIter** iter) { const InfRequestResultSaveSession* data; g_return_if_fail(result != NULL); g_return_if_fail(result->len == sizeof(InfRequestResultSaveSession)); data = (const InfRequestResultSaveSession*)result->data; if(browser != NULL) *browser = data->browser; if(iter != NULL) *iter = data->iter; } typedef struct _InfRequestResultSubscribeSession InfRequestResultSubscribeSession; struct _InfRequestResultSubscribeSession { InfBrowser* browser; const InfBrowserIter* iter; InfSessionProxy* proxy; }; /** * inf_request_result_make_subscribe_session: * @browser: A #InfBrowser. * @iter: An iterator pointing to the node to which a subscription was made. * @proxy: The #InfSessionProxy for the subscription. * * Creates a new #InfRequestResult for a "subscribe-session" request, see * inf_browser_subscribe(). The #InfRequestResult object is only valid * as long as the caller maintains a reference to @browser and @proxy. * * Returns: (transfer full): A new #InfRequestResult. Free with * inf_request_result_free(). */ InfRequestResult* inf_request_result_make_subscribe_session(InfBrowser* browser, const InfBrowserIter* iter, InfSessionProxy* proxy) { InfRequestResultSubscribeSession* data; g_return_val_if_fail(INF_IS_BROWSER(browser), NULL); g_return_val_if_fail(iter != NULL, NULL); g_return_val_if_fail(INF_IS_SESSION_PROXY(proxy), NULL); data = g_malloc(sizeof(InfRequestResultSubscribeSession)); data->browser = browser; data->iter = iter; data->proxy = proxy; return inf_request_result_new(data, sizeof(*data)); } /** * inf_request_result_get_subscribe_session: * @result: A #InfRequestResult: * @browser: (out) (allow-none) (transfer none): Output value of the browser * that made the request, or %NULL. * @iter: (out) (allow-none) (transfer none): Output value for the node that * has been subscribed to, or %NULL. * @proxy: (out) (allow-none) (transfer none): Output value for the subscribed * session's proxy, or %NULL. * * Decomposes @result into its components. The object must have been created * with inf_request_result_make_subscribe_session(). */ void inf_request_result_get_subscribe_session(const InfRequestResult* result, InfBrowser** browser, const InfBrowserIter** iter, InfSessionProxy** proxy) { const InfRequestResultSubscribeSession* data; g_return_if_fail(result != NULL); g_return_if_fail(result->len == sizeof(InfRequestResultSubscribeSession)); data = (const InfRequestResultSubscribeSession*)result->data; if(browser != NULL) *browser = data->browser; if(iter != NULL) *iter = data->iter; if(proxy != NULL) *proxy = data->proxy; } typedef struct _InfRequestResultSubscribeChat InfRequestResultSubscribeChat; struct _InfRequestResultSubscribeChat { InfBrowser* browser; InfSessionProxy* proxy; }; /** * inf_request_result_make_subscribe_chat: * @browser: A #InfBrowser. * @proxy: The #InfSessionProxy for the subscribed session. * * Creates a new #InfRequestResult for a "subscribe-chat" request, see * infc_browser_subscribe_chat(). The #InfRequestResult object is only valid * as long as the caller maintains a reference to @browser and @proxy. * * Returns: (transfer full): A new #InfRequestResult. Free with * inf_request_result_free(). */ InfRequestResult* inf_request_result_make_subscribe_chat(InfBrowser* browser, InfSessionProxy* proxy) { InfRequestResultSubscribeChat* data; g_return_val_if_fail(INF_IS_BROWSER(browser), NULL); g_return_val_if_fail(INF_IS_SESSION_PROXY(proxy), NULL); data = g_malloc(sizeof(InfRequestResultSubscribeChat)); data->browser = browser; data->proxy = proxy; return inf_request_result_new(data, sizeof(*data)); } /** * inf_request_result_get_subscribe_chat: * @result: A #InfRequestResult: * @browser: (out) (allow-none) (transfer none): Output value of the browser * that made the request, or %NULL. * @proxy: (out) (allow-none) (transfer none): Output value for the * subscribed session's proxy, or %NULL. * * Decomposes @result into its components. The object must have been created * with inf_request_result_make_subscribe_chat(). */ void inf_request_result_get_subscribe_chat(const InfRequestResult* result, InfBrowser** browser, InfSessionProxy** proxy) { const InfRequestResultSubscribeChat* data; g_return_if_fail(result != NULL); g_return_if_fail(result->len == sizeof(InfRequestResultSubscribeChat)); data = (const InfRequestResultSubscribeChat*)result->data; if(browser != NULL) *browser = data->browser; if(proxy != NULL) *proxy = data->proxy; } typedef struct _InfRequestResultQueryAclAccountList InfRequestResultQueryAclAccountList; struct _InfRequestResultQueryAclAccountList { InfBrowser* browser; const InfAclAccount* accounts; guint n_accounts; gboolean does_notifications; }; /** * inf_request_result_make_query_acl_account_list: * @browser: A #InfBrowser. * @accounts: (array length=n_accounts): The list of accounts. * @n_accounts: The number of items in the account list. * @does_notifications: Whether the server notifies the clients about added * or removed accounts. * * Creates a new #InfRequestResult for a "query-acl-account-list" request, see * inf_browser_query_acl_account_list(). The #InfRequestResult object is only valid * as long as the caller maintains a reference to @browser. * * Returns: (transfer full): A new #InfRequestResult. Free with * inf_request_result_free(). */ InfRequestResult* inf_request_result_make_query_acl_account_list(InfBrowser* browser, const InfAclAccount* accounts, guint n_accounts, gboolean does_notifications) { InfRequestResultQueryAclAccountList* data; g_return_val_if_fail(INF_IS_BROWSER(browser), NULL); data = g_malloc(sizeof(InfRequestResultQueryAclAccountList)); data->browser = browser; data->accounts = accounts; data->n_accounts = n_accounts; data->does_notifications = does_notifications; return inf_request_result_new(data, sizeof(*data)); } /** * inf_request_result_get_query_acl_account_list: * @result: A #InfRequestResult: * @browser: (out) (transfer none) (allow-none): Output value of the browser * that made the request, or %NULL. * @accounts: (out) (array length=n_accounts) (transfer none) (allow-none): * Output value for the list of accounts, or %NULL. * @n_accounts: (out) (transfer none) (allow-none): Output value for the size * of the account list, or %NULL. * @does_notifications: Output value for the flag whether the server notifies * the client about added or removed accounts, or %NULL. * * Decomposes @result into its components. The object must have been created * with inf_request_result_make_query_acl_account_list(). */ void inf_request_result_get_query_acl_account_list(const InfRequestResult* result, InfBrowser** browser, const InfAclAccount** accounts, guint* n_accounts, gboolean* does_notifications) { const InfRequestResultQueryAclAccountList* data; g_return_if_fail(result != NULL); g_return_if_fail( result->len == sizeof(InfRequestResultQueryAclAccountList) ); data = (const InfRequestResultQueryAclAccountList*)result->data; if(browser != NULL) *browser = data->browser; if(accounts != NULL) *accounts = data->accounts; if(n_accounts != NULL) *n_accounts = data->n_accounts; if(does_notifications != NULL) *does_notifications = data->does_notifications; } typedef struct _InfRequestResultLookupAclAccounts InfRequestResultLookupAclAccounts; struct _InfRequestResultLookupAclAccounts { InfBrowser* browser; const InfAclAccount* accounts; guint n_accounts; }; /** * inf_request_result_make_lookup_acl_accounts: * @browser: A #InfBrowser. * @accounts: (array length=n_accounts): The list of accounts. * @n_accounts: The number of entries in the account list. * * Creates a new #InfRequestResult for a "lookup-acl-accounts" request, see * inf_browser_lookup_acl_accounts(). The #InfRequestResult object is only valid * as long as the caller maintains a reference to @browser. * * Returns: (transfer full): A new #InfRequestResult. Free with * inf_request_result_free(). */ InfRequestResult* inf_request_result_make_lookup_acl_accounts(InfBrowser* browser, const InfAclAccount* accounts, guint n_accounts) { InfRequestResultLookupAclAccounts* data; g_return_val_if_fail(INF_IS_BROWSER(browser), NULL); data = g_malloc(sizeof(InfRequestResultLookupAclAccounts)); data->browser = browser; data->accounts = accounts; data->n_accounts = n_accounts; return inf_request_result_new(data, sizeof(*data)); } /** * inf_request_result_get_lookup_acl_accounts: * @result: A #InfRequestResult: * @browser: (out) (transfer none) (allow-none): Output value of the browser * that made the request, or %NULL. * @accounts: (out) (transfer none) (allow-none) (array length=n_accounts): * Output value for the list of accounts, or %NULL. * @n_accounts: (out) (transfer none) (allow-none): Output value for the size * of the account list, or %NULL. * * Decomposes @result into its components. The object must have been created * with inf_request_result_make_lookup_acl_accounts(). */ void inf_request_result_get_lookup_acl_accounts(const InfRequestResult* result, InfBrowser** browser, const InfAclAccount** accounts, guint* n_accounts) { const InfRequestResultLookupAclAccounts* data; g_return_if_fail(result != NULL); g_return_if_fail( result->len == sizeof(InfRequestResultLookupAclAccounts) ); data = (const InfRequestResultLookupAclAccounts*)result->data; if(browser != NULL) *browser = data->browser; if(accounts != NULL) *accounts = data->accounts; if(n_accounts != NULL) *n_accounts = data->n_accounts; } typedef struct _InfRequestResultCreateAclAccount InfRequestResultCreateAclAccount; struct _InfRequestResultCreateAclAccount { InfBrowser* browser; const InfAclAccount* account; InfCertificateChain* certificate; }; /** * inf_request_result_make_create_acl_account: * @browser: A #InfBrowser. * @account: The created #InfAclAccount. * @certificate: (transfer none): The certificate which can be used to log into @account. * * Creates a new #InfRequestResult for a "create-acl-account" request, see * inf_browser_create_acl_account(). The #InfRequestResult object is only valid * as long as the caller maintains a reference to @browser. * * Returns: (transfer full): A new #InfRequestResult. Free with * inf_request_result_free(). */ InfRequestResult* inf_request_result_make_create_acl_account(InfBrowser* browser, const InfAclAccount* account, InfCertificateChain* certificate) { InfRequestResultCreateAclAccount* data; g_return_val_if_fail(INF_IS_BROWSER(browser), NULL); g_return_val_if_fail(certificate != NULL, NULL); data = g_malloc(sizeof(InfRequestResultCreateAclAccount)); data->browser = browser; data->account = account; data->certificate = certificate; return inf_request_result_new(data, sizeof(*data)); } /** * inf_request_result_get_create_acl_account: * @result: A #InfRequestResult: * @browser: (out) (transfer none) (allow-none): Output value of the browser * that made the request, or %NULL. * @account: (out) (transfer none) (allow-none): Output value for the created * #InfAclAccount, or %NULL. * @certificate: (out) (transfer none) (allow-none): Output value for the * certificate which can be used to log into the account, or %NULL. * * Decomposes @result into its components. The object must have been created * with inf_request_result_make_create_acl_account(). */ void inf_request_result_get_create_acl_account(const InfRequestResult* result, InfBrowser** browser, const InfAclAccount** account, InfCertificateChain** certificate) { const InfRequestResultCreateAclAccount* data; g_return_if_fail(result != NULL); g_return_if_fail(result->len == sizeof(InfRequestResultCreateAclAccount)); data = (const InfRequestResultCreateAclAccount*)result->data; if(browser != NULL) *browser = data->browser; if(account != NULL) *account = data->account; if(certificate != NULL) *certificate = data->certificate; } typedef struct _InfRequestResultRemoveAclAccount InfRequestResultRemoveAclAccount; struct _InfRequestResultRemoveAclAccount { InfBrowser* browser; const InfAclAccount* account; }; /** * inf_request_result_make_remove_acl_account: * @browser: A #InfBrowser. * @account: The removed #InfAclAccount. * * Creates a new #InfRequestResult for a "remove-acl-account" request, see * inf_browser_remove_acl_account(). The #InfRequestResult object is only valid * as long as the caller maintains a reference to @browser. * * Returns: (transfer full): A new #InfRequestResult. Free with * inf_request_result_free(). */ InfRequestResult* inf_request_result_make_remove_acl_account(InfBrowser* browser, const InfAclAccount* account) { InfRequestResultRemoveAclAccount* data; g_return_val_if_fail(INF_IS_BROWSER(browser), NULL); g_return_val_if_fail(account != NULL, NULL); data = g_malloc(sizeof(InfRequestResultRemoveAclAccount)); data->browser = browser; data->account = account; return inf_request_result_new(data, sizeof(*data)); } /** * inf_request_result_get_remove_acl_account: * @result: A #InfRequestResult: * @browser: (out) (transfer none) (allow-none): Output value of the browser * that made the request, or %NULL. * @account: (out) (transfer none) (allow-none): Output value for the removed * #InfAclAccount, or %NULL. * * Decomposes @result into its components. The object must have been created * with inf_request_result_make_remove_acl_account(). */ void inf_request_result_get_remove_acl_account(const InfRequestResult* result, InfBrowser** browser, const InfAclAccount** account) { const InfRequestResultRemoveAclAccount* data; g_return_if_fail(result != NULL); g_return_if_fail(result->len == sizeof(InfRequestResultRemoveAclAccount)); data = (const InfRequestResultRemoveAclAccount*)result->data; if(browser != NULL) *browser = data->browser; if(account != NULL) *account = data->account; } typedef struct _InfRequestResultQueryAcl InfRequestResultQueryAcl; struct _InfRequestResultQueryAcl { InfBrowser* browser; const InfBrowserIter* iter; const InfAclSheetSet* sheet_set; }; /** * inf_request_result_make_query_acl: * @browser: A #InfBrowser. * @iter: An iterator pointing to the node whose ACL was queried. * @sheet_set: The sheet set for the queried node. * * Creates a new #InfRequestResult for a "query-acl" request, see * inf_browser_query_acl(). The #InfRequestResult object is only valid * as long as the caller maintains a reference to @browser and @proxy. * * Returns: (transfer full): A new #InfRequestResult. Free with * inf_request_result_free(). */ InfRequestResult* inf_request_result_make_query_acl(InfBrowser* browser, const InfBrowserIter* iter, const InfAclSheetSet* sheet_set) { InfRequestResultQueryAcl* data; g_return_val_if_fail(INF_IS_BROWSER(browser), NULL); g_return_val_if_fail(iter != NULL, NULL); data = g_malloc(sizeof(InfRequestResultQueryAcl)); data->browser = browser; data->iter = iter; data->sheet_set = sheet_set; return inf_request_result_new(data, sizeof(*data)); } /** * inf_request_result_get_query_acl: * @result: A #InfRequestResult: * @browser: (out) (transfer none) (allow-none): Output value of the browser * that made the request, or %NULL. * @iter: (out) (transfer none) (allow-none): Output value for the node * whose ACL was queried. * @sheet_set: (out) (transfer none) (allow-none): Output value for the * node's ACL sheets. * * Decomposes @result into its components. The object must have been created * with inf_request_result_make_query_acl(). */ void inf_request_result_get_query_acl(const InfRequestResult* result, InfBrowser** browser, const InfBrowserIter** iter, const InfAclSheetSet** sheet_set) { const InfRequestResultQueryAcl* data; g_return_if_fail(result != NULL); g_return_if_fail(result->len == sizeof(InfRequestResultQueryAcl)); data = (const InfRequestResultQueryAcl*)result->data; if(browser != NULL) *browser = data->browser; if(iter != NULL) *iter = data->iter; if(sheet_set != NULL) *sheet_set = data->sheet_set; } typedef struct _InfRequestResultSetAcl InfRequestResultSetAcl; struct _InfRequestResultSetAcl { InfBrowser* browser; const InfBrowserIter* iter; }; /** * inf_request_result_make_set_acl: * @browser: A #InfBrowser. * @iter: An iterator pointing to the node whose ACL was set. * * Creates a new #InfRequestResult for a "set-acl" request, see * inf_browser_set_acl(). The #InfRequestResult object is only valid * as long as the caller maintains a reference to @browser and @proxy. * * Returns: (transfer full): A new #InfRequestResult. Free with * inf_request_result_free(). */ InfRequestResult* inf_request_result_make_set_acl(InfBrowser* browser, const InfBrowserIter* iter) { InfRequestResultSetAcl* data; g_return_val_if_fail(INF_IS_BROWSER(browser), NULL); g_return_val_if_fail(iter != NULL, NULL); data = g_malloc(sizeof(InfRequestResultSetAcl)); data->browser = browser; data->iter = iter; return inf_request_result_new(data, sizeof(*data)); } /** * inf_request_result_get_set_acl: * @result: A #InfRequestResult: * @browser: (out) (transfer none) (allow-none): Output value of the browser * that made the request, or %NULL. * @iter: (out) (transfer none) (allow-none): Output value for the node whose * ACL was set. * * Decomposes @result into its components. The object must have been created * with inf_request_result_make_set_acl(). */ void inf_request_result_get_set_acl(const InfRequestResult* result, InfBrowser** browser, const InfBrowserIter** iter) { const InfRequestResultSetAcl* data; g_return_if_fail(result != NULL); g_return_if_fail(result->len == sizeof(InfRequestResultSetAcl)); data = (const InfRequestResultSetAcl*)result->data; if(browser != NULL) *browser = data->browser; if(iter != NULL) *iter = data->iter; } typedef struct _InfRequestResultJoinUser InfRequestResultJoinUser; struct _InfRequestResultJoinUser { InfSessionProxy* proxy; InfUser* user; }; /** * inf_request_result_make_join_user: * @proxy: A #InfSessionProxy. * @user: The joined user. * * Creates a new #InfRequestResult for a "join-user" request, see * inf_session_proxy_join_user(). The #InfRequestResult object is only valid * as long as the caller maintains a reference to @proxy. * * Returns: (transfer full): A new #InfRequestResult. Free with * inf_request_result_free(). */ InfRequestResult* inf_request_result_make_join_user(InfSessionProxy* proxy, InfUser* user) { InfRequestResultJoinUser* data; g_return_val_if_fail(INF_IS_SESSION_PROXY(proxy), NULL); g_return_val_if_fail(user != NULL, NULL); data = g_malloc(sizeof(InfRequestResultJoinUser)); data->proxy = proxy; data->user = user; return inf_request_result_new(data, sizeof(*data)); } /** * inf_request_result_get_join_user: * @result: A #InfRequestResult: * @proxy: (out) (transfer none) (allow-none): Output value of the session * proxy that made the request, or %NULL. * @user: (out) (transfer none) (allow-none): Output value for the joined * user. * * Decomposes @result into its components. The object must have been created * with inf_request_result_make_join_user(). */ void inf_request_result_get_join_user(const InfRequestResult* result, InfSessionProxy** proxy, InfUser** user) { const InfRequestResultJoinUser* data; g_return_if_fail(result != NULL); g_return_if_fail(result->len == sizeof(InfRequestResultJoinUser)); data = (const InfRequestResultJoinUser*)result->data; if(proxy != NULL) *proxy = data->proxy; if(user != NULL) *user = data->user; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-local-publisher.c0000644000000000000000000000013213034342512023413 xustar0030 mtime=1483851082.033718448 30 atime=1483851082.033718448 30 ctime=1488261589.064138925 libinfinity-0.7.1/libinfinity/common/inf-local-publisher.c0000644000175000017500000000577613034342512024164 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-local-publisher * @short_description: Publish services on the local network * @include: libinfinity/common/inf-local-publisher.h * @see_also: #InfDiscoveryAvahi * * #InfLocalPublisher provides a common interface to publish services on the * local network. */ #include G_DEFINE_INTERFACE(InfLocalPublisher, inf_local_publisher, G_TYPE_OBJECT) static void inf_local_publisher_default_init(InfLocalPublisherInterface* iface) { } /** * inf_local_publisher_publish: * @publisher: A #InfLocalPublisher. * @type: The service type to publish, such as _http._tcp. * @name: The name of the service. * @port: The port the service is listening on. * * Publishes a service through @publisher so that it can be discovered with * an appropriate #InfDiscovery. * * Return Value: (transfer none): A #InfLocalPublisherItem that can be used * to unpublish the service again. **/ InfLocalPublisherItem* inf_local_publisher_publish(InfLocalPublisher* publisher, const gchar* type, const gchar* name, guint port) { InfLocalPublisherInterface* iface; g_return_val_if_fail(INF_IS_LOCAL_PUBLISHER(publisher), NULL); g_return_val_if_fail(type != NULL, NULL); g_return_val_if_fail(name != NULL, NULL); g_return_val_if_fail(port != 0, NULL); iface = INF_LOCAL_PUBLISHER_GET_IFACE(publisher); g_return_val_if_fail(iface->publish != NULL, NULL); return iface->publish(publisher, type, name, port); } /** * inf_local_publisher_unpublish: * @publisher: A #InfLocalPublisher. * @item: A published item obtained from inf_local_publisher_publish(). * * Unpublishes @item so that it can no longer be found in the network. **/ void inf_local_publisher_unpublish(InfLocalPublisher* publisher, InfLocalPublisherItem* item) { InfLocalPublisherInterface* iface; g_return_if_fail(INF_IS_LOCAL_PUBLISHER(publisher)); g_return_if_fail(item != NULL); iface = INF_LOCAL_PUBLISHER_GET_IFACE(publisher); g_return_if_fail(iface->unpublish != NULL); iface->unpublish(publisher, item); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-async-operation.h0000644000000000000000000000013213034342512023446 xustar0030 mtime=1483851082.029718427 30 atime=1483851082.029718427 30 ctime=1488261588.932139214 libinfinity-0.7.1/libinfinity/common/inf-async-operation.h0000644000175000017500000000516713034342512024211 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_ASYNC_OPERATION_H__ #define __INF_ASYNC_OPERATION_H__ #include #include G_BEGIN_DECLS /** * InfAsyncOperationRunFunc: * @run_data: Location where to write the result of the asynchronous * operation. * @run_notify: Function to be used to free @run_data, or %NULL. * @user_data: Data passed in inf_async_operation_new(). * * This function performs the asynchronous task and is executed in a separate * thread. The pointer written into @run_data is passed back to the main * thread after the function has finished executing. */ typedef void(*InfAsyncOperationRunFunc)(gpointer* run_data, GDestroyNotify* run_notify, gpointer user_data); /** * InfAsyncOperationDoneFunc: * @run_data: The result of the asynchronous operation. * @user_data: Data passed in inf_async_operation_new(). * * This function is called in the main thread once the asynchronous operation * has finished. */ typedef void(*InfAsyncOperationDoneFunc)(gpointer run_data, gpointer user_data); /** * InfAsyncOperation: (foreign) * * #InfAsyncOperation is an opaque data type and should only be accessed via * the public API functions. */ typedef struct _InfAsyncOperation InfAsyncOperation; InfAsyncOperation* inf_async_operation_new(InfIo* io, InfAsyncOperationRunFunc run_func, InfAsyncOperationDoneFunc done_func, gpointer user_data); gboolean inf_async_operation_start(InfAsyncOperation* op, GError** error); void inf_async_operation_free(InfAsyncOperation* op); G_END_DECLS #endif /* __INF_ASYNC_OPERATION_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-browser.h0000644000000000000000000000013213034342512022016 xustar0030 mtime=1483851082.029718427 30 atime=1483851082.029718427 30 ctime=1488261588.932139214 libinfinity-0.7.1/libinfinity/common/inf-browser.h0000644000175000017500000004632613034342512022563 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_BROWSER_H__ #define __INF_BROWSER_H__ #include #include #include #include #include #include G_BEGIN_DECLS #define INF_TYPE_BROWSER (inf_browser_get_type()) #define INF_BROWSER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_TYPE_BROWSER, InfBrowser)) #define INF_IS_BROWSER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_TYPE_BROWSER)) #define INF_BROWSER_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), INF_TYPE_BROWSER, InfBrowserInterface)) #define INF_TYPE_BROWSER_STATUS (inf_browser_status_get_type()) /** * InfBrowser: * * #InfBrowser is an opaque data type. You should only access it * via the public API functions. */ typedef struct _InfBrowser InfBrowser; typedef struct _InfBrowserInterface InfBrowserInterface; /** * InfBrowserStatus: * @INF_BROWSER_CLOSED: The browser is closed and cannot be used currently. * @INF_BROWSER_OPENING: The browser is currently being opened but cannot be * used yet. * @INF_BROWSER_OPEN: The browser is open and can be used to browse the * directory. * * This enumeration contains possible status values for * #InfBrowser. Several operations, such as exploring a node or subscribing * to a session can only be performed when the browser is open (for example, * connected to a remote infinote server). */ typedef enum _InfBrowserStatus { INF_BROWSER_CLOSED, INF_BROWSER_OPENING, INF_BROWSER_OPEN } InfBrowserStatus; /** * InfBrowserInterface: * @error: Default signal handler for the #InfBrowser::error signal. * @node_added: Default signal handler for the #InfBrowser::node-added * signal. * @node_removed: Default signal handler for the #InfBrowser::node-removed * signal. * @subscribe_session: Default signal handler for the * #InfBrowser::subscribe-session signal. * @unsubscribe_session: Default signal handler for the * #InfBrowser::unsubscribe-session signal. * @begin_request: Default signal handler for the * #InfBrowser::begin-request signal. * @acl_account_added: Default signal handler for the * #InfBrowser::acl-account-added signal. * @acl_account_removed: Default signal handler for the * #InfBrowser::acl-account-removed signal. * @acl_local_account_changed: Default signal handler for the * #InfBrowser::acl-local-account-changed signal. * @acl_changed: Default signal handler for the * #InfBrowser::acl-changed signal. * @get_root: Virtual function to return the root node of the browser. * @get_next: Virtual function to return the next sibling in a browser. * @get_prev: Virtual function to return the previous sibling in a browser. * @get_parent: Virtual function to return the parent node in a browser. * @get_child: Virtual function to return the first child node in a browser. * @explore: Virtual function to start exploring a node. * @get_explored: Virtual function to query whether a node is explored * already. * @is_subdirectory: Virtual function to find out whether a node is a * subdirectory node. * @add_note: Virtual function to add a new leaf node to the directory. * @add_subdirectory: Virtual function to a new subdirectory node to the * directory. * @remove_node: Virtual function to remove a node from the directory. * @get_node_name: Virtual function to return the name of a node in a browser. * @get_node_type: Virtual function to return the type of a node in a browser. * @subscribe: Virtual function to subscribe to a session of a node in a * browser. * @get_session: Virtual function to return a session for a node in a browser. * @list_pending_requests: Virtual function to return a list of all pending * requests for a node in a browser. * @iter_from_request: Virtual function to return an iterator pointing to the * node a given request was made for. * @get_acl_default_account: Virtual function to return the * "default" ACL account. * @get_acl_local_account: Virtual function to return the ACL account of the * local host. * @query_acl_account_list: Virtual function for querying the list of * accounts. * @lookup_acl_accounts: Virtual function to find accounts by their ID. * @lookup_acl_account_by_name: Virtual function to find an account by its * name. * @create_acl_account: Virtual function to create a new account. * @remove_acl_account: Virtual function to remove an account. * @query_acl: Virtual function for querying the ACL for a node for all * other users. * @has_acl: Virtual function for checking whether the ACL has been queried * or is otherwise available. * @get_acl: Virtual function for obtaining the full ACL for a node. * @set_acl: Virtual function for changing the ACL for one node. * * Signals and virtual functions for the #InfBrowser interface. */ struct _InfBrowserInterface { /*< private >*/ GTypeInterface parent; /* Signals */ /*< public >*/ void (*error)(InfBrowser* browser, const GError* error); void (*node_added)(InfBrowser* browser, const InfBrowserIter* iter, InfRequest* request); void (*node_removed)(InfBrowser* browser, const InfBrowserIter* iter, InfRequest* request); void (*subscribe_session)(InfBrowser* browser, const InfBrowserIter* iter, InfSessionProxy* proxy, InfRequest* request); void (*unsubscribe_session)(InfBrowser* browser, const InfBrowserIter* iter, InfSessionProxy* proxy, InfRequest* request); void (*begin_request)(InfBrowser* browser, const InfBrowserIter* iter, InfRequest* request); void (*acl_account_added)(InfBrowser* browser, const InfAclAccount* account, InfRequest* request); void (*acl_account_removed)(InfBrowser* browser, const InfAclAccount* account, InfRequest* request); void (*acl_local_account_changed)(InfBrowser* browser, const InfAclAccount* account, InfRequest* request); void (*acl_changed)(InfBrowser* browser, const InfBrowserIter* iter, const InfAclSheetSet* sheet_set, InfRequest* request); /* Virtual functions */ gboolean (*get_root)(InfBrowser* browser, InfBrowserIter* iter); gboolean (*get_next)(InfBrowser* browser, InfBrowserIter* iter); gboolean (*get_prev)(InfBrowser* browser, InfBrowserIter* iter); gboolean (*get_parent)(InfBrowser* browser, InfBrowserIter* iter); gboolean (*get_child)(InfBrowser* browser, InfBrowserIter* iter); InfRequest* (*explore)(InfBrowser* browser, const InfBrowserIter* iter, InfRequestFunc func, gpointer user_data); gboolean (*get_explored)(InfBrowser* browser, const InfBrowserIter* iter); gboolean (*is_subdirectory)(InfBrowser* browser, const InfBrowserIter* iter); InfRequest* (*add_note)(InfBrowser* browser, const InfBrowserIter* iter, const char* name, const char* type, const InfAclSheetSet* acl, InfSession* session, gboolean initial_subscribe, InfRequestFunc func, gpointer user_data); InfRequest* (*add_subdirectory)(InfBrowser* browser, const InfBrowserIter* iter, const char* name, const InfAclSheetSet* acl, InfRequestFunc func, gpointer user_data); InfRequest* (*remove_node)(InfBrowser* browser, const InfBrowserIter* iter, InfRequestFunc func, gpointer user_data); const gchar* (*get_node_name)(InfBrowser* browser, const InfBrowserIter* iter); const gchar* (*get_node_type)(InfBrowser* browser, const InfBrowserIter* iter); InfRequest* (*subscribe)(InfBrowser* browser, const InfBrowserIter* iter, InfRequestFunc func, gpointer user_data); InfSessionProxy* (*get_session)(InfBrowser* browser, const InfBrowserIter* iter); GSList* (*list_pending_requests)(InfBrowser* browser, const InfBrowserIter* iter, const gchar* request_type); gboolean (*iter_from_request)(InfBrowser* browser, InfRequest* request, InfBrowserIter* iter); const InfAclAccount* (*get_acl_default_account)(InfBrowser* browser); const InfAclAccount* (*get_acl_local_account)(InfBrowser* browser); InfRequest* (*query_acl_account_list)(InfBrowser* browser, InfRequestFunc func, gpointer user_data); InfRequest* (*lookup_acl_accounts)(InfBrowser* browser, const InfAclAccountId* ids, guint n_ids, InfRequestFunc func, gpointer user_data); InfRequest* (*lookup_acl_account_by_name)(InfBrowser* browser, const gchar* name, InfRequestFunc func, gpointer user_data); InfRequest* (*create_acl_account)(InfBrowser* browser, gnutls_x509_crq_t crq, InfRequestFunc func, gpointer user_data); InfRequest* (*remove_acl_account)(InfBrowser* browser, InfAclAccountId account, InfRequestFunc func, gpointer user_data); InfRequest* (*query_acl)(InfBrowser* browser, const InfBrowserIter* iter, InfRequestFunc func, gpointer user_data); gboolean (*has_acl)(InfBrowser* browser, const InfBrowserIter* iter, InfAclAccountId account); const InfAclSheetSet* (*get_acl)(InfBrowser* browser, const InfBrowserIter* iter); InfRequest* (*set_acl)(InfBrowser* browser, const InfBrowserIter* iter, const InfAclSheetSet* sheet_set, InfRequestFunc func, gpointer user_data); }; GType inf_browser_status_get_type(void) G_GNUC_CONST; GType inf_browser_get_type(void) G_GNUC_CONST; gboolean inf_browser_get_root(InfBrowser* browser, InfBrowserIter* iter); gboolean inf_browser_get_next(InfBrowser* browser, InfBrowserIter* iter); gboolean inf_browser_get_prev(InfBrowser* browser, InfBrowserIter* iter); gboolean inf_browser_get_parent(InfBrowser* browser, InfBrowserIter* iter); gboolean inf_browser_get_child(InfBrowser* browser, InfBrowserIter* iter); gboolean inf_browser_is_ancestor(InfBrowser* browser, const InfBrowserIter* ancestor, const InfBrowserIter* iter); InfRequest* inf_browser_explore(InfBrowser* browser, const InfBrowserIter* iter, InfRequestFunc func, gpointer user_data); gboolean inf_browser_get_explored(InfBrowser* browser, const InfBrowserIter* iter); gboolean inf_browser_is_subdirectory(InfBrowser* browser, const InfBrowserIter* iter); InfRequest* inf_browser_add_note(InfBrowser* browser, const InfBrowserIter* iter, const char* name, const char* type, const InfAclSheetSet* acl, InfSession* session, gboolean initial_subscribe, InfRequestFunc func, gpointer user_data); InfRequest* inf_browser_add_subdirectory(InfBrowser* browser, const InfBrowserIter* iter, const char* name, const InfAclSheetSet* acl, InfRequestFunc func, gpointer user_data); InfRequest* inf_browser_remove_node(InfBrowser* browser, const InfBrowserIter* iter, InfRequestFunc func, gpointer user_data); const gchar* inf_browser_get_node_name(InfBrowser* browser, const InfBrowserIter* iter); const gchar* inf_browser_get_node_type(InfBrowser* browser, const InfBrowserIter* iter); gchar* inf_browser_get_path(InfBrowser* browser, const InfBrowserIter* iter); InfRequest* inf_browser_subscribe(InfBrowser* browser, const InfBrowserIter* iter, InfRequestFunc func, gpointer user_data); InfSessionProxy* inf_browser_get_session(InfBrowser* browser, const InfBrowserIter* iter); GSList* inf_browser_list_pending_requests(InfBrowser* browser, const InfBrowserIter* iter, const gchar* request_type); gboolean inf_browser_iter_from_request(InfBrowser* browser, InfRequest* request, InfBrowserIter* iter); InfRequest* inf_browser_get_pending_request(InfBrowser* browser, const InfBrowserIter* iter, const gchar* request_type); const InfAclAccount* inf_browser_get_acl_default_account(InfBrowser* browser); const InfAclAccount* inf_browser_get_acl_local_account(InfBrowser* browser); InfRequest* inf_browser_query_acl_account_list(InfBrowser* browser, InfRequestFunc func, gpointer user_data); InfRequest* inf_browser_lookup_acl_accounts(InfBrowser* browser, const InfAclAccountId* ids, guint n_ids, InfRequestFunc func, gpointer user_data); InfRequest* inf_browser_lookup_acl_account_by_name(InfBrowser* browser, const gchar* name, InfRequestFunc func, gpointer user_data); InfRequest* inf_browser_create_acl_account(InfBrowser* browser, gnutls_x509_crq_t crq, InfRequestFunc func, gpointer user_data); InfRequest* inf_browser_remove_acl_account(InfBrowser* browser, InfAclAccountId account, InfRequestFunc func, gpointer user_data); InfRequest* inf_browser_query_acl(InfBrowser* browser, const InfBrowserIter* iter, InfRequestFunc func, gpointer user_data); gboolean inf_browser_has_acl(InfBrowser* browser, const InfBrowserIter* iter, InfAclAccountId account); const InfAclSheetSet* inf_browser_get_acl(InfBrowser* browser, const InfBrowserIter* iter); InfRequest* inf_browser_set_acl(InfBrowser* browser, const InfBrowserIter* iter, const InfAclSheetSet* sheet_set, InfRequestFunc func, gpointer user_data); gboolean inf_browser_check_acl(InfBrowser* browser, const InfBrowserIter* iter, InfAclAccountId account, const InfAclMask* check_mask, InfAclMask* out_mask); void inf_browser_error(InfBrowser* browser, const GError* error); void inf_browser_node_added(InfBrowser* browser, const InfBrowserIter* iter, InfRequest* request); void inf_browser_node_removed(InfBrowser* browser, const InfBrowserIter* iter, InfRequest* request); void inf_browser_subscribe_session(InfBrowser* browser, const InfBrowserIter* iter, InfSessionProxy* proxy, InfRequest* request); void inf_browser_unsubscribe_session(InfBrowser* browser, const InfBrowserIter* iter, InfSessionProxy* proxy, InfRequest* request); void inf_browser_begin_request(InfBrowser* browser, const InfBrowserIter* iter, InfRequest* request); void inf_browser_acl_account_added(InfBrowser* browser, const InfAclAccount* account, InfRequest* request); void inf_browser_acl_account_removed(InfBrowser* browser, const InfAclAccount* account, InfRequest* request); void inf_browser_acl_local_account_changed(InfBrowser* browser, const InfAclAccount* account, InfRequest* request); void inf_browser_acl_changed(InfBrowser* browser, const InfBrowserIter* iter, const InfAclSheetSet* sheet_set, InfRequest* request); G_END_DECLS #endif /* __INF_BROWSER_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-file-util.h0000644000000000000000000000013213034342512022225 xustar0030 mtime=1483851082.033718448 30 atime=1483851082.033718448 30 ctime=1488261588.948139179 libinfinity-0.7.1/libinfinity/common/inf-file-util.h0000644000175000017500000000672113034342512022765 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_FILE_UTIL_H__ #define __INF_FILE_UTIL_H__ #include G_BEGIN_DECLS /** * InfFileType: * @INF_FILE_TYPE_UNKNOWN: Unknown file type. * @INF_FILE_TYPE_REG: File is a regular file. * @INF_FILE_TYPE_DIR: File is a directory. * @INF_FILE_TYPE_LNK: File is a symbolic link. * * This type represents the possible file types that * inf_file_util_list_directory() can report. */ typedef enum _InfFileType { INF_FILE_TYPE_UNKNOWN, INF_FILE_TYPE_REG, INF_FILE_TYPE_DIR, INF_FILE_TYPE_LNK } InfFileType; /** * InfFileListFunc: * @name: The name of the current file. * @path: The full path to the current file. * @type: The type of the current file. * @user_data: User data specified at the time of the call. * @error: Location to store error information, if any, or %NULL. * * This is the prototype of the callback function passed to * inf_file_util_list_directory(). If the function returns %FALSE then * directory traversal is stopped immediately. In addition @error can be set * and it is propagated to the caller of inf_file_util_list_directory(). * * Returns: %TRUE if the iteration should be continued or %FALSE otherwise. */ typedef gboolean(*InfFileListFunc)(const gchar* name, const gchar* path, InfFileType type, gpointer user_data, GError** error); gboolean inf_file_util_create_single_directory(const gchar* path, int mode, GError** error); gboolean inf_file_util_create_directory(const gchar* path, int mode, GError** error); gboolean inf_file_util_list_directory(const gchar* path, InfFileListFunc func, gpointer user_data, GError** error); gboolean inf_file_util_delete_file(const gchar* path, GError** error); gboolean inf_file_util_delete_single_directory(const gchar* path, GError** error); gboolean inf_file_util_delete_directory(const gchar* path, GError** error); gboolean inf_file_util_delete(const gchar* path, GError** error); gboolean inf_file_util_write_private_data(const gchar* filename, const void* data, size_t length, GError** error); G_END_DECLS #endif /* __INF_FILE_UTIL_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-native-socket.h0000644000000000000000000000013213034342512023107 xustar0030 mtime=1483851082.033718448 30 atime=1483851082.033718448 30 ctime=1488261588.956139161 libinfinity-0.7.1/libinfinity/common/inf-native-socket.h0000644000175000017500000000420413034342512023641 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_NATIVE_SOCKET_H__ #define __INF_NATIVE_SOCKET_H__ #include #ifdef G_OS_WIN32 # include #endif G_BEGIN_DECLS /** * InfNativeSocket: * * Native socket type on the target platform. This typedef is a simple #int * on Unix and a #SOCKET on Windows. */ #ifdef G_OS_WIN32 typedef SOCKET InfNativeSocket; #else typedef int InfNativeSocket; #endif #ifdef G_OS_WIN32 # define INF_NATIVE_SOCKET_SENDRECV_FLAGS 0 # define INF_NATIVE_SOCKET_LAST_ERROR WSAGetLastError() # define INF_NATIVE_SOCKET_EINTR WSAEINTR # define INF_NATIVE_SOCKET_EAGAIN WSAEWOULDBLOCK /* This is not a typo here. On Windows, connect() returns WSAEWOULDBLOCK on * a non-blocking socket. */ # define INF_NATIVE_SOCKET_EINPROGRESS WSAEWOULDBLOCK #else extern const int INF_NATIVE_SOCKET_SENDRECV_FLAGS; # define INF_NATIVE_SOCKET_LAST_ERROR errno # define INF_NATIVE_SOCKET_EINTR EINTR # define INF_NATIVE_SOCKET_EAGAIN EAGAIN # define INF_NATIVE_SOCKET_EINPROGRESS EINPROGRESS # define closesocket(s) close(s) # define INVALID_SOCKET -1 #endif GQuark inf_native_socket_error_quark(void); void inf_native_socket_make_error(int code, GError** error); G_END_DECLS #endif /* __INF_NATIVE_SOCKET_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-request-result.h0000644000000000000000000000013213034342512023337 xustar0030 mtime=1483851082.033718448 30 atime=1483851082.033718448 30 ctime=1488261588.960139153 libinfinity-0.7.1/libinfinity/common/inf-request-result.h0000644000175000017500000001574613034342512024106 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_REQUEST_RESULT_H__ #define __INF_REQUEST_RESULT_H__ #include #include #include #include G_BEGIN_DECLS #define INF_TYPE_REQUEST_RESULT (inf_request_result_get_type()) GType inf_request_result_get_type(void) G_GNUC_CONST; InfRequestResult* inf_request_result_new(gpointer data, gsize len); InfRequestResult* inf_request_result_copy(const InfRequestResult* result); void inf_request_result_free(InfRequestResult* result); gconstpointer inf_request_result_get(const InfRequestResult* result, gsize* length); InfRequestResult* inf_request_result_make_add_node(InfBrowser* browser, const InfBrowserIter* iter, const InfBrowserIter* new_node); void inf_request_result_get_add_node(const InfRequestResult* result, InfBrowser** browser, const InfBrowserIter** iter, const InfBrowserIter** new_node); InfRequestResult* inf_request_result_make_remove_node(InfBrowser* browser, const InfBrowserIter* iter); void inf_request_result_get_remove_node(const InfRequestResult* result, InfBrowser** browser, const InfBrowserIter** iter); InfRequestResult* inf_request_result_make_explore_node(InfBrowser* browser, const InfBrowserIter* iter); void inf_request_result_get_explore_node(const InfRequestResult* result, InfBrowser** browser, const InfBrowserIter** iter); InfRequestResult* inf_request_result_make_save_session(InfBrowser* browser, const InfBrowserIter* iter); void inf_request_result_get_save_session(const InfRequestResult* result, InfBrowser** browser, const InfBrowserIter** iter); InfRequestResult* inf_request_result_make_subscribe_session(InfBrowser* browser, const InfBrowserIter* iter, InfSessionProxy* proxy); void inf_request_result_get_subscribe_session(const InfRequestResult* result, InfBrowser** browser, const InfBrowserIter** iter, InfSessionProxy** proxy); InfRequestResult* inf_request_result_make_subscribe_chat(InfBrowser* browser, InfSessionProxy* proxy); void inf_request_result_get_subscribe_chat(const InfRequestResult* result, InfBrowser** browser, InfSessionProxy** proxy); InfRequestResult* inf_request_result_make_query_acl_account_list(InfBrowser* browser, const InfAclAccount* accounts, guint n_accounts, gboolean does_notifications); void inf_request_result_get_query_acl_account_list(const InfRequestResult* result, InfBrowser** browser, const InfAclAccount** accounts, guint* n_accounts, gboolean* does_notifications); InfRequestResult* inf_request_result_make_lookup_acl_accounts(InfBrowser* browser, const InfAclAccount* accounts, guint n_accounts); void inf_request_result_get_lookup_acl_accounts(const InfRequestResult* result, InfBrowser** browser, const InfAclAccount** accounts, guint* n_accounts); InfRequestResult* inf_request_result_make_create_acl_account(InfBrowser* browser, const InfAclAccount* account, InfCertificateChain* certificate); void inf_request_result_get_create_acl_account(const InfRequestResult* result, InfBrowser** browser, const InfAclAccount** account, InfCertificateChain** certificate); InfRequestResult* inf_request_result_make_remove_acl_account(InfBrowser* browser, const InfAclAccount* account); void inf_request_result_get_remove_acl_account(const InfRequestResult* result, InfBrowser** browser, const InfAclAccount** account); InfRequestResult* inf_request_result_make_query_acl(InfBrowser* browser, const InfBrowserIter* iter, const InfAclSheetSet* sheet_set); void inf_request_result_get_query_acl(const InfRequestResult* result, InfBrowser** browser, const InfBrowserIter** iter, const InfAclSheetSet** sheet_set); InfRequestResult* inf_request_result_make_set_acl(InfBrowser* browser, const InfBrowserIter* iter); void inf_request_result_get_set_acl(const InfRequestResult* result, InfBrowser** browser, const InfBrowserIter** iter); InfRequestResult* inf_request_result_make_join_user(InfSessionProxy* proxy, InfUser* user); void inf_request_result_get_join_user(const InfRequestResult* result, InfSessionProxy** proxy, InfUser** user); G_END_DECLS #endif /* __INF_REQUEST_RESULT_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-certificate-chain.c0000644000000000000000000000013213034342512023670 xustar0030 mtime=1483851082.029718427 30 atime=1483851082.029718427 30 ctime=1488261589.044138969 libinfinity-0.7.1/libinfinity/common/inf-certificate-chain.c0000644000175000017500000001123013034342512024417 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-certificate-chain * @title: InfCertificateChain * @short_description: X.509 certificate chains * @see_also: #InfXmppConnection * @include: libinfinity/common/inf-certificate-chain.h * @stability: Unstable * * #InfCertificateChain is a reference-counted wrapper around an array of * gnutls_x509_crt_t structures, representing a certificate chain. **/ #include #include G_DEFINE_BOXED_TYPE(InfCertificateChain, inf_certificate_chain, inf_certificate_chain_ref, inf_certificate_chain_unref) struct _InfCertificateChain { guint ref_count; gnutls_x509_crt_t* certs; guint n_certs; }; /** * inf_certificate_chain_new: * @certs: (array length=n_certs): Array of certificates. * @n_certs: Number of elements in @certs. * * Creates a new #InfCertificateChain with the given certificates. The @certs * array needs to be allocated with g_malloc. This function takes ownership * of @certs. * * Return Value: (transfer full): A new #InfCertificateChain. **/ InfCertificateChain* inf_certificate_chain_new(gnutls_x509_crt_t* certs, guint n_certs) { InfCertificateChain* chain; chain = g_slice_new(InfCertificateChain); chain->ref_count = 1; chain->certs = certs; chain->n_certs = n_certs; return chain; } /** * inf_certificate_chain_ref: * @chain: A #InfCertificateChain: * * Increases the reference count of @chain by one. * * Returns: The same @chain. */ InfCertificateChain* inf_certificate_chain_ref(InfCertificateChain* chain) { ++ chain->ref_count; return chain; } /** * inf_certificate_chain_unref: * @chain: A #InfCertificateChain. * * Decreases the reference count of @chain by one. If the reference count * reaches zero, then @chain is freed. */ void inf_certificate_chain_unref(InfCertificateChain* chain) { guint i; -- chain->ref_count; if(chain->ref_count == 0) { for(i = 0; i < chain->n_certs; ++ i) gnutls_x509_crt_deinit(chain->certs[i]); g_free(chain->certs); g_slice_free(InfCertificateChain, chain); } } /** * inf_certificate_chain_get_raw: * @chain: A #InfCertificateChain. * * Returns the raw array of certificates in the chain. * * Returns: An array of certificates owned by the chain. */ gnutls_x509_crt_t* inf_certificate_chain_get_raw(const InfCertificateChain* chain) { return chain->certs; } /** * inf_certificate_chain_get_root_certificate: * @chain: A #InfCertificateChain. * * Returns the last certificate in the chain. * * Returns: The last certificate in the chain. */ gnutls_x509_crt_t inf_certificate_chain_get_root_certificate(const InfCertificateChain* chain) { return chain->certs[chain->n_certs - 1]; } /** * inf_certificate_chain_get_own_certificate: * @chain: A #InfCertificateChain. * * TODO: Rename this function into something more appropriate. * * Returns the first certificate in the chain. * * Returns: The first certificate in the chain. */ gnutls_x509_crt_t inf_certificate_chain_get_own_certificate(const InfCertificateChain* chain) { return chain->certs[0]; } /** * inf_certificate_chain_get_nth_certificate: * @chain: A #InfCertificateChain. * @n: Index of the certificate to retrieve. * * Returns the @nth certificate in the chain. * * Returns: The nth certificate in the chain. */ gnutls_x509_crt_t inf_certificate_chain_get_nth_certificate(const InfCertificateChain* chain, guint n) { g_return_val_if_fail(n < chain->n_certs, NULL); return chain->certs[n]; } /** * inf_certificate_chain_get_n_certificates: * @chain: A #InfCertificateChain. * * Returns the number of certificates in @chain. * * Returns: The number of certificates in @chain. */ guint inf_certificate_chain_get_n_certificates(const InfCertificateChain* chain) { return chain->n_certs; } libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-discovery.h0000644000000000000000000000013213034342512022342 xustar0030 mtime=1483851082.033718448 30 atime=1483851082.033718448 30 ctime=1488261588.944139188 libinfinity-0.7.1/libinfinity/common/inf-discovery.h0000644000175000017500000001261713034342512023103 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_DISCOVERY_H__ #define __INF_DISCOVERY_H__ #include #include G_BEGIN_DECLS #define INF_TYPE_DISCOVERY (inf_discovery_get_type()) #define INF_DISCOVERY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_TYPE_DISCOVERY, InfDiscovery)) #define INF_IS_DISCOVERY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_TYPE_DISCOVERY)) #define INF_DISCOVERY_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), INF_TYPE_DISCOVERY, InfDiscoveryInterface)) /** * InfDiscovery: * * #InfDiscovery is an opaque data type. You should only access it * via the public API functions. */ typedef struct _InfDiscovery InfDiscovery; typedef struct _InfDiscoveryInterface InfDiscoveryInterface; /** * InfDiscoveryInfo: * * #InfDiscoveryInfo is an opaque data type. You should only access it * via the public API functions. */ typedef struct _InfDiscoveryInfo InfDiscoveryInfo; /** * InfDiscoveryResolvCompleteFunc: * @info: The resolved #InfDiscoveryInfo. * @connection: The resulting #InfXmlConnection. * @error: Reason in case of failure. * @user_data: The user_data passed to inf_discovery_resolve(). * * This callback is called when a call to inf_discovery_resolve() finished. */ typedef void(*InfDiscoveryResolvCompleteFunc)(InfDiscoveryInfo* info, InfXmlConnection* connection, const GError* error, gpointer user_data); /** * InfDiscoveryInterface: * @discover: Virtual function to start discovery of services of the given * type. If the discovery was already started ealier, then this function does * nothing. * @get_discovered: Virtual function to retrieve a list of * #InfDiscoveryInfos that represent discovered services. * It needs to be freed by the caller via g_slist_free(). * @resolve: Virtual function that attempts to resolve the given discovery * info. It guarantees to either call @complete_func or @error_func when the * process has finished. * @info_get_service_name: Returns the service name of the given * #InfDiscoveryInfo as a new string, to be freed by the caller with g_free(). * @info_get_service_type: Returns the type of the discovered service of the * given #InfDiscoveryInfo as a static string. * @discovered: Default signal handler for the #InfDiscovery::discovered * signal. * @undiscovered: Default signal handler for the #InfDiscovery::undiscovered * signal. * * The virtual methods and default signal handlers of #InfDiscovery. * Implementing these allows discovering infinote servers. */ struct _InfDiscoveryInterface { /*< private >*/ GTypeInterface parent; /*< public >*/ void (*discover)(InfDiscovery* discovery, const gchar* type); GSList* (*get_discovered)(InfDiscovery* discovery, const gchar* type); void (*resolve)(InfDiscovery* discovery, InfDiscoveryInfo* info, InfDiscoveryResolvCompleteFunc complete_func, gpointer user_data); gchar*(*info_get_service_name)(InfDiscovery* discovery, InfDiscoveryInfo* info); const gchar*(*info_get_service_type)(InfDiscovery* discovery, InfDiscoveryInfo* info); /* Signals */ void (*discovered)(InfDiscovery* discovery, InfDiscoveryInfo* info); void (*undiscovered)(InfDiscovery* discovery, InfDiscoveryInfo* info); }; GType inf_discovery_get_type(void) G_GNUC_CONST; void inf_discovery_discover(InfDiscovery* discovery, const gchar* type); GSList* inf_discovery_get_discovered(InfDiscovery* discovery, const gchar* type); void inf_discovery_resolve(InfDiscovery* discovery, InfDiscoveryInfo* info, InfDiscoveryResolvCompleteFunc complete_func, gpointer user_data); gchar* inf_discovery_info_get_service_name(InfDiscovery* discovery, InfDiscoveryInfo* info); const gchar* inf_discovery_info_get_service_type(InfDiscovery* discovery, InfDiscoveryInfo* info); void inf_discovery_discovered(InfDiscovery* discovery, InfDiscoveryInfo* info); void inf_discovery_undiscovered(InfDiscovery* discovery, InfDiscoveryInfo* info); G_END_DECLS #endif /* __INF_DISCOVERY_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-discovery-avahi.c0000644000000000000000000000013213034342512023423 xustar0030 mtime=1483851082.029718427 30 atime=1483851082.029718427 30 ctime=1488261589.052138951 libinfinity-0.7.1/libinfinity/common/inf-discovery-avahi.c0000644000175000017500000013527213034342512024167 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-discovery-avahi * @short_description: Service Discovery via Avahi * @include: libinfinity/common/inf-discovery-avahi.h * @see_also: #InfDiscovery, #InfLocalPublisher * * #InfDiscoveryAvahi implements the #InfDiscovery and #InfLocalPublisher * interfaces on top of avahi. It resolves services to client-side * #InfXmppConnections. * * This class is only available if the macro * LIBINFINITY_HAVE_AVAHI is defined. */ #include #include #include #include #include /* LIBINFINITY_HAVE_AVAHI */ #ifdef LIBINFINITY_HAVE_AVAHI #include #include #include #include #include #include #include #include #include /* Required by FreeBSD, see #430 */ #include /* For if_indextoname */ #include struct AvahiWatch { InfDiscoveryAvahi* avahi; InfIoWatch* watch; InfNativeSocket socket; AvahiWatchEvent occured_events; AvahiWatchCallback callback; void* userdata; }; struct AvahiTimeout { InfDiscoveryAvahi* avahi; InfIoTimeout* timeout; AvahiTimeoutCallback callback; void* userdata; }; typedef struct _InfDiscoveryAvahiInfoResolv InfDiscoveryAvahiInfoResolv; struct _InfDiscoveryAvahiInfoResolv { InfDiscoveryResolvCompleteFunc complete_func; gpointer user_data; }; struct _InfDiscoveryInfo { gchar* service_name; /* pointing to InfDiscoveryAvahiDiscoverInfo.type: */ const gchar* service_type; gchar* domain; AvahiIfIndex interface; AvahiProtocol protocol; AvahiServiceResolver* service_resolver; InfXmppConnection* resolved; GSList* resolv; }; struct _InfLocalPublisherItem { gchar* type; char* name; guint port; AvahiEntryGroup* entry_group; }; typedef struct _InfDiscoveryAvahiDiscoverInfo InfDiscoveryAvahiDiscoverInfo; struct _InfDiscoveryAvahiDiscoverInfo { gchar* type; /* also used as key in hash table */ AvahiServiceBrowser* service_browser; GSList* discovered; }; typedef struct _InfDiscoveryAvahiPrivate InfDiscoveryAvahiPrivate; struct _InfDiscoveryAvahiPrivate { AvahiPoll poll; InfIo* io; InfXmppManager* xmpp_manager; InfXmppConnectionSecurityPolicy security_policy; InfKeepalive keepalive; InfCertificateCredentials* creds; InfSaslContext* sasl_context; gchar* sasl_mechanisms; AvahiClient* client; GSList* published; GHashTable* discovered; /* type -> InfDiscoveryAvahiDiscoverInfo */ }; enum { PROP_0, /* construct only */ PROP_XMPP_MANAGER, PROP_IO, /* read/write */ PROP_CREDENTIALS, PROP_SASL_CONTEXT, PROP_SASL_MECHANISMS, PROP_SECURITY_POLICY, PROP_KEEPALIVE }; #define INF_DISCOVERY_AVAHI_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INF_TYPE_DISCOVERY_AVAHI, InfDiscoveryAvahiPrivate)) static GQuark inf_discovery_avahi_error_quark; static void inf_discovery_avahi_discovery_iface_init(InfDiscoveryInterface* iface); static void inf_discovery_avahi_local_publisher_iface_init(InfLocalPublisherInterface* iface); G_DEFINE_TYPE_WITH_CODE(InfDiscoveryAvahi, inf_discovery_avahi, G_TYPE_OBJECT, G_ADD_PRIVATE(InfDiscoveryAvahi) G_IMPLEMENT_INTERFACE(INF_TYPE_DISCOVERY, inf_discovery_avahi_discovery_iface_init) G_IMPLEMENT_INTERFACE(INF_TYPE_LOCAL_PUBLISHER, inf_discovery_avahi_local_publisher_iface_init)) /* * Destroy notification callbacks */ static void inf_discovery_avahi_discovery_info_resolved_destroy_cb(gpointer user_data, GObject* object) { InfDiscoveryInfo* info; info = (InfDiscoveryInfo*)user_data; /* Connection has gone, next time we resolve this discovery we cannot use * the cached connection anymore. */ info->resolved = NULL; } static void inf_discovery_avahi_info_resolv_complete(InfDiscoveryInfo* info) { GSList* item; InfDiscoveryAvahiInfoResolv* resolv; g_assert(info->resolved != NULL); for(item = info->resolv; item != NULL; item = g_slist_next(item)) { resolv = (InfDiscoveryAvahiInfoResolv*)item->data; resolv->complete_func( info, INF_XML_CONNECTION(info->resolved), NULL, resolv->user_data ); g_slice_free(InfDiscoveryAvahiInfoResolv, resolv); } g_slist_free(info->resolv); info->resolv = NULL; } static void inf_discovery_avahi_info_resolv_error(InfDiscoveryInfo* info, const GError* error) { GSList* item; InfDiscoveryAvahiInfoResolv* resolv; for(item = info->resolv; item != NULL; item = g_slist_next(item)) { resolv = (InfDiscoveryAvahiInfoResolv*)item->data; resolv->complete_func(info, NULL, error, resolv->user_data); g_slice_free(InfDiscoveryAvahiInfoResolv, resolv); } g_slist_free(info->resolv); info->resolv = NULL; } static void inf_discovery_avahi_discovery_info_free(InfDiscoveryInfo* info) { g_free(info->service_name); g_free(info->domain); if(info->service_resolver != NULL) avahi_service_resolver_free(info->service_resolver); if(info->resolved != NULL) { g_object_weak_unref( G_OBJECT(info->resolved), inf_discovery_avahi_discovery_info_resolved_destroy_cb, info ); } /* TODO: Get an error from somewhere. If the avahi daemon goes down, * all InfDiscoveryInfos are discarded, but it would be nice to show a * correct error message for pending resolvs. */ inf_discovery_avahi_info_resolv_error(info, NULL); g_slist_free(info->resolv); g_slice_free(InfDiscoveryInfo, info); } static void inf_discovery_avahi_publisher_item_free(gpointer data) { InfLocalPublisherItem* item; item = (InfLocalPublisherItem*)data; if(item->entry_group != NULL) avahi_entry_group_free(item->entry_group); g_free(item->type); avahi_free(item->name); g_slice_free(InfLocalPublisherItem, item); } static void inf_discovery_avahi_discover_info_free(gpointer data) { InfDiscoveryAvahiDiscoverInfo* info; GSList* item; info = (InfDiscoveryAvahiDiscoverInfo*)data; for(item = info->discovered; item != NULL; item = g_slist_next(item)) inf_discovery_avahi_discovery_info_free((InfDiscoveryInfo*)item->data); if(info->service_browser != NULL) avahi_service_browser_free(info->service_browser); g_slist_free(info->discovered); g_free(info->type); g_slice_free(InfDiscoveryAvahiDiscoverInfo, info); } /* * Avahi callbacks and utilities */ static void inf_discovery_avahi_service_resolver_callback(AvahiServiceResolver* resolver, AvahiIfIndex interface, AvahiProtocol protocol, AvahiResolverEvent event, const char* name, const char* type, const char* domain, const char* host_name, const AvahiAddress* address, uint16_t port, AvahiStringList* txt, AvahiLookupResultFlags flags, void* userdata) { InfDiscoveryAvahi* avahi; InfDiscoveryAvahiPrivate* priv; InfDiscoveryAvahiDiscoverInfo* info; InfDiscoveryInfo* discovery_info; GSList* item; InfIpAddress* inf_addr; InfTcpConnection* tcp; InfXmppConnection* xmpp; InfXmlConnectionStatus status; GError* error; avahi = INF_DISCOVERY_AVAHI(userdata); priv = INF_DISCOVERY_AVAHI_PRIVATE(avahi); info = g_hash_table_lookup(priv->discovered, type); g_assert(info != NULL); /* Lookup discovery info for this service resolver */ for(item = info->discovered; item != NULL; item = g_slist_next(item)) { discovery_info = (InfDiscoveryInfo*)item->data; if(discovery_info->service_resolver == resolver) break; } /* If there was no discovery_info, we should have deleted the service * resolver before this callback could happen. */ g_assert(item != NULL); /* There is no need to create a service resolver if this is * already resolved. */ g_assert(discovery_info->resolved == NULL); /* So that the callbacks can recreate the resolver by resolving this * info again: */ discovery_info->service_resolver = NULL; switch(event) { case AVAHI_RESOLVER_FOUND: switch(address->proto) { case AVAHI_PROTO_INET: inf_addr = inf_ip_address_new_raw4(address->data.ipv4.address); break; case AVAHI_PROTO_INET6: inf_addr = inf_ip_address_new_raw6(address->data.ipv6.address); break; default: g_assert_not_reached(); break; } xmpp = inf_xmpp_manager_lookup_connection_by_address( priv->xmpp_manager, inf_addr, port ); if(xmpp == NULL) { tcp = inf_tcp_connection_new(priv->io, inf_addr, port); g_object_set( G_OBJECT(tcp), "device-index", discovery_info->interface, NULL ); error = NULL; if(!inf_tcp_connection_set_keepalive(tcp, &priv->keepalive, &error) || !inf_tcp_connection_open(tcp, &error)) { inf_discovery_avahi_info_resolv_error(discovery_info, error); g_error_free(error); g_object_unref(tcp); } else { xmpp = inf_xmpp_connection_new( tcp, INF_XMPP_CONNECTION_CLIENT, NULL, host_name, priv->security_policy, priv->creds, priv->sasl_context, priv->sasl_context == NULL ? NULL : priv->sasl_mechanisms ); g_object_unref(tcp); inf_xmpp_manager_add_connection(priv->xmpp_manager, xmpp); discovery_info->resolved = xmpp; g_object_weak_ref( G_OBJECT(xmpp), inf_discovery_avahi_discovery_info_resolved_destroy_cb, discovery_info ); inf_discovery_avahi_info_resolv_complete(discovery_info); g_object_unref(xmpp); } } else { discovery_info->resolved = xmpp; g_object_weak_ref( G_OBJECT(xmpp), inf_discovery_avahi_discovery_info_resolved_destroy_cb, discovery_info ); g_object_get(G_OBJECT(xmpp), "status", &status, NULL); /* TODO: There is similar code in inf_discovery_avahi_resolve; should * probably go into an extra function. */ if(status == INF_XML_CONNECTION_CLOSING) { /* TODO: That's a bit a sad case here. We should wait for the * connection being closed, and then reopen it: */ inf_discovery_avahi_info_resolv_error(discovery_info, NULL); } else if(status == INF_XML_CONNECTION_CLOSED) { error = NULL; if(!inf_xml_connection_open(INF_XML_CONNECTION(xmpp), &error)) { inf_discovery_avahi_info_resolv_error(discovery_info, error); g_error_free(error); } else { inf_discovery_avahi_info_resolv_complete(discovery_info); } } else { inf_discovery_avahi_info_resolv_complete(discovery_info); } } inf_ip_address_free(inf_addr); break; case AVAHI_RESOLVER_FAILURE: error = NULL; g_set_error_literal( &error, inf_discovery_avahi_error_quark, avahi_client_errno(avahi_service_resolver_get_client(resolver)), avahi_strerror( avahi_client_errno(avahi_service_resolver_get_client(resolver)) ) ); inf_discovery_avahi_info_resolv_error(discovery_info, error); g_error_free(error); break; } avahi_service_resolver_free(resolver); } static void inf_discovery_avahi_perform_undiscover(InfDiscoveryAvahi* avahi, InfDiscoveryAvahiDiscoverInfo* info); static void inf_discovery_avahi_perform_unpublish_item(InfLocalPublisherItem* item); static void inf_discovery_avahi_service_browser_callback(AvahiServiceBrowser* browser, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char* name, const char* type, const char* domain, AvahiLookupResultFlags flags, void* userdata) { InfDiscoveryAvahi* avahi; InfDiscoveryAvahiPrivate* priv; InfDiscoveryAvahiDiscoverInfo* info; InfDiscoveryInfo* discovery_info; GSList* item; avahi = INF_DISCOVERY_AVAHI(userdata); priv = INF_DISCOVERY_AVAHI_PRIVATE(avahi); info = g_hash_table_lookup(priv->discovered, type); g_assert(info != NULL); switch(event) { case AVAHI_BROWSER_NEW: /* Ignore what we published ourselves */ if((flags & AVAHI_LOOKUP_RESULT_OUR_OWN) == 0) { discovery_info = g_slice_new(InfDiscoveryInfo); discovery_info->service_name = g_strdup(name); discovery_info->service_type = info->type; discovery_info->domain = g_strdup(domain); discovery_info->interface = interface; discovery_info->protocol = protocol; discovery_info->service_resolver = NULL; discovery_info->resolved = NULL; discovery_info->resolv = NULL; info->discovered = g_slist_prepend(info->discovered, discovery_info); inf_discovery_discovered(INF_DISCOVERY(avahi), discovery_info); } break; case AVAHI_BROWSER_REMOVE: for(item = info->discovered; item != NULL; item = g_slist_next(item)) { discovery_info = (InfDiscoveryInfo*)item->data; g_assert(strcmp(discovery_info->service_type, type) == 0); /* TODO: Do we need to compare domain? */ if(strcmp(discovery_info->service_name, name) == 0 && discovery_info->interface == interface && discovery_info->protocol == protocol) { inf_discovery_undiscovered(INF_DISCOVERY(avahi), discovery_info); info->discovered = g_slist_remove(info->discovered, discovery_info); inf_discovery_avahi_discovery_info_free(discovery_info); break; } } break; case AVAHI_BROWSER_CACHE_EXHAUSTED: /* Ignore */ break; case AVAHI_BROWSER_ALL_FOR_NOW: /* Ignore */ break; case AVAHI_BROWSER_FAILURE: g_warning( _("Avahi service browser is in failure state. Services of type '%s' " "are no longer discovered.\n\nThe failure was: %s\n"), info->type, avahi_strerror( avahi_client_errno(avahi_service_browser_get_client(browser)) ) ); inf_discovery_avahi_perform_undiscover(avahi, info); break; default: g_assert_not_reached(); break; } } static void inf_discovery_avahi_entry_group_add_service(InfLocalPublisherItem* item) { char* new_name; int res; do { res = avahi_entry_group_add_service( item->entry_group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, item->name, item->type, NULL, NULL, item->port, NULL ); if(res != AVAHI_ERR_COLLISION) break; new_name = avahi_alternative_service_name(item->name); avahi_free(item->name); item->name = new_name; } while(1); if(res != 0) { g_warning( "Failed to publish service \"%s\" via avahi: %s", item->name, avahi_strerror(res) ); } } static void inf_discovery_avahi_entry_group_callback(AvahiEntryGroup* group, AvahiEntryGroupState state, void* userdata) { InfLocalPublisherItem* item; char* new_name; item = (InfLocalPublisherItem*)userdata; switch(state) { case AVAHI_ENTRY_GROUP_UNCOMMITED: /* Not yet committed */ break; case AVAHI_ENTRY_GROUP_REGISTERING: /* This is currently being registered */ break; case AVAHI_ENTRY_GROUP_ESTABLISHED: /* The service is published */ break; case AVAHI_ENTRY_GROUP_COLLISION: /* There was a name collision, choose a new name */ new_name = avahi_alternative_service_name(item->name); avahi_free(item->name); item->name = new_name; avahi_entry_group_reset(item->entry_group); inf_discovery_avahi_entry_group_add_service(item); avahi_entry_group_commit(item->entry_group); break; case AVAHI_ENTRY_GROUP_FAILURE: g_warning( _("Avahi entry group is in failure state. The service '%s' of type " "'%s' is no longer published.\n\nThe failure was: %s\n"), item->name, item->type, avahi_strerror(avahi_client_errno(avahi_entry_group_get_client(group))) ); /* There was a failure, remove entry group */ inf_discovery_avahi_perform_unpublish_item(item); break; default: g_assert_not_reached(); break; } } static void inf_discovery_avahi_perform_publish_item(InfDiscoveryAvahi* avahi, InfLocalPublisherItem* item) { InfDiscoveryAvahiPrivate* priv; priv = INF_DISCOVERY_AVAHI_PRIVATE(avahi); if(item->entry_group == NULL) { /* TODO: Error handling if one of these calls fail */ item->entry_group = avahi_entry_group_new( priv->client, inf_discovery_avahi_entry_group_callback, item ); inf_discovery_avahi_entry_group_add_service(item); avahi_entry_group_commit(item->entry_group); } } static void inf_discovery_avahi_perform_unpublish_item(InfLocalPublisherItem* item) { if(item->entry_group != NULL) { avahi_entry_group_free(item->entry_group); item->entry_group = NULL; } } static void inf_discovery_avahi_perform_publish_all(InfDiscoveryAvahi* avahi) { InfDiscoveryAvahiPrivate* priv; GSList* item; priv = INF_DISCOVERY_AVAHI_PRIVATE(avahi); for(item = priv->published; item != NULL; item = g_slist_next(item)) { inf_discovery_avahi_perform_publish_item( avahi, (InfLocalPublisherItem*)item->data ); } } static void inf_discovery_avahi_perform_unpublish_all(InfDiscoveryAvahi* avahi) { InfDiscoveryAvahiPrivate* priv; GSList* item; priv = INF_DISCOVERY_AVAHI_PRIVATE(avahi); for(item = priv->published; item != NULL; item = g_slist_next(item)) { inf_discovery_avahi_perform_unpublish_item( (InfLocalPublisherItem*)item->data ); } } static void inf_discovery_avahi_perform_discover(InfDiscoveryAvahi* avahi, InfDiscoveryAvahiDiscoverInfo* info) { InfDiscoveryAvahiPrivate* priv; priv = INF_DISCOVERY_AVAHI_PRIVATE(avahi); if(info->service_browser == NULL) { info->service_browser = avahi_service_browser_new( priv->client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, info->type, NULL, 0, inf_discovery_avahi_service_browser_callback, avahi ); } } static void inf_discovery_avahi_perform_undiscover(InfDiscoveryAvahi* avahi, InfDiscoveryAvahiDiscoverInfo* info) { /* Remove discovered infos, these might no longer be valid. They are * rediscovered when inf_discovery_avahi_perform_discover() is called * again. */ InfDiscoveryInfo* discovery_info; GSList* next; for(; info->discovered != NULL; info->discovered = next) { next = info->discovered->next; discovery_info = (InfDiscoveryInfo*)info->discovered->data; inf_discovery_undiscovered(INF_DISCOVERY(avahi), discovery_info); inf_discovery_avahi_discovery_info_free(discovery_info); info->discovered = g_slist_delete_link( info->discovered, info->discovered ); } if(info->service_browser != NULL) { avahi_service_browser_free(info->service_browser); info->service_browser = NULL; } } static void inf_discovery_avahi_perform_discover_all_foreach_func(gpointer key, gpointer value, gpointer user_data) { inf_discovery_avahi_perform_discover( INF_DISCOVERY_AVAHI(user_data), (InfDiscoveryAvahiDiscoverInfo*)value ); } static void inf_discovery_avahi_perform_undiscover_all_foreach_func(gpointer key, gpointer value, gpointer user_data) { inf_discovery_avahi_perform_undiscover( INF_DISCOVERY_AVAHI(user_data), (InfDiscoveryAvahiDiscoverInfo*)value ); } static void inf_discovery_avahi_perform_discover_all(InfDiscoveryAvahi* avahi) { InfDiscoveryAvahiPrivate* priv; priv = INF_DISCOVERY_AVAHI_PRIVATE(avahi); g_hash_table_foreach( priv->discovered, inf_discovery_avahi_perform_discover_all_foreach_func, avahi ); } static void inf_discovery_avahi_perform_undiscover_all(InfDiscoveryAvahi* avahi) { InfDiscoveryAvahiPrivate* priv; priv = INF_DISCOVERY_AVAHI_PRIVATE(avahi); g_hash_table_foreach( priv->discovered, inf_discovery_avahi_perform_undiscover_all_foreach_func, avahi ); } /* Required by inf_discovery_avahi_create_client() */ static void inf_discovery_avahi_client_callback(AvahiClient* client, AvahiClientState state, void* userdata); static void inf_discovery_avahi_create_client(InfDiscoveryAvahi* discovery) { InfDiscoveryAvahiPrivate* priv; int error; priv = INF_DISCOVERY_AVAHI_PRIVATE(discovery); priv->client = avahi_client_new( &priv->poll, AVAHI_CLIENT_NO_FAIL, inf_discovery_avahi_client_callback, discovery, &error ); /* This still seems to happen sometimes, even though we pass * AVAHI_CLIENT_NO_FAIL */ if(priv->client == NULL) { g_warning(_ ("Failed to start Avahi client. Service discovery or publishing " "will not be possible.\n\nThe occurred failure was: %s"), avahi_strerror(error) ); } } static void inf_discovery_avahi_client_callback(AvahiClient* client, AvahiClientState state, void* userdata) { InfDiscoveryAvahi* avahi; InfDiscoveryAvahiPrivate* priv; avahi = INF_DISCOVERY_AVAHI(userdata); priv = INF_DISCOVERY_AVAHI_PRIVATE(avahi); switch(state) { case AVAHI_CLIENT_S_COLLISION: /* TODO: What to do in that case. Should we handle this as an error, * i.e. withdraw service browsers and entry groups? */ break; case AVAHI_CLIENT_S_REGISTERING: /* Wait for client to become running */ break; case AVAHI_CLIENT_S_RUNNING: /* Discovery and publish when running */ inf_discovery_avahi_perform_publish_all(avahi); inf_discovery_avahi_perform_discover_all(avahi); break; case AVAHI_CLIENT_FAILURE: inf_discovery_avahi_perform_unpublish_all(avahi); inf_discovery_avahi_perform_undiscover_all(avahi); if(avahi_client_errno(client) != AVAHI_ERR_DISCONNECTED) { inf_discovery_avahi_create_client(avahi); } else { g_warning( _("Avahi client is in failure state. Service discovery or " "publishing is no longer possible.\n\nThe occured failure " "was: %s\n"), avahi_strerror(avahi_client_errno(client)) ); } case AVAHI_CLIENT_CONNECTING: /* Wait for connection */ break; default: g_assert_not_reached(); break; } } /* * AvahiPoll implementation */ static AvahiWatchEvent inf_discovery_avahi_from_io_event(InfIoEvent event) { AvahiWatchEvent res; res = 0; if(event & INF_IO_INCOMING) res |= AVAHI_WATCH_IN; if(event & INF_IO_OUTGOING) res |= AVAHI_WATCH_OUT; if(event & INF_IO_ERROR) res |= AVAHI_WATCH_ERR; return res; } static InfIoEvent inf_discovery_avahi_to_io_event(AvahiWatchEvent event) { InfIoEvent res; res = 0; if(event & AVAHI_WATCH_IN) res |= INF_IO_INCOMING; if(event & AVAHI_WATCH_OUT) res |= INF_IO_OUTGOING; if(event & (AVAHI_WATCH_ERR | AVAHI_WATCH_HUP)) res |= INF_IO_ERROR; return res; } static void inf_discovery_avahi_watch_cb(InfNativeSocket* socket, InfIoEvent event, gpointer user_data) { AvahiWatch* watch; watch = (AvahiWatch*)user_data; watch->occured_events = inf_discovery_avahi_from_io_event(event); watch->callback(watch, *socket, watch->occured_events, watch->userdata); } static void inf_discovery_avahi_timeout_cb(gpointer user_data) { AvahiTimeout* timeout; timeout = (AvahiTimeout*)user_data; timeout->timeout = NULL; timeout->callback(timeout, timeout->userdata); } static AvahiWatch* inf_discovery_avahi_watch_new(const AvahiPoll* api, int fd, AvahiWatchEvent event, AvahiWatchCallback callback, void* userdata) { InfDiscoveryAvahi* avahi; InfDiscoveryAvahiPrivate* priv; AvahiWatch* watch; avahi = INF_DISCOVERY_AVAHI(api->userdata); priv = INF_DISCOVERY_AVAHI_PRIVATE(avahi); watch = g_slice_new(AvahiWatch); watch->avahi = avahi; watch->socket = fd; watch->occured_events = 0; watch->callback = callback; watch->userdata = userdata; watch->watch = inf_io_add_watch( priv->io, &watch->socket, inf_discovery_avahi_to_io_event(event), inf_discovery_avahi_watch_cb, watch, NULL ); return watch; } static void inf_discovery_avahi_watch_update(AvahiWatch* watch, AvahiWatchEvent event) { InfDiscoveryAvahiPrivate* priv; priv = INF_DISCOVERY_AVAHI_PRIVATE(watch->avahi); inf_io_update_watch( priv->io, watch->watch, inf_discovery_avahi_to_io_event(event) ); } static AvahiWatchEvent inf_discovery_avahi_watch_get_events(AvahiWatch* watch) { return watch->occured_events; } static void inf_discovery_avahi_watch_free(AvahiWatch* watch) { InfDiscoveryAvahiPrivate* priv; priv = INF_DISCOVERY_AVAHI_PRIVATE(watch->avahi); inf_io_remove_watch(priv->io, watch->watch); g_slice_free(AvahiWatch, watch); } static AvahiTimeout* inf_discovery_avahi_timeout_new(const AvahiPoll* api, const struct timeval* tv, AvahiTimeoutCallback callback, void* userdata) { InfDiscoveryAvahi* avahi; InfDiscoveryAvahiPrivate* priv; AvahiTimeout* timeout; AvahiUsec usec; avahi = INF_DISCOVERY_AVAHI(api->userdata); priv = INF_DISCOVERY_AVAHI_PRIVATE(avahi); timeout = g_slice_new(AvahiTimeout); timeout->avahi = avahi; timeout->callback = callback; timeout->userdata = userdata; if(tv != NULL) { /* Timeout in the past is triggered instantly */ usec = avahi_age(tv); if(usec > 0) usec = 0; timeout->timeout = inf_io_add_timeout( priv->io, ((-usec) + 500) / 1000, inf_discovery_avahi_timeout_cb, timeout, NULL ); } else { timeout->timeout = NULL; } return timeout; } static void inf_discovery_avahi_timeout_update(AvahiTimeout* timeout, const struct timeval* tv) { InfDiscoveryAvahiPrivate* priv; AvahiUsec usec; priv = INF_DISCOVERY_AVAHI_PRIVATE(timeout->avahi); if(timeout->timeout != NULL) inf_io_remove_timeout(priv->io, timeout->timeout); if(tv != NULL) { /* Timeout in the past is triggered instantly */ usec = avahi_age(tv); if(usec > 0) usec = 0; timeout->timeout = inf_io_add_timeout( priv->io, ((-usec) + 500) / 1000, inf_discovery_avahi_timeout_cb, timeout, NULL ); } else { timeout->timeout = NULL; } } static void inf_discovery_avahi_timeout_free(AvahiTimeout* timeout) { InfDiscoveryAvahiPrivate* priv; priv = INF_DISCOVERY_AVAHI_PRIVATE(timeout->avahi); if(timeout->timeout != NULL) inf_io_remove_timeout(priv->io, timeout->timeout); g_slice_free(AvahiTimeout, timeout); } /* * GObject overrides */ static void inf_discovery_avahi_init(InfDiscoveryAvahi* avahi) { InfDiscoveryAvahiPrivate* priv; priv = INF_DISCOVERY_AVAHI_PRIVATE(avahi); priv->poll.userdata = avahi; priv->poll.watch_new = inf_discovery_avahi_watch_new; priv->poll.watch_update = inf_discovery_avahi_watch_update; priv->poll.watch_get_events = inf_discovery_avahi_watch_get_events; priv->poll.watch_free = inf_discovery_avahi_watch_free; priv->poll.timeout_new = inf_discovery_avahi_timeout_new; priv->poll.timeout_update = inf_discovery_avahi_timeout_update; priv->poll.timeout_free = inf_discovery_avahi_timeout_free; priv->io = NULL; priv->xmpp_manager = NULL; priv->security_policy = INF_XMPP_CONNECTION_SECURITY_BOTH_PREFER_TLS; priv->keepalive.mask = 0; priv->creds = NULL; priv->sasl_context = NULL; priv->sasl_mechanisms = NULL; priv->client = NULL; priv->published = NULL; priv->discovered = g_hash_table_new_full( g_str_hash, g_str_equal, NULL, /* key is owned by value */ inf_discovery_avahi_discover_info_free ); } static void inf_discovery_avahi_constructed(GObject* object) { InfDiscoveryAvahiPrivate* priv; G_OBJECT_CLASS(inf_discovery_avahi_parent_class)->constructed(object); priv = INF_DISCOVERY_AVAHI_PRIVATE(object); /* Must have been set as construct only property */ g_assert(priv->io != NULL); inf_discovery_avahi_create_client(INF_DISCOVERY_AVAHI(object)); } static void inf_discovery_avahi_dispose(GObject* object) { InfDiscoveryAvahi* avahi; InfDiscoveryAvahiPrivate* priv; GSList* item; avahi = INF_DISCOVERY_AVAHI(object); priv = INF_DISCOVERY_AVAHI_PRIVATE(avahi); g_hash_table_destroy(priv->discovered); priv->discovered = NULL; for(item = priv->published; item != NULL; item = g_slist_next(item)) inf_discovery_avahi_publisher_item_free(item->data); g_slist_free(priv->published); priv->published = NULL; if(priv->client != NULL) { avahi_client_free(priv->client); priv->client = NULL; } if(priv->xmpp_manager != NULL) { g_object_unref(G_OBJECT(priv->xmpp_manager)); priv->xmpp_manager = NULL; } if(priv->creds != NULL) { inf_certificate_credentials_unref(priv->creds); priv->creds = NULL; } if(priv->sasl_context != NULL) { inf_sasl_context_unref(priv->sasl_context); priv->sasl_context = NULL; } if(priv->io != NULL) { g_object_unref(G_OBJECT(priv->io)); priv->io = NULL; } G_OBJECT_CLASS(inf_discovery_avahi_parent_class)->dispose(object); } static void inf_discovery_avahi_finalize(GObject* object) { InfDiscoveryAvahi* avahi; InfDiscoveryAvahiPrivate* priv; avahi = INF_DISCOVERY_AVAHI(object); priv = INF_DISCOVERY_AVAHI_PRIVATE(avahi); g_free(priv->sasl_mechanisms); G_OBJECT_CLASS(inf_discovery_avahi_parent_class)->finalize(object); } static void inf_discovery_avahi_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfDiscoveryAvahi* avahi; InfDiscoveryAvahiPrivate* priv; avahi = INF_DISCOVERY_AVAHI(object); priv = INF_DISCOVERY_AVAHI_PRIVATE(avahi); switch(prop_id) { case PROP_IO: g_assert(priv->io == NULL); /* construct only */ priv->io = INF_IO(g_value_dup_object(value)); break; case PROP_XMPP_MANAGER: g_assert(priv->xmpp_manager == NULL); /* construct only */ priv->xmpp_manager = INF_XMPP_MANAGER(g_value_dup_object(value)); break; case PROP_CREDENTIALS: if(priv->creds != NULL) inf_certificate_credentials_unref(priv->creds); priv->creds = (InfCertificateCredentials*)g_value_dup_boxed(value); break; case PROP_SASL_CONTEXT: priv->sasl_context = (InfSaslContext*)g_value_dup_boxed(value); break; case PROP_SASL_MECHANISMS: g_free(priv->sasl_mechanisms); priv->sasl_mechanisms = g_value_dup_string(value); break; case PROP_SECURITY_POLICY: priv->security_policy = g_value_get_enum(value); break; case PROP_KEEPALIVE: g_assert(g_value_get_boxed(value) != NULL); priv->keepalive = *(const InfKeepalive*)g_value_get_boxed(value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void inf_discovery_avahi_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfDiscoveryAvahi* avahi; InfDiscoveryAvahiPrivate* priv; avahi = INF_DISCOVERY_AVAHI(object); priv = INF_DISCOVERY_AVAHI_PRIVATE(avahi); switch(prop_id) { case PROP_IO: g_value_set_object(value, G_OBJECT(priv->io)); break; case PROP_XMPP_MANAGER: g_value_set_object(value, G_OBJECT(priv->xmpp_manager)); break; case PROP_CREDENTIALS: g_value_set_boxed(value, priv->creds); break; case PROP_SASL_CONTEXT: g_value_set_boxed(value, priv->sasl_context); break; case PROP_SASL_MECHANISMS: g_value_set_string(value, priv->sasl_mechanisms); break; case PROP_SECURITY_POLICY: g_value_set_enum(value, priv->security_policy); break; case PROP_KEEPALIVE: g_value_set_boxed(value, &priv->keepalive); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } /* * InfDiscovery implementation. */ static void inf_discovery_avahi_discover(InfDiscovery* discovery, const gchar* type) { InfDiscoveryAvahiPrivate* priv; InfDiscoveryAvahiDiscoverInfo* info; priv = INF_DISCOVERY_AVAHI_PRIVATE(discovery); info = g_hash_table_lookup(priv->discovered, type); if(info == NULL) { info = g_slice_new(InfDiscoveryAvahiDiscoverInfo); info->type = g_strdup(type); info->service_browser = NULL; info->discovered = NULL; g_hash_table_insert(priv->discovered, info->type, info); if(priv->client != NULL && avahi_client_get_state(priv->client) == AVAHI_CLIENT_S_RUNNING) { inf_discovery_avahi_perform_discover( INF_DISCOVERY_AVAHI(discovery), info ); } } } static GSList* inf_discovery_avahi_get_discovered(InfDiscovery* discovery, const gchar* type) { InfDiscoveryAvahiPrivate* priv; InfDiscoveryAvahiDiscoverInfo* info; priv = INF_DISCOVERY_AVAHI_PRIVATE(discovery); info = g_hash_table_lookup(priv->discovered, type); if(info == NULL) return NULL; return g_slist_copy(info->discovered); } static void inf_discovery_avahi_resolve(InfDiscovery* discovery, InfDiscoveryInfo* info, InfDiscoveryResolvCompleteFunc complete_func, gpointer user_data) { InfDiscoveryAvahiPrivate* priv; InfDiscoveryAvahiInfoResolv* resolv; InfXmlConnectionStatus status; int errno; GError* error; priv = INF_DISCOVERY_AVAHI_PRIVATE(discovery); g_assert(priv->client != NULL); g_assert(avahi_client_get_state(priv->client) == AVAHI_CLIENT_S_RUNNING); if(info->resolved != NULL) { g_object_get(G_OBJECT(info->resolved), "status", &status, NULL); switch(status) { case INF_XML_CONNECTION_CLOSED: error = NULL; if(!inf_xml_connection_open(INF_XML_CONNECTION(info->resolved), &error)) { complete_func(info, NULL, error, user_data); g_error_free(error); } else { complete_func( info, INF_XML_CONNECTION(info->resolved), NULL, user_data ); } break; case INF_XML_CONNECTION_CLOSING: /* TODO: We should add ourselves to the resolver list, and wait for * the connection being closed and reopen it afterwards. */ complete_func(info, NULL, NULL, user_data); break; case INF_XML_CONNECTION_OPENING: case INF_XML_CONNECTION_OPEN: complete_func( info, INF_XML_CONNECTION(info->resolved), NULL, user_data ); break; default: g_assert_not_reached(); break; } } else { resolv = g_slice_new(InfDiscoveryAvahiInfoResolv); resolv->complete_func = complete_func; resolv->user_data = user_data; info->resolv = g_slist_prepend(info->resolv, resolv); if(info->service_resolver == NULL) { info->service_resolver = avahi_service_resolver_new( priv->client, info->interface, info->protocol, info->service_name, info->service_type, info->domain, AVAHI_PROTO_UNSPEC, 0, inf_discovery_avahi_service_resolver_callback, discovery ); if(info->service_resolver == NULL) { error = NULL; errno = avahi_client_errno( avahi_service_resolver_get_client(info->service_resolver) ); g_set_error_literal( &error, inf_discovery_avahi_error_quark, errno, avahi_strerror(errno) ); inf_discovery_avahi_info_resolv_error(info, error); g_error_free(error); } } } } static gchar* inf_discovery_avahi_info_get_service_name(InfDiscovery* discovery, InfDiscoveryInfo* info) { char device_name[IF_NAMESIZE]; if(if_indextoname(info->interface, device_name) == NULL) return NULL; return g_strdup_printf( info->protocol == AVAHI_PROTO_INET ? /* Translators: This is " (via on *
)", for example "ck (via eth0 on IPv4)". */ _("%s (via %s on IPv4)") : _("%s (via %s on IPv6)"), info->service_name, device_name ); } static const gchar* inf_discovery_avahi_info_get_service_type(InfDiscovery* discovery, InfDiscoveryInfo* info) { return info->service_type; } static InfLocalPublisherItem* inf_discovery_avahi_publish(InfLocalPublisher* publisher, const gchar* type, const gchar* name, guint port) { InfDiscoveryAvahiPrivate* priv; InfLocalPublisherItem* item; priv = INF_DISCOVERY_AVAHI_PRIVATE(publisher); item = g_slice_new(InfLocalPublisherItem); item->type = g_strdup(type); item->name = avahi_strdup(name); item->port = port; item->entry_group = NULL; priv->published = g_slist_prepend(priv->published, item); if(priv->client != NULL && avahi_client_get_state(priv->client) == AVAHI_CLIENT_S_RUNNING) { inf_discovery_avahi_perform_publish_item( INF_DISCOVERY_AVAHI(publisher), item ); } return item; } static void inf_discovery_avahi_unpublish(InfLocalPublisher* publisher, InfLocalPublisherItem* item) { InfDiscoveryAvahiPrivate* priv; priv = INF_DISCOVERY_AVAHI_PRIVATE(publisher); g_assert(g_slist_find(priv->published, item) != NULL); inf_discovery_avahi_publisher_item_free(item); priv->published = g_slist_remove(priv->published, item); } /* * Gype registration. */ static void inf_discovery_avahi_class_init(InfDiscoveryAvahiClass* avahi_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(avahi_class); object_class->constructed = inf_discovery_avahi_constructed; object_class->dispose = inf_discovery_avahi_dispose; object_class->finalize = inf_discovery_avahi_finalize; object_class->set_property = inf_discovery_avahi_set_property; object_class->get_property = inf_discovery_avahi_get_property; inf_discovery_avahi_error_quark = g_quark_from_static_string( "INF_DISCOVERY_AVAHI_ERROR" ); g_object_class_install_property( object_class, PROP_IO, g_param_spec_object( "io", "IO", "The IO object used for watching sockets and timeouts", INF_TYPE_IO, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_XMPP_MANAGER, g_param_spec_object( "xmpp-manager", "XMPP manager", "The XMPP manager to register resolved XMPP connections", INF_TYPE_XMPP_MANAGER, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_CREDENTIALS, g_param_spec_boxed( "credentials", "Certificate credentials", "The GnuTLS certificate credentials used for encrypting XMPP streams", INF_TYPE_CERTIFICATE_CREDENTIALS, G_PARAM_READWRITE ) ); g_object_class_install_property( object_class, PROP_SASL_CONTEXT, g_param_spec_boxed( "sasl-context", "SASL context", "The SASL context used for authentication", INF_TYPE_SASL_CONTEXT, G_PARAM_READWRITE ) ); g_object_class_install_property( object_class, PROP_SASL_MECHANISMS, g_param_spec_string( "sasl-mechanisms", "SASL mechanisms", "The accepted SASL mechanisms for authentication", NULL, G_PARAM_READWRITE ) ); g_object_class_install_property( object_class, PROP_SECURITY_POLICY, g_param_spec_enum( "security-policy", "Security policy", "How to decide whether to use TLS", INF_TYPE_XMPP_CONNECTION_SECURITY_POLICY, INF_XMPP_CONNECTION_SECURITY_BOTH_PREFER_TLS, G_PARAM_READWRITE ) ); g_object_class_install_property( object_class, PROP_KEEPALIVE, g_param_spec_boxed( "keepalive", "Keepalive", "The keepalive settings for new connections", INF_TYPE_KEEPALIVE, G_PARAM_READWRITE ) ); } static void inf_discovery_avahi_discovery_iface_init(InfDiscoveryInterface* iface) { iface->discover = inf_discovery_avahi_discover; iface->get_discovered = inf_discovery_avahi_get_discovered; iface->resolve = inf_discovery_avahi_resolve; iface->info_get_service_name = inf_discovery_avahi_info_get_service_name; iface->info_get_service_type = inf_discovery_avahi_info_get_service_type; iface->discovered = NULL; iface->undiscovered = NULL; } static void inf_discovery_avahi_local_publisher_iface_init( InfLocalPublisherInterface* iface) { iface->publish = inf_discovery_avahi_publish; iface->unpublish = inf_discovery_avahi_unpublish; } /* * Public API. */ /** * inf_discovery_avahi_new: (constructor) * @io: A #InfIo object used for watching sockets and timeouts. * @manager: A #InfXmppManager. * @creds: The certificate credentials used for GnuTLS encryption. * @sasl_context: A SASL context used for authentication. * @sasl_mechanisms: A whitespace-separated list of accepted SASL mechanisms, * or %NULL. * * Created a new #InfDiscoveryAvahi object which can be used to publish and * discovery Infinote services on the local network. When resolving a * #InfDiscoveryInfo (which means obtaining a #InfXmlConnection for the * discovered service) a new #InfXmppConnection needs to be created if there * is not already one for the destination host in @manager. Such * connections are created with the @creds and @sasl_context parameters. * These may be %NULL in which case #InfXmppConnection uses builtin * credentials or a builtin context, respectively. * * If this #InfDiscoveryAvahi is not used to discover services but only to * publish any, then @creds, @sasl_context and @sasl_mechanisms are ignored * and can safely set to be %NULL. * * @sasl_mechanisms specifies allowed mechanisms used for authentication with * the server. It can be %NULL, in which case all available mechanisms are * accepted. * * Return Value: (transfer full): A new #InfDiscoveryAvahi. **/ InfDiscoveryAvahi* inf_discovery_avahi_new(InfIo* io, InfXmppManager* manager, InfCertificateCredentials* creds, InfSaslContext* sasl_context, const gchar* sasl_mechanisms) { GObject* object; g_return_val_if_fail(INF_IS_IO(io), NULL); g_return_val_if_fail(INF_IS_XMPP_MANAGER(manager), NULL); object = g_object_new( INF_TYPE_DISCOVERY_AVAHI, "io", io, "xmpp-manager", manager, "credentials", creds, "sasl-context", sasl_context, "sasl-mechanisms", sasl_mechanisms, NULL ); return INF_DISCOVERY_AVAHI(object); } /** * inf_discovery_avahi_set_security_policy: * @discovery: A #InfDiscoveryAvahi. * @plcy: The new security policy. * * Sets the #InfXmppConnectionSecurityPolicy for newly created * #InfXmppConnections. It does not affect already existing * connections. */ void inf_discovery_avahi_set_security_policy(InfDiscoveryAvahi* discovery, InfXmppConnectionSecurityPolicy plcy) { g_return_if_fail(INF_IS_DISCOVERY_AVAHI(discovery)); INF_DISCOVERY_AVAHI_PRIVATE(discovery)->security_policy = plcy; } /** * inf_discovery_avahi_get_security_policy: * @discovery: A #InfDiscoveryAvahi. * * Returns the current security policy used for new * #InfXmppConnections. * * Returns: The current security policy. */ InfXmppConnectionSecurityPolicy inf_discovery_avahi_get_security_policy(InfDiscoveryAvahi* discovery) { g_return_val_if_fail( INF_IS_DISCOVERY_AVAHI(discovery), INF_XMPP_CONNECTION_SECURITY_BOTH_PREFER_TLS ); return INF_DISCOVERY_AVAHI_PRIVATE(discovery)->security_policy; } /** * inf_discovery_avahi_set_keepalive: * @discovery: A #InfDiscoveryAvahi. * @keepalive: The new keepalive configuration. * * Sets the keepalive settings for newly created connections. It does not * affect already existing connections. */ void inf_discovery_avahi_set_keepalive(InfDiscoveryAvahi* discovery, const InfKeepalive* keepalive) { g_return_if_fail(INF_IS_DISCOVERY_AVAHI(discovery)); g_return_if_fail(keepalive != NULL); INF_DISCOVERY_AVAHI_PRIVATE(discovery)->keepalive = *keepalive; } /** * inf_discovery_avahi_get_keepalive: * @discovery: A #InfDiscoveryAvahi. * * Returns the keepalive settings that will be used for new connections. * * Returns: A #InfKeepalive set for new connections, owned by @discovery. */ const InfKeepalive* inf_discovery_avahi_get_keepalive(InfDiscoveryAvahi* discovery) { g_return_val_if_fail(INF_IS_DISCOVERY_AVAHI(discovery), NULL); return &INF_DISCOVERY_AVAHI_PRIVATE(discovery)->keepalive; } #endif /* LIBINFINITY_HAVE_AVAHI */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-session.c0000644000000000000000000000013213034342512022011 xustar0030 mtime=1483851082.033718448 30 atime=1483851082.033718448 30 ctime=1488261589.076138899 libinfinity-0.7.1/libinfinity/common/inf-session.c0000644000175000017500000024074413034342512022556 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-session * @title: InfSession * @short_description: Basic session object and synchronization * @include: libinfinity/common/inf-session.h * @stability: Unstable * * #InfSession represents an editing session. The actual type of document that * is edited is not specified, so instantiating #InfSession does not make * any sense. You rather want to use a derived class such as #InfTextSession. * Normally, the #InfcBrowser or #InfdDirectory, respectively, already take * care of instantiating the correct #InfSession. * * A session basically consists of the document being edited (also called * buffer, see #InfBuffer) and the users that are working on the document, * see #InfUserTable. * * A session can either start in %INF_SESSION_RUNNING state, in which it * is created with the initial buffer and user table. It may also start in * %INF_SESSION_SYNCHRONIZING state. In this case, both buffer and user table * are initially empty and are copied from another system over the network. * When the copy is complete, the session enters %INF_SESSION_RUNNING state. * * To be notified about changes other users make to a session, you need to * subscribe to the session (on client side), or wait for incoming * subscriptions (on server side). This is normally done by * inf_browser_subscribe(). The first action that is performed * upon subscription is a synchronization as described above. When the * synchronization is complete, the #InfSession::synchronization-complete signal * is emitted. * * After subscription, one can observe modifications other users make, but it is * not possible to make own modifications. Before doing so, a #InfUser needs to * be joined. This is done by client/server specific API from * #InfSessionProxy, in particular inf_session_proxy_join_user(). The * required parameters still depend on the actual note type, which is why most * note implementations offer their own API to join a user. **/ #include #include #include #include #include #include #include #include #include /* TODO: Set buffer to non-editable during synchronization */ /* TODO: Cache requests received by other group members * during synchronization and process them afterwards */ static const GEnumValue inf_session_status_values[] = { { INF_SESSION_PRESYNC, "INF_SESSION_PRESYNC", "presync" }, { INF_SESSION_SYNCHRONIZING, "INF_SESSION_SYNCHRONIZING", "synchronizing" }, { INF_SESSION_RUNNING, "INF_SESSION_RUNNING", "running" }, { INF_SESSION_CLOSED, "INF_SESSION_CLOSED", "closed" }, { 0, NULL, NULL } }; typedef struct _InfSessionSync InfSessionSync; struct _InfSessionSync { InfCommunicationGroup* group; InfXmlConnection* conn; guint messages_total; guint messages_sent; InfSessionSyncStatus status; }; typedef struct _InfSessionPrivate InfSessionPrivate; struct _InfSessionPrivate { InfCommunicationManager* manager; InfBuffer* buffer; InfUserTable* user_table; InfSessionStatus status; /* Group of subscribed connections */ InfCommunicationGroup* subscription_group; union { /* INF_SESSION_PRESYNC */ struct { InfCommunicationGroup* group; InfXmlConnection* conn; gboolean closing; } presync; /* INF_SESSION_SYNCHRONIZING */ struct { InfCommunicationGroup* group; InfXmlConnection* conn; guint messages_total; guint messages_received; gboolean closing; } sync; /* INF_SESSION_RUNNING */ struct { GSList* syncs; } run; } shared; }; typedef struct _InfSessionXmlData InfSessionXmlData; struct _InfSessionXmlData { InfSession* session; xmlNodePtr xml; }; enum { PROP_0, /* construct only */ PROP_COMMUNICATION_MANAGER, PROP_BUFFER, PROP_USER_TABLE, PROP_STATUS, PROP_SYNC_CONNECTION, PROP_SYNC_GROUP, /* read/write */ PROP_SUBSCRIPTION_GROUP }; enum { CLOSE, ERROR, SYNCHRONIZATION_BEGIN, SYNCHRONIZATION_PROGRESS, SYNCHRONIZATION_COMPLETE, SYNCHRONIZATION_FAILED, LAST_SIGNAL }; #define INF_SESSION_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INF_TYPE_SESSION, InfSessionPrivate)) static guint session_signals[LAST_SIGNAL]; static GQuark inf_session_sync_error_quark; static void inf_session_communication_object_iface_init(InfCommunicationObjectInterface* iface); INF_DEFINE_ENUM_TYPE(InfSessionStatus, inf_session_status, inf_session_status_values) G_DEFINE_TYPE_WITH_CODE(InfSession, inf_session, G_TYPE_OBJECT, G_ADD_PRIVATE(InfSession) G_IMPLEMENT_INTERFACE(INF_COMMUNICATION_TYPE_OBJECT, inf_session_communication_object_iface_init)) /* * Utility functions. */ static const gchar* inf_session_sync_strerror(InfSessionSyncError errcode) { switch(errcode) { case INF_SESSION_SYNC_ERROR_GOT_MESSAGE_IN_PRESYNC: return _("Unexpectedly got an XML message in presync"); case INF_SESSION_SYNC_ERROR_UNEXPECTED_NODE: return _("Got unexpected XML node during synchronization"); case INF_SESSION_SYNC_ERROR_ID_NOT_PRESENT: return _("'id' attribute in user message is missing"); case INF_SESSION_SYNC_ERROR_ID_IN_USE: return _("User ID is already in use"); case INF_SESSION_SYNC_ERROR_NAME_NOT_PRESENT: return _("'name' attribute in user message is missing"); case INF_SESSION_SYNC_ERROR_NAME_IN_USE: return _("User Name is already in use"); case INF_SESSION_SYNC_ERROR_CONNECTION_CLOSED: return _("The connection was closed unexpectedly"); case INF_SESSION_SYNC_ERROR_SENDER_CANCELLED: return _("The sender cancelled the synchronization"); case INF_SESSION_SYNC_ERROR_RECEIVER_CANCELLED: return _("The receiver cancelled the synchronization"); case INF_SESSION_SYNC_ERROR_UNEXPECTED_BEGIN_OF_SYNC: return _("Got begin-of-sync message, but synchronization is already " "in progress"); case INF_SESSION_SYNC_ERROR_NUM_MESSAGES_MISSING: return _("begin-of-sync message does not contain the number of messages " "to expect"); case INF_SESSION_SYNC_ERROR_UNEXPECTED_END_OF_SYNC: return _("Got end-of-sync message, but synchronization is still in " "progress"); case INF_SESSION_SYNC_ERROR_EXPECTED_BEGIN_OF_SYNC: return _("Expected begin-of-sync message as first message during " "synchronization"); case INF_SESSION_SYNC_ERROR_EXPECTED_END_OF_SYNC: return _("Expected end-of-sync message as last message during " "synchronization"); case INF_SESSION_SYNC_ERROR_FAILED: return _("An unknown synchronization error has occured"); default: return _("An error with unknown error code occured"); } } static const gchar* inf_session_get_sync_error_message(GQuark domain, guint code) { if(domain == inf_session_sync_error_quark) return inf_session_sync_strerror(code); /* TODO: Add a possibilty for sub classes to register their error domains * that can occur in process_xml_sync. Maybe via a translate_error_sync * vfunc. */ return _("An error with unknown error domain occured"); } static GSList* inf_session_find_sync_item_by_connection(InfSession* session, InfXmlConnection* conn) { InfSessionPrivate* priv; GSList* item; priv = INF_SESSION_PRIVATE(session); g_return_val_if_fail(priv->status == INF_SESSION_RUNNING, NULL); for(item = priv->shared.run.syncs; item != NULL; item = g_slist_next(item)) { if( ((InfSessionSync*)item->data)->conn == conn) return item; } return NULL; } static InfSessionSync* inf_session_find_sync_by_connection(InfSession* session, InfXmlConnection* conn) { GSList* item; item = inf_session_find_sync_item_by_connection(session, conn); if(item == NULL) return NULL; return (InfSessionSync*)item->data; } /* Required by inf_session_release_connection() */ static void inf_session_connection_notify_status_cb(InfXmlConnection* connection, GParamSpec* pspec, gpointer user_data); static void inf_session_release_connection(InfSession* session, InfXmlConnection* connection) { InfSessionPrivate* priv; InfSessionSync* sync; GSList* item; /* gboolean has_connection;*/ priv = INF_SESSION_PRIVATE(session); switch(priv->status) { case INF_SESSION_PRESYNC: g_assert(priv->shared.presync.conn == connection); g_assert(priv->shared.presync.group != NULL); g_object_unref(priv->shared.presync.group); priv->shared.presync.conn = NULL; priv->shared.presync.group = NULL; break; case INF_SESSION_SYNCHRONIZING: g_assert(priv->shared.sync.conn == connection); g_assert(priv->shared.sync.group != NULL); g_object_unref(priv->shared.sync.group); priv->shared.sync.conn = NULL; priv->shared.sync.group = NULL; break; case INF_SESSION_RUNNING: item = inf_session_find_sync_item_by_connection(session, connection); g_assert(item != NULL); sync = item->data; g_object_unref(sync->group); g_slice_free(InfSessionSync, sync); priv->shared.run.syncs = g_slist_delete_link( priv->shared.run.syncs, item ); break; case INF_SESSION_CLOSED: default: g_assert_not_reached(); break; } inf_signal_handlers_disconnect_by_func( G_OBJECT(connection), G_CALLBACK(inf_session_connection_notify_status_cb), session ); g_object_unref(connection); } static void inf_session_send_sync_error(InfSession* session, GError* error) { InfSessionPrivate* priv; xmlNodePtr node; priv = INF_SESSION_PRIVATE(session); g_return_if_fail(priv->status == INF_SESSION_SYNCHRONIZING); g_return_if_fail(priv->shared.sync.conn != NULL); node = inf_xml_util_new_node_from_error(error, NULL, "sync-error"); inf_communication_group_send_message( priv->shared.sync.group, priv->shared.sync.conn, node ); } /* * Signal handlers. */ static void inf_session_connection_notify_status_cb(InfXmlConnection* connection, GParamSpec* pspec, gpointer user_data) { InfSession* session; InfSessionPrivate* priv; InfXmlConnectionStatus status; GError* error; session = INF_SESSION(user_data); priv = INF_SESSION_PRIVATE(session); error = NULL; g_object_get(G_OBJECT(connection), "status", &status, NULL); if(status == INF_XML_CONNECTION_CLOSED || status == INF_XML_CONNECTION_CLOSING) { g_set_error_literal( &error, inf_session_sync_error_quark, INF_SESSION_SYNC_ERROR_CONNECTION_CLOSED, inf_session_sync_strerror(INF_SESSION_SYNC_ERROR_CONNECTION_CLOSED) ); switch(priv->status) { case INF_SESSION_PRESYNC: g_assert(connection == priv->shared.presync.conn); g_signal_emit( G_OBJECT(session), session_signals[SYNCHRONIZATION_FAILED], 0, connection, error ); break; case INF_SESSION_SYNCHRONIZING: g_assert(connection == priv->shared.sync.conn); g_signal_emit( G_OBJECT(session), session_signals[SYNCHRONIZATION_FAILED], 0, connection, error ); break; case INF_SESSION_RUNNING: g_assert( inf_session_find_sync_by_connection(session, connection) != NULL ); g_signal_emit( G_OBJECT(session), session_signals[SYNCHRONIZATION_FAILED], 0, connection, error ); break; case INF_SESSION_CLOSED: default: g_assert_not_reached(); break; } g_error_free(error); } } /* * GObject overrides. */ static void inf_session_init(InfSession* session) { InfSessionPrivate* priv; priv = INF_SESSION_PRIVATE(session); priv->manager = NULL; priv->buffer = NULL; priv->user_table = NULL; priv->status = INF_SESSION_RUNNING; priv->shared.run.syncs = NULL; } static void inf_session_constructed(GObject* object) { InfSessionPrivate* priv; InfXmlConnection* sync_conn; G_OBJECT_CLASS(inf_session_parent_class)->constructed(object); priv = INF_SESSION_PRIVATE(object); /* Create empty user table if property was not initialized */ if(priv->user_table == NULL) priv->user_table = inf_user_table_new(); switch(priv->status) { case INF_SESSION_PRESYNC: g_assert(priv->shared.presync.conn != NULL && priv->shared.presync.group != NULL); sync_conn = priv->shared.presync.conn; break; case INF_SESSION_SYNCHRONIZING: g_assert(priv->shared.sync.conn != NULL && priv->shared.sync.group != NULL); sync_conn = priv->shared.sync.conn; break; case INF_SESSION_RUNNING: case INF_SESSION_CLOSED: sync_conn = NULL; break; default: g_assert_not_reached(); break; } if(sync_conn != NULL) { g_signal_connect( G_OBJECT(sync_conn), "notify::status", G_CALLBACK(inf_session_connection_notify_status_cb), object ); } } static void inf_session_dispose(GObject* object) { InfSession* session; InfSessionPrivate* priv; session = INF_SESSION(object); priv = INF_SESSION_PRIVATE(session); if(priv->status != INF_SESSION_CLOSED) { /* Close session. This cancells all running synchronizations and tells * everyone that the session no longer exists. */ inf_session_close(session); } g_object_unref(G_OBJECT(priv->user_table)); priv->user_table = NULL; g_object_unref(G_OBJECT(priv->buffer)); priv->buffer = NULL; g_object_unref(G_OBJECT(priv->manager)); priv->manager = NULL; G_OBJECT_CLASS(inf_session_parent_class)->dispose(object); } static void inf_session_finalize(GObject* object) { InfSession* session; InfSessionPrivate* priv; session = INF_SESSION(object); priv = INF_SESSION_PRIVATE(session); G_OBJECT_CLASS(inf_session_parent_class)->finalize(object); } static void inf_session_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfSession* session; InfSessionPrivate* priv; session = INF_SESSION(object); priv = INF_SESSION_PRIVATE(session); switch(prop_id) { case PROP_COMMUNICATION_MANAGER: g_assert(priv->manager == NULL); /* construct only */ priv->manager = INF_COMMUNICATION_MANAGER(g_value_dup_object(value)); break; case PROP_BUFFER: g_assert(priv->buffer == NULL); /* construct only */ priv->buffer = INF_BUFFER(g_value_dup_object(value)); break; case PROP_USER_TABLE: g_assert(priv->user_table == NULL); /* construct only */ priv->user_table = INF_USER_TABLE(g_value_dup_object(value)); break; case PROP_STATUS: /* construct only, INF_SESSION_RUNNING is the default */ g_assert(priv->status == INF_SESSION_RUNNING); priv->status = g_value_get_enum(value); switch(priv->status) { case INF_SESSION_PRESYNC: priv->shared.presync.conn = NULL; priv->shared.presync.group = NULL; priv->shared.presync.closing = FALSE; break; case INF_SESSION_SYNCHRONIZING: priv->shared.sync.conn = NULL; priv->shared.sync.group = NULL; priv->shared.sync.messages_total = 0; priv->shared.sync.messages_received = 0; priv->shared.sync.closing = FALSE; break; case INF_SESSION_RUNNING: /* was default */ g_assert(priv->shared.run.syncs == NULL); break; case INF_SESSION_CLOSED: break; default: g_assert_not_reached(); break; } break; case PROP_SYNC_CONNECTION: /* Need to have status sync or presync to set sync-connection */ switch(priv->status) { case INF_SESSION_PRESYNC: g_assert(priv->shared.presync.conn == NULL); /* construct only */ priv->shared.presync.conn = INF_XML_CONNECTION(g_value_dup_object(value)); break; case INF_SESSION_SYNCHRONIZING: g_assert(priv->shared.sync.conn == NULL); /* construct only */ priv->shared.sync.conn = INF_XML_CONNECTION(g_value_dup_object(value)); break; case INF_SESSION_RUNNING: g_assert(g_value_get_object(value) == NULL); break; case INF_SESSION_CLOSED: default: g_assert_not_reached(); break; } break; case PROP_SYNC_GROUP: switch(priv->status) { case INF_SESSION_PRESYNC: g_assert(priv->shared.presync.group == NULL); /* construct only */ priv->shared.presync.group = INF_COMMUNICATION_GROUP(g_value_dup_object(value)); break; case INF_SESSION_SYNCHRONIZING: g_assert(priv->shared.sync.group == NULL); /* construct only */ priv->shared.sync.group = INF_COMMUNICATION_GROUP(g_value_dup_object(value)); break; case INF_SESSION_RUNNING: g_assert(g_value_get_object(value) == NULL); break; case INF_SESSION_CLOSED: default: g_assert_not_reached(); break; } break; case PROP_SUBSCRIPTION_GROUP: if(priv->subscription_group != NULL) g_object_unref(priv->subscription_group); priv->subscription_group = INF_COMMUNICATION_GROUP(g_value_dup_object(value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void inf_session_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfSession* session; InfSessionPrivate* priv; session = INF_SESSION(object); priv = INF_SESSION_PRIVATE(session); switch(prop_id) { case PROP_COMMUNICATION_MANAGER: g_value_set_object(value, G_OBJECT(priv->manager)); break; case PROP_BUFFER: g_value_set_object(value, G_OBJECT(priv->buffer)); break; case PROP_USER_TABLE: g_value_set_object(value, G_OBJECT(priv->user_table)); break; case PROP_STATUS: g_value_set_enum(value, priv->status); break; case PROP_SYNC_CONNECTION: switch(priv->status) { case INF_SESSION_PRESYNC: g_value_set_object(value, G_OBJECT(priv->shared.presync.conn)); break; case INF_SESSION_SYNCHRONIZING: g_value_set_object(value, G_OBJECT(priv->shared.sync.conn)); break; case INF_SESSION_RUNNING: case INF_SESSION_CLOSED: g_value_set_object(value, NULL); break; default: g_assert_not_reached(); break; } break; case PROP_SYNC_GROUP: switch(priv->status) { case INF_SESSION_PRESYNC: g_value_set_object(value, G_OBJECT(priv->shared.presync.group)); break; case INF_SESSION_SYNCHRONIZING: g_value_set_object(value, G_OBJECT(priv->shared.sync.group)); break; case INF_SESSION_RUNNING: case INF_SESSION_CLOSED: g_value_set_object(value, NULL); break; default: g_assert_not_reached(); break; } break; case PROP_SUBSCRIPTION_GROUP: g_value_set_object(value, G_OBJECT(priv->subscription_group)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } /* * Network messages */ static InfCommunicationScope inf_session_handle_user_status_change(InfSession* session, InfXmlConnection* connection, xmlNodePtr xml, GError** error) { InfSessionPrivate* priv; InfUser* user; guint id; xmlChar* status_attr; gboolean has_status; InfUserStatus status; priv = INF_SESSION_PRIVATE(session); if(!inf_xml_util_get_attribute_uint_required(xml, "id", &id, error)) return INF_COMMUNICATION_SCOPE_PTP; user = inf_user_table_lookup_user_by_id(priv->user_table, id); if(user == NULL) { g_set_error( error, inf_user_error_quark(), INF_USER_ERROR_NO_SUCH_USER, _("No such user with ID %u"), id ); return INF_COMMUNICATION_SCOPE_PTP; } if(inf_user_get_status(user) == INF_USER_UNAVAILABLE || inf_user_get_connection(user) != connection) { g_set_error_literal( error, inf_user_error_quark(), INF_USER_ERROR_NOT_JOINED, _("User did not join from this connection") ); return INF_COMMUNICATION_SCOPE_PTP; } status_attr = xmlGetProp(xml, (const xmlChar*)"status"); has_status = inf_user_status_from_string((const char*)status_attr, &status, error); xmlFree(status_attr); if(!has_status) return FALSE; if(inf_user_get_status(user) != status) g_object_set(G_OBJECT(user), "status", status, NULL); return INF_COMMUNICATION_SCOPE_GROUP; } /* * VFunc implementations. */ static void inf_session_to_xml_sync_impl_foreach_func(InfUser* user, gpointer user_data) { InfSessionXmlData* data; xmlNodePtr usernode; data = (InfSessionXmlData*)user_data; usernode = xmlNewNode(NULL, (const xmlChar*)"sync-user"); inf_session_user_to_xml(data->session, user, usernode); xmlAddChild(data->xml, usernode); } static void inf_session_to_xml_sync_impl(InfSession* session, xmlNodePtr parent) { InfSessionPrivate* priv; InfSessionXmlData data; priv = INF_SESSION_PRIVATE(session); data.session = session; data.xml = parent; inf_user_table_foreach_user( priv->user_table, inf_session_to_xml_sync_impl_foreach_func, &data ); } static gboolean inf_session_process_xml_sync_impl(InfSession* session, InfXmlConnection* connection, const xmlNodePtr xml, GError** error) { InfSessionPrivate* priv; InfSessionClass* session_class; GArray* user_props; InfUser* user; guint i; const GParameter* param; GParameter* connparam; priv = INF_SESSION_PRIVATE(session); session_class = INF_SESSION_GET_CLASS(session); g_return_val_if_fail(session_class->get_xml_user_props != NULL, FALSE); g_return_val_if_fail(priv->status == INF_SESSION_SYNCHRONIZING, FALSE); g_return_val_if_fail(connection == priv->shared.sync.conn, FALSE); if(strcmp((const char*)xml->name, "sync-user") == 0) { user_props = session_class->get_xml_user_props( session, connection, xml ); param = inf_session_lookup_user_property( (const GParameter*)user_props->data, user_props->len, "status" ); if(param != NULL && g_value_get_enum(¶m->value) != INF_USER_UNAVAILABLE) { /* Assume that the connection for this available user is the one that * the synchronization comes from if the "connection" property is * not given. */ connparam = inf_session_get_user_property(user_props, "connection"); if(!G_IS_VALUE(&connparam->value)) { g_value_init(&connparam->value, INF_TYPE_XML_CONNECTION); g_value_set_object(&connparam->value, G_OBJECT(connection)); } } user = inf_session_add_user( session, (GParameter*)user_props->data, user_props->len ); for(i = 0; i < user_props->len; ++ i) g_value_unset(&g_array_index(user_props, GParameter, i).value); g_array_free(user_props, TRUE); if(user == NULL) return FALSE; return TRUE; } else { g_set_error( error, inf_session_sync_error_quark, INF_SESSION_SYNC_ERROR_UNEXPECTED_NODE, "Received unexpected XML message \"%s\" during synchronization", (const gchar*)xml->name ); return FALSE; } } static InfCommunicationScope inf_session_process_xml_run_impl(InfSession* session, InfXmlConnection* connection, const xmlNodePtr xml, GError** error) { if(strcmp((const char*)xml->name, "user-status-change") == 0) { return inf_session_handle_user_status_change( session, connection, xml, error ); } else { /* TODO: Proper error quark and code */ g_set_error( error, g_quark_from_static_string("INF_SESSION_ERROR"), 0, _("Received unhandled XML message '%s'"), (const gchar*)xml->name ); return INF_COMMUNICATION_SCOPE_PTP; } } static GArray* inf_session_get_xml_user_props_impl(InfSession* session, InfXmlConnection* conn, const xmlNodePtr xml) { InfSessionPrivate* priv; GArray* array; GParameter* parameter; xmlChar* name; xmlChar* id; xmlChar* status; #if 0 xmlChar* connection; InfXmlConnection* real_conn; #endif priv = INF_SESSION_PRIVATE(session); array = g_array_sized_new(FALSE, FALSE, sizeof(GParameter), 16); name = xmlGetProp(xml, (const xmlChar*)"name"); id = xmlGetProp(xml, (const xmlChar*)"id"); status = xmlGetProp(xml, (const xmlChar*)"status"); #if 0 connection = xmlGetProp(xml, (const xmlChar*)"connection"); #endif if(id != NULL) { parameter = inf_session_get_user_property(array, "id"); g_value_init(¶meter->value, G_TYPE_UINT); g_value_set_uint(¶meter->value, strtoul((const gchar*)id, NULL, 10)); xmlFree(id); } if(name != NULL) { parameter = inf_session_get_user_property(array, "name"); g_value_init(¶meter->value, G_TYPE_STRING); g_value_set_string(¶meter->value, (const gchar*)name); xmlFree(name); } if(status != NULL) { parameter = inf_session_get_user_property(array, "status"); g_value_init(¶meter->value, INF_TYPE_USER_STATUS); if(strcmp((const char*)status, "active") == 0) g_value_set_enum(¶meter->value, INF_USER_ACTIVE); else if(strcmp((const char*)status, "inactive") == 0) g_value_set_enum(¶meter->value, INF_USER_INACTIVE); else /* TODO: Error reporting for get_xml_user_props */ g_value_set_enum(¶meter->value, INF_USER_UNAVAILABLE); xmlFree(status); } #if 0 if(connection != NULL) { real_conn = inf_connection_manager_group_lookup_connection( priv->subscription_group, connection ); if(real_conn != NULL) { parameter = inf_session_get_user_property(array, "connection"); g_value_init(¶meter->value, INF_TYPE_XML_CONNECTION); g_value_set_object(¶meter->value, G_OBJECT(real_conn)); } else { /* TODO: This should be an error. */ } } #endif return array; } static void inf_session_set_xml_user_props_impl(InfSession* session, const GParameter* params, guint n_params, xmlNodePtr xml) { guint i; gchar id_buf[16]; const gchar* name; InfUserStatus status; #if 0 InfXmlConnection* conn; gchar* remote_address; #endif for(i = 0; i < n_params; ++ i) { if(strcmp(params[i].name, "id") == 0) { sprintf(id_buf, "%u", g_value_get_uint(¶ms[i].value)); xmlNewProp(xml, (const xmlChar*)"id", (const xmlChar*)id_buf); } else if(strcmp(params[i].name, "name") == 0) { name = g_value_get_string(¶ms[i].value); xmlNewProp(xml, (const xmlChar*)"name", (const xmlChar*)name); } else if(strcmp(params[i].name, "status") == 0) { status = g_value_get_enum(¶ms[i].value); inf_xml_util_set_attribute( xml, "status", inf_user_status_to_string(status) ); } /* else if(strcmp(params[i].name, "connection") == 0) { connection = INF_XML_CONNECTION(g_value_get_object(¶ms[i].value)); g_object_get_property( G_OBJECT(connection), "remote-address", &remote_address, NULL ); g_free(addr); }*/ } } static gboolean inf_session_validate_user_props_impl(InfSession* session, const GParameter* params, guint n_params, InfUser* exclude, GError** error) { InfSessionPrivate* priv; const GParameter* parameter; const gchar* name; InfUser* user; guint id; priv = INF_SESSION_PRIVATE(session); /* TODO: Use InfSessionError and/or InfRequestError here */ parameter = inf_session_lookup_user_property(params, n_params, "id"); if(parameter == NULL) { g_set_error_literal( error, inf_session_sync_error_quark, INF_SESSION_SYNC_ERROR_ID_NOT_PRESENT, inf_session_sync_strerror(INF_SESSION_SYNC_ERROR_ID_NOT_PRESENT) ); return FALSE; } id = g_value_get_uint(¶meter->value); user = inf_user_table_lookup_user_by_id(priv->user_table, id); if(user != NULL && user != exclude) { g_set_error_literal( error, inf_session_sync_error_quark, INF_SESSION_SYNC_ERROR_ID_IN_USE, inf_session_sync_strerror(INF_SESSION_SYNC_ERROR_ID_IN_USE) ); return FALSE; } parameter = inf_session_lookup_user_property(params, n_params, "name"); if(parameter == NULL) { g_set_error_literal( error, inf_session_sync_error_quark, INF_SESSION_SYNC_ERROR_NAME_NOT_PRESENT, inf_session_sync_strerror(INF_SESSION_SYNC_ERROR_NAME_NOT_PRESENT) ); return FALSE; } name = g_value_get_string(¶meter->value); user = inf_user_table_lookup_user_by_name(priv->user_table, name); if(user != NULL && user != exclude) { g_set_error_literal( error, inf_session_sync_error_quark, INF_SESSION_SYNC_ERROR_NAME_IN_USE, inf_session_sync_strerror(INF_SESSION_SYNC_ERROR_NAME_IN_USE) ); return FALSE; } return TRUE; } /* * InfCommunicationObject implementation. */ static gboolean inf_session_handle_received_sync_message(InfSession* session, InfXmlConnection* connection, const xmlNodePtr node, GError** error) { InfSessionClass* session_class; InfSessionPrivate* priv; xmlChar* num_messages; gboolean result; xmlNodePtr xml_reply; GError* local_error; session_class = INF_SESSION_GET_CLASS(session); priv = INF_SESSION_PRIVATE(session); g_assert(session_class->process_xml_sync != NULL); g_assert(priv->status == INF_SESSION_SYNCHRONIZING); if(strcmp((const gchar*)node->name, "sync-cancel") == 0) { local_error = NULL; g_set_error_literal( &local_error, inf_session_sync_error_quark, INF_SESSION_SYNC_ERROR_SENDER_CANCELLED, inf_session_sync_strerror(INF_SESSION_SYNC_ERROR_SENDER_CANCELLED) ); g_signal_emit( G_OBJECT(session), session_signals[SYNCHRONIZATION_FAILED], 0, connection, local_error ); #if 0 /* Synchronization was cancelled by remote site, so release connection * prior to closure, otherwise we would try to tell the remote site * that the session was closed, but there is no point in this because * it just was the other way around. */ /* Note: This is actually done by the default handler of the * synchronization-failed signal. */ inf_session_close(session); #endif g_error_free(local_error); /* Return FALSE, but do not set error because we handled it. Otherwise, * inf_session_communication_object_received() would try to send a * sync-error to the synchronizer which is pointless as mentioned * above. */ return FALSE; } else if(strcmp((const gchar*)node->name, "sync-begin") == 0) { if(priv->shared.sync.messages_total > 0) { g_set_error_literal( error, inf_session_sync_error_quark, INF_SESSION_SYNC_ERROR_UNEXPECTED_BEGIN_OF_SYNC, inf_session_sync_strerror( INF_SESSION_SYNC_ERROR_UNEXPECTED_BEGIN_OF_SYNC ) ); return FALSE; } else { num_messages = xmlGetProp(node, (const xmlChar*)"num-messages"); if(num_messages == NULL) { g_set_error_literal( error, inf_session_sync_error_quark, INF_SESSION_SYNC_ERROR_NUM_MESSAGES_MISSING, inf_session_sync_strerror( INF_SESSION_SYNC_ERROR_NUM_MESSAGES_MISSING ) ); return FALSE; } else { /* 2 + [...] because we also count this initial sync-begin message * and the sync-end. This way, we can use a messages_total of 0 to * indicate that we did not yet get a sync-begin, even if the * whole sync does not contain any messages. */ priv->shared.sync.messages_total = 2 + strtoul( (const gchar*)num_messages, NULL, 0 ); priv->shared.sync.messages_received = 1; xmlFree(num_messages); g_signal_emit( G_OBJECT(session), session_signals[SYNCHRONIZATION_PROGRESS], 0, connection, 1.0 / (double)priv->shared.sync.messages_total ); return TRUE; } } } else if(strcmp((const gchar*)node->name, "sync-end") == 0) { ++ priv->shared.sync.messages_received; if(priv->shared.sync.messages_received != priv->shared.sync.messages_total) { g_set_error_literal( error, inf_session_sync_error_quark, INF_SESSION_SYNC_ERROR_UNEXPECTED_END_OF_SYNC, inf_session_sync_strerror( INF_SESSION_SYNC_ERROR_UNEXPECTED_END_OF_SYNC ) ); return FALSE; } else { /* Server is waiting for ACK so that he knows the synchronization cannot * fail anymore. */ xml_reply = xmlNewNode(NULL, (const xmlChar*)"sync-ack"); inf_communication_group_send_message( priv->shared.sync.group, connection, xml_reply ); /* Synchronization complete */ g_signal_emit( G_OBJECT(session), session_signals[SYNCHRONIZATION_COMPLETE], 0, connection ); return TRUE; } } else { if(priv->shared.sync.messages_received == 0) { g_set_error_literal( error, inf_session_sync_error_quark, INF_SESSION_SYNC_ERROR_EXPECTED_BEGIN_OF_SYNC, inf_session_sync_strerror( INF_SESSION_SYNC_ERROR_EXPECTED_BEGIN_OF_SYNC ) ); return FALSE; } else if(priv->shared.sync.messages_received == priv->shared.sync.messages_total - 1) { g_set_error_literal( error, inf_session_sync_error_quark, INF_SESSION_SYNC_ERROR_EXPECTED_END_OF_SYNC, inf_session_sync_strerror(INF_SESSION_SYNC_ERROR_EXPECTED_END_OF_SYNC) ); return FALSE; } else { result = session_class->process_xml_sync( session, connection, node, error ); if(result == FALSE) return FALSE; /* Some callback could have cancelled the synchronization via * inf_session_cancel_synchronization. */ if(priv->status == INF_SESSION_CLOSED) return TRUE; ++ priv->shared.sync.messages_received; g_signal_emit( G_OBJECT(session), session_signals[SYNCHRONIZATION_PROGRESS], 0, connection, (double)priv->shared.sync.messages_received / (double)priv->shared.sync.messages_total ); return TRUE; } } } static void inf_session_communication_object_sent(InfCommunicationObject* comm_object, InfXmlConnection* connection, const xmlNodePtr node) { InfSession* session; InfSessionPrivate* priv; InfSessionSync* sync; session = INF_SESSION(comm_object); priv = INF_SESSION_PRIVATE(session); if(priv->status == INF_SESSION_RUNNING) { sync = inf_session_find_sync_by_connection(session, connection); /* This can be any message from some session that is not related to * the synchronization, so do not assert here. Also, we might already have * sent stuff that is meant to be processed after the synchronization, so * make sure here that this messages still belongs to the * synchronization. */ if(sync != NULL && sync->messages_sent < sync->messages_total) { ++ sync->messages_sent; g_signal_emit( G_OBJECT(comm_object), session_signals[SYNCHRONIZATION_PROGRESS], 0, connection, (gdouble)sync->messages_sent / (gdouble)sync->messages_total ); /* We need to wait for the sync-ack before synchronization is * completed so that the synchronizee still has a chance to tell * us if something goes wrong. */ } } } static void inf_session_communication_object_enqueued(InfCommunicationObject* comm_object, InfXmlConnection* connection, const xmlNodePtr node) { InfSessionSync* sync; if(strcmp((const gchar*)node->name, "sync-end") == 0) { /* Remember when the last synchronization messages is enqueued because * we cannot cancel any synchronizations beyond that point. */ sync = inf_session_find_sync_by_connection( INF_SESSION(comm_object), connection ); /* This should really be in the list if the node's name is sync-end, * otherwise most probably someone else sent a sync-end message via * this communication object. */ g_assert(sync != NULL); g_assert(sync->status == INF_SESSION_SYNC_IN_PROGRESS); sync->status = INF_SESSION_SYNC_AWAITING_ACK; } } static InfCommunicationScope inf_session_communication_object_received(InfCommunicationObject* comm_object, InfXmlConnection* connection, const xmlNodePtr node) { InfSessionClass* session_class; InfSession* session; InfSessionPrivate* priv; InfSessionSync* sync; gboolean result; InfCommunicationScope scope; GError* local_error; const gchar* local_message; session = INF_SESSION(comm_object); priv = INF_SESSION_PRIVATE(session); switch(priv->status) { case INF_SESSION_PRESYNC: g_assert(connection == priv->shared.presync.conn); /* We do not expect any messages in presync. The whole idea of presync is * that one can keep a session around that is going to be synchronized * later, ie. when telling the remote site about it. */ local_error = NULL; g_set_error( &local_error, inf_session_sync_error_quark, INF_SESSION_SYNC_ERROR_GOT_MESSAGE_IN_PRESYNC, _("Unexpectedly received XML message \"%s\" in presync"), (const gchar*)node->name ); g_signal_emit( G_OBJECT(session), session_signals[ERROR], 0, connection, node, local_error ); /* Don't forward unexpected message */ return INF_COMMUNICATION_SCOPE_PTP; case INF_SESSION_SYNCHRONIZING: g_assert(connection == priv->shared.sync.conn); local_error = NULL; result = inf_session_handle_received_sync_message( session, connection, node, &local_error ); if(result == FALSE && local_error != NULL) { inf_session_send_sync_error(session, local_error); /* Note the default handler resets shared->sync.conn and * shared->sync.group. */ g_signal_emit( G_OBJECT(session), session_signals[SYNCHRONIZATION_FAILED], 0, connection, local_error ); g_error_free(local_error); } /* Synchronization is always ptp only, don't forward */ return INF_COMMUNICATION_SCOPE_PTP; case INF_SESSION_RUNNING: sync = inf_session_find_sync_by_connection(session, connection); if(sync != NULL) { if(strcmp((const gchar*)node->name, "sync-error") == 0) { /* There was an error during synchronization, cancel remaining * messages. */ inf_communication_group_cancel_messages(sync->group, connection); local_error = inf_xml_util_new_error_from_node(node); if(local_error != NULL) { local_message = inf_session_get_sync_error_message(local_error->domain, local_error->code); if(local_message != NULL) { if(local_error->message != NULL) g_free(local_error->message); local_error->message = g_strdup(local_message); } } else { g_set_error_literal( &local_error, inf_session_sync_error_quark, INF_SESSION_SYNC_ERROR_FAILED, inf_session_sync_strerror(INF_SESSION_SYNC_ERROR_FAILED) ); } /* Note the default handler actually removes the sync */ g_signal_emit( G_OBJECT(session), session_signals[SYNCHRONIZATION_FAILED], 0, connection, local_error ); g_error_free(local_error); } else if(strcmp((const gchar*)node->name, "sync-ack") == 0 && sync->status == INF_SESSION_SYNC_AWAITING_ACK) { /* Got ack we were waiting for */ g_signal_emit( G_OBJECT(comm_object), session_signals[SYNCHRONIZATION_COMPLETE], 0, connection ); } else { local_error = NULL; g_set_error( &local_error, inf_session_sync_error_quark, INF_SESSION_SYNC_ERROR_UNEXPECTED_NODE, _("Received unexpected XML message \"%s\" while synchronizing"), (const gchar*)node->name ); /* We got sent something by the other session, even though we do not * expect anything really. We consider it an error, and cancel the * synchronization here. */ g_error_free(local_error); } /* Synchronization is always ptp only, don't forward */ return INF_COMMUNICATION_SCOPE_PTP; } else { session_class = INF_SESSION_GET_CLASS(session); g_assert(session_class->process_xml_run != NULL); local_error = NULL; scope = session_class->process_xml_run( session, connection, node, &local_error ); if(local_error != NULL) { /* At this point we don't really know what's wrong with the session, * or whether the error is fatal in a sense or not. We emit the * "error" signal here, so that anyone who is interested can handle * it, for example by closing the session, or logging it into a file * for human inspection. */ g_signal_emit( G_OBJECT(session), session_signals[ERROR], 0, connection, node, local_error ); g_error_free(local_error); } return scope; } case INF_SESSION_CLOSED: default: g_assert_not_reached(); return INF_COMMUNICATION_SCOPE_PTP; } } /* * Default signal handlers. */ static void inf_session_close_handler(InfSession* session) { InfSessionPrivate* priv; InfSessionSync* sync; priv = INF_SESSION_PRIVATE(session); g_object_freeze_notify(G_OBJECT(session)); switch(priv->status) { case INF_SESSION_PRESYNC: if(priv->shared.presync.closing == FALSE) { /* So that the "synchronization-failed" default signal handler does * does not emit the close signal again: */ priv->shared.presync.closing = TRUE; inf_session_cancel_synchronization(session, priv->shared.presync.conn); } inf_session_release_connection(session, priv->shared.presync.conn); break; case INF_SESSION_SYNCHRONIZING: if(priv->shared.sync.closing == FALSE) { /* So that the "synchronization-failed" default signal handler does * does not emit the close signal again: */ priv->shared.sync.closing = TRUE; inf_session_cancel_synchronization(session, priv->shared.sync.conn); } inf_session_release_connection(session, priv->shared.sync.conn); break; case INF_SESSION_RUNNING: /* TODO: Set status of all users (except local) to unavailable? We * probably should do that here instead of in the session proxies, * or at least in addition (InfcSessionProxy needs to do it anway, * because it keeps the running state even on disconnection...) */ while(priv->shared.run.syncs != NULL) { sync = (InfSessionSync*)priv->shared.run.syncs->data; inf_session_cancel_synchronization(session, sync->conn); } break; case INF_SESSION_CLOSED: default: g_assert_not_reached(); break; } if(priv->subscription_group != NULL) { g_object_unref(priv->subscription_group); priv->subscription_group = NULL; g_object_notify(G_OBJECT(session), "subscription-group"); } priv->status = INF_SESSION_CLOSED; g_object_notify(G_OBJECT(session), "status"); g_object_thaw_notify(G_OBJECT(session)); } static void inf_session_synchronization_begin_handler(InfSession* session, InfCommunicationGroup* group, InfXmlConnection* connection) { InfSessionPrivate* priv; InfSessionClass* session_class; InfSessionSync* sync; xmlNodePtr messages; xmlNodePtr next; xmlNodePtr xml; gchar num_messages_buf[16]; priv = INF_SESSION_PRIVATE(session); g_assert(priv->status == INF_SESSION_RUNNING); g_assert(inf_session_find_sync_by_connection(session, connection) == NULL); session_class = INF_SESSION_GET_CLASS(session); g_return_if_fail(session_class->to_xml_sync != NULL); sync = g_slice_new(InfSessionSync); sync->conn = connection; sync->messages_sent = 0; sync->messages_total = 2; /* including sync-begin and sync-end */ sync->status = INF_SESSION_SYNC_IN_PROGRESS; g_object_ref(G_OBJECT(connection)); priv->shared.run.syncs = g_slist_prepend(priv->shared.run.syncs, sync); g_signal_connect_after( G_OBJECT(connection), "notify::status", G_CALLBACK(inf_session_connection_notify_status_cb), session ); sync->group = group; g_object_ref(sync->group); /* The group needs to contain that connection, of course. */ g_assert(inf_communication_group_is_member(sync->group, connection)); /* Name is irrelevant because the node is only used to collect the child * nodes via the to_xml_sync vfunc. */ messages = xmlNewNode(NULL, (const xmlChar*)"sync-container"); session_class->to_xml_sync(session, messages); for(xml = messages->children; xml != NULL; xml = xml->next) ++ sync->messages_total; sprintf(num_messages_buf, "%u", sync->messages_total - 2); xml = xmlNewNode(NULL, (const xmlChar*)"sync-begin"); xmlNewProp( xml, (const xmlChar*)"num-messages", (const xmlChar*)num_messages_buf ); inf_communication_group_send_message(sync->group, connection, xml); /* TODO: Add a function that can send multiple messages */ for(xml = messages->children; xml != NULL; xml = next) { next = xml->next; xmlUnlinkNode(xml); inf_communication_group_send_message(sync->group, connection, xml); } xmlFreeNode(messages); xml = xmlNewNode(NULL, (const xmlChar*)"sync-end"); inf_communication_group_send_message(sync->group, connection, xml); } static void inf_session_synchronization_complete_handler(InfSession* session, InfXmlConnection* connection) { InfSessionPrivate* priv; priv = INF_SESSION_PRIVATE(session); switch(priv->status) { case INF_SESSION_PRESYNC: g_assert_not_reached(); break; case INF_SESSION_SYNCHRONIZING: g_assert(connection == priv->shared.sync.conn); inf_session_release_connection(session, connection); priv->status = INF_SESSION_RUNNING; priv->shared.run.syncs = NULL; g_object_notify(G_OBJECT(session), "status"); break; case INF_SESSION_RUNNING: g_assert( inf_session_find_sync_by_connection(session, connection) != NULL ); inf_session_release_connection(session, connection); break; case INF_SESSION_CLOSED: default: g_assert_not_reached(); break; } } static void inf_session_synchronization_failed_handler(InfSession* session, InfXmlConnection* connection, const GError* error) { InfSessionPrivate* priv; priv = INF_SESSION_PRIVATE(session); switch(priv->status) { case INF_SESSION_PRESYNC: g_assert(connection == priv->shared.presync.conn); if(priv->shared.presync.closing == FALSE) { /* So that the "close" default signal handler does not emit the * "synchronization failed" signal again. */ priv->shared.presync.closing = TRUE; inf_session_close(session); } break; case INF_SESSION_SYNCHRONIZING: g_assert(connection == priv->shared.sync.conn); if(priv->shared.sync.closing == FALSE) { /* So that the "close" default signal handler does not emit the * "synchronization failed" signal again. */ priv->shared.sync.closing = TRUE; inf_session_close(session); } break; case INF_SESSION_RUNNING: g_assert( inf_session_find_sync_by_connection(session, connection) != NULL ); inf_session_release_connection(session, connection); break; case INF_SESSION_CLOSED: /* Don't assert, some signal handler could have called inf_session_close() * between the start of the signal emission and the run of the default * handler. */ break; default: g_assert_not_reached(); break; } } /* * Gype registration. */ static void inf_session_class_init(InfSessionClass* session_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(session_class); object_class->constructed = inf_session_constructed; object_class->dispose = inf_session_dispose; object_class->finalize = inf_session_finalize; object_class->set_property = inf_session_set_property; object_class->get_property = inf_session_get_property; session_class->to_xml_sync = inf_session_to_xml_sync_impl; session_class->process_xml_sync = inf_session_process_xml_sync_impl; session_class->process_xml_run = inf_session_process_xml_run_impl; session_class->get_xml_user_props = inf_session_get_xml_user_props_impl; session_class->set_xml_user_props = inf_session_set_xml_user_props_impl; session_class->validate_user_props = inf_session_validate_user_props_impl; session_class->user_new = NULL; session_class->close = inf_session_close_handler; session_class->error = NULL; session_class->synchronization_begin = inf_session_synchronization_begin_handler; session_class->synchronization_progress = NULL; session_class->synchronization_complete = inf_session_synchronization_complete_handler; session_class->synchronization_failed = inf_session_synchronization_failed_handler; inf_session_sync_error_quark = g_quark_from_static_string( "INF_SESSION_SYNC_ERROR" ); g_object_class_install_property( object_class, PROP_COMMUNICATION_MANAGER, g_param_spec_object( "communication-manager", "Communication manager", "The communication manager used for sending requests", INF_COMMUNICATION_TYPE_MANAGER, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_BUFFER, g_param_spec_object( "buffer", "Buffer", "The buffer in which the document content is stored", INF_TYPE_BUFFER, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_USER_TABLE, g_param_spec_object( "user-table", "User table", "User table containing the users of the session", INF_TYPE_USER_TABLE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_STATUS, g_param_spec_enum( "status", "Session Status", "Current status of the session", INF_TYPE_SESSION_STATUS, INF_SESSION_RUNNING, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_SYNC_CONNECTION, g_param_spec_object( "sync-connection", "Synchronizing connection", "Connection which synchronizes the initial session state", INF_TYPE_XML_CONNECTION, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_SYNC_GROUP, g_param_spec_object( "sync-group", "Synchronization group", "Communication group in which to perform synchronization", INF_COMMUNICATION_TYPE_GROUP, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_SUBSCRIPTION_GROUP, g_param_spec_object( "subscription-group", "Subscription group", "Communication group of subscribed connections", INF_COMMUNICATION_TYPE_GROUP, G_PARAM_READWRITE ) ); /** * InfSession::close: * @session: The #InfSession that is being closed * * This signal is emitted if the session is closed. Note that this signal * is not called as a client if the connection to the sessions has merely * been lost, only the relevant #InfXmlConnection has its * #InfXmlConnection:status property changed. */ session_signals[CLOSE] = g_signal_new( "close", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfSessionClass, close), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0 ); /** * InfSession::error: * @session: The #InfSession having an error. * @connection: The #InfXmlConnection which sent the erroneous request. * @xml: The XML request that produced the error. * @error: A #GError providing information about the error. * * This signal is emitted when the session detects an error. The session * itself does not know much about the nature of the error. It might mean * the session is in an inconsistent state, or it might be recoverable. * This signal can be used to handle the error or to write error * information into a log file or bring to a user's attention in another * manner. */ session_signals[ERROR] = g_signal_new( "error", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfSessionClass, error), NULL, NULL, NULL, G_TYPE_NONE, 3, INF_TYPE_XML_CONNECTION, G_TYPE_POINTER, /* actually a xmlNodePtr */ G_TYPE_ERROR ); /** * InfSession::synchronization-begin: * @session: The #InfSession that is synchronizing. * @group: The #InfCommunicationGroup used for synchronization. * @connection: The #InfXmlConnection to which the session is synchronized. * * This signal is emitted whenever the session is started to be synchronized * to another connection. Note that, in contrast to * #InfSession::synchronization-progress, * #InfSession::synchronization-failed and * #InfSession::synchronization-complete it cannot happen that the signal * is emitted when @session is being synchronized itself, because that can * happen at construction time only when no one had a chance to connect * signal handlers anyway. */ session_signals[SYNCHRONIZATION_BEGIN] = g_signal_new( "synchronization-begin", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfSessionClass, synchronization_begin), NULL, NULL, NULL, G_TYPE_NONE, 2, INF_COMMUNICATION_TYPE_GROUP, INF_TYPE_XML_CONNECTION ); /** * InfSession::synchronization-progress: * @session: The #InfSession that is synchronizing or being synchronized * @connection: The #InfXmlConnection through which progress is made * @progress: A #gdouble value ranging from 0.0 to 1.0. * * This signal is emitted whenever a new XML node has been sent or received * over @connection as part of a synchronization. The process is completed * when @progress reaches the value 1.0. At this point, * #InfSession::synchronization-complete is also emitted. * * If @session's status is %INF_SESSION_SYNCHRONIZING, the local * side is being synchronized by the remote side. If the status is * %INF_SESSION_RUNNING, the local side is updating the remote side. */ session_signals[SYNCHRONIZATION_PROGRESS] = g_signal_new( "synchronization-progress", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfSessionClass, synchronization_progress), NULL, NULL, NULL, G_TYPE_NONE, 2, INF_TYPE_XML_CONNECTION, G_TYPE_DOUBLE ); /** * InfSession::synchronization-complete: * @session: The #InfSession that has or was synchronized * @connection: The #InfXmlConnection through which synchronization happened * * This signal is emitted when synchronization has completed, in addition * to #InfSession::synchronization-progress with a progress value of 1.0. * * If a callback is connected before the default handler, it can find out * whether the remote side is synchronizing the local side by comparing * @sessions's status with %INF_SESSION_SYNCHRONIZING. The default * signal handler sets the status to %INF_SESSION_RUNNING, so checking * afterwards is not too useful. */ session_signals[SYNCHRONIZATION_COMPLETE] = g_signal_new( "synchronization-complete", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfSessionClass, synchronization_complete), NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, INF_TYPE_XML_CONNECTION ); /** * InfSession::synchronization-failed: * @session: The #InfSession that failed to synchronize or be synchronized * @connection: The #InfXmlConnection through which synchronization happened * @error: A pointer to a #GError object with details on the error * * This signal is emitted when synchronization has failed before its * completion due to malformed data from the other side or network failure. * * If this happens during initial synchronization, #InfSession::close is * emitted as well at this point. */ session_signals[SYNCHRONIZATION_FAILED] = g_signal_new( "synchronization-failed", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfSessionClass, synchronization_failed), NULL, NULL, NULL, G_TYPE_NONE, 2, INF_TYPE_XML_CONNECTION, G_TYPE_ERROR ); } static void inf_session_communication_object_iface_init( InfCommunicationObjectInterface* iface) { iface->sent = inf_session_communication_object_sent; iface->enqueued = inf_session_communication_object_enqueued; iface->received = inf_session_communication_object_received; } /* * Public API. */ /** * inf_session_lookup_user_property: * @params: (array length=n_params): A pointer to an array of containing * #GParameter values. * @n_params: The number of elements in the aforementioned array * @name: Name to look up. * * Looks up the parameter with the given name in @array. * * Return Value: A #GParameter, or %NULL. **/ const GParameter* inf_session_lookup_user_property(const GParameter* params, guint n_params, const gchar* name) { guint i; g_return_val_if_fail(params != NULL || n_params == 0, NULL); g_return_val_if_fail(name != NULL, NULL); for(i = 0; i < n_params; ++ i) if(strcmp(params[i].name, name) == 0) return ¶ms[i]; return NULL; } /** * inf_session_get_user_property: * @array: (element-type GParameter): A #GArray containing #GParameter values. * @name: Name to look up. * * Looks up the paremeter with the given name in @array. If there is no such * parameter, a new one will be created. * * Return Value: (transfer none): A #GParameter. **/ GParameter* inf_session_get_user_property(GArray* array, const gchar* name) { GParameter* parameter; guint i; g_return_val_if_fail(array != NULL, NULL); g_return_val_if_fail(name != NULL, NULL); for(i = 0; i < array->len; ++ i) if(strcmp(g_array_index(array, GParameter, i).name, name) == 0) return &g_array_index(array, GParameter, i); g_array_set_size(array, array->len + 1); parameter = &g_array_index(array, GParameter, array->len - 1); parameter->name = name; memset(¶meter->value, 0, sizeof(GValue)); return parameter; } /** * inf_session_user_to_xml: * @session: A #InfSession. * @user: A #InfUser contained in @session. * @xml: An XML node to which to add user information. * * This is a convenience function that queries @user's properties and * calls set_xml_user_props with them. This adds the properties of @user * to @xml. * * An equivalent user object may be built by calling the get_xml_user_props * vfunc on @xml and then calling the user_new vfunc with the resulting * properties. **/ void inf_session_user_to_xml(InfSession* session, InfUser* user, xmlNodePtr xml) { InfSessionClass* session_class; GParamSpec** pspecs; GParameter* params; guint n_params; guint i; g_return_if_fail(INF_IS_SESSION(session)); g_return_if_fail(INF_IS_USER(user)); g_return_if_fail(xml != NULL); session_class = INF_SESSION_GET_CLASS(session); g_return_if_fail(session_class->set_xml_user_props != NULL); pspecs = g_object_class_list_properties( G_OBJECT_CLASS(INF_USER_GET_CLASS(user)), &n_params ); params = g_malloc(n_params * sizeof(GParameter)); for(i = 0; i < n_params; ++ i) { params[i].name = pspecs[i]->name; memset(¶ms[i].value, 0, sizeof(GValue)); g_value_init(¶ms[i].value, pspecs[i]->value_type); g_object_get_property(G_OBJECT(user), params[i].name, ¶ms[i].value); } session_class->set_xml_user_props(session, params, n_params, xml); for(i = 0; i < n_params; ++ i) g_value_unset(¶ms[i].value); g_free(params); g_free(pspecs); } /** * inf_session_close: * @session: A #InfSession. * * Closes a running session. When a session is closed, it unrefs all * connections and no longer handles requests. */ void inf_session_close(InfSession* session) { g_return_if_fail(INF_IS_SESSION(session)); g_return_if_fail(inf_session_get_status(session) != INF_SESSION_CLOSED); g_signal_emit(G_OBJECT(session), session_signals[CLOSE], 0); } /** * inf_session_get_communication_manager: * @session: A #InfSession. * * Returns the communication manager for @session. * * Return Value: (transfer none): A #InfCommunicationManager. **/ InfCommunicationManager* inf_session_get_communication_manager(InfSession* session) { g_return_val_if_fail(INF_IS_SESSION(session), NULL); return INF_SESSION_PRIVATE(session)->manager; } /** * inf_session_get_buffer: * @session: A #InfSession. * * Returns the buffer used by @session. * * Return Value: (transfer none): A #InfBuffer. **/ InfBuffer* inf_session_get_buffer(InfSession* session) { g_return_val_if_fail(INF_IS_SESSION(session), NULL); return INF_SESSION_PRIVATE(session)->buffer; } /** * inf_session_get_user_table: * @session:A #InfSession. * * Returns the user table used by @session. * * Return Value: (transfer none): A #InfUserTable. **/ InfUserTable* inf_session_get_user_table(InfSession* session) { g_return_val_if_fail(INF_IS_SESSION(session), NULL); return INF_SESSION_PRIVATE(session)->user_table; } /** * inf_session_get_status: * @session: A #InfSession. * * Returns the session's status. * * Return Value: The status of @session. **/ InfSessionStatus inf_session_get_status(InfSession* session) { g_return_val_if_fail(INF_IS_SESSION(session), INF_SESSION_CLOSED); return INF_SESSION_PRIVATE(session)->status; } /** * inf_session_add_user: * @session: A #InfSession. * @params: (array length=n_params): Construction parameters for the #InfUser * (or derived) object. * @n_params: Number of parameters. * * Adds a user to @session. The user object is constructed via the * user_new vfunc of #InfSessionClass. This will create a new #InfUser * object by default, but may be overridden by subclasses to create * different kinds of users. * * Note that this function does not tell the other participants that the * user was added. To avoid conflicts, normally only the publisher of the * session can add users and notifies others accordingly. This is handled * by #InfdSessionProxy or #InfcSessionProxy, respectively. * * You should not call this function unless you know what you are doing. * If @params comes from an untrusted source, they should be checked first * with the validate_user_props virtual function. * * Returns: (transfer none): The new #InfUser. **/ InfUser* inf_session_add_user(InfSession* session, const GParameter* params, guint n_params) { InfSessionPrivate* priv; InfSessionClass* session_class; InfUser* user; gboolean result; g_return_val_if_fail(INF_IS_SESSION(session), NULL); session_class = INF_SESSION_GET_CLASS(session); g_return_val_if_fail(session_class->validate_user_props != NULL, NULL); g_return_val_if_fail(session_class->user_new != NULL, NULL); priv = INF_SESSION_PRIVATE(session); g_return_val_if_fail( session_class->validate_user_props(session, params, n_params, NULL, NULL), NULL ); /* No idea why g_object_newv wants unconst GParameter list */ user = session_class->user_new( session, *(GParameter**)(gpointer)¶ms, n_params ); inf_user_table_add_user(priv->user_table, user); g_object_unref(user); /* We rely on the usertable holding a reference */ return user; } /** * inf_session_set_user_status: * @session: A #InfSession. * @user: A local #InfUser from @session's user table. * @status: New status for @user. * * Changes the status of the given @user which needs to have the * %INF_USER_LOCAL flag set for this function to be called. If the status * is changed to %INF_USER_UNAVAILABLE, then the user leaves the session. To * rejoin use inf_session_proxy_join_user() for a proxy proxying @session. **/ void inf_session_set_user_status(InfSession* session, InfUser* user, InfUserStatus status) { InfSessionPrivate* priv; xmlNodePtr xml; g_return_if_fail(INF_IS_SESSION(session)); g_return_if_fail(INF_IS_USER(user)); g_return_if_fail(inf_session_get_status(session) == INF_SESSION_RUNNING); g_return_if_fail(inf_user_get_status(user) != INF_USER_UNAVAILABLE); g_return_if_fail( (inf_user_get_flags(user) & INF_USER_LOCAL) != 0); priv = INF_SESSION_PRIVATE(session); if(inf_user_get_status(user) != status) { xml = xmlNewNode(NULL, (const xmlChar*)"user-status-change"); inf_xml_util_set_attribute_uint(xml, "id", inf_user_get_id(user)); inf_xml_util_set_attribute( xml, "status", inf_user_status_to_string(status) ); if(priv->subscription_group != NULL) inf_session_send_to_subscriptions(session, xml); g_object_set(G_OBJECT(user), "status", status, NULL); } } /** * inf_session_synchronize_from: * @session: A #InfSession in status %INF_SESSION_PRESYNC. * * Switches @session's status to %INF_SESSION_SYNCHRONIZING. In * %INF_SESSION_PRESYNC, all messages from incoming the synchronizing * connection are ignored, and no cancellation request is sent to the remote * site if the status changes to %INF_SESSION_CLOSED. The rationale behind * that status is that one can prepare a session for synchronization but start * the actual synchronization later, after having made sure that the remote * site is ready to perform the synchronization. */ void inf_session_synchronize_from(InfSession* session) { InfSessionPrivate* priv; InfCommunicationGroup* group; InfXmlConnection* connection; /* TODO: Maybe add InfCommunicationGroup*, InfXmlConnection* arguments, * and remove them from the priv->shared.presync. This might simplify code * elsewhere. */ g_return_if_fail(inf_session_get_status(session) == INF_SESSION_PRESYNC); priv = INF_SESSION_PRIVATE(session); g_return_if_fail(priv->shared.presync.closing == FALSE); group = priv->shared.presync.group; connection = priv->shared.presync.conn; priv->status = INF_SESSION_SYNCHRONIZING; priv->shared.sync.group = group; priv->shared.sync.conn = connection; priv->shared.sync.messages_total = 0; priv->shared.sync.messages_received = 0; priv->shared.sync.closing = FALSE; g_object_notify(G_OBJECT(session), "status"); } /** * inf_session_synchronize_to: * @session: A #InfSession in status %INF_SESSION_RUNNING. * @group: A #InfCommunicationGroup. * @connection: A #InfXmlConnection. * * Initiates a synchronization to @connection. On the other end of * @connection, a new session with the sync-connection and sync-group * construction properties set should have been created. @group is used * as a group in the communication manager. It is allowed for @group to have * another #InfCommunicationObject than @session, however, you should forward * the #InfCommunicationObject messages your object receives to @session then. * Also, @connection must already be present in @group, and should not be * removed until synchronization finished. * * A synchronization can only be initiated if @session is in state * %INF_SESSION_RUNNING. **/ void inf_session_synchronize_to(InfSession* session, InfCommunicationGroup* group, InfXmlConnection* connection) { g_return_if_fail(INF_IS_SESSION(session)); g_return_if_fail(group != NULL); g_return_if_fail(INF_IS_XML_CONNECTION(connection)); g_return_if_fail(inf_session_get_status(session) == INF_SESSION_RUNNING); g_return_if_fail( inf_session_find_sync_by_connection(session, connection) == NULL ); g_signal_emit( G_OBJECT(session), session_signals[SYNCHRONIZATION_BEGIN], 0, group, connection ); } /** * inf_session_cancel_synchronization: * @session: A #InfSession. * @connection: The #InfXmlConnection with which to cancel synchronization. * * Cancells an ongaing synchronization to or from @connection. If @session * is in state %INF_SESSION_PRESYNC or %INF_SESSION_SYNCHRONIZING, * @connection must match the connection that @session is synchronizing with. * If @session is in state %INF_SESSION_RUNNING, @connection can be any * connection that the session is currently being synchronized to. * * In any case, the #InfSession::synchronization-failed signal will be * emitted for the cancelled synchronization. If the session is in state * %INF_SESSION_PRESYNC or %INF_SESSION_SYNCHRONIZING, the session will also * be closed, with the #InfSession::close signal being emited. */ void inf_session_cancel_synchronization(InfSession* session, InfXmlConnection* connection) { InfSessionPrivate* priv; InfXmlConnectionStatus status; InfSessionSync* sync; xmlNodePtr xml; GError* error; g_return_if_fail(INF_IS_SESSION(session)); g_return_if_fail(INF_IS_XML_CONNECTION(connection)); priv = INF_SESSION_PRIVATE(session); error = NULL; switch(priv->status) { case INF_SESSION_PRESYNC: g_return_if_fail(connection == priv->shared.presync.conn); g_set_error_literal( &error, inf_session_sync_error_quark, INF_SESSION_SYNC_ERROR_RECEIVER_CANCELLED, inf_session_sync_strerror(INF_SESSION_SYNC_ERROR_RECEIVER_CANCELLED) ); break; case INF_SESSION_SYNCHRONIZING: g_return_if_fail(connection == priv->shared.sync.conn); g_set_error_literal( &error, inf_session_sync_error_quark, INF_SESSION_SYNC_ERROR_RECEIVER_CANCELLED, inf_session_sync_strerror(INF_SESSION_SYNC_ERROR_RECEIVER_CANCELLED) ); g_object_get(G_OBJECT(connection), "status", &status, NULL); if(status == INF_XML_CONNECTION_OPEN) inf_session_send_sync_error(session, error); break; case INF_SESSION_RUNNING: sync = inf_session_find_sync_by_connection(session, connection); g_return_if_fail(sync != NULL); /* If the sync-end message has already been enqueued within the * connection manager, we cannot cancel it anymore, so the remote * site will receive the full sync nevertheless, so we do not need * to cancel anything. */ if(sync->status == INF_SESSION_SYNC_IN_PROGRESS) { inf_communication_group_cancel_messages(sync->group, sync->conn); xml = xmlNewNode(NULL, (const xmlChar*)"sync-cancel"); inf_communication_group_send_message(sync->group, sync->conn, xml); } g_set_error_literal( &error, inf_session_sync_error_quark, INF_SESSION_SYNC_ERROR_SENDER_CANCELLED, inf_session_sync_strerror(INF_SESSION_SYNC_ERROR_SENDER_CANCELLED) ); break; case INF_SESSION_CLOSED: g_return_if_reached(); break; default: g_assert_not_reached(); break; } g_signal_emit( G_OBJECT(session), session_signals[SYNCHRONIZATION_FAILED], 0, connection, error ); g_error_free(error); } /** * inf_session_get_synchronization_status: * @session: A #InfSession. * @connection: A #InfXmlConnection. * * If @session is in status %INF_SESSION_SYNCHRONIZING, this always returns * %INF_SESSION_SYNC_IN_PROGRESS if @connection is the connection with which * the session is synchronized, and %INF_SESSION_SYNC_NONE otherwise. * * If @session is in status %INF_SESSION_RUNNING, this returns the status * of the synchronization to @connection. %INF_SESSION_SYNC_NONE is returned, * when there is currently no synchronization ongoing to @connection, * %INF_SESSION_SYNC_IN_PROGRESS is returned, if there is one, and * %INF_SESSION_SYNC_AWAITING_ACK if the synchronization is finished but we * are waiting for the acknowledgement from the remote site that all * synchronization data has been progressed successfully. The synchronization * can still fail in this state but it can no longer by cancelled. * * If @session is in status $INF_SESSION_CLOSED, this always returns * %INF_SESSION_SYNC_NONE. * * Return Value: The synchronization status of @connection. **/ InfSessionSyncStatus inf_session_get_synchronization_status(InfSession* session, InfXmlConnection* connection) { InfSessionPrivate* priv; InfSessionSync* sync; g_return_val_if_fail(INF_IS_SESSION(session), INF_SESSION_SYNC_NONE); g_return_val_if_fail( INF_IS_XML_CONNECTION(connection), INF_SESSION_SYNC_NONE ); priv = INF_SESSION_PRIVATE(session); switch(priv->status) { case INF_SESSION_SYNCHRONIZING: if(connection == priv->shared.sync.conn) return INF_SESSION_SYNC_IN_PROGRESS; return INF_SESSION_SYNC_NONE; case INF_SESSION_RUNNING: sync = inf_session_find_sync_by_connection(session, connection); if(sync == NULL) return INF_SESSION_SYNC_NONE; return sync->status; case INF_SESSION_CLOSED: return INF_SESSION_SYNC_NONE; default: g_assert_not_reached(); break; } } /** * inf_session_get_synchronization_progress: * @session: A #InfSession. * @connection: A #InfXmlConnection. * * This function requires that the synchronization status of @connection * is %INF_SESSION_SYNC_IN_PROGRESS or %INF_SESSION_SYNC_AWAITING_ACK * (see inf_session_get_synchronization_status()). Then, it returns a value * between 0.0 and 1.0 specifying how much synchronization data has already * been transferred to the remote site. * * Note that if the session is in status %INF_SESSION_RUNNING, it is * possible that this function returns 1.0 (i.e. all data has been * transmitted) but the synchronization is not yet complete, because the * remote site must still acknowledge the synchronization. The synchronization * then is in status %INF_SESSION_SYNC_AWAITING_ACK. * * Return Value: A value between 0.0 and 1.0. **/ gdouble inf_session_get_synchronization_progress(InfSession* session, InfXmlConnection* connection) { InfSessionPrivate* priv; InfSessionSync* sync; g_return_val_if_fail(INF_IS_SESSION(session), 0.0); g_return_val_if_fail(INF_IS_XML_CONNECTION(connection), 0.0); g_return_val_if_fail( inf_session_get_synchronization_status( session, connection ) != INF_SESSION_SYNC_NONE, 0.0 ); priv = INF_SESSION_PRIVATE(session); switch(priv->status) { case INF_SESSION_PRESYNC: g_assert(connection == priv->shared.presync.conn); return 0.0; case INF_SESSION_SYNCHRONIZING: g_assert(connection == priv->shared.sync.conn); /* messages_total is still zero in case we did not yet even receive * sync-begin. We are at the very beginning of the synchronization in * that case. */ if(priv->shared.sync.messages_total == 0) return 0.0; return (gdouble)priv->shared.sync.messages_received / (gdouble)priv->shared.sync.messages_total; case INF_SESSION_RUNNING: sync = inf_session_find_sync_by_connection(session, connection); g_assert(sync != NULL); return (gdouble)sync->messages_sent / (gdouble)sync->messages_total; case INF_SESSION_CLOSED: default: g_assert_not_reached(); return 0.0; } } /** * inf_session_has_synchronizations: * @session: A #InfSession. * * Returns whether there are currently ongoing synchronizations. If the * session is in status %INF_SESSION_SYNCHRONIZING, then this returns always * %TRUE, if it is in %INF_SESSION_CLOSED, then it returns always %FALSE. * If the session is in status %INF_SESSION_RUNNING, then it returns %TRUE * when the session is currently at least synchronized to one connection and * %FALSE otherwise. * * Returns: Whether there are ongoing synchronizations. **/ gboolean inf_session_has_synchronizations(InfSession* session) { InfSessionPrivate* priv; g_return_val_if_fail(INF_IS_SESSION(session), FALSE); priv = INF_SESSION_PRIVATE(session); switch(priv->status) { case INF_SESSION_PRESYNC: case INF_SESSION_SYNCHRONIZING: return TRUE; case INF_SESSION_RUNNING: if(priv->shared.run.syncs == NULL) return FALSE; else return TRUE; case INF_SESSION_CLOSED: return FALSE; default: g_assert_not_reached(); return FALSE; } } /** * inf_session_get_subscription_group: * @session: A #InfSession. * * Returns the subscription group for @session, if any. * * Return Value: (transfer none): A #InfCommunicationGroup, or %NULL. **/ InfCommunicationGroup* inf_session_get_subscription_group(InfSession* session) { g_return_val_if_fail(INF_IS_SESSION(session), NULL); return INF_SESSION_PRIVATE(session)->subscription_group; } /** * inf_session_set_subscription_group: * @session: A #InfSession. * @group: A #InfCommunicationGroup. * * Sets the subscription group for @session. The subscription group is the * group in which all connections subscribed to the session are a member of. * * #InfSession itself does not deal with subscriptions, so it is your job * to keep @group up-to-date (for example if you add non-local users to * @session). This is normally done by a so-called session proxy such as * #InfcSessionProxy or #InfdSessionProxy, respectively. **/ void inf_session_set_subscription_group(InfSession* session, InfCommunicationGroup* group) { InfSessionPrivate* priv; g_return_if_fail(INF_IS_SESSION(session)); priv = INF_SESSION_PRIVATE(session); if(priv->subscription_group != group) { if(priv->subscription_group != NULL) g_object_unref(priv->subscription_group); priv->subscription_group = group; if(group != NULL) g_object_ref(group); g_object_notify(G_OBJECT(session), "subscription-group"); } } /** * inf_session_send_to_subscriptions: * @session: A #InfSession. * @xml: (transfer full): The message to send. * * Sends a XML message to the all members of @session's subscription group. * This function can only be called if the subscription group is non-%NULL. It * takes ownership of @xml. **/ void inf_session_send_to_subscriptions(InfSession* session, xmlNodePtr xml) { InfSessionPrivate* priv; g_return_if_fail(INF_IS_SESSION(session)); g_return_if_fail(xml != NULL); priv = INF_SESSION_PRIVATE(session); g_return_if_fail(priv->subscription_group != NULL); inf_communication_group_send_group_message(priv->subscription_group, xml); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-certificate-chain.h0000644000000000000000000000013213034342512023675 xustar0030 mtime=1483851082.029718427 30 atime=1483851082.029718427 30 ctime=1488261588.936139205 libinfinity-0.7.1/libinfinity/common/inf-certificate-chain.h0000644000175000017500000000433213034342512024431 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_CERTIFICATE_CHAIN_H__ #define __INF_CERTIFICATE_CHAIN_H__ #include /* Get ssize_t on MSVC, required by gnutls.h */ #include #include G_BEGIN_DECLS #define INF_TYPE_CERTIFICATE_CHAIN (inf_certificate_chain_get_type()) /** * InfCertificateChain: * * #InfCertificateChain is an opaque data type. You should only access it * via the public API functions. */ typedef struct _InfCertificateChain InfCertificateChain; GType inf_certificate_chain_get_type(void) G_GNUC_CONST; InfCertificateChain* inf_certificate_chain_new(gnutls_x509_crt_t* certs, guint n_certs); InfCertificateChain* inf_certificate_chain_ref(InfCertificateChain* chain); void inf_certificate_chain_unref(InfCertificateChain* chain); gnutls_x509_crt_t* inf_certificate_chain_get_raw(const InfCertificateChain* chain); gnutls_x509_crt_t inf_certificate_chain_get_root_certificate(const InfCertificateChain* chain); gnutls_x509_crt_t inf_certificate_chain_get_own_certificate(const InfCertificateChain* chain); gnutls_x509_crt_t inf_certificate_chain_get_nth_certificate(const InfCertificateChain* chain, guint n); guint inf_certificate_chain_get_n_certificates(const InfCertificateChain* chain); G_END_DECLS #endif /* __INF_CERTIFICATE_CHAIN_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-cert-util.c0000644000000000000000000000013213034342512022236 xustar0030 mtime=1483851082.029718427 30 atime=1483851082.029718427 30 ctime=1488261589.048138961 libinfinity-0.7.1/libinfinity/common/inf-cert-util.c0000644000175000017500000012047213034342512022776 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-cert-util * @title: Certificate utility functions * @short_description: Helper functions to read and write information from * X.509 certificates. * @include: libinfinity/common/inf-cert-util.h * @stability: Unstable * * These functions are utility functions that can be used when dealing with * certificates, private key and Diffie-Hellman parameters for key exchange. * The functionality these functions provide include creating, reading and * writing these data structures to disk in PEM format, or to read values from * certificates. **/ #include #include #include #include #include #include #include #define X509_BEGIN_1 "-----BEGIN CERTIFICATE-----" #define X509_BEGIN_2 "-----BEGIN X509 CERTIFICATE-----" #define X509_END_1 "-----END CERTIFICATE-----" #define X509_END_2 "-----END X509 CERTIFICATE----" typedef enum _InfCertUtilError { INF_CERT_UTIL_ERROR_DUPLICATE_HOST_ENTRY } InfCertUtilError; /* * Helper functions */ static const unsigned int DAYS = 24 * 60 * 60; /* memrchr does not seem to be available everywhere, so we implement it * ourselves. */ static void* inf_cert_util_memrchr(void* buf, char c, size_t len) { char* pos; char* end; pos = buf + len; end = buf; while(pos > end) { if(*(pos - 1) == c) return pos - 1; --pos; } return NULL; } static int inf_cert_util_create_certificate_impl(gnutls_x509_crt_t cert, gnutls_x509_privkey_t key, const InfCertUtilDescription* desc) { char buffer[5]; time_t timestamp; int res; res = gnutls_x509_crt_set_key(cert, key); if(res != 0) return res; timestamp = time(NULL); buffer[4] = (timestamp ) & 0xff; buffer[3] = (timestamp >> 8) & 0xff; buffer[2] = (timestamp >> 16) & 0xff; buffer[1] = (timestamp >> 24) & 0xff; buffer[0] = (timestamp >> 32) & 0xff; res = gnutls_x509_crt_set_serial(cert, buffer, 5); if(res != 0) return res; /* Set the activation time a bit in the past, so that if someones * clock is slightly offset they don't find the certificate invalid */ res = gnutls_x509_crt_set_activation_time(cert, timestamp - DAYS / 10); if(res != 0) return res; res = gnutls_x509_crt_set_expiration_time(cert, timestamp + desc->validity); if(res != 0) return res; res = gnutls_x509_crt_set_basic_constraints(cert, 0, -1); if(res != 0) return res; res = gnutls_x509_crt_set_key_usage(cert, GNUTLS_KEY_DIGITAL_SIGNATURE); if(res != 0) return res; res = gnutls_x509_crt_set_version(cert, 3); if(res != 0) return res; if(desc->dn_common_name != NULL) { res = gnutls_x509_crt_set_dn_by_oid( cert, GNUTLS_OID_X520_COMMON_NAME, 0, desc->dn_common_name, strlen(desc->dn_common_name) ); if(res != 0) return res; } if(desc->san_dnsname != NULL) { res = gnutls_x509_crt_set_subject_alternative_name( cert, GNUTLS_SAN_DNSNAME, desc->san_dnsname ); if(res != 0) return res; } return 0; } static gboolean inf_cert_util_write_certificates_string(gnutls_x509_crt_t* certs, guint n_certs, GString* string, GError** error) { guint i; gnutls_x509_crt_t cert; int res; size_t size; gchar* buffer; GIOStatus status; for(i = 0; i < n_certs; ++ i) { if(i > 0) { g_string_append_c(string, '\n'); } cert = (gnutls_x509_crt_t)certs[i]; size = 0; res = gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_PEM, NULL, &size); if(res != GNUTLS_E_SHORT_MEMORY_BUFFER) { inf_gnutls_set_error(error, res); return FALSE; } buffer = g_malloc(size); res = gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_PEM, buffer, &size); if(res != GNUTLS_E_SUCCESS) { g_free(buffer); inf_gnutls_set_error(error, res); return FALSE; } /* TODO: We could optimize this by directly filling string's buffer, * instead of copying the output buffer here. */ g_string_append_len(string, buffer, size); g_free(buffer); } return TRUE; } static gboolean inf_cert_util_write_private_key_string(gnutls_x509_privkey_t key, GString* string, GError** error) { unsigned char* data; size_t size; int res; gboolean bres; GIOStatus status; size = 0; data = NULL; bres = FALSE; res = gnutls_x509_privkey_export( key, GNUTLS_X509_FMT_PEM, NULL, &size ); g_assert(res != 0); /* cannot succeed */ if(res != GNUTLS_E_SHORT_MEMORY_BUFFER) { inf_gnutls_set_error(error, res); return FALSE; } else { data = g_malloc(size); res = gnutls_x509_privkey_export( key, GNUTLS_X509_FMT_PEM, data, &size ); if(res != 0) { g_free(data); inf_gnutls_set_error(error, res); return FALSE; } else { /* TODO: We could optimize this by directly filling string's buffer, * instead of copying the output buffer here. */ g_string_append_len(string, data, size); g_free(data); } } return TRUE; } static gchar* inf_cert_util_format_time(time_t time) { struct tm* tm; gsize alloc; gchar* result; gchar* converted; size_t ret; tm = localtime(&time); alloc = 128; result = NULL; do { result = g_realloc(result, alloc); ret = strftime(result, alloc, "%c", tm); alloc *= 2; } while(ret == 0); converted = g_locale_to_utf8(result, -1, NULL, NULL, NULL); g_free(result); /* The conversion sequence should be always valid, otherwise strftime * is screwed!? */ g_assert(converted != NULL); return converted; } static gchar* inf_cert_util_format_hexadecimal(const guchar* data, gsize size) { gchar* formatted; gchar* cur; gsize i; formatted = g_malloc(3 * size); cur = formatted; for(i = 0; i < size; ++ i) { g_sprintf(cur, "%.2X", (unsigned int)data[i]); cur[2] = ':'; cur += 3; } cur[-1] = '\0'; return formatted; } static void inf_cert_util_free_array(GPtrArray* array, GPtrArray* current, guint current_len) { /* If current is given, then free all entries from current, keeping only * the first current_len entries. If not, free array completely. */ guint i; if(current != NULL) { for(i = current_len; i < current->len; ++ i) gnutls_x509_crt_deinit((gnutls_x509_crt_t)g_ptr_array_index(array, i)); } else { for(i = 0; i < array->len; ++ i) gnutls_x509_crt_deinit((gnutls_x509_crt_t)g_ptr_array_index(array, i)); g_ptr_array_free(array, TRUE); } } /* * Public API. */ /** * inf_cert_util_create_dh_params: * @error: Location to store error information, if any. * * Creates new, random Diffie-Hellman parameters. * * Returns: (transfer full): New dhparams to be freed * with gnutls_dh_params_deinit(), or %NULL in case of error. */ gnutls_dh_params_t inf_cert_util_create_dh_params(GError** error) { gnutls_dh_params_t params; int res; params = NULL; res = gnutls_dh_params_init(¶ms); if(res != 0) { inf_gnutls_set_error(error, res); return NULL; } res = gnutls_dh_params_generate2(params, 2048); if(res != 0) { gnutls_dh_params_deinit(params); inf_gnutls_set_error(error, res); return NULL; } return params; } /** * inf_cert_util_read_dh_params: * @filename: (type filename): A path to a DH parameters file. * @error: Location to store error information, if any. * * Reads the Diffie-Hellman parameters located at @filename into a * gnutls_dh_params_t structure. * * Returns: (transfer full): New dhparams to be freed with * gnutls_dh_params_deinit(), or %NULL in case of error. */ gnutls_dh_params_t inf_cert_util_read_dh_params(const gchar* filename, GError** error) { gnutls_dh_params_t params; gnutls_datum_t datum; gchar* data; gsize size; int res; params = NULL; data = NULL; if(g_file_get_contents(filename, &data, &size, error) == TRUE) { res = gnutls_dh_params_init(¶ms); if(res != 0) { inf_gnutls_set_error(error, res); } else { datum.data = (unsigned char*)data; datum.size = (unsigned int)size; res = gnutls_dh_params_import_pkcs3( params, &datum, GNUTLS_X509_FMT_PEM ); if(res != 0) { gnutls_dh_params_deinit(params); inf_gnutls_set_error(error, res); params = NULL; } } g_free(data); } return params; } /** * inf_cert_util_write_dh_params: * @params: (transfer none): An initialized #gnutls_dh_params_t * structure. * @filename: (type filename): The path at which so store @params. * @error: Location to store error information, if any. * * Writes the given Diffie-Hellman parameters to the given path on the * filesystem. If an error occurs, @error is set and %FALSE is returned. * * Returns: %TRUE on success or %FALSE otherwise. */ gboolean inf_cert_util_write_dh_params(gnutls_dh_params_t params, const gchar* filename, GError** error) { unsigned char* data; size_t size; int res; gboolean bres; size = 0; data = NULL; bres = FALSE; res = gnutls_dh_params_export_pkcs3( params, GNUTLS_X509_FMT_PEM, NULL, &size ); g_assert(res != 0); /* cannot succeed */ if(res != GNUTLS_E_SHORT_MEMORY_BUFFER) { inf_gnutls_set_error(error, res); } else { data = g_malloc(size); res = gnutls_dh_params_export_pkcs3( params, GNUTLS_X509_FMT_PEM, data, &size ); if(res != 0) inf_gnutls_set_error(error, res); else bres = g_file_set_contents(filename, (gchar*)data, size, error); g_free(data); } return bres; } /** * inf_cert_util_create_private_key: * @algo: The key algorithm to use (RSA or DSA). * @bits: The length of the key to generate. * @error: Location to store error information, if any. * * Generates a new, random X.509 private key. This function is a thin * wrapper around gnutls_x509_privkey_generate() which provides GError-style * error reporting. * * Returns: (transfer full): A new key to be freed with * gnutls_x509_privkey_deinit(), or %NULL if an error occured. */ gnutls_x509_privkey_t inf_cert_util_create_private_key(gnutls_pk_algorithm_t algo, unsigned int bits, GError** error) { gnutls_x509_privkey_t key; int res; res = gnutls_x509_privkey_init(&key); if(res != 0) { inf_gnutls_set_error(error, res); return NULL; } res = gnutls_x509_privkey_generate(key, algo, bits, 0); if(res != 0) { inf_gnutls_set_error(error, res); gnutls_x509_privkey_deinit(key); return NULL; } return key; } /** * inf_cert_util_read_private_key: * @filename: (type filename): A path to a X.509 private key file * @error: Location for error information, if any. * * Reads the key located at @filename into a gnutls_x509_privkey_t * structure. * * Returns: (transfer full): A private key. Free with * gnutls_x509_privkey_deinit(). */ gnutls_x509_privkey_t inf_cert_util_read_private_key(const gchar* filename, GError** error) { gnutls_x509_privkey_t key; gnutls_datum_t datum; gchar* data; gsize size; int res; key = NULL; data = NULL; if(g_file_get_contents(filename, &data, &size, error) == TRUE) { res = gnutls_x509_privkey_init(&key); if(res != 0) { inf_gnutls_set_error(error, res); } else { datum.data = (unsigned char*)data; datum.size = (unsigned int)size; res = gnutls_x509_privkey_import( key, &datum, GNUTLS_X509_FMT_PEM ); if(res != 0) { gnutls_x509_privkey_deinit(key); inf_gnutls_set_error(error, res); key = NULL; } } g_free(data); } return key; } /** * inf_cert_util_write_private_key: * @key: (transfer none): An initialized #gnutls_x509_privkey_t * structure. * @filename: (type filename): The path at which so store the key. * @error: Location to store error information, if any. * * Writes @key to the location specified by @filename on the filesystem. * If an error occurs, the function returns %FALSE and @error is set. * * Returns: %TRUE on success, %FALSE otherwise. */ gboolean inf_cert_util_write_private_key(gnutls_x509_privkey_t key, const gchar* filename, GError** error) { GString* string; gboolean result; string = g_string_sized_new(4096); result = inf_cert_util_write_private_key_string(key, string, error); if(result == FALSE) { g_string_free(string, TRUE); return FALSE; } result = inf_file_util_write_private_data( filename, string->str, string->len, error ); g_string_free(string, TRUE); return result; } /** * inf_cert_util_create_certificate: * @key: (transfer none): The private key to be used for the new * certificate. * @desc: The certificate properties. * @error: Location to store error information, if any, or %NULL. * * Creates a new X.509 certificate with the given key and properties. If * an error occurs the function returns %NULL and @error is set. The * returned certificate will not be signed. * * Returns: (transfer full): A new #gnutls_x509_crt_t, or %NULL. * Free with gnutls_x509_crt_deinit() when no longer needed. */ gnutls_x509_crt_t inf_cert_util_create_certificate(gnutls_x509_privkey_t key, const InfCertUtilDescription* desc, GError** error) { gnutls_x509_crt_t cert; int res; res = gnutls_x509_crt_init(&cert); if(res != 0) { inf_gnutls_set_error(error, res); return NULL; } res = inf_cert_util_create_certificate_impl(cert, key, desc); if(res != 0) { gnutls_x509_crt_deinit(cert); inf_gnutls_set_error(error, res); return NULL; } return cert; } /** * inf_cert_util_create_signed_certificate: * @key: (transfer none): The private key to be used for the new * certificate. * @desc: The certificate properties. * @sign_cert: (transfer none): A certificate used to sign the newly * created certificate. * @sign_key: (transfer none): The private key for @sign_cert. * @error: Location to store error information, if any, or %NULL. * * Creates a new X.509 certificate with the given key and properties. If * an error occurs the function returns %NULL and @error is set. The * returned certificate will be signed by @sign_cert. * * Returns: (transfer full): A new #gnutls_x509_crt_t, or %NULL. * Free with gnutls_x509_crt_deinit() when no longer needed. */ gnutls_x509_crt_t inf_cert_util_create_signed_certificate(gnutls_x509_privkey_t key, const InfCertUtilDescription* desc, gnutls_x509_crt_t sign_cert, gnutls_x509_privkey_t sign_key, GError** error) { gnutls_x509_crt_t cert; int res; cert = inf_cert_util_create_certificate(key, desc, error); if(cert == NULL) return NULL; res = gnutls_x509_crt_sign2( cert, sign_cert, sign_key, GNUTLS_DIG_SHA256, 0 ); if(res != 0) { gnutls_x509_crt_deinit(cert); inf_gnutls_set_error(error, res); return NULL; } return cert; } /** * inf_cert_util_create_self_signed_certificate: * @key: (transfer none): The private key to be used for the new * certificate. * @desc: The certificate properties. * @error: Location to store error information, if any, or %NULL. * * Creates a new X.509 certificate with the given key and properties. If * an error occurs the function returns %NULL and @error is set. The * returned certificate will be signed by itself. * * Returns: (transfer full): A new #gnutls_x509_crt_t, or %NULL. * Free with gnutls_x509_crt_deinit() when no longer needed. */ gnutls_x509_crt_t inf_cert_util_create_self_signed_certificate(gnutls_x509_privkey_t key, const InfCertUtilDescription* desc, GError** error) { gnutls_x509_crt_t cert; int res; cert = inf_cert_util_create_certificate(key, desc, error); if(cert == NULL) return NULL; res = gnutls_x509_crt_sign2( cert, cert, key, GNUTLS_DIG_SHA256, 0 ); if(res != 0) { gnutls_x509_crt_deinit(cert); inf_gnutls_set_error(error, res); return NULL; } return cert; } /** * inf_cert_util_read_certificate: * @filename: (type filename): A path to a X.509 certificate file. * @current: (element-type gnutls_x509_crt_t) (allow-none) (transfer full): An * array of #gnutls_x509_crt_t objects, or %NULL. * @error: Location to store error information, if any. * * Loads X.509 certificates in PEM format from the file at @filename. There * can be any number of certificates in the file. If @current is not %NULL, * the new certificates are appended to the array. Otherwise, a new array * with the read certificates is returned. * * If an error occurs, the function returns %NULL and @error is set. If * @current is non-%NULL and the function succeeds, the return value is the * same as @current. * * Returns: (transfer full) (element-type gnutls_x509_crt_t): An array of the * read certificates, or %NULL on error. */ GPtrArray* inf_cert_util_read_certificate(const gchar* filename, GPtrArray* current, GError** error) { gchar* contents; gsize length; GPtrArray* result; guint current_len; gchar* begin; gchar* end; int ret; gnutls_datum_t import_data; gnutls_x509_crt_t crt; if(!g_file_get_contents(filename, &contents, &length, error)) return NULL; if(current == NULL) { result = g_ptr_array_new(); } else { result = current; current_len = current->len; } end = contents; for(;;) { begin = g_strstr_len(end, length - (end - contents), X509_BEGIN_1); if(begin) { end = g_strstr_len(begin, length - (begin - contents), X509_END_1); if(!end) break; end += sizeof(X509_END_1); } else { begin = g_strstr_len(end, length - (end - contents), X509_BEGIN_2); if(!begin) break; end = g_strstr_len(begin, length - (begin - contents), X509_END_2); if(!end) break; end += sizeof(X509_END_2); } import_data.data = (unsigned char*)begin; import_data.size = end - begin; ret = gnutls_x509_crt_init(&crt); if(ret != GNUTLS_E_SUCCESS) { inf_cert_util_free_array(result, current, current_len); inf_gnutls_set_error(error, ret); g_free(contents); return NULL; } ret = gnutls_x509_crt_import(crt, &import_data, GNUTLS_X509_FMT_PEM); if(ret != GNUTLS_E_SUCCESS) { gnutls_x509_crt_deinit(crt); inf_cert_util_free_array(result, current, current_len); inf_gnutls_set_error(error, ret); g_free(contents); return NULL; } g_ptr_array_add(result, crt); } g_free(contents); return result; } /** * inf_cert_util_write_certificate: * @certs: (array length=n_certs) (transfer none): An array of * #gnutls_x509_crt_t objects. * @n_certs: Number of certificates in the error. * @filename: (type filename): The path at which to store the certificates. * @error: Location to store error information, if any. * * This function writes the certificates in the array @certs to disk, in * PEM format. If an error occurs the function returns %FALSE and @error * is set. * * Returns: %TRUE on success or %FALSE otherwise. */ gboolean inf_cert_util_write_certificate(gnutls_x509_crt_t* certs, guint n_certs, const gchar* filename, GError** error) { GString* string; gboolean result; string = g_string_sized_new(n_certs * 4096); result = inf_cert_util_write_certificates_string( certs, n_certs, string, error ); if(result == FALSE) { g_string_free(string, TRUE); return FALSE; } result = g_file_set_contents( filename, string->str, string->len, error ); g_string_free(string, TRUE); return result; } /** * inf_cert_util_write_certificate_mem: * @certs: (transfer none): An * array of #gnutls_x509_crt_t objects. * @n_certs: Number of certificates in the error. * @error: Location to store error information, if any. * * This function writes the certificates in the array @certs into memory, in * PEM format. If an error occurs the function returns %NULL and @error * is set. * * Returns: (transfer full): A string with PEM-encoded certificate data, or * %NULL on error. Free with g_free(). */ gchar* inf_cert_util_write_certificate_mem(gnutls_x509_crt_t* certs, guint n_certs, GError** error) { GString* string; gboolean result; string = g_string_sized_new(n_certs * 4096); result = inf_cert_util_write_certificates_string( certs, n_certs, string, error ); if(result == FALSE) { g_string_free(string, TRUE); return FALSE; } return g_string_free(string, FALSE); } /** * inf_cert_util_write_certificate_with_key: * @key: (transfer none): An initialized #gnutls_x509_privkey_t * structure. * @certs: (transfer none) (array length=n_certs): An array of * #gnutls_x509_crt_t objects. * @n_certs: Number of certificates in the error. * @filename: (type filename): The path at which to store the certificates. * @error: Location to store error information, if any. * * This function writes both the private key @key as well as the * certificates in the array @certs to disk, in PEM format. If an error * occurs the function returns %FALSE and @error is set. * * Returns: %TRUE on success or %FALSE otherwise. */ gboolean inf_cert_util_write_certificate_with_key(gnutls_x509_privkey_t key, gnutls_x509_crt_t* certs, guint n_certs, const gchar* filename, GError** error) { GString* string; gboolean result; string = g_string_sized_new( (n_certs + 1) * 4096); result = inf_cert_util_write_private_key_string(key, string, error); if(result == FALSE) { g_string_free(string, TRUE); return FALSE; } result = inf_cert_util_write_certificates_string( certs, n_certs, string, error ); if(result == FALSE) { g_string_free(string, TRUE); return FALSE; } result = inf_file_util_write_private_data( filename, string->str, string->len, error ); g_string_free(string, TRUE); return result; } /** * inf_cert_util_copy_certificate: * @src: (transfer none): The certificate to copy. * @error: Location to store error information, if any. * * Creates a copy of the certificate @src and returns the copy. If the * function fails %FALSE is returned and @error is set. * * Returns: (transfer full): A copy of @src, or %NULL on error. Free * with gnutls_x509_crt_deinit() when no longer in use. */ gnutls_x509_crt_t inf_cert_util_copy_certificate(gnutls_x509_crt_t src, GError** error) { gnutls_x509_crt_t dest; int ret; size_t der_size; gpointer data; gnutls_datum_t tmp; der_size = 0; ret = gnutls_x509_crt_export(src, GNUTLS_X509_FMT_DER, NULL, &der_size); if (ret != GNUTLS_E_SHORT_MEMORY_BUFFER) { inf_gnutls_set_error(error, ret); return NULL; } data = g_malloc(der_size); ret = gnutls_x509_crt_export(src, GNUTLS_X509_FMT_DER, data, &der_size); if (ret < 0) { g_free(data); inf_gnutls_set_error(error, ret); return NULL; } gnutls_x509_crt_init(&dest); tmp.data = data; tmp.size = der_size; ret = gnutls_x509_crt_import(dest, &tmp, GNUTLS_X509_FMT_DER); g_free(data); if (ret < 0) { gnutls_x509_crt_deinit(dest); inf_gnutls_set_error(error, ret); return NULL; } return dest; } /** * inf_cert_util_read_certificate_map: * @filename: The filename to read the certificate map from. * @error: Location to store error information, if any. * * Reads a certificate map, i.e. a mapping from hostname to certificate, * from the given file. The format of the file is expected to be one entry * per line, where each entry consists of the hostname, then a colon * character (':'), and then the base64-encoded certificate in DER format. * * If the file with the given filename does not exist, an empty hash table * is returned and the function succeeds. * * Returns: (transfer container) (element-type string gnutls_x509_crt_t): * A hash table with the read mapping, or %NULL on error. Use * g_hash_table_unref() to free the hash table when no longer needed. */ GHashTable* inf_cert_util_read_certificate_map(const gchar* filename, GError** error) { GHashTable* table; gchar* content; gsize size; GError* local_error; gchar* out_buf; gsize out_buf_len; gchar* pos; gchar* prev; gchar* next; gchar* sep; gsize len; gsize out_len; gint base64_state; guint base64_save; gnutls_datum_t data; gnutls_x509_crt_t cert; int res; table = g_hash_table_new_full( g_str_hash, g_str_equal, g_free, (GDestroyNotify)gnutls_x509_crt_deinit ); local_error = NULL; g_file_get_contents(filename, &content, &size, &local_error); if(local_error != NULL) { if(local_error->domain == G_FILE_ERROR && local_error->code == G_FILE_ERROR_NOENT) { return table; } g_propagate_error(error, local_error); g_hash_table_destroy(table); return NULL; } out_buf = NULL; out_buf_len = 0; prev = content; for(prev = content; prev != NULL; prev = next) { pos = strchr(prev, '\n'); next = NULL; if(pos == NULL) pos = content + size; else next = pos + 1; sep = inf_cert_util_memrchr(prev, ':', pos - prev); if(sep == NULL) continue; /* ignore line */ *sep = '\0'; if(g_hash_table_lookup(table, prev) != NULL) { g_set_error( error, g_quark_from_static_string("INF_CERT_UTIL_ERROR"), INF_CERT_UTIL_ERROR_DUPLICATE_HOST_ENTRY, _("Certificate for host \"%s\" appears twice"), prev ); g_hash_table_destroy(table); g_free(out_buf); g_free(content); return NULL; } /* decode base64, import DER certificate */ len = (pos - (sep + 1)); out_len = len * 3 / 4; if(out_len > out_buf_len) { out_buf = g_realloc(out_buf, out_len); out_buf_len = out_len; } base64_state = 0; base64_save = 0; out_len = g_base64_decode_step( sep + 1, len, out_buf, &base64_state, &base64_save ); cert = NULL; res = gnutls_x509_crt_init(&cert); if(res == GNUTLS_E_SUCCESS) { data.data = out_buf; data.size = out_len; res = gnutls_x509_crt_import(cert, &data, GNUTLS_X509_FMT_DER); } if(res != GNUTLS_E_SUCCESS) { inf_gnutls_set_error(&local_error, res); g_propagate_prefixed_error( error, local_error, _("Failed to read certificate for host \"%s\""), prev ); if(cert != NULL) gnutls_x509_crt_deinit(cert); g_hash_table_destroy(table); g_free(out_buf); g_free(content); return NULL; } g_hash_table_insert(table, g_strdup(prev), cert); } g_free(out_buf); g_free(content); return table; } /** * inf_cert_util_write_certificate_map: * @cert_map: (transfer none) (element-type string gnutls_x509_crt_t): A * certificate mapping, i.e. a hash table mapping hostname strings to * #gnutls_x509_crt_t instances. * @filename: The name of the file to write the mapping to. * @error: Location to store error information, if any. * * Writes the given certificate mapping to a file with the given filename. * See inf_cert_util_read_certificate_map() for the format of the written * file. If an error occurs, @error is set and the function returns %FALSE. * * This function can be useful to implement trust-on-first-use (TOFU) * semantics. * * Returns: %TRUE on success or %FALSE on error. */ gboolean inf_cert_util_write_certificate_map(GHashTable* cert_map, const gchar* filename, GError** error) { gchar* dirname; GString* string; GHashTableIter iter; gpointer key; gpointer value; const gchar* hostname; gnutls_x509_crt_t cert; size_t size; int res; gchar* buffer; gchar* encoded_cert; string = g_string_sized_new(4096 * g_hash_table_size(cert_map)); g_hash_table_iter_init(&iter, cert_map); while(g_hash_table_iter_next(&iter, &key, &value)) { hostname = (const gchar*)key; cert = (gnutls_x509_crt_t)value; size = 0; res = gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_DER, NULL, &size); g_assert(res != GNUTLS_E_SUCCESS); buffer = NULL; if(res == GNUTLS_E_SHORT_MEMORY_BUFFER) { buffer = g_malloc(size); res = gnutls_x509_crt_export(cert, GNUTLS_X509_FMT_DER, buffer, &size); } if(res != GNUTLS_E_SUCCESS) { g_free(buffer); g_string_free(string, TRUE); inf_gnutls_set_error(error, res); return FALSE; } encoded_cert = g_base64_encode(buffer, size); g_free(buffer); g_string_append(string, hostname); g_string_append_c(string, ':'); g_string_append(string, encoded_cert); g_string_append_c(string, '\n'); g_free(encoded_cert); } g_file_set_contents( filename, string->str, string->len, error ); g_string_free(string, TRUE); return TRUE; } /** * inf_cert_util_check_certificate_key: * @cert: (transfer none): The certificate to be checked. * @key: (transfer none): The private key to be checked. * * This function returns %TRUE if @key is the private key belonging to @cert, * or %FALSE otherwise. * * Returns: %TRUE if @cert was signed with @key, or %FALSE otherwise. */ gboolean inf_cert_util_check_certificate_key(gnutls_x509_crt_t cert, gnutls_x509_privkey_t key) { unsigned char cert_id[20]; size_t cert_id_size; unsigned char key_id[20]; size_t key_id_size; g_return_val_if_fail(cert != NULL, FALSE); g_return_val_if_fail(key != NULL, FALSE); cert_id_size = 20; if(gnutls_x509_crt_get_key_id(cert, 0, cert_id, &cert_id_size) != 0) return FALSE; key_id_size = 20; if(gnutls_x509_privkey_get_key_id(key, 0, key_id, &key_id_size) != 0) return FALSE; if(memcmp(cert_id, key_id, 20) != 0) return FALSE; return TRUE; } /** * inf_cert_util_compare_fingerprint: * @cert1: The first certificate to compare. * @cert2: The second certificate to compare. * @error: Location to store error information, if any. * * Checks whether the SHA-256 fingerprints of the two given certificates are * identical or not. If a fingerprint cannot be obtained, the function * returns %FALSE and @error is set. * * Returns: Whether the two certificates have identical fingerprints. Returns * %FALSE on error. */ gboolean inf_cert_util_compare_fingerprint(gnutls_x509_crt_t cert1, gnutls_x509_crt_t cert2, GError** error) { static const unsigned int SHA256_DIGEST_SIZE = 32; size_t size; guchar cert1_fingerprint[SHA256_DIGEST_SIZE]; guchar cert2_fingerprint[SHA256_DIGEST_SIZE]; int ret; int cmp; size = SHA256_DIGEST_SIZE; ret = gnutls_x509_crt_get_fingerprint( cert1, GNUTLS_DIG_SHA256, cert1_fingerprint, &size ); if(ret == GNUTLS_E_SUCCESS) { g_assert(size == SHA256_DIGEST_SIZE); ret = gnutls_x509_crt_get_fingerprint( cert2, GNUTLS_DIG_SHA256, cert2_fingerprint, &size ); } if(ret != GNUTLS_E_SUCCESS) { inf_gnutls_set_error(error, ret); return FALSE; } cmp = memcmp(cert1_fingerprint, cert2_fingerprint, SHA256_DIGEST_SIZE); if(cmp != 0) return FALSE; return TRUE; } /** * inf_cert_util_get_dn: * @cert: (transfer none): An initialized #gnutls_x509_crt_t. * * Retrieves the full distinguished name (DN) from the certificate, allocating * memory for the return value. * * Returns: (transfer full): The DN of the certificate. Free with g_free() * after use. */ gchar* inf_cert_util_get_dn(gnutls_x509_crt_t cert) { size_t size; gchar* buffer; int ret; buffer = NULL; size = 0; ret = gnutls_x509_crt_get_dn(cert, buffer, &size); if(ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) return NULL; g_assert(ret == GNUTLS_E_SHORT_MEMORY_BUFFER); buffer = g_malloc(size); ret = gnutls_x509_crt_get_dn(cert, buffer, &size); if(ret < 0) { g_free(buffer); buffer = NULL; } return buffer; } /** * inf_cert_util_get_dn_by_oid: * @cert: (transfer none): An initialized #gnutls_x509_crt_t. * @oid: The name of the requested entry. * @index: Index of the entry to retrieve. * * Retrieves the given item from the certificate. This function is a thin * wrapper around gnutls_x509_crt_get_dn_by_oid(), allocating memory for the * return value. The function returns %NULL if there is no such entry in the * certificate. * * Returns: (transfer full): The certificate entry, or %NULL if it is not * present. Free with g_free() after use. */ gchar* inf_cert_util_get_dn_by_oid(gnutls_x509_crt_t cert, const char* oid, unsigned int index) { size_t size; gchar* buffer; int ret; buffer = NULL; size = 0; ret = gnutls_x509_crt_get_dn_by_oid(cert, oid, index, 0, buffer, &size); if(ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) return NULL; g_assert(ret == GNUTLS_E_SHORT_MEMORY_BUFFER); buffer = g_malloc(size); ret = gnutls_x509_crt_get_dn_by_oid(cert, oid, index, 0, buffer, &size); if(ret < 0) { g_free(buffer); buffer = NULL; } return buffer; } /** * inf_cert_util_get_issuer_dn_by_oid: * @cert: (transfer none): An initialized #gnutls_x509_crt_t. * @oid: The name of the requested entry. * @index: Index of the entry to retrieve. * * Retrieves the given item from the issuer of the certificate. This function * is a thin wrapper around gnutls_x509_crt_get_issuer_dn_by_oid(), * allocating memory for the return value. The functions returns %NULL if * there is no such entry in the certificate. * * Returns: (transfer full): The certificate entry, or %NULL if it is not * present. Free with g_free() after use. */ gchar* inf_cert_util_get_issuer_dn_by_oid(gnutls_x509_crt_t cert, const char* oid, unsigned int index) { size_t size; gchar* buffer; int ret; buffer = NULL; size = 0; ret = gnutls_x509_crt_get_issuer_dn_by_oid( cert, oid, index, 0, buffer, &size ); if(ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) return NULL; g_assert(ret == GNUTLS_E_SHORT_MEMORY_BUFFER); buffer = g_malloc(size); ret = gnutls_x509_crt_get_issuer_dn_by_oid( cert, oid, index, 0, buffer, &size ); if(ret < 0) { g_free(buffer); buffer = NULL; } return buffer; } /** * inf_cert_util_get_hostname: * @cert: (transfer none): An initialized gnutls_x509_crt_t. * * Attempts to read the hostname of a certificate. This is done by looking * at the DNS name and IP address SANs. If both are not available, the common * name of the certificate is returned. * * Returns: (transfer full) (allow-none): The best guess for the * certificate's hostname, or %NULL when it cannot be retrieved. Free with * g_free() after use. */ gchar* inf_cert_util_get_hostname(gnutls_x509_crt_t cert) { guint i; int ret; size_t size; gchar* buffer; buffer = NULL; size = 0; for(i = 0; ; ++ i) { ret = gnutls_x509_crt_get_subject_alt_name(cert, i, buffer, &size, NULL); if(ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) break; if(ret == GNUTLS_E_SHORT_MEMORY_BUFFER) { buffer = g_realloc(buffer, size); ret = gnutls_x509_crt_get_subject_alt_name( cert, i, buffer, &size, NULL ); } if(ret == GNUTLS_SAN_DNSNAME || ret == GNUTLS_SAN_IPADDRESS) return buffer; } g_free(buffer); return inf_cert_util_get_dn_by_oid(cert, GNUTLS_OID_X520_COMMON_NAME, 0); } /** * inf_cert_util_get_serial_number: * @cert: (transfer none): An initialized #gnutls_x509_crt_t. * * Read the serial number of a certificate and return it in hexadecimal * format. If the serial number cannot be read %NULL is returned. * * Returns: (transfer full): The serial number of the certificate, or %NULL. * Free with g_free() after use. */ gchar* inf_cert_util_get_serial_number(gnutls_x509_crt_t cert) { int ret; size_t size; guchar* value; gchar* formatted; size = 0; ret = gnutls_x509_crt_get_serial(cert, NULL, &size); if(ret != GNUTLS_E_SHORT_MEMORY_BUFFER) return NULL; value = g_malloc(size); ret = gnutls_x509_crt_get_serial(cert, value, &size); if(ret != GNUTLS_E_SUCCESS) return NULL; formatted = inf_cert_util_format_hexadecimal(value, size); g_free(value); return formatted; } /** * inf_cert_util_get_fingerprint: * @cert: (transfer none): An initialized #gnutls_x509_crt_t. * @algo: The hashing algorithm to use. * * Returns the fingerprint of the certificate hashed with the specified * algorithm, in hexadecimal format. If the fingerprint cannot be read %NULL * is returned. * * Returns: (transfer full): The fingerprint of the certificate, or %NULL. * Free with g_free() after use. */ gchar* inf_cert_util_get_fingerprint(gnutls_x509_crt_t cert, gnutls_digest_algorithm_t algo) { int ret; size_t size; guchar* value; gchar* formatted; size = 0; ret = gnutls_x509_crt_get_fingerprint(cert, algo, NULL, &size); if(ret != GNUTLS_E_SHORT_MEMORY_BUFFER) return NULL; value = g_malloc(size); ret = gnutls_x509_crt_get_fingerprint(cert, algo, value, &size); if(ret != GNUTLS_E_SUCCESS) return NULL; formatted = inf_cert_util_format_hexadecimal(value, size); g_free(value); return formatted; } /** * inf_cert_util_get_activation_time: * @cert: (transfer none): An initialized #gnutls_x509_crt_t. * * Returns the activation time of the certificate as a string in * human-readable format. If the activation time cannot be read %NULL is * returned. * * Returns: (transfer full): The activation time of the certificate, or %NULL. * Free with g_free() after use. */ gchar* inf_cert_util_get_activation_time(gnutls_x509_crt_t cert) { time_t time; time = gnutls_x509_crt_get_activation_time(cert); if(time == (time_t)(-1)) return NULL; return inf_cert_util_format_time(time); } /** * inf_cert_util_get_expiration_time: * @cert: (transfer none): An initialized #gnutls_x509_crt_t. * * Returns the expiration time of the certificate as a string in * human-readable format. If the expiration time cannot be read %NULL is * returned. * * Returns: (transfer full): The expiration time of the certificate, or %NULL. * Free with g_free() after use. */ gchar* inf_cert_util_get_expiration_time(gnutls_x509_crt_t cert) { time_t time; time = gnutls_x509_crt_get_expiration_time(cert); if(time == (time_t)(-1)) return NULL; return inf_cert_util_format_time(time); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-sasl-context.h0000644000000000000000000000013213034342512022757 xustar0030 mtime=1483851082.033718448 30 atime=1483851082.033718448 30 ctime=1488261588.960139153 libinfinity-0.7.1/libinfinity/common/inf-sasl-context.h0000644000175000017500000001504313034342512023514 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_SASL_CONTEXT_H__ #define __INF_SASL_CONTEXT_H__ #include #include #include G_BEGIN_DECLS #define INF_TYPE_SASL_CONTEXT (inf_sasl_context_get_type()) /** * InfSaslContext: * * #InfSaslContext is an opaque data type. You should only access it via the * public API functions. */ typedef struct _InfSaslContext InfSaslContext; /** * InfSaslContextSession: (foreign) * * #InfSaslContextSession represents an ongoing authentication session. Create * with inf_sasl_context_server_start_session() or * inf_sasl_context_client_start_session(). */ typedef struct _InfSaslContextSession InfSaslContextSession; /** * InfSaslContextCallbackFunc: * @session: A #InfSaslContextSession. * @property: The property requested. * @session_data: The session data for session specified in * inf_sasl_context_server_start_session() or * inf_sasl_context_client_start_session(). * @user_data: The user data specified in inf_sasl_context_set_callback(). * * This callback is called whenever a property is required to proceed with * authentication. For example, when a password is required, the callback is * called with @property set to %GSASL_PASSCODE. * * The function is then expected to set that property using * inf_sasl_context_session_set_property() and, once it is done, call * inf_sasl_context_session_continue(). This can happen fully asynchronously, * that is it does not need to take place directly within the callback but the * callback can, for example, open a dialog for the user to enter a password * and then once the user closes the dialog call the two functions mentioned * above. */ typedef void(*InfSaslContextCallbackFunc)(InfSaslContextSession* session, Gsasl_property property, gpointer session_data, gpointer user_data); /** * InfSaslContextSessionFeedFunc: * @session: A #InfSaslContextSession. * @data: The response to the fed data, base64 encoded and null-terminated. * @needs_more: If %TRUE then inf_sasl_context_session_feed() needs to be * called again with more data, otherwise the authentication has finished. * @error: This is nonzero if an error occured while processing the input * data. * @user_data: The user data specified in inf_sasl_context_session_feed(). * * This function is called in response to inf_sasl_context_session_feed(). * When all required properties (if any) have been provided by the callback * function then this function is called with the response to send to the * remote site. * * If an error occurred then @error will be set and @data will be %NULL. */ typedef void(*InfSaslContextSessionFeedFunc)(InfSaslContextSession* session, const char* data, gboolean needs_more, const GError* error, gpointer user_data); GType inf_sasl_context_get_type(void) G_GNUC_CONST; InfSaslContext* inf_sasl_context_new(GError** error); InfSaslContext* inf_sasl_context_ref(InfSaslContext* context); void inf_sasl_context_unref(InfSaslContext* context); void inf_sasl_context_set_callback(InfSaslContext* context, InfSaslContextCallbackFunc callback, gpointer user_data, GDestroyNotify notify); InfSaslContextSession* inf_sasl_context_client_start_session(InfSaslContext* context, InfIo* io, const char* mech, gpointer session_data, GError** error); char* inf_sasl_context_client_list_mechanisms(InfSaslContext* context, GError** error); gboolean inf_sasl_context_client_supports_mechanism(InfSaslContext* context, const char* mech); const char* inf_sasl_context_client_suggest_mechanism(InfSaslContext* context, const char* mechanisms); InfSaslContextSession* inf_sasl_context_server_start_session(InfSaslContext* context, InfIo* io, const char* mech, gpointer session_data, GError** error); char* inf_sasl_context_server_list_mechanisms(InfSaslContext* context, GError** error); gboolean inf_sasl_context_server_supports_mechanism(InfSaslContext* context, const char* mech); void inf_sasl_context_stop_session(InfSaslContext* context, InfSaslContextSession* session); const char* inf_sasl_context_session_get_property(InfSaslContextSession* session, Gsasl_property prop); void inf_sasl_context_session_set_property(InfSaslContextSession* session, Gsasl_property prop, const char* value); void inf_sasl_context_session_continue(InfSaslContextSession* session, int retval); void inf_sasl_context_session_feed(InfSaslContextSession* session, const char* data, InfSaslContextSessionFeedFunc func, gpointer user_data); gboolean inf_sasl_context_session_is_processing(InfSaslContextSession* session); G_END_DECLS #endif /* __INF_SASL_CONTEXT_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-certificate-verify.h0000644000000000000000000000013213034342512024117 xustar0030 mtime=1483851082.029718427 30 atime=1483851082.029718427 30 ctime=1488261588.940139196 libinfinity-0.7.1/libinfinity/common/inf-certificate-verify.h0000644000175000017500000001025113034342512024650 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef __INF_CERTIFICATE_VERIFY_H__ #define __INF_CERTIFICATE_VERIFY_H__ #include #include #include G_BEGIN_DECLS #define INF_TYPE_CERTIFICATE_VERIFY (inf_certificate_verify_get_type()) #define INF_CERTIFICATE_VERIFY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_TYPE_CERTIFICATE_VERIFY, InfCertificateVerify)) #define INF_CERTIFICATE_VERIFY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INF_TYPE_CERTIFICATE_VERIFY, InfCertificateVerifyClass)) #define INF_IS_CERTIFICATE_VERIFY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_TYPE_CERTIFICATE_VERIFY)) #define INF_IS_CERTIFICATE_VERIFY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INF_TYPE_CERTIFICATE_VERIFY)) #define INF_CERTIFICATE_VERIFY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INF_TYPE_CERTIFICATE_VERIFY, InfCertificateVerifyClass)) #define INF_TYPE_CERTIFICATE_VERIFY_FLAGS (inf_certificate_verify_flags_get_type()) typedef struct _InfCertificateVerify InfCertificateVerify; typedef struct _InfCertificateVerifyClass InfCertificateVerifyClass; /** * InfCertificateVerifyFlags: * @INF_CERTIFICATE_VERIFY_HOSTNAME_MISMATCH: The hostname of the * machine connected to does not match the one from the certificate. * @INF_CERTIFICATE_VERIFY_ISSUER_NOT_KNOWN: The issuer of the * certificate is not trusted, i.e. is not in the list of trusted CAs. * @INF_CERTIFICATE_VERIFY_NOT_PINNED: We have pinned a certificate for this * host, but the certificate presented is a different one. * * Various flags for why a certificate is not trusted. */ typedef enum _InfCertificateVerifyFlags { INF_CERTIFICATE_VERIFY_HOSTNAME_MISMATCH = 1 << 0, INF_CERTIFICATE_VERIFY_ISSUER_NOT_KNOWN = 1 << 1, INF_CERTIFICATE_VERIFY_NOT_PINNED = 1 << 2 } InfCertificateVerifyFlags; /** * InfCertificateVerifyClass: * @check_certificate: Default signal handler for the * #InfCertificateVerify::check-certificate signal. * * This structure contains default signal handlers for #InfCertificateVerify. */ struct _InfCertificateVerifyClass { /*< private >*/ GObjectClass parent_class; /*< public >*/ void (*check_certificate)(InfCertificateVerify* verify, InfXmppConnection* connection, InfCertificateChain* certificate_chain, gnutls_x509_crt_t pinned_certificate, InfCertificateVerifyFlags flags); void (*check_cancelled)(InfCertificateVerify* verify, InfXmppConnection* connection); }; /** * InfCertificateVerify: * * #InfCertificateVerify is an opaque data type. You should only access it * via the public API functions. */ struct _InfCertificateVerify { /*< private >*/ GObject parent; }; GType inf_certificate_verify_flags_get_type(void) G_GNUC_CONST; GType inf_certificate_verify_get_type(void) G_GNUC_CONST; InfCertificateVerify* inf_certificate_verify_new(InfXmppManager* xmpp_manager, const gchar* known_hosts_file); void inf_certificate_verify_checked(InfCertificateVerify* verify, InfXmppConnection* connection, gboolean result); G_END_DECLS #endif /* __INF_CERTIFICATE_VERIFY_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-file-util.c0000644000000000000000000000013213034342512022220 xustar0030 mtime=1483851082.033718448 30 atime=1483851082.033718448 30 ctime=1488261589.056138943 libinfinity-0.7.1/libinfinity/common/inf-file-util.c0000644000175000017500000003724613034342512022766 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-file-util * @title: File and directory utility functions * @short_description: Helper functions to handle directories. * @include: libinfinity/common/inf-file-util.h * @stability: Unstable * * These functions are utility functions that can be used when dealing with * directories. It allows platform-independent creation, deletion and * traversal of directories, with proper error reporting. **/ #include #include #include #include "config.h" #ifdef G_OS_WIN32 #include #else #include #include #include #include #include #include #endif #ifdef G_OS_WIN32 static void inf_file_util_set_error_from_win32(GError** error, int code) { GFileError gcode; gchar* message; switch(code) { case ERROR_FILE_NOT_FOUND: gcode = G_FILE_ERROR_NOENT; break; case ERROR_PATH_NOT_FOUND: gcode = G_FILE_ERROR_NOENT; break; case ERROR_TOO_MANY_OPEN_FILES: gcode = G_FILE_ERROR_MFILE; break; case ERROR_ACCESS_DENIED: gcode = G_FILE_ERROR_ACCES; break; case ERROR_ALREADY_EXISTS: gcode = G_FILE_ERROR_EXIST; break; case ERROR_OUTOFMEMORY: gcode = G_FILE_ERROR_NOMEM; break; case ERROR_INVALID_DRIVE: gcode = G_FILE_ERROR_NXIO; break; case ERROR_CURRENT_DIRECTORY: gcode = G_FILE_ERROR_PERM; break; /* EBUSY */ case ERROR_NOT_SAME_DEVICE: gcode = G_FILE_ERROR_NODEV; break; /*EXDEV */ case ERROR_NOT_READY: gcode = G_FILE_ERROR_FAILED; break; /* EBUSY */ case ERROR_NOT_SUPPORTED: gcode = G_FILE_ERROR_NOSYS; break; case ERROR_FILE_EXISTS: gcode = G_FILE_ERROR_EXIST; break; case ERROR_DISK_FULL: gcode = G_FILE_ERROR_NOSPC; break; case ERROR_INVALID_NAME: gcode = G_FILE_ERROR_INVAL; break; case ERROR_DIR_NOT_EMPTY: gcode = G_FILE_ERROR_EXIST; break; case ERROR_PATH_BUSY: gcode = G_FILE_ERROR_FAILED; break; /* EBUSY */ case ERROR_BAD_ARGUMENTS: gcode = G_FILE_ERROR_INVAL; break; case ERROR_BAD_PATHNAME: gcode = G_FILE_ERROR_INVAL; break; case ERROR_BUSY: gcode = G_FILE_ERROR_FAILED; break; /* EBUSY */ case ERROR_FILENAME_EXCED_RANGE: gcode = G_FILE_ERROR_NAMETOOLONG; break; case ERROR_DIRECTORY: gcode = G_FILE_ERROR_ISDIR; break; case ERROR_DELETE_PENDING: gcode = G_FILE_ERROR_NOENT; break; case ERROR_INVALID_ADDRESS: gcode = G_FILE_ERROR_FAULT; break; default: gcode = G_FILE_ERROR_FAILED; break; } message = g_win32_error_message(code); g_set_error_literal( error, G_FILE_ERROR, G_FILE_ERROR_FAILED, message ); g_free(message); } #else static void inf_file_util_set_error_from_errno(GError** error, int code) { g_set_error_literal( error, G_FILE_ERROR, g_file_error_from_errno(code), g_strerror(code) ); } #endif static gboolean inf_file_util_delete_directory_list_func(const gchar* name, const gchar* path, InfFileType type, gpointer user_data, GError** error) { switch(type) { case INF_FILE_TYPE_UNKNOWN: case INF_FILE_TYPE_REG: case INF_FILE_TYPE_LNK: if(inf_file_util_delete_file(path, error) == FALSE) return FALSE; return TRUE; case INF_FILE_TYPE_DIR: if(inf_file_util_delete_directory(path, error) == FALSE) return FALSE; return TRUE; default: g_assert_not_reached(); return FALSE; } } /** * inf_file_util_create_single_directory: * @path: (type filename): The directory to create. * @mode: Permissions to use for the newly created directory. * @error: Location to store error information, if any, or %NULL. * * Attempts to create a directory at @path. The @mode parameter is only used * on Unix in which case it specifies the permissions to use for all newly * created directories in the same way as g_mkdir() would. * * Returns: %TRUE on success or %FALSE on error. */ gboolean inf_file_util_create_single_directory(const gchar* path, int mode, GError** error) { #ifdef G_OS_WIN32 gunichar2* path16; int code; path16 = g_utf8_to_utf16(path, -1, NULL, NULL, error); if(!path16) return FALSE; if(CreateDirectoryW(path16, NULL) == FALSE) { g_free(path16); code = GetLastError(); inf_file_util_set_error_from_win32(error, code); return FALSE; } g_free(path16); return TRUE; #else int code; if(g_mkdir(path, mode) == -1) { code = errno; inf_file_util_set_error_from_errno(error, code); return FALSE; } return TRUE; #endif } /** * inf_file_util_create_directory: * @path: (type filename): The directory to create. * @mode: Permissions to use for the newly created directory. * @error: Location to store error information, if any, or %NULL. * * Attempts to create a directory at @path, creating intermediate directories * as necessary. The @mode parameter is only used on Unix in which case it * specifies the permissions to use for all newly created directories in the * same way as g_mkdir() would. * * Returns: %TRUE on success or %FALSE on error. */ gboolean inf_file_util_create_directory(const gchar* path, int mode, GError** error) { gchar* dirname; gboolean result; if(g_file_test(path, G_FILE_TEST_IS_DIR)) return TRUE; dirname = g_path_get_dirname(path); result = inf_file_util_create_directory(dirname, mode, error); g_free(dirname); if(result == FALSE) return FALSE; return inf_file_util_create_single_directory(path, mode, error); } /** * inf_file_util_list_directory: * @path: (type filename): The directory to explore. * @func: (scope call): Callback function to be called for each child of the * directory at @path. * @user_data: Additional data to pass to @func. * @error: Location to store error information, if any, or %NULL. * * Calls @func for each file within the given directory. It also passes the * type of the found file to the callback function. The callback function can * return %FALSE to stop the iteration. If it does this, then this function * still returns %TRUE. This can for example be used to find a file in a * directory. If, in addition, the callback function sets @error, then this * function returns %FALSE and propagates the error. * * Returns: %TRUE on success or %FALSE on error. */ gboolean inf_file_util_list_directory(const gchar* path, InfFileListFunc func, gpointer user_data, GError** error) { #if !defined(G_OS_WIN32) && !defined(__APPLE__) int dir_fd; DIR* dir; struct dirent* dir_entry; struct dirent* dir_result; struct stat stat_buf; int saved_errno; InfFileType filetype; gchar* file_path; gboolean result; GError* local_error; #ifdef HAVE_O_NOFOLLOW dir_fd = open(path, O_NOFOLLOW | O_RDONLY); #else dir_fd = open(path, O_RDONLY); #endif if(dir_fd == -1 || (dir = fdopendir(dir_fd)) == NULL) { inf_file_util_set_error_from_errno(error, errno); if(dir_fd != -1) close(dir_fd); return FALSE; } result = TRUE; local_error = NULL; dir_entry = g_malloc(offsetof(struct dirent, d_name) + fpathconf(dir_fd, _PC_NAME_MAX) + 1); for(saved_errno = readdir_r(dir, dir_entry, &dir_result); result == TRUE && saved_errno == 0 && dir_result != NULL; saved_errno = readdir_r(dir, dir_entry, &dir_result)) { if(strcmp(dir_result->d_name, ".") == 0 || strcmp(dir_result->d_name, "..") == 0) { continue; } filetype = INF_FILE_TYPE_UNKNOWN; file_path = g_build_filename(path, dir_result->d_name, NULL); #ifdef HAVE_D_TYPE if(dir_result->d_type == DT_LNK) filetype = INF_FILE_TYPE_LNK; else if(dir_result->d_type == DT_DIR) filetype = INF_FILE_TYPE_DIR; else if(dir_result->d_type == DT_REG) filetype = INF_FILE_TYPE_REG; else if(dir_result->d_type == DT_UNKNOWN) #endif { /* Some filesystems, such as reiserfs, don't support reporting the * entry's file type. In that case we do an additional lstat here. * Also lstat if d_type is not available on this platform. */ if(lstat(file_path, &stat_buf) == 0) { if(S_ISDIR(stat_buf.st_mode)) filetype = INF_FILE_TYPE_DIR; else if(S_ISREG(stat_buf.st_mode)) filetype = INF_FILE_TYPE_REG; else if(S_ISLNK(stat_buf.st_mode)) filetype = INF_FILE_TYPE_LNK; } } result = func( dir_result->d_name, file_path, filetype, user_data, &local_error ); g_free(file_path); } g_free(dir_entry); if(closedir(dir) == -1) if(saved_errno != 0) saved_errno = errno; if(local_error == NULL) { if(saved_errno != 0) { inf_file_util_set_error_from_errno(error, saved_errno); return FALSE; } } else { g_propagate_error(error, local_error); return FALSE; } return TRUE; #else GDir* dir; const gchar* name; gchar* file_path; InfFileType filetype; gboolean result; GError* local_error; dir = g_dir_open(path, 0, error); if(dir == NULL) return FALSE; local_error = NULL; result = TRUE; for(name = g_dir_read_name(dir); name != NULL && result == TRUE; name = g_dir_read_name(dir)) { file_path = g_build_filename(path, name, NULL); filetype = INF_FILE_TYPE_UNKNOWN; if(g_file_test(file_path, G_FILE_TEST_IS_DIR)) filetype = INF_FILE_TYPE_DIR; else if(g_file_test(file_path, G_FILE_TEST_IS_REGULAR)) filetype = INF_FILE_TYPE_REG; result = func(name, file_path, filetype, user_data, &local_error); g_free(file_path); } g_dir_close(dir); if(local_error != NULL) { g_propagate_error(error, local_error); return FALSE; } return TRUE; #endif } /** * inf_file_util_delete_file: * @path: (type filename): Path to the file to delete. * @error: Location to store error information, if any, or %NULL. * * Removes the file at @path if it is empty. Fails if @path points to a * directory and not a regular file. If the function fails %FALSE is returned * and @error is set. * * Returns: %TRUE on success or %FALSE on error. */ gboolean inf_file_util_delete_file(const gchar* path, GError** error) { #ifdef G_OS_WIN32 gunichar2* path16; path16 = g_utf8_to_utf16(path, -1, NULL, NULL, error); if(!path16) return FALSE; if(DeleteFileW(path16) == 0) { inf_file_util_set_error_from_win32(error, GetLastError()); g_free(path16); return FALSE; } g_free(path16); return TRUE; #else if(g_unlink(path) == -1) { inf_file_util_set_error_from_errno(error, errno); return FALSE; } return TRUE; #endif } /** * inf_file_util_delete_single_directory: * @path: (type filename): Path to the directory to delete. * @error: Location to store error information, if any, or %NULL. * * Removes the directory at @path if it is empty, or fails otherwise. Fails * if @path points to a regular file and not a directory. If the function * fails %FALSE is returned and @error is set. * * Returns: %TRUE on success or %FALSE on error. */ gboolean inf_file_util_delete_single_directory(const gchar* path, GError** error) { #ifdef G_OS_WIN32 gunichar2* path16; path16 = g_utf8_to_utf16(path, -1, NULL, NULL, error); if(!path16) return FALSE; if(RemoveDirectoryW(path16) == 0) { inf_file_util_set_error_from_win32(error, GetLastError()); g_free(path16); return FALSE; } g_free(path16); return TRUE; #else if(g_rmdir(path) == -1) { inf_file_util_set_error_from_errno(error, errno); return FALSE; } return TRUE; #endif } /** * inf_file_util_delete_directory: * @path: (type filename): Path to the directory to delete. * @error: Location to store error information, if any, or %NULL. * * Removes the directory at @path recursively. Fails if @path points to a * regular file and not a directory. If the function fails %FALSE is returned * and @error is set. * * Returns: %TRUE on success or %FALSE on error. */ gboolean inf_file_util_delete_directory(const gchar* path, GError** error) { gboolean result; result = inf_file_util_list_directory( path, inf_file_util_delete_directory_list_func, NULL, error ); if(result == FALSE) return FALSE; return inf_file_util_delete_single_directory(path, error); } /** * inf_file_util_delete: * @path: (type filename): Path to the object to delete. * @error: Location to store error information, if any, or %NULL. * * Removes the file or directory at @path. If it is a directory the directory * is deleted recursively. If the function fails %FALSE is returned * and @error is set. * * Returns: %TRUE on success or %FALSE on error. */ gboolean inf_file_util_delete(const gchar* path, GError** error) { if(g_file_test(path, G_FILE_TEST_IS_DIR)) return inf_file_util_delete_directory(path, error); else return inf_file_util_delete_file(path, error); } /** * inf_file_util_write_private_data: * @filename: Filename of the file to be written to. * @data: Data that should be written to file. * @length: Length of data in bytes. * @error: Location to store error information, if any, or %NULL. * * Writes @data to the file pointed to by @filename. On Unix-like systems, * @filename is created with 0600 permission. If the function fails, %FALSE is * returned and @error is set. * * Returns: %TRUE on success or %FALSE on error. */ gboolean inf_file_util_write_private_data(const gchar* filename, const void* data, size_t length, GError** error) { #ifdef G_OS_WIN32 return g_file_set_contents( filename, data, length, error ); #else gchar *temp_file = g_strconcat(filename, ".XXXXXX", NULL); gint fd = g_mkstemp_full( temp_file, O_WRONLY|O_CREAT|O_TRUNC, 0600 ); if (fd == -1) { inf_file_util_set_error_from_errno(error, errno); g_free(temp_file); return FALSE; } size_t remaining = length; while (remaining > 0) { ssize_t written = write(fd, data, remaining); if (written == -1) { inf_file_util_set_error_from_errno(error, errno); g_close(fd, NULL); g_unlink(temp_file); g_free(temp_file); return FALSE; } remaining -= written; data = ((gchar*)data) + written; } if (g_close(fd, error) == FALSE) { g_unlink(temp_file); g_free(temp_file); return FALSE; } if (g_rename(temp_file, filename) == -1) { inf_file_util_set_error_from_errno(error, errno); g_unlink(temp_file); g_free(temp_file); return FALSE; } g_free(temp_file); return TRUE; #endif } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-certificate-credentials.h0000644000000000000000000000013213034342512025110 xustar0030 mtime=1483851082.029718427 30 atime=1483851082.029718427 30 ctime=1488261588.936139205 libinfinity-0.7.1/libinfinity/common/inf-certificate-credentials.h0000644000175000017500000000355313034342512025650 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_CERTIFICATE_CREDENTIALS_H__ #define __INF_CERTIFICATE_CREDENTIALS_H__ #include /* Get ssize_t on MSVC, required by gnutls.h */ #include #include G_BEGIN_DECLS #define INF_TYPE_CERTIFICATE_CREDENTIALS (inf_certificate_credentials_get_type()) /** * InfCertificateCredentials: * * #InfCertificateCredentials is an opaque data type. You should only access * it via the public API functions. */ typedef struct _InfCertificateCredentials InfCertificateCredentials; GType inf_certificate_credentials_get_type(void) G_GNUC_CONST; InfCertificateCredentials* inf_certificate_credentials_new(void); InfCertificateCredentials* inf_certificate_credentials_ref(InfCertificateCredentials* creds); void inf_certificate_credentials_unref(InfCertificateCredentials* creds); gnutls_certificate_credentials_t inf_certificate_credentials_get(InfCertificateCredentials* creds); G_END_DECLS #endif /* __INF_CERTIFICATE_CREDENTIALS_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-xmpp-manager.c0000644000000000000000000000013013034342512022720 xustar0029 mtime=1483851082.03771847 29 atime=1483851082.03771847 30 ctime=1488261589.092138864 libinfinity-0.7.1/libinfinity/common/inf-xmpp-manager.c0000644000175000017500000006613713034342512023471 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include #include #include #include /** * SECTION:inf-xmpp-manager * @title: InfXmppManager * @short_description: Reuse existing connections * @include: libinfinity/common/inf-xmpp-manager.h * @stability: Unstable * * #InfXmppManager stores #InfXmppConnection objects and allows to look them * up by the IP address and port number of their underlaying * #InfTcpConnections. This can be used to reuse existing network * connections instead of creating new ones. * * Each object which needs to make connections should be passed a * #InfXmppManager. Then, when making a connection to a certain address/port * pair, it should first look in the XMPP manager whether there is already * an existing connection to the destination host, via * inf_xmpp_manager_lookup_connection_by_address(). If there is, it should * use it (maybe reopen it if it is closed). Otherwise, it should create a * new connection and add it to the XMPP manager via * inf_xmpp_manager_add_connection() for others to use. * * The XMPP manager can also handle connections whose address is still to be * looked up. Such connections are looked up by the hostname given to the * name resolver. Once the hostname has been looked up, and if another * connection with the same address and port number exists already, the new * connection is removed in favor of the already existing one. */ typedef enum _InfXmppManagerKeyKind { INF_XMPP_MANAGER_KEY_HOSTNAME, INF_XMPP_MANAGER_KEY_ADDRESS } InfXmppManagerKeyKind; typedef struct _InfXmppManagerKey InfXmppManagerKey; struct _InfXmppManagerKey { InfXmppManagerKeyKind kind; union { struct { InfIpAddress* address; guint port; } address; struct { gchar* hostname; gchar* service; gchar* srv; } hostname; } shared; }; typedef struct _InfXmppManagerConnectionInfo InfXmppManagerConnectionInfo; struct _InfXmppManagerConnectionInfo { InfXmppManager* manager; InfXmppConnection* xmpp; InfNameResolver* resolver; /* TCPs resolver */ InfXmppManagerKey** keys; guint n_keys; }; typedef struct _InfXmppManagerPrivate InfXmppManagerPrivate; struct _InfXmppManagerPrivate { GTree* connections; }; enum { CONNECTION_ADDED, CONNECTION_REMOVED, LAST_SIGNAL }; #define INF_XMPP_MANAGER_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INF_TYPE_XMPP_MANAGER, InfXmppManagerPrivate)) static guint xmpp_manager_signals[LAST_SIGNAL]; G_DEFINE_TYPE_WITH_CODE(InfXmppManager, inf_xmpp_manager, G_TYPE_OBJECT, G_ADD_PRIVATE(InfXmppManager)) /* Make a deep copy of a key. This is typically not required for lookup, but * it is required for storage in the tree. */ static InfXmppManagerKey* inf_xmpp_manager_key_copy(const InfXmppManagerKey* orig_key) { InfXmppManagerKey* key; key = g_slice_new(InfXmppManagerKey); key->kind = orig_key->kind; switch(key->kind) { case INF_XMPP_MANAGER_KEY_ADDRESS: key->shared.address.address = inf_ip_address_copy(orig_key->shared.address.address); key->shared.address.port = orig_key->shared.address.port; break; case INF_XMPP_MANAGER_KEY_HOSTNAME: key->shared.hostname.hostname = g_strdup(orig_key->shared.hostname.hostname); key->shared.hostname.service = g_strdup(orig_key->shared.hostname.service); key->shared.hostname.srv = g_strdup(orig_key->shared.hostname.srv); break; default: g_assert_not_reached(); break; } return key; } static void inf_xmpp_manager_key_free(gpointer key_ptr) { InfXmppManagerKey* key; key = (InfXmppManagerKey*)key_ptr; switch(key->kind) { case INF_XMPP_MANAGER_KEY_ADDRESS: inf_ip_address_free(key->shared.address.address); break; case INF_XMPP_MANAGER_KEY_HOSTNAME: g_free(key->shared.hostname.hostname); g_free(key->shared.hostname.service); g_free(key->shared.hostname.srv); break; default: g_assert_not_reached(); break; } g_slice_free(InfXmppManagerKey, key); } static int inf_xmpp_manager_strcmp_nul(const gchar* str1, const gchar* str2) { if(str1 == NULL && str2 == NULL) return 0; else if(str1 == NULL && str2 != NULL) return +1; else if(str1 != NULL && str2 == NULL) return -1; else return strcmp(str1, str2); } static int inf_xmpp_manager_key_cmp(gconstpointer first, gconstpointer second, G_GNUC_UNUSED gpointer data) { const InfXmppManagerKey* first_key; const InfXmppManagerKey* second_key; int cmp; first_key = (const InfXmppManagerKey*)first; second_key = (const InfXmppManagerKey*)second; if(first_key->kind < second_key->kind) return -1; else if(first_key->kind > second_key->kind) return 1; switch(first_key->kind) { case INF_XMPP_MANAGER_KEY_ADDRESS: if(first_key->shared.address.port < second_key->shared.address.port) { return -1; } else if(first_key->shared.address.port > second_key->shared.address.port) { return 1; } else { return inf_ip_address_collate( first_key->shared.address.address, second_key->shared.address.address ); } case INF_XMPP_MANAGER_KEY_HOSTNAME: cmp = strcmp( first_key->shared.hostname.hostname, second_key->shared.hostname.hostname ); if(cmp != 0) return cmp; cmp = inf_xmpp_manager_strcmp_nul( first_key->shared.hostname.service, second_key->shared.hostname.service ); if(cmp != 0) return cmp; cmp = inf_xmpp_manager_strcmp_nul( first_key->shared.hostname.srv, second_key->shared.hostname.srv ); return cmp; default: g_assert_not_reached(); return 0; } } InfXmppManagerConnectionInfo* inf_xmpp_manager_lookup_connection(InfXmppManager* manager, InfXmppConnection* connection) { InfXmppManagerPrivate* priv; InfXmppManagerKey key; InfTcpConnection* tcp; InfNameResolver* resolver; InfXmppManagerConnectionInfo* info; priv = INF_XMPP_MANAGER_PRIVATE(manager); /* We can choose any key of connection, if things are consistent, * it should work. */ g_object_get(G_OBJECT(connection), "tcp-connection", &tcp, NULL); key.shared.address.address = inf_tcp_connection_get_remote_address(tcp); key.shared.address.port = inf_tcp_connection_get_remote_port(tcp); if(key.shared.address.address == NULL || key.shared.address.port == 0) { g_object_get(G_OBJECT(tcp), "resolver", &resolver, NULL); if(resolver == NULL) return NULL; /* no keys available */ key.kind = INF_XMPP_MANAGER_KEY_HOSTNAME; key.shared.hostname.hostname = (gchar*)inf_name_resolver_get_hostname(resolver); key.shared.hostname.service = (gchar*)inf_name_resolver_get_service(resolver); key.shared.hostname.srv = (gchar*)inf_name_resolver_get_srv(resolver); g_object_unref(resolver); } else { key.kind = INF_XMPP_MANAGER_KEY_ADDRESS; } g_object_unref(tcp); info = g_tree_lookup(priv->connections, &key); return info; } static InfXmppManagerConnectionInfo* inf_xmpp_manager_check_key(InfXmppManager* manager, InfXmppManagerConnectionInfo* info, const InfXmppManagerKey* key, gboolean* has_keys) { InfXmppManagerPrivate* priv; InfXmppManagerKey* permanent_key; InfXmppManagerConnectionInfo* lookup; guint i; priv = INF_XMPP_MANAGER_PRIVATE(manager); lookup = g_tree_lookup(priv->connections, key); /* Check for duplicates */ if(lookup != NULL && lookup != info) return lookup; if(lookup == NULL) { /* This key is not yet associated to the connection info, but it is * a valid key for the connection, so we add it. */ permanent_key = inf_xmpp_manager_key_copy(key); g_tree_insert(priv->connections, permanent_key, info); info->keys = g_realloc( info->keys, sizeof(InfXmppManagerKey*) * (info->n_keys + 1) ); info->keys[info->n_keys] = permanent_key; ++info->n_keys; } else { /* Check which of the saved keys, if any, this one corresponds to, so * that we can detect keys that are no longer active. */ for(i = 0; i < info->n_keys; ++i) { if(inf_xmpp_manager_key_cmp(info->keys[i], key, NULL) == 0) { has_keys[i] = TRUE; break; } } } return NULL; } static void inf_xmpp_manager_connection_info_free(InfXmppManagerConnectionInfo* info); /* Updates all keys for the given connection info. is_added should be TRUE if * before the caller the connection was already added to the manager, i.e. * whether the connection-added signal has been emitted for the connection. * Returns FALSE if the connection is removed from the manager due to no keys * or a conflict. */ static gboolean inf_xmpp_manager_update_keys(InfXmppManager* manager, InfXmppManagerConnectionInfo* info, gboolean is_added) { InfXmppManagerPrivate* priv; guint n_keys; gboolean* has_keys; guint i; InfTcpConnection* tcp; InfNameResolver* resolver; InfXmppManagerKey key; InfXmppManagerConnectionInfo* duplicate_info; InfXmppConnection* xmpp; gboolean result; priv = INF_XMPP_MANAGER_PRIVATE(manager); n_keys = info->n_keys; if(n_keys > 0) has_keys = g_malloc(n_keys * sizeof(gboolean)); else has_keys = NULL; for(i = 0; i < n_keys; ++i) has_keys[i] = FALSE; duplicate_info = NULL; g_object_get(G_OBJECT(info->xmpp), "tcp-connection", &tcp, NULL); /* Gather all keys */ key.kind = INF_XMPP_MANAGER_KEY_ADDRESS; key.shared.address.address = inf_tcp_connection_get_remote_address(tcp); key.shared.address.port = inf_tcp_connection_get_remote_port(tcp); if(key.shared.address.address != NULL && key.shared.address.port != 0) { duplicate_info = inf_xmpp_manager_check_key(manager, info, &key, has_keys); } if(duplicate_info == NULL) { g_object_get(G_OBJECT(tcp), "resolver", &resolver, NULL); if(resolver != NULL) { key.kind = INF_XMPP_MANAGER_KEY_HOSTNAME; key.shared.hostname.hostname = (gchar*)inf_name_resolver_get_hostname(resolver); key.shared.hostname.service = (gchar*)inf_name_resolver_get_service(resolver); key.shared.hostname.srv = (gchar*)inf_name_resolver_get_srv(resolver); duplicate_info = inf_xmpp_manager_check_key(manager, info, &key, has_keys); /* TODO: We should also be able to access the resolved entries if we * are looking up backup addresses. */ if(duplicate_info == NULL && inf_name_resolver_finished(resolver) == TRUE) { for(i = 0; i < inf_name_resolver_get_n_addresses(resolver); ++i) { key.kind = INF_XMPP_MANAGER_KEY_ADDRESS; key.shared.address.address = (InfIpAddress*)inf_name_resolver_get_address(resolver, i); key.shared.address.port = inf_name_resolver_get_port(resolver, i); duplicate_info = inf_xmpp_manager_check_key(manager, info, &key, has_keys); if(duplicate_info != NULL) break; } } g_object_unref(resolver); } } g_object_unref(tcp); result = TRUE; if(duplicate_info == NULL) { for(i = 0; i < n_keys; ) { if(has_keys[i] == FALSE) { /* This key is not valid anymore, so remove it */ g_tree_remove(priv->connections, info->keys[i]); g_assert(n_keys > 0); g_assert(info->n_keys > 0); g_assert(info->n_keys >= n_keys); info->keys[i] = info->keys[n_keys - 1]; has_keys[i] = has_keys[n_keys - 1]; /* In case there are new keys added by the code above */ info->keys[n_keys - 1] = info->keys[info->n_keys - 1]; --n_keys; if(info->n_keys > 1) { info->keys = g_realloc( info->keys, sizeof(InfXmppManagerKey*) * (info->n_keys - 1) ); --info->n_keys; } else { g_free(info->keys); info->keys = NULL; info->n_keys = 0; } } else { ++i; } } if(info->n_keys == 0) { xmpp = info->xmpp; g_object_ref(xmpp); g_warning("Connection has no keys anymore!"); inf_xmpp_manager_connection_info_free(info); /* This should typically not happen. It only happens when someone resets * both the resolver and the remote-address and remote-port properties * of a connection that stays within the XMPP manager. */ if(is_added == TRUE) { g_signal_emit( G_OBJECT(manager), xmpp_manager_signals[CONNECTION_REMOVED], 0, xmpp, NULL ); } g_object_unref(xmpp); result = FALSE; } } else { for(i = 0; i < info->n_keys; ++i) g_tree_remove(priv->connections, info->keys[i]); xmpp = info->xmpp; g_object_ref(xmpp); inf_xmpp_manager_connection_info_free(info); if(is_added == TRUE) { g_signal_emit( G_OBJECT(manager), xmpp_manager_signals[CONNECTION_REMOVED], 0, xmpp, duplicate_info->xmpp ); } g_object_unref(xmpp); result = FALSE; } g_free(has_keys); return result; } static void inf_xmpp_manager_notify_cb(GObject* object, GParamSpec* pspec, gpointer user_data) { InfXmppManagerConnectionInfo* info; info = (InfXmppManagerConnectionInfo*)user_data; inf_xmpp_manager_update_keys(info->manager, info, TRUE); } static void inf_xmpp_manager_resolved_cb(InfNameResolver* resolver, const GError* error, gpointer user_data) { InfXmppManagerConnectionInfo* info; info = (InfXmppManagerConnectionInfo*)user_data; inf_xmpp_manager_update_keys(info->manager, info, TRUE); } static void inf_xmpp_manager_connection_info_set_resolver(InfXmppManagerConnectionInfo* info, InfNameResolver* resolver) { if(info->resolver != NULL) { inf_signal_handlers_disconnect_by_func( info->resolver, G_CALLBACK(inf_xmpp_manager_notify_cb), info ); inf_signal_handlers_disconnect_by_func( info->resolver, G_CALLBACK(inf_xmpp_manager_resolved_cb), info ); g_object_unref(info->resolver); } info->resolver = resolver; if(resolver != NULL) { g_object_ref(resolver); g_signal_connect( G_OBJECT(resolver), "notify::hostname", G_CALLBACK(inf_xmpp_manager_notify_cb), info ); g_signal_connect( G_OBJECT(resolver), "notify::service", G_CALLBACK(inf_xmpp_manager_notify_cb), info ); g_signal_connect( G_OBJECT(resolver), "notify::srv", G_CALLBACK(inf_xmpp_manager_notify_cb), info ); g_signal_connect( G_OBJECT(resolver), "resolved", G_CALLBACK(inf_xmpp_manager_resolved_cb), info ); } } static void inf_xmpp_manager_notify_resolver_cb(GObject* object, GParamSpec* pspec, gpointer user_data) { InfXmppManagerConnectionInfo* info; InfNameResolver* resolver; g_object_get(object, "resolver", &resolver, NULL); info = (InfXmppManagerConnectionInfo*)user_data; inf_xmpp_manager_connection_info_set_resolver(info, resolver); g_object_unref(resolver); inf_xmpp_manager_update_keys(info->manager, info, TRUE); } static InfXmppManagerConnectionInfo* inf_xmpp_manager_connection_info_new(InfXmppManager* manager, InfXmppConnection* xmpp) { InfXmppManagerConnectionInfo* info; InfTcpConnection* tcp; InfNameResolver* resolver; g_object_get(G_OBJECT(xmpp), "tcp-connection", &tcp, NULL); g_assert(tcp != NULL); info = g_slice_new(InfXmppManagerConnectionInfo); info->manager = manager; info->xmpp = xmpp; info->resolver = NULL; info->keys = NULL; info->n_keys = 0; g_object_ref(xmpp); g_signal_connect( G_OBJECT(tcp), "notify::remote-address", G_CALLBACK(inf_xmpp_manager_notify_cb), info ); g_signal_connect( G_OBJECT(tcp), "notify::remote-port", G_CALLBACK(inf_xmpp_manager_notify_cb), info ); g_signal_connect( G_OBJECT(tcp), "notify::resolver", G_CALLBACK(inf_xmpp_manager_notify_resolver_cb), info ); g_object_get(G_OBJECT(tcp), "resolver", &resolver, NULL); if(resolver != NULL) { inf_xmpp_manager_connection_info_set_resolver(info, resolver); g_object_unref(resolver); } g_object_unref(tcp); return info; } static void inf_xmpp_manager_connection_info_free(InfXmppManagerConnectionInfo* info) { InfTcpConnection* tcp; g_object_get(G_OBJECT(info->xmpp), "tcp-connection", &tcp, NULL); g_assert(tcp != NULL); inf_xmpp_manager_connection_info_set_resolver(info, NULL); inf_signal_handlers_disconnect_by_func( tcp, G_CALLBACK(inf_xmpp_manager_notify_cb), info ); inf_signal_handlers_disconnect_by_func( tcp, G_CALLBACK(inf_xmpp_manager_notify_resolver_cb), info ); g_object_unref(tcp); g_object_unref(info->xmpp); g_free(info->keys); g_slice_free(InfXmppManagerConnectionInfo, info); } static gboolean inf_xmpp_manager_dispose_destroy_func(gpointer key, gpointer value, gpointer data) { InfXmppManagerConnectionInfo* info; info = (InfXmppManagerConnectionInfo*)value; if(--info->n_keys == 0) inf_xmpp_manager_connection_info_free(value); return FALSE; } static void inf_xmpp_manager_init(InfXmppManager* manager) { InfXmppManagerPrivate* priv; priv = INF_XMPP_MANAGER_PRIVATE(manager); priv->connections = g_tree_new_full( inf_xmpp_manager_key_cmp, NULL, inf_xmpp_manager_key_free, NULL ); } static void inf_xmpp_manager_dispose(GObject* object) { InfXmppManager* manager; InfXmppManagerPrivate* priv; manager = INF_XMPP_MANAGER(object); priv = INF_XMPP_MANAGER_PRIVATE(object); g_tree_foreach( priv->connections, inf_xmpp_manager_dispose_destroy_func, manager ); g_tree_destroy(priv->connections); priv->connections = NULL; G_OBJECT_CLASS(inf_xmpp_manager_parent_class)->dispose(object); } static void inf_xmpp_manager_class_init(InfXmppManagerClass* xmpp_manager_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(xmpp_manager_class); object_class->dispose = inf_xmpp_manager_dispose; xmpp_manager_class->connection_added = NULL; xmpp_manager_class->connection_removed = NULL; /** * InfXmppManager::connection-added: * @xmpp_manager: The #InfXmppManager emitting the signal. * @connection: The #InfXmppConnection that was added to @xmpp_manager. * * This signal is emitted whenever a new connection has been added to the * #InfXmppManager, via inf_xmpp_manager_add_connection(). */ xmpp_manager_signals[CONNECTION_ADDED] = g_signal_new( "connection-added", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfXmppManagerClass, connection_added), NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, INF_TYPE_XMPP_CONNECTION ); /** * InfXmppManager::remove-connection: * @xmpp_manager: The #InfXmppManager emitting the signal. * @connection: The #InfXmppConnection that was removed from @xmpp_manager. * @replaced_by: A #InfXmppConnection to the same host, if there was a * conflict, or %NULL otherwise. * * This signal is emitted whenever a connection has been removed from the * #InfXmppManager, via inf_xmpp_manager_remove_connection(), or when a * collision occurs such that two connections point to the same host, or * when a connection loses all its address and hostname information. */ xmpp_manager_signals[CONNECTION_REMOVED] = g_signal_new( "connection-removed", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfXmppManagerClass, connection_removed), NULL, NULL, NULL, G_TYPE_NONE, 2, INF_TYPE_XMPP_CONNECTION, INF_TYPE_XMPP_CONNECTION ); } /** * inf_xmpp_manager_new: (constructor) * * Creates a new xmpp manager. * * Returns: (transfer full): A new #InfXmppManager. **/ InfXmppManager* inf_xmpp_manager_new(void) { GObject* object; object = g_object_new(INF_TYPE_XMPP_MANAGER, NULL); return INF_XMPP_MANAGER(object); } /** * inf_xmpp_manager_lookup_connection_by_address: * @manager: A #InfXmppManager. * @address: The remote #InfIpAddress of the connection to look for. * @port: The remote port number of the connection to look for. * * Looks for a #InfXmppConnection contained in @manager whose underlaying * #InfTcpConnection has the given address and port set. Returns %NULL if * there is no such connection. * * This function may also return a closed connection. You can then attempt to * reopen it, or remove it from the manager using * inf_xmpp_manager_remove_connection() when that fails. * * Returns: (transfer none) (allow-none): A #InfXmppConnection with the given * address and port, or %NULL if not found. **/ InfXmppConnection* inf_xmpp_manager_lookup_connection_by_address(InfXmppManager* manager, const InfIpAddress* address, guint port) { InfXmppManagerPrivate* priv; InfXmppManagerKey key; InfXmppManagerConnectionInfo* info; g_return_val_if_fail(INF_IS_XMPP_MANAGER(manager), NULL); g_return_val_if_fail(address != NULL, NULL); priv = INF_XMPP_MANAGER_PRIVATE(manager); key.kind = INF_XMPP_MANAGER_KEY_ADDRESS; key.shared.address.address = (InfIpAddress*)address; key.shared.address.port = port; info = g_tree_lookup(priv->connections, &key); if(info == NULL) return NULL; return info->xmpp; } /** * inf_xmpp_manager_lookup_connection_by_hostname: * @manager: A #InfXmppManager. * @hostname: The remote hostname to look for. * @service: (allow-none): The service string of the connection to look for. * @srv: (allow-none): The SRV record corresponding to the connection. * * Looks for a #InfXmppConnection contained in @manager whose underlaying * #InfTcpConnection has a #InfNameResolver with the given properties. * * This function may also return a closed connection. You can then attempt to * reopen it, or remove it from the manager using * inf_xmpp_manager_remove_connection() when that fails. * * Returns: (transfer none) (allow-none): A #InfXmppConnection with the given * hostname, service and srv, or %NULL if not found. **/ InfXmppConnection* inf_xmpp_manager_lookup_connection_by_hostname(InfXmppManager* manager, const gchar* hostname, const gchar* service, const gchar* srv) { /* TODO: Allow not to provide service, srv or both, and then return a * connection to the given hostname for any service or srv. * This could be done with g_tree_search, and the current tree * sort order. */ InfXmppManagerPrivate* priv; InfXmppManagerKey key; InfXmppManagerConnectionInfo* info; g_return_val_if_fail(INF_IS_XMPP_MANAGER(manager), NULL); g_return_val_if_fail(hostname != NULL, NULL); priv = INF_XMPP_MANAGER_PRIVATE(manager); key.kind = INF_XMPP_MANAGER_KEY_HOSTNAME; key.shared.hostname.hostname = (gchar*)hostname; key.shared.hostname.service = (gchar*)service; key.shared.hostname.srv = (gchar*)srv; info = g_tree_lookup(priv->connections, &key); if(info == NULL) return NULL; return info->xmpp; } /** * inf_xmpp_manager_contains_connection: * @manager: A #InfXmppManager. * @connection: A #InfXmppConnection. * * Returns whether @connection is contained in @manager. * * Returns: %TRUE if @connection is contained in @manager, %FALSE * otherwise. */ gboolean inf_xmpp_manager_contains_connection(InfXmppManager* manager, InfXmppConnection* connection) { InfXmppManagerConnectionInfo* info; g_return_val_if_fail(INF_IS_XMPP_MANAGER(manager), FALSE); g_return_val_if_fail(INF_IS_XMPP_CONNECTION(connection), FALSE); info = inf_xmpp_manager_lookup_connection(manager, connection); if(info == NULL) return FALSE; return TRUE; } /** * inf_xmpp_manager_add_connection: * @manager: A #InfXmppManager. * @connection: A #InfXmppConnection not yet contained in @manager. * * Adds the given connection to @manager so that it is found by * inf_xmpp_manager_lookup_connection_by_address(), * inf_xmpp_manager_lookup_connection_by_hostname() and * inf_xmpp_manager_contains_connection(). */ void inf_xmpp_manager_add_connection(InfXmppManager* manager, InfXmppConnection* connection) { InfXmppManagerConnectionInfo* info; gboolean was_added; g_return_if_fail(INF_IS_XMPP_MANAGER(manager)); g_return_if_fail(INF_IS_XMPP_CONNECTION(connection)); info = inf_xmpp_manager_connection_info_new(manager, connection); was_added = inf_xmpp_manager_update_keys(manager, info, FALSE); if(was_added == FALSE) inf_xmpp_manager_connection_info_free(info); g_return_if_fail(was_added == TRUE); g_signal_emit( G_OBJECT(manager), xmpp_manager_signals[CONNECTION_ADDED], 0, connection ); } /** * inf_xmpp_manager_remove_connection: * @manager: A #InfXmppManager. * @connection: A #InfXmppConnection contained in @manager. * * Removes the given connection from @manager. */ void inf_xmpp_manager_remove_connection(InfXmppManager* manager, InfXmppConnection* connection) { InfXmppManagerPrivate* priv; InfXmppManagerConnectionInfo* info; guint i; g_return_if_fail(INF_IS_XMPP_MANAGER(manager)); g_return_if_fail(INF_IS_XMPP_CONNECTION(connection)); priv = INF_XMPP_MANAGER_PRIVATE(manager); info = inf_xmpp_manager_lookup_connection(manager, connection); g_return_if_fail(info != NULL); /* Remove all keys */ for(i = 0; i < info->n_keys; ++i) g_tree_remove(priv->connections, info->keys[i]); g_object_ref(connection); inf_xmpp_manager_connection_info_free(info); g_signal_emit( G_OBJECT(manager), xmpp_manager_signals[CONNECTION_REMOVED], 0, connection, NULL ); g_object_unref(connection); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-ip-address.h0000644000000000000000000000013213034342512022366 xustar0030 mtime=1483851082.033718448 30 atime=1483851082.033718448 30 ctime=1488261588.952139171 libinfinity-0.7.1/libinfinity/common/inf-ip-address.h0000644000175000017500000000471713034342512023131 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_IP_ADDRESS_H__ #define __INF_IP_ADDRESS_H__ #include G_BEGIN_DECLS #define INF_TYPE_IP_ADDRESS (inf_ip_address_get_type()) #define INF_TYPE_IP_ADDRESS_FAMILY (inf_ip_address_family_get_type()) /** * InfIpAddress: * * #InfIpAddress is an opaque data type. You should only access it * via the public API functions. */ typedef struct _InfIpAddress InfIpAddress; /** * InfIpAddressFamily: * @INF_IP_ADDRESS_IPV4: This specifies an IPv4 address. * @INF_IP_ADDRESS_IPV6: This specifies an IPv6 address. * * This enumeration specifies different types of IP addresses. */ typedef enum _InfIpAddressFamily { INF_IP_ADDRESS_IPV4, INF_IP_ADDRESS_IPV6 } InfIpAddressFamily; GType inf_ip_address_family_get_type(void) G_GNUC_CONST; GType inf_ip_address_get_type(void) G_GNUC_CONST; InfIpAddress* inf_ip_address_new_raw4(guint32 address); InfIpAddress* inf_ip_address_new_loopback4(void); InfIpAddress* inf_ip_address_new_raw6(const guint8 address[16]); InfIpAddress* inf_ip_address_new_loopback6(void); InfIpAddress* inf_ip_address_new_from_string(const gchar* str); InfIpAddress* inf_ip_address_copy(const InfIpAddress* address); void inf_ip_address_free(InfIpAddress* address); InfIpAddressFamily inf_ip_address_get_family(const InfIpAddress* address); gconstpointer inf_ip_address_get_raw(const InfIpAddress* address); gchar* inf_ip_address_to_string(const InfIpAddress* address); int inf_ip_address_collate(const InfIpAddress* address1, const InfIpAddress* address2); G_END_DECLS #endif /* __INF_IP_ADDRESS_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-name-resolver.c0000644000000000000000000000013213034342512023105 xustar0030 mtime=1483851082.033718448 30 atime=1483851082.033718448 30 ctime=1488261589.068138917 libinfinity-0.7.1/libinfinity/common/inf-name-resolver.c0000644000175000017500000010650313034342512023644 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-name-resolver * @title: InfNameResolver * @short_description: Asynchronous DNS name lookup with support for SRV * records * @include: libinfinity/common/inf-name-resolver.h * @stability: Unstable * * #InfNameResolver provides a portable interface to look up DNS entries. When * a resorver object has been created, the name lookup can be started with * inf_name_resolver_start(), and once it finishes, the * #InfNameResolver::resolved signal is emitted. The * inf_name_resolver_get_address() and inf_name_resolver_get_port() functions * can then be used to obtain the result. * * There can at most be one hostname lookup at a time. If you need more than * one concurrent hostname lookup, use multiple #InfNameResolver objects. **/ #include #include #include /* For getaddrinfo */ #ifdef G_OS_WIN32 # include /* We need to include wspiapi.h to support getaddrinfo on Windows 2000. * See the MSDN article for getaddrinfo * http://msdn.microsoft.com/en-us/library/ms738520(VS.85).aspx * and bug #425. */ # include #else # include # include # include /* Required for FreeBSD. See bug #431. */ # include #endif /* For SRV lookup */ #ifdef G_OS_WIN32 # include #else # include # include # include #endif #include #include typedef struct _InfNameResolverEntry InfNameResolverEntry; struct _InfNameResolverEntry { InfIpAddress* address; guint port; }; typedef struct _InfNameResolverSRV InfNameResolverSRV; struct _InfNameResolverSRV { guint priority; guint weight; guint port; gchar* address; }; typedef struct _InfNameResolverResult InfNameResolverResult; struct _InfNameResolverResult { /* The primarily resolved entries */ InfNameResolverEntry* entries; guint n_entries; /* Not-yet-checked SRV records. If none of the above entries work, we can * look up these as a backup. */ InfNameResolverSRV* srvs; guint n_srvs; GError* error; }; typedef struct _InfNameResolverPrivate InfNameResolverPrivate; struct _InfNameResolverPrivate { InfIo* io; gchar* hostname; gchar* service; gchar* srv; InfAsyncOperation* operation; /* Output */ InfNameResolverResult result; }; enum { PROP_0, PROP_IO, PROP_HOSTNAME, PROP_SERVICE, PROP_SRV }; enum { RESOLVED, LAST_SIGNAL }; #define INF_NAME_RESOLVER_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INF_TYPE_NAME_RESOLVER, InfNameResolverPrivate)) static guint name_resolver_signals[LAST_SIGNAL]; G_DEFINE_TYPE_WITH_CODE(InfNameResolver, inf_name_resolver, G_TYPE_OBJECT, G_ADD_PRIVATE(InfNameResolver)) static void inf_name_resolver_result_nullify(InfNameResolverResult* result) { result->entries = NULL; result->n_entries = 0; result->srvs = NULL; result->n_srvs = 0; result->error = NULL; } static void inf_name_resolver_result_cleanup(InfNameResolverResult* result) { guint i; for(i = 0; i < result->n_entries; ++i) inf_ip_address_free(result->entries[i].address); g_free(result->entries); for(i = 0; i < result->n_srvs; ++i) g_free(result->srvs[i].address); g_free(result->srvs); if(result->error != NULL) g_error_free(result->error); } static void inf_name_resolver_result_free(gpointer result_ptr) { InfNameResolverResult* result; result = (InfNameResolverResult*)result_ptr; inf_name_resolver_result_cleanup(result); g_slice_free(InfNameResolverResult, result); } /* Worker thread */ #ifndef G_OS_WIN32 static void inf_name_resolver_set_herrno_error(GError** error, int code) { g_set_error_literal( error, g_quark_from_static_string("INF_NAME_RESOLVER_HERRNO_ERROR"), code, hstrerror(code) ); } static void inf_name_resolver_set_errno_error(GError** error, int code) { g_set_error_literal( error, g_quark_from_static_string("INF_NAME_RESOLVER_ERRNO_ERROR"), code, strerror(code) ); } static void inf_name_resolver_set_incomplete_error(GError** error) { g_set_error_literal( error, g_quark_from_static_string("INF_NAME_RESOLVER_INCOMPLETE_ERROR"), 0, _("The reply from the DNS server is incomplete") ); } static const char* inf_name_resolver_parse_dns_uint16(const char* msg, const char* end, const char* cur, guint16* result, GError** error) { if(cur + 2 > end) { inf_name_resolver_set_incomplete_error(error); return NULL; } *result = ntohs(*((guint16*)cur)); return cur + 2; } static const char* inf_name_resolver_parse_dns_uint32(const char* msg, const char* end, const char* cur, guint32* result, GError** error) { if(cur + 4 > end) { inf_name_resolver_set_incomplete_error(error); return NULL; } *result = ntohl(*((guint32*)cur)); return cur + 4; } static const char* inf_name_resolver_parse_dns_host(const char* msg, const char* end, const char* cur, gchar* result, gsize reslen, GError** error) { int len; len = dn_expand(msg, end, cur, result, reslen); if(len < 0) { inf_name_resolver_set_errno_error(error, errno); return NULL; } if(cur + len > end) { inf_name_resolver_set_incomplete_error(error); return NULL; } return cur + len; } static const char* inf_name_resolver_parse_srv_record(const char* msg, const char* end, const char* cur, InfNameResolverSRV* srv, GError** error) { gchar buf[256]; gsize bufsize; guint16 type; guint16 cls; guint32 ttl; guint16 msglen; guint16 prio; guint16 weight; guint16 port; bufsize = sizeof(buf); cur = inf_name_resolver_parse_dns_host(msg, end, cur, buf, bufsize, error); if(cur == NULL) return NULL; cur = inf_name_resolver_parse_dns_uint16(msg, end, cur, &type, error); if(cur == NULL) return NULL; cur = inf_name_resolver_parse_dns_uint16(msg, end, cur, &cls, error); if(cur == NULL) return NULL; cur = inf_name_resolver_parse_dns_uint32(msg, end, cur, &ttl, error); if(cur == NULL) return NULL; cur = inf_name_resolver_parse_dns_uint16(msg, end, cur, &msglen, error); if(cur == NULL) return NULL; if(type != T_SRV) { srv->address = NULL; cur += msglen; return cur; } cur = inf_name_resolver_parse_dns_uint16(msg, end, cur, &prio, error); if(cur == NULL) return NULL; cur = inf_name_resolver_parse_dns_uint16(msg, end, cur, &weight, error); if(cur == NULL) return NULL; cur = inf_name_resolver_parse_dns_uint16(msg, end, cur, &port, error); if(cur == NULL) return NULL; cur = inf_name_resolver_parse_dns_host(msg, end, cur, buf, bufsize, error); if(cur == NULL) return NULL; srv->priority = prio; srv->weight = weight; srv->port = port; srv->address = g_strdup(buf); return cur; } #endif static gchar* inf_name_resolver_choose_srv(InfNameResolverSRV** srvs, guint* n_srvs, guint* port) { InfNameResolverSRV** low_prio_srvs; guint n_low_prio_srvs; guint total_weight; guint accum_weight; guint rand; guint i; guint index; gchar* selected_address; guint selected_port; g_assert(*n_srvs > 0); /* Choose the SRV records with lowest priority */ low_prio_srvs = g_malloc(sizeof(InfNameResolverSRV*) * (*n_srvs)); n_low_prio_srvs = 0; total_weight = 0; for(i = 0; i < *n_srvs; ++i) { if(n_low_prio_srvs == 0 || (*srvs)[i].priority < low_prio_srvs[0]->priority) { n_low_prio_srvs = 1; low_prio_srvs[0] = &(*srvs)[i]; total_weight = (*srvs)[i].weight; } else if( (*srvs)[i].priority == low_prio_srvs[0]->priority) { low_prio_srvs[n_low_prio_srvs++] = &(*srvs)[i]; total_weight += (*srvs)[i].weight; } } /* Choose a server randomly, according to their weight */ if(total_weight == 0) { /* No weight available, chose uniformly */ i = g_random_int_range(0, n_low_prio_srvs); } else { rand = g_random_int_range(0, total_weight); accum_weight = 0; for(i = 0; i < n_low_prio_srvs; ++i) { accum_weight += low_prio_srvs[i]->weight; if(rand < accum_weight) break; } } g_assert(i < n_low_prio_srvs); /* Select the SRV record with index i */ index = low_prio_srvs[i] - *srvs; selected_address = (*srvs)[index].address; selected_port = (*srvs)[index].port; g_free(low_prio_srvs); /* Remove the chosen SRV entry from the array, so that we don't try the * same record again if the selected one does not work. */ (*srvs)[index] = (*srvs)[*n_srvs - 1]; *srvs = g_realloc(*srvs, sizeof(InfNameResolverSRV) * (*n_srvs - 1)); --*n_srvs; if(port != NULL) *port = selected_port; return selected_address; } static InfNameResolverSRV* inf_name_resolver_lookup_srv(const gchar* query, guint* n_srvs, GError** error) { #ifdef G_OS_WIN32 PDNS_RECORD data; PDNS_RECORD item; DNS_STATUS status; gchar* str; GArray* array; InfNameResolverSRV srv; status = DnsQuery_UTF8( query, DNS_TYPE_SRV, DNS_QUERY_STANDARD, NULL, &data, NULL ); if(status != 0) { str = g_win32_error_message(status); g_set_error_literal( error, g_quark_from_static_string("WIN32_ERROR"), status, str ); g_free(str); return NULL; } array = g_array_new(FALSE, FALSE, sizeof(InfNameResolverSRV)); for(item = data; item != NULL; item = item->pNext) { if(item->wType != DNS_TYPE_SRV) continue; srv.priority = item->Data.SRV.wPriority; srv.weight = item->Data.SRV.wWeight; srv.port = item->Data.SRV.wPort; srv.address = g_strdup(item->Data.SRV.pNameTarget); // TODO: utf16_to_utf8? g_array_append_val(array, srv); } DnsRecordListFree(data, DnsFreeRecordListDeep); *n_srvs = array->len; return (InfNameResolverSRV*)g_array_free(array, FALSE); #else char ansbuf[4096]; char hostbuf[256]; int len; HEADER* header; int query_count; int answer_count; const char* msg; const char* cur; const char* end; InfNameResolverSRV* srvs; guint n_answers; int i; /* libresolv uses a global struct for its operation, and is not threadsafe. * Therefore, we protect this function callby a mutex. */ static GMutex mutex; /* Make the DNS query */ g_mutex_lock(&mutex); *n_srvs = 0; h_errno = 0; len = res_query(query, C_IN, T_SRV, ansbuf, sizeof(ansbuf)); if(h_errno != 0) { /* If the host was not found, simply return 0 SRV entries */ if(h_errno != HOST_NOT_FOUND) inf_name_resolver_set_herrno_error(error, h_errno); g_mutex_unlock(&mutex); return NULL; } /* At this point we have the DNS answer, and the rest of the function * is thread-safe. */ g_mutex_unlock(&mutex); if(len < sizeof(HEADER)) { inf_name_resolver_set_incomplete_error(error); return NULL; } msg = ansbuf; end = ansbuf + len; cur = ansbuf + sizeof(HEADER); header = (HEADER*)msg; query_count = ntohs(header->qdcount); answer_count = ntohs(header->ancount); /* Skip over the query */ for(i = 0; i < query_count; ++i) { len = dn_expand(msg, end, cur, hostbuf, sizeof(hostbuf)); if(len < 0) { inf_name_resolver_set_errno_error(error, errno); return NULL; } if(cur + len + QFIXEDSZ > end) { inf_name_resolver_set_incomplete_error(error); return NULL; } cur += len + QFIXEDSZ; } /* Go over the answers */ srvs = g_malloc(sizeof(InfNameResolverSRV) * answer_count); n_answers = 0; for(i = 0; i < answer_count; ++i) { cur = inf_name_resolver_parse_srv_record( msg, end, cur, &srvs[n_answers], error ); if(cur == NULL) { for(i = 0; i < n_answers; ++i) g_free(srvs[i].address); g_free(srvs); return NULL; } if(srvs[n_answers].address != NULL) ++n_answers; } if(n_answers < answer_count) srvs = g_realloc(srvs, n_answers * sizeof(InfNameResolverSRV)); *n_srvs = n_answers; return srvs; #endif } static InfNameResolverEntry* inf_name_resolver_lookup_a_aaaa(const gchar* hostname, const gchar* service, guint* n_entries, GError** error) { struct addrinfo hint; struct addrinfo* res; int err; GArray* array; InfNameResolverEntry entry; struct addrinfo* item; #ifdef AI_ADDRCONFIG hint.ai_flags = AI_ADDRCONFIG; #else hint.ai_flags = 0; #endif hint.ai_family = AF_UNSPEC; hint.ai_socktype = SOCK_STREAM; hint.ai_protocol = 0; hint.ai_addrlen = 0; hint.ai_canonname = NULL; hint.ai_addr = NULL; hint.ai_next = NULL; res = NULL; err = getaddrinfo(hostname, service, &hint, &res); if(err != 0) { g_set_error_literal( error, g_quark_from_static_string("GETADDRINFO_ERROR"), err, gai_strerror(err) ); *n_entries = 0; return NULL; } else { g_assert(res != NULL); array = g_array_new(FALSE, FALSE, sizeof(InfNameResolverEntry)); for(item = res; item != NULL; item = item->ai_next) { switch(item->ai_family) { case AF_INET: entry.address = inf_ip_address_new_raw4( ((struct sockaddr_in*)item->ai_addr)->sin_addr.s_addr ); entry.port = ntohs( ((struct sockaddr_in*)item->ai_addr)->sin_port); break; case AF_INET6: entry.address = inf_ip_address_new_raw6( ((struct sockaddr_in6*)item->ai_addr)->sin6_addr.s6_addr ); entry.port = ntohs( ((struct sockaddr_in6*)item->ai_addr)->sin6_port); break; default: g_assert_not_reached(); break; } g_array_append_val(array, entry); } freeaddrinfo(res); *n_entries = array->len; return (InfNameResolverEntry*)g_array_free(array, FALSE); } } static InfNameResolverEntry* inf_name_resolver_resolve_srv(InfNameResolverSRV** srvs, guint* n_srvs, const gchar* service, guint* n_entries, GError** error) { gchar* srvaddr; guint srvport; GError* local_error; InfNameResolverEntry* entries; guint i; g_assert(*n_srvs > 0); local_error = NULL; /* We have at least one SRV record. Choose one of the SRV records. */ srvaddr = inf_name_resolver_choose_srv(srvs, n_srvs, &srvport); while(srvaddr != NULL) { /* Look it up */ entries = inf_name_resolver_lookup_a_aaaa( srvaddr, service, n_entries, &local_error ); g_free(srvaddr); srvaddr = NULL; /* If there was an error, try the next SRV record */ if(entries == NULL) { if(*n_srvs > 0) srvaddr = inf_name_resolver_choose_srv(srvs, n_srvs, &srvport); /* Skip error if we have another record */ if(srvaddr != NULL) { g_error_free(local_error); local_error = NULL; } } else { /* Fill in default port from SRV record */ for(i = 0; i < *n_entries; ++i) if(entries[i].port == 0) entries[i].port = srvport; /* Remember the remaining SRV entries, in case connecting to the * chosen one does not work. */ return entries; } } /* SRV records exhausted; report last error */ g_assert(local_error != NULL); g_propagate_error(error, local_error); return NULL; } static InfNameResolverResult* inf_name_resolver_resolve(const gchar* hostname, const gchar* service, const gchar* srv) { InfNameResolverResult* result; gchar* query; GError* error; error = NULL; result = g_slice_new(InfNameResolverResult); inf_name_resolver_result_nullify(result); /* Look up a SRV record */ if(srv != NULL) { query = g_strdup_printf("%s.%s", srv, hostname); result->srvs = inf_name_resolver_lookup_srv( query, &result->n_srvs, &error ); g_free(query); if(error != NULL) { g_warning( _("Failure during SRV record lookup: %s\n" "Will go on with normal A/AAAA lookup"), error->message ); g_error_free(error); error = NULL; } else if(result->n_srvs > 0) { result->entries = inf_name_resolver_resolve_srv( &result->srvs, &result->n_srvs, service, &result->n_entries, &result->error ); /* If we failed to look up the SRV record, we do not attempt to look up * the original hostname as A/AAAA record -- we only do that if no SRV * records exist. */ return result; } } /* If that did not yield a result, lookup A/AAAA record */ result->entries = inf_name_resolver_lookup_a_aaaa( hostname, service, &result->n_entries, &result->error ); return result; } static void inf_name_resolver_run_func(gpointer* run_data, GDestroyNotify* run_notify, gpointer user_data) { InfNameResolver* resolver; InfNameResolverPrivate* priv; gchar* hostname; gchar* service; gchar* srv; InfNameResolverResult* result; resolver = INF_NAME_RESOLVER(user_data); priv = INF_NAME_RESOLVER_PRIVATE(resolver); hostname = g_strdup(priv->hostname); service = g_strdup(priv->service); srv = g_strdup(priv->srv); g_object_unref(resolver); result = inf_name_resolver_resolve(hostname, service, srv); g_free(hostname); g_free(service); g_free(srv); *run_data = result; *run_notify = inf_name_resolver_result_free; } static void inf_name_resolver_backup_run_func(gpointer* run_data, GDestroyNotify* run_notify, gpointer user_data) { InfNameResolver* resolver; InfNameResolverPrivate* priv; InfNameResolverResult* result; gchar* service; resolver = INF_NAME_RESOLVER(user_data); priv = INF_NAME_RESOLVER_PRIVATE(resolver); result = g_slice_new(InfNameResolverResult); result->srvs = priv->result.srvs; result->n_srvs = priv->result.n_srvs; service = g_strdup(priv->service); priv->result.srvs = NULL; priv->result.n_srvs = 0; g_object_unref(resolver); g_assert(result->n_srvs > 0); result->error = NULL; result->entries = inf_name_resolver_resolve_srv( &result->srvs, &result->n_srvs, service, &result->n_entries, &result->error ); g_free(service); *run_data = result; *run_notify = inf_name_resolver_result_free; } /* Main thread */ static void inf_name_resolver_done_func(gpointer run_data, gpointer user_data) { InfNameResolver* resolver; InfNameResolverPrivate* priv; InfNameResolverResult* result; resolver = INF_NAME_RESOLVER(user_data); priv = INF_NAME_RESOLVER_PRIVATE(resolver); result = (InfNameResolverResult*)run_data; g_assert(priv->result.n_entries == 0); g_assert(priv->result.n_srvs == 0); g_assert(priv->result.error == NULL); priv->operation = NULL; priv->result = *result; /* Nullify this so that the destroy notify lets the data alive */ inf_name_resolver_result_nullify(result); g_signal_emit( G_OBJECT(resolver), name_resolver_signals[RESOLVED], 0, priv->result.error ); } static void inf_name_resolver_backup_done_func(gpointer run_data, gpointer user_data) { InfNameResolver* resolver; InfNameResolverPrivate* priv; InfNameResolverResult* result; guint i; resolver = INF_NAME_RESOLVER(user_data); priv = INF_NAME_RESOLVER_PRIVATE(resolver); result = (InfNameResolverResult*)run_data; g_assert(priv->result.n_srvs == 0); g_assert(priv->result.error == NULL); /* Push the remaining SRV entries back for later lookup */ priv->operation = NULL; priv->result.srvs = result->srvs; priv->result.n_srvs = result->n_srvs; priv->result.error = result->error; /* If there are new addresses, append them */ if(result->n_entries > 0) { priv->result.entries = g_realloc( priv->result.entries, sizeof(InfNameResolverEntry) * (priv->result.n_entries + result->n_entries) ); for(i = 0; i < result->n_entries; ++i) priv->result.entries[priv->result.n_entries + i] = result->entries[i]; priv->result.n_entries += result->n_entries; } /* Nullify this so that the destroy notify lets the data alive */ inf_name_resolver_result_nullify(result); g_signal_emit( G_OBJECT(resolver), name_resolver_signals[RESOLVED], 0, priv->result.error ); } static void inf_name_resolver_init(InfNameResolver* resolver) { InfNameResolverPrivate* priv; priv = INF_NAME_RESOLVER_PRIVATE(resolver); priv->io = NULL; priv->hostname = NULL; priv->service = NULL; priv->srv = NULL; priv->operation = NULL; inf_name_resolver_result_nullify(&priv->result); } static void inf_name_resolver_dispose(GObject* object) { InfNameResolver* resolver; InfNameResolverPrivate* priv; resolver = INF_NAME_RESOLVER(object); priv = INF_NAME_RESOLVER_PRIVATE(resolver); if(priv->operation != NULL) { inf_async_operation_free(priv->operation); priv->operation = NULL; } if(priv->io != NULL) { g_object_unref(G_OBJECT(priv->io)); priv->io = NULL; } G_OBJECT_CLASS(inf_name_resolver_parent_class)->dispose(object); } static void inf_name_resolver_finalize(GObject* object) { InfNameResolver* resolver; InfNameResolverPrivate* priv; resolver = INF_NAME_RESOLVER(object); priv = INF_NAME_RESOLVER_PRIVATE(resolver); inf_name_resolver_result_cleanup(&priv->result); g_free(priv->hostname); g_free(priv->service); g_free(priv->srv); G_OBJECT_CLASS(inf_name_resolver_parent_class)->finalize(object); } static void inf_name_resolver_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfNameResolver* connection; InfNameResolverPrivate* priv; connection = INF_NAME_RESOLVER(object); priv = INF_NAME_RESOLVER_PRIVATE(connection); switch(prop_id) { case PROP_IO: g_assert(priv->operation == NULL); if(priv->io != NULL) g_object_unref(priv->io); priv->io = INF_IO(g_value_dup_object(value)); break; case PROP_HOSTNAME: g_assert(priv->operation == NULL); g_free(priv->hostname); priv->hostname = g_value_dup_string(value); break; case PROP_SERVICE: g_assert(priv->operation == NULL); g_free(priv->service); priv->service = g_value_dup_string(value); break; case PROP_SRV: g_assert(priv->operation == NULL); g_free(priv->srv); priv->srv = g_value_dup_string(value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void inf_name_resolver_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfNameResolver* connection; InfNameResolverPrivate* priv; connection = INF_NAME_RESOLVER(object); priv = INF_NAME_RESOLVER_PRIVATE(connection); switch(prop_id) { case PROP_IO: g_value_set_object(value, G_OBJECT(priv->io)); break; case PROP_HOSTNAME: g_value_set_string(value, priv->hostname); break; case PROP_SERVICE: g_value_set_string(value, priv->service); break; case PROP_SRV: g_value_set_string(value, priv->srv); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void inf_name_resolver_class_init(InfNameResolverClass* name_resolver_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(name_resolver_class); object_class->dispose = inf_name_resolver_dispose; object_class->finalize = inf_name_resolver_finalize; object_class->set_property = inf_name_resolver_set_property; object_class->get_property = inf_name_resolver_get_property; name_resolver_class->resolved = NULL; g_object_class_install_property( object_class, PROP_IO, g_param_spec_object( "io", "IO", "I/O handler", INF_TYPE_IO, G_PARAM_READWRITE | G_PARAM_CONSTRUCT ) ); g_object_class_install_property( object_class, PROP_HOSTNAME, g_param_spec_string( "hostname", "Hostname", "The hostname to be looked up", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT ) ); g_object_class_install_property( object_class, PROP_SERVICE, g_param_spec_string( "service", "Service", "The expected service at the remote endpoint", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT ) ); g_object_class_install_property( object_class, PROP_SRV, g_param_spec_string( "srv", "SRV", "The SRV record to look up for the given hostname, e.g. _jabber._tcp", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT ) ); /** * InfNameResolver::resolved: * @resolver: The #InfNameResolver that has resolved a hostname. * @error: A description of the error that occurred, or %NULL. * * This signal is emitted when the hostname has been resolved. The function * inf_name_resolver_get_address() and inf_name_resolver_get_port() can be * called to obtain the resolved addresses. */ name_resolver_signals[RESOLVED] = g_signal_new( "resolved", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfNameResolverClass, resolved), NULL, NULL, g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE, 1, G_TYPE_ERROR ); } /** * inf_name_resolver_new: (constructor) * @io: A #InfIo object used to schedule events in the main thread. * @hostname: The hostname to look up. * @service: (allow-none): The name of the service to look up, or %NULL. * @srv: (allow-none): The SRV record to look up, or %NULL. * * Creates a new #InfNameResolver. Use inf_name_resolver_start() to start * resolving the hostname. * * If @service is not %NULL, it should be a decimal port number or a * well-known service name that is translated into a port number, such as * "http". If @srv is not %NULL, the function will first attempt * a SRV lookup, and fall back to a regular A/AAAA lookup in case no SRV * record exists. Otherwise the SRV result is taken. If @service is * provided, it always overwrites the port number obtained from the hostname * lookup. * * The recommended procedure is to call this function with @service equal to * the port number entered by the user, or %NULL if the user did not provide * an explicit port number. If the resulting port number obtained with * inf_name_resolver_get_port() is then different from 0, then use that * port number, otherwise the default port number for the service. * * Returns: (transfer full): A new #InfNameResolver. Free with * g_object_unref(). **/ InfNameResolver* inf_name_resolver_new(InfIo* io, const gchar* hostname, const gchar* service, const gchar* srv) { InfNameResolver* resolver; g_return_val_if_fail(INF_IS_IO(io), NULL); resolver = INF_NAME_RESOLVER( g_object_new( INF_TYPE_NAME_RESOLVER, "io", io, "hostname", hostname, "service", service, "srv", srv, NULL ) ); return resolver; } /** * inf_name_resolver_get_hostname: * @resolver: A #InfNameResolver. * * Returns the currently configured hostname that @resolver will look up. * * Returns: (allow-none): The currently configured hostname. */ const gchar* inf_name_resolver_get_hostname(InfNameResolver* resolver) { g_return_val_if_fail(INF_IS_NAME_RESOLVER(resolver), NULL); return INF_NAME_RESOLVER_PRIVATE(resolver)->hostname; } /** * inf_name_resolver_get_service: * @resolver: A #InfNameResolver. * * Returns the currently configured service that @resolver will look up. * * Returns: (allow-none): The currently configured service. */ const gchar* inf_name_resolver_get_service(InfNameResolver* resolver) { g_return_val_if_fail(INF_IS_NAME_RESOLVER(resolver), NULL); return INF_NAME_RESOLVER_PRIVATE(resolver)->service; } /** * inf_name_resolver_get_srv: * @resolver: A #InfNameResolver. * * Returns the currently configured SRV record that @resolver will look up. * * Returns: (allow-none): The currently configured SRV record. */ const gchar* inf_name_resolver_get_srv(InfNameResolver* resolver) { g_return_val_if_fail(INF_IS_NAME_RESOLVER(resolver), NULL); return INF_NAME_RESOLVER_PRIVATE(resolver)->srv; } /** * inf_name_resolver_start: * @resolver: A #InfNameResolver. * @error: Location to store error information, if any. * * Starts the name resolution for the hostname configured with @resolver. * * When the hostname lookup has finished, the #InfNameResolver::resolved * signal is emitted. The function can only be called again once this signal * has been emitted. When this function is called, the previously looked up * result can no longer be obtained with the inf_name_resolver_get_address() * and inf_name_resolver_get_port() functions. * * Returns: %TRUE on success or %FALSE if a (synchronous) error occurred. */ gboolean inf_name_resolver_start(InfNameResolver* resolver, GError** error) { InfNameResolverPrivate* priv; gboolean success; g_return_val_if_fail(INF_IS_NAME_RESOLVER(resolver), FALSE); g_return_val_if_fail(error == NULL || *error == NULL, FALSE); priv = INF_NAME_RESOLVER_PRIVATE(resolver); g_return_val_if_fail(priv->operation == NULL, FALSE); inf_name_resolver_result_cleanup(&priv->result); inf_name_resolver_result_nullify(&priv->result); priv->operation = inf_async_operation_new( priv->io, inf_name_resolver_run_func, inf_name_resolver_done_func, resolver ); g_object_ref(resolver); success = inf_async_operation_start(priv->operation, error); if(success == FALSE) { g_object_unref(resolver); priv->operation = FALSE; return FALSE; } /* The launched thread takes over the reference on resolver */ return TRUE; } /** * inf_name_resolver_lookup_backup: * @resolver: A #InfNameResolver. * @error: Location to store error information, if any, or %NULL. * * Tries to look up backup addresses for the configured hostname. This should * be used if connecting to none of the initially reported addresses works. * The function returns %FALSE if there are no backup addresses available, or * %TRUE otherwise. If it returns %TRUE, it the #InfNameResolver::resolved * signal will be emitted again, and when it is, more addresses might be * available from the resolver object. * * Returns: %TRUE if looking up backup addresses is attempted, or %FALSE * otherwise. */ gboolean inf_name_resolver_lookup_backup(InfNameResolver* resolver, GError** error) { InfNameResolverPrivate* priv; gboolean success; g_return_val_if_fail(INF_IS_NAME_RESOLVER(resolver), FALSE); g_return_val_if_fail(error == NULL || *error == NULL, FALSE); priv = INF_NAME_RESOLVER_PRIVATE(resolver); g_return_val_if_fail(priv->operation == NULL, FALSE); if(priv->result.n_srvs == 0) return FALSE; if(priv->result.error != NULL) { g_error_free(priv->result.error); priv->result.error = NULL; } priv->operation = inf_async_operation_new( priv->io, inf_name_resolver_backup_run_func, inf_name_resolver_backup_done_func, resolver ); g_object_ref(resolver); success = inf_async_operation_start(priv->operation, error); if(success == FALSE) { g_object_unref(resolver); priv->operation = FALSE; return FALSE; } /* The launched thread takes over the reference on resolver */ return TRUE; } /** * inf_name_resolver_finished: * @resolver: A #InfNameResolver. * * Returns whether the resolver is currently looking up a hostname, or whether * it is ready to start a new lookup with inf_name_resolver_start(). * * Returns: Whether a call to inf_name_resolver_start() can be made. */ gboolean inf_name_resolver_finished(InfNameResolver* resolver) { InfNameResolverPrivate* priv; g_return_val_if_fail(INF_IS_NAME_RESOLVER(resolver), FALSE); priv = INF_NAME_RESOLVER_PRIVATE(resolver); if(priv->operation != NULL) return FALSE; return TRUE; } /** * inf_name_resolver_get_n_addresses: * @resolver: A #InfNameResolver. * * Returns the number of resolved addresses that belongs to the hostname * that was looked up. * * Returns: The number of addresses available. */ guint inf_name_resolver_get_n_addresses(InfNameResolver* resolver) { g_return_val_if_fail(INF_IS_NAME_RESOLVER(resolver), 0); return INF_NAME_RESOLVER_PRIVATE(resolver)->result.n_entries; } /** * inf_name_resolver_get_address: * @resolver: A #InfNameResolver. * @index: The index for which to return the address, in case multiple * IP addresses correspond to the same hostname. * * Returns the @indexth address looked up in the last hostname * resolution operation. * * Returns: (transfer none): The looked up #InfIpAddress. */ const InfIpAddress* inf_name_resolver_get_address(InfNameResolver* resolver, guint index) { InfNameResolverPrivate* priv; g_return_val_if_fail(INF_IS_NAME_RESOLVER(resolver), NULL); priv = INF_NAME_RESOLVER_PRIVATE(resolver); g_return_val_if_fail(index < priv->result.n_entries, NULL); return priv->result.entries[index].address; } /** * inf_name_resolver_get_port: * @resolver: A #InfNameResolver. * @index: The index for which to return the port, in case multiple * IP addresses correspond to the same hostname. * * Returns the @indexth port looked up in the last hostname * resolution operation. This can be 0 if the @service parameter in * inf_name_resolver_start() has been set to %NULL and no SRV record has * been found. * * Returns: The looked up #InfIpAddress. */ guint inf_name_resolver_get_port(InfNameResolver* resolver, guint index) { InfNameResolverPrivate* priv; g_return_val_if_fail(INF_IS_NAME_RESOLVER(resolver), 0); priv = INF_NAME_RESOLVER_PRIVATE(resolver); g_return_val_if_fail(index < priv->result.n_entries, 0); return priv->result.entries[index].port; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-simulated-connection.c0000644000000000000000000000013113034342512024451 xustar0030 mtime=1483851082.033718448 30 atime=1483851082.033718448 29 ctime=1488261589.08013889 libinfinity-0.7.1/libinfinity/common/inf-simulated-connection.c0000644000175000017500000004071013034342512025206 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-simulated-connection * @title: InfSimulatedConnection * @short_description: Simulated network connection * @include: libinfinity/common/inf-simulated-connection.h * @stability: Unstable * * #InfSimulatedConnection simulates a connection and can be used everywhere * where a #InfXmlConnection is expected. Use * inf_simulated_connection_connect() to connect two such connections so that * data sent through one is received by the other. */ #include #include #include static const GEnumValue inf_simulated_connection_mode_values[] = { { INF_SIMULATED_CONNECTION_IMMEDIATE, "INF_SIMULATED_CONNECTION_IMMEDIATE", "immediate" }, { INF_SIMULATED_CONNECTION_DELAYED, "INF_SIMULATED_CONNECTION_DELAYED", "delayed" }, { INF_SIMULATED_CONNECTION_IO_CONTROLLED, "INF_SIMULATED_CONNECTION_IO_CONTROLLED", "io-controlled" }, { 0, NULL, NULL } }; typedef struct _InfSimulatedConnectionPrivate InfSimulatedConnectionPrivate; struct _InfSimulatedConnectionPrivate { InfIo* io; InfIoDispatch* io_handler; InfSimulatedConnection* target; InfSimulatedConnectionMode mode; xmlNodePtr queue; xmlNodePtr queue_last_item; }; enum { PROP_0, PROP_IO, PROP_TARGET, PROP_MODE, /* From InfXmlConnection */ PROP_STATUS, PROP_NETWORK, PROP_LOCAL_ID, PROP_REMOTE_ID, PROP_LOCAL_CERTIFICATE, PROP_REMOTE_CERTIFICATE }; #define INF_SIMULATED_CONNECTION_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INF_TYPE_SIMULATED_CONNECTION, InfSimulatedConnectionPrivate)) static void inf_simulated_connection_xml_connection_iface_init(InfXmlConnectionInterface* iface); INF_DEFINE_ENUM_TYPE(InfSimulatedConnectionMode, inf_simulated_connection_mode, inf_simulated_connection_mode_values) G_DEFINE_TYPE_WITH_CODE(InfSimulatedConnection, inf_simulated_connection, G_TYPE_OBJECT, G_ADD_PRIVATE(InfSimulatedConnection) G_IMPLEMENT_INTERFACE(INF_TYPE_XML_CONNECTION, inf_simulated_connection_xml_connection_iface_init)) static void inf_simulated_connection_clear_queue(InfSimulatedConnection* connection) { InfSimulatedConnectionPrivate* priv; xmlNodePtr next; priv = INF_SIMULATED_CONNECTION_PRIVATE(connection); if(priv->io_handler != NULL) { g_assert(priv->io != NULL); inf_io_remove_dispatch(priv->io, priv->io_handler); priv->io_handler = NULL; } while(priv->queue != NULL) { next = priv->queue->next; xmlFreeNode(priv->queue); priv->queue = next; } priv->queue_last_item = NULL; } static void inf_simulated_connection_unset_target(InfSimulatedConnection* connection) { InfSimulatedConnectionPrivate* priv; InfSimulatedConnection* target; InfSimulatedConnectionPrivate* target_priv; priv = INF_SIMULATED_CONNECTION_PRIVATE(connection); target = priv->target; if(target != NULL) { target_priv = INF_SIMULATED_CONNECTION_PRIVATE(priv->target); g_assert(target_priv->target == connection); priv->target = NULL; target_priv->target = NULL; inf_simulated_connection_clear_queue(connection); inf_simulated_connection_clear_queue(target); g_object_notify(G_OBJECT(connection), "target"); g_object_notify(G_OBJECT(connection), "status"); g_object_notify(G_OBJECT(target), "target"); g_object_notify(G_OBJECT(target), "status"); } } static void inf_simulated_connection_set_target(InfSimulatedConnection* connection, InfSimulatedConnection* target) { InfSimulatedConnectionPrivate* priv; inf_simulated_connection_unset_target(connection); if(target != NULL) inf_simulated_connection_unset_target(target); priv = INF_SIMULATED_CONNECTION_PRIVATE(connection); priv->target = target; if(target != NULL) { priv = INF_SIMULATED_CONNECTION_PRIVATE(target); priv->target = connection; } g_object_notify(G_OBJECT(connection), "target"); g_object_notify(G_OBJECT(connection), "status"); if(target != NULL) { g_object_notify(G_OBJECT(target), "target"); g_object_notify(G_OBJECT(target), "status"); } } /* * GObject overrides */ static void inf_simulated_connection_init(InfSimulatedConnection* connection) { InfSimulatedConnectionPrivate* priv; priv = INF_SIMULATED_CONNECTION_PRIVATE(connection); priv->io = NULL; priv->target = NULL; priv->mode = INF_SIMULATED_CONNECTION_IMMEDIATE; } static void inf_simulated_connection_dispose(GObject* object) { InfSimulatedConnection* connection; InfSimulatedConnectionPrivate* priv; connection = INF_SIMULATED_CONNECTION(object); priv = INF_SIMULATED_CONNECTION_PRIVATE(connection); inf_simulated_connection_unset_target(connection); g_assert(priv->io_handler == NULL); if(priv->io != NULL) { g_object_unref(priv->io); priv->io = NULL; } G_OBJECT_CLASS(inf_simulated_connection_parent_class)->dispose(object); } static void inf_simulated_connection_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfSimulatedConnection* sim; InfSimulatedConnectionPrivate* priv; sim = INF_SIMULATED_CONNECTION(object); priv = INF_SIMULATED_CONNECTION_PRIVATE(sim); switch(prop_id) { case PROP_IO: g_assert(priv->io == NULL); /* construct only */ priv->io = INF_IO(g_value_get_object(value)); if(priv->io) g_object_ref(priv->io); break; case PROP_TARGET: inf_simulated_connection_set_target( sim, INF_SIMULATED_CONNECTION(g_value_get_object(value)) ); break; case PROP_MODE: inf_simulated_connection_set_mode(sim, g_value_get_enum(value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void inf_simulated_connection_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfSimulatedConnection* sim; InfSimulatedConnectionPrivate* priv; gchar* id; sim = INF_SIMULATED_CONNECTION(object); priv = INF_SIMULATED_CONNECTION_PRIVATE(sim); switch(prop_id) { case PROP_IO: g_value_set_object(value, G_OBJECT(priv->io)); break; case PROP_TARGET: g_value_set_object(value, G_OBJECT(priv->target)); break; case PROP_MODE: g_value_set_enum(value, priv->mode); break; case PROP_STATUS: if(priv->target != NULL) g_value_set_enum(value, INF_XML_CONNECTION_OPEN); else g_value_set_enum(value, INF_XML_CONNECTION_CLOSED); break; case PROP_NETWORK: g_value_set_static_string(value, "simulated"); break; case PROP_LOCAL_ID: id = g_strdup_printf("simulated-%p", (void*)sim); g_value_take_string(value, id); break; case PROP_REMOTE_ID: g_assert(priv->target != NULL); id = g_strdup_printf("simulated-%p", (void*)priv->target); g_value_take_string(value, id); break; case PROP_LOCAL_CERTIFICATE: g_value_set_pointer(value, NULL); break; case PROP_REMOTE_CERTIFICATE: g_value_set_boxed(value, NULL); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } /* * InfXmlConnection interface implementation */ static void inf_simulated_connection_xml_connection_close(InfXmlConnection* connection) { InfSimulatedConnectionPrivate* priv; priv = INF_SIMULATED_CONNECTION_PRIVATE(connection); g_assert(priv->target != NULL); inf_simulated_connection_unset_target(INF_SIMULATED_CONNECTION(connection)); } static void inf_simulated_connection_dispatch_func(gpointer user_data) { InfSimulatedConnection* connection; InfSimulatedConnectionPrivate* priv; connection = INF_SIMULATED_CONNECTION(user_data); priv = INF_SIMULATED_CONNECTION_PRIVATE(connection); priv->io_handler = NULL; inf_simulated_connection_flush(connection); } static void inf_simulated_connection_xml_connection_send(InfXmlConnection* connection, xmlNodePtr xml) { InfSimulatedConnectionPrivate* priv; priv = INF_SIMULATED_CONNECTION_PRIVATE(connection); g_assert(priv->target != NULL); switch(priv->mode) { case INF_SIMULATED_CONNECTION_IMMEDIATE: inf_xml_connection_sent(connection, xml); inf_xml_connection_received(INF_XML_CONNECTION(priv->target), xml); xmlFreeNode(xml); break; case INF_SIMULATED_CONNECTION_DELAYED: case INF_SIMULATED_CONNECTION_IO_CONTROLLED: xmlUnlinkNode(xml); if(priv->queue == NULL) { priv->queue = xml; priv->queue_last_item = xml; } else { priv->queue_last_item->next = xml; priv->queue_last_item = xml; } if(priv->mode == INF_SIMULATED_CONNECTION_IO_CONTROLLED) { if(priv->io_handler == NULL) { g_assert(priv->io != NULL); priv->io_handler = inf_io_add_dispatch( priv->io, inf_simulated_connection_dispatch_func, connection, NULL ); } } break; default: g_assert_not_reached(); break; } } /* * GObject type registration */ static void inf_simulated_connection_class_init( InfSimulatedConnectionClass* connection_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(connection_class); object_class->dispose = inf_simulated_connection_dispose; object_class->set_property = inf_simulated_connection_set_property; object_class->get_property = inf_simulated_connection_get_property; g_object_class_install_property( object_class, PROP_IO, g_param_spec_object( "io", "IO", "The main loop to be used for IO_CONTROLLED mode", INF_TYPE_IO, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_TARGET, g_param_spec_object( "target", "Target connection", "The simulated connection receiving data sent through this connection", INF_TYPE_SIMULATED_CONNECTION, G_PARAM_READWRITE ) ); g_object_class_install_property( object_class, PROP_MODE, g_param_spec_enum( "mode", "Mode", "The mode of the simulated connection", INF_TYPE_SIMULATED_CONNECTION_MODE, INF_SIMULATED_CONNECTION_IMMEDIATE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT ) ); g_object_class_override_property(object_class, PROP_STATUS, "status"); g_object_class_override_property(object_class, PROP_NETWORK, "network"); g_object_class_override_property(object_class, PROP_LOCAL_ID, "local-id"); g_object_class_override_property(object_class, PROP_REMOTE_ID, "remote-id"); g_object_class_override_property( object_class, PROP_LOCAL_CERTIFICATE, "local-certificate" ); g_object_class_override_property( object_class, PROP_REMOTE_CERTIFICATE, "remote-certificate" ); } static void inf_simulated_connection_xml_connection_iface_init( InfXmlConnectionInterface* iface) { iface->close = inf_simulated_connection_xml_connection_close; iface->send = inf_simulated_connection_xml_connection_send; } /* * Public API */ /** * inf_simulated_connection_new: (constructor) * * Creates a new #InfSimulatedConnection. A connection created this way cannot * be switched to %INF_SIMULATED_CONNECTION_IO_CONTROLLED mode. Use * inf_simulated_connection_new_with_io() instead if you intend to do that. * * Returns: (transfer full): A new #InfSimulatedConnection. **/ InfSimulatedConnection* inf_simulated_connection_new(void) { GObject* object; object = g_object_new(INF_TYPE_SIMULATED_CONNECTION, NULL); return INF_SIMULATED_CONNECTION(object); } /** * inf_simulated_connection_new_with_io: (constructor) * @io: The main loop to be used for %INF_SIMULATED_CONNECTION_IO_CONTROLLED * mode. * * Creates a new #InfSimulatedConnection with the given #InfIo. This * connection can be used with %INF_SIMULATED_CONNECTION_IO_CONTROLLED mode. * If you don't intend to use that mode then using * inf_simulated_connection_new() is also good enough since the #InfIo object * is not required in that case. * * Returns: (transfer full): A new #InfSimulatedConnection. */ InfSimulatedConnection* inf_simulated_connection_new_with_io(InfIo* io) { GObject* object; g_return_val_if_fail(INF_IS_IO(io), NULL); object = g_object_new(INF_TYPE_SIMULATED_CONNECTION, "io", io, NULL); return INF_SIMULATED_CONNECTION(object); } /** * inf_simulated_connection_connect: * @connection: A #InfSimulatedConnection. * @to: The target connection. * * Connects two simulated connections, so that data sent through one of them * is received by the other one and vice versa. So one call to this function * connects both #InfSimulatedConnections to each other. There is no * need to call this function once for each connection. * * If one or both of the connections already have another target, then the * simulated connection between those is closed first. */ void inf_simulated_connection_connect(InfSimulatedConnection* connection, InfSimulatedConnection* to) { inf_simulated_connection_set_target(connection, to); } /** * inf_simulated_connection_set_mode: * @connection: A #InfSimulatedConnection. * @mode: The new mode to set. * * Sets the mode of the simulated connection. * * In %INF_SIMULATED_CONNECTION_IMMEDIATE mode, messages sent through the * connection are received by the target during the call to * inf_xml_connection_send(). * * In %INF_SIMULATED_CONNECTION_DELAYED mode, messages sent are queued and * received by the target when inf_simulated_connection_flush() is called. * * In %INF_SIMULATED_CONNECTION_IO_CONTROLLED mode, messages are queued and * received by the target as soon as a dispatch handler (see * inf_io_add_dispatch()) installed on the main loop is called. * * When changing the mode from %INF_SIMULATED_CONNECTION_DELAYED or * %INF_SIMULATED_CONNECTION_IO_CONTROLLED to * %INF_SIMULATED_CONNECTION_IMMEDIATE, then the queue is flushed, too. */ void inf_simulated_connection_set_mode(InfSimulatedConnection* connection, InfSimulatedConnectionMode mode) { InfSimulatedConnectionPrivate* priv; priv = INF_SIMULATED_CONNECTION_PRIVATE(connection); g_return_if_fail(priv->io != NULL || mode != INF_SIMULATED_CONNECTION_IO_CONTROLLED); if(priv->mode != mode) { if(mode == INF_SIMULATED_CONNECTION_IMMEDIATE) inf_simulated_connection_flush(connection); priv->mode = mode; g_object_notify(G_OBJECT(connection), "mode"); } } /** * inf_simulated_connection_flush: * @connection: A #InfSimulatedConnection. * * When @connection's mode is %INF_SIMULATED_CONNECTION_DELAYED or * %INF_SIMULATED_CONNECTION_IO_CONTROLLED, then calling this function makes * the target connection receive all the queued messages. */ void inf_simulated_connection_flush(InfSimulatedConnection* connection) { InfSimulatedConnectionPrivate* priv; xmlNodePtr next; priv = INF_SIMULATED_CONNECTION_PRIVATE(connection); g_return_if_fail(priv->target != NULL); if(priv->mode == INF_SIMULATED_CONNECTION_IO_CONTROLLED) { g_assert(priv->io != NULL); if(priv->io_handler != NULL) { inf_io_remove_dispatch(priv->io, priv->io_handler); priv->io_handler = NULL; } } while(priv->queue != NULL) { inf_xml_connection_sent( INF_XML_CONNECTION(connection), priv->queue ); inf_xml_connection_received( INF_XML_CONNECTION(priv->target), priv->queue ); next = priv->queue->next; xmlFreeNode(priv->queue); priv->queue = next; } priv->queue_last_item = NULL; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-chat-session.h0000644000000000000000000000013213034342512022733 xustar0030 mtime=1483851082.029718427 30 atime=1483851082.029718427 30 ctime=1488261588.940139196 libinfinity-0.7.1/libinfinity/common/inf-chat-session.h0000644000175000017500000000736513034342512023500 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef __INF_CHAT_SESSION_H__ #define __INF_CHAT_SESSION_H__ #include #include #include #include G_BEGIN_DECLS #define INF_TYPE_CHAT_SESSION (inf_chat_session_get_type()) #define INF_CHAT_SESSION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_TYPE_CHAT_SESSION, InfChatSession)) #define INF_CHAT_SESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INF_TYPE_CHAT_SESSION, InfChatSessionClass)) #define INF_IS_CHAT_SESSION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_TYPE_CHAT_SESSION)) #define INF_IS_CHAT_SESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INF_TYPE_CHAT_SESSION)) #define INF_CHAT_SESSION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INF_TYPE_CHAT_SESSION, InfChatSessionClass)) typedef struct _InfChatSession InfChatSession; typedef struct _InfChatSessionClass InfChatSessionClass; /** * InfChatSessionError: * @INF_CHAT_SESSION_ERROR_TYPE_INVALID: An invalid message type was sent. * @INF_CHAT_SESSION_ERROR_NO_SUCH_USER: A message referred to a nonexisting * user. * @INF_CHAT_SESSION_ERROR_FAILED: Generic error code when no further reason * of failure is known. * * Errors that can occur with a chat session, especially in the * process_xml_sync and process_xml_run vfunc implementations. */ typedef enum _InfChatSessionError { INF_CHAT_SESSION_ERROR_TYPE_INVALID, INF_CHAT_SESSION_ERROR_NO_SUCH_USER, INF_CHAT_SESSION_ERROR_FAILED } InfChatSessionError; /** * InfChatSessionClass: * @receive_message: Default signal handler for the * #InfChatSession::receive-message signal. * @send_message: Default signal handler for the * #InfChatSession::send-message signal. * * This structure contains default signal handlers for #InfChatSession. */ struct _InfChatSessionClass { /*< private >*/ InfSessionClass parent_class; /*< public >*/ void (*receive_message)(InfChatSession* session, const InfChatBufferMessage* message); void (*send_message)(InfChatSession* session, const InfChatBufferMessage* message); }; /** * InfChatSession: * * #InfChatSession is an opaque data type. You should only access it via the * public API functions. */ struct _InfChatSession { /*< private >*/ InfSession parent; }; GType inf_chat_session_get_type(void) G_GNUC_CONST; InfChatSession* inf_chat_session_new(InfCommunicationManager* manager, InfChatBuffer* buffer, InfSessionStatus status, InfCommunicationGroup* sync_group, InfXmlConnection* sync_connection); gboolean inf_chat_session_set_log_file(InfChatSession* session, const gchar* log_file, GError** error); G_END_DECLS #endif /* __INF_CHAT_SESSION_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-standalone-io.h0000644000000000000000000000013013034342512023066 xustar0029 mtime=1483851082.03771847 29 atime=1483851082.03771847 30 ctime=1488261588.964139144 libinfinity-0.7.1/libinfinity/common/inf-standalone-io.h0000644000175000017500000000512413034342512023624 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_STANDALONE_IO_H__ #define __INF_STANDALONE_IO_H__ #include G_BEGIN_DECLS #define INF_TYPE_STANDALONE_IO (inf_standalone_io_get_type()) #define INF_STANDALONE_IO(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_TYPE_STANDALONE_IO, InfStandaloneIo)) #define INF_STANDALONE_IO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INF_TYPE_STANDALONE_IO, InfStandaloneIoClass)) #define INF_IS_STANDALONE_IO(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_TYPE_STANDALONE_IO)) #define INF_IS_STANDALONE_IO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INF_TYPE_STANDALONE_IO)) #define INF_STANDALONE_IO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INF_TYPE_STANDALONE_IO, InfStandaloneIoClass)) typedef struct _InfStandaloneIo InfStandaloneIo; typedef struct _InfStandaloneIoClass InfStandaloneIoClass; /** * InfStandaloneIoClass: * * This structure does not contain any public fields. */ struct _InfStandaloneIoClass { /*< private >*/ GObjectClass parent_class; }; /** * InfStandaloneIo: * * #InfStandaloneIo is an opaque data type. You should only access it via the * public API functions. */ struct _InfStandaloneIo { /*< private >*/ GObject parent; }; GType inf_standalone_io_get_type(void) G_GNUC_CONST; InfStandaloneIo* inf_standalone_io_new(void); void inf_standalone_io_iteration(InfStandaloneIo* io); void inf_standalone_io_iteration_timeout(InfStandaloneIo* io, guint timeout); void inf_standalone_io_loop(InfStandaloneIo* io); void inf_standalone_io_loop_quit(InfStandaloneIo* io); gboolean inf_standalone_io_loop_running(InfStandaloneIo* io); G_END_DECLS #endif /* __INF_STANDALONE_IO_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-local-publisher.h0000644000000000000000000000013213034342512023420 xustar0030 mtime=1483851082.033718448 30 atime=1483851082.033718448 30 ctime=1488261588.952139171 libinfinity-0.7.1/libinfinity/common/inf-local-publisher.h0000644000175000017500000000645713034342512024166 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_LOCAL_PUBLISHER_H__ #define __INF_LOCAL_PUBLISHER_H__ #include #include G_BEGIN_DECLS #define INF_TYPE_LOCAL_PUBLISHER (inf_local_publisher_get_type()) #define INF_LOCAL_PUBLISHER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_TYPE_LOCAL_PUBLISHER, InfLocalPublisher)) #define INF_IS_LOCAL_PUBLISHER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_TYPE_LOCAL_PUBLISHER)) #define INF_LOCAL_PUBLISHER_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), INF_TYPE_LOCAL_PUBLISHER, InfLocalPublisherInterface)) /** * InfLocalPublisher: * * #InfLocalPublisher is an opaque data type. You should only access it * via the public API functions. */ typedef struct _InfLocalPublisher InfLocalPublisher; typedef struct _InfLocalPublisherInterface InfLocalPublisherInterface; /** * InfLocalPublisherItem: * * #InfLocalPublisherItem is an opaque data type. You should only access it * via the public API functions. */ typedef struct _InfLocalPublisherItem InfLocalPublisherItem; /** * InfLocalPublisherInterface: * @publish: Virtual function to announce a service of the given type with * the given name on the given port. The returned #InfLocalPublisherItem is * valid as long as the service is published and the #InfLocalPublisher is * alive. It can be used to unpublish the service again using the @unpublish * function. * @unpublish: Virtual function to unpublish a previously published service. * * Virtual functions for #InfLocalPublisher. */ struct _InfLocalPublisherInterface { /*< private >*/ GTypeInterface parent; /* Virtual table */ /*< public >*/ InfLocalPublisherItem* (*publish)(InfLocalPublisher* publisher, const gchar* type, const gchar* name, guint port); void (*unpublish)(InfLocalPublisher* publisher, InfLocalPublisherItem* item); }; GType inf_local_publisher_get_type(void) G_GNUC_CONST; InfLocalPublisherItem* inf_local_publisher_publish(InfLocalPublisher* publisher, const gchar* type, const gchar* name, guint port); void inf_local_publisher_unpublish(InfLocalPublisher* publisher, InfLocalPublisherItem* item); G_END_DECLS #endif /* __INF_LOCAL_PUBLISHER_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-browser-iter.h0000644000000000000000000000013213034342512022757 xustar0030 mtime=1483851082.029718427 30 atime=1483851082.029718427 30 ctime=1488261588.932139214 libinfinity-0.7.1/libinfinity/common/inf-browser-iter.h0000644000175000017500000000313713034342512023515 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_BROWSER_ITER_H__ #define __INF_BROWSER_ITER_H__ #include G_BEGIN_DECLS #define INF_TYPE_BROWSER_ITER (inf_browser_iter_get_type()) /** * InfBrowserIter: * * The #InfBrowserIter structure is opaque, however it is guaranteed that * it can be copied by value and does not hold any dynamic data that would * need to be freed explicitly. */ typedef struct _InfBrowserIter InfBrowserIter; struct _InfBrowserIter { /*< private >*/ guint node_id; gpointer node; }; GType inf_browser_iter_get_type(void) G_GNUC_CONST; InfBrowserIter* inf_browser_iter_copy(const InfBrowserIter* iter); void inf_browser_iter_free(InfBrowserIter* iter); G_END_DECLS #endif /* __INF_BROWSER_ITER_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-request.h0000644000000000000000000000013213034342512022023 xustar0030 mtime=1483851082.033718448 30 atime=1483851082.033718448 30 ctime=1488261588.960139153 libinfinity-0.7.1/libinfinity/common/inf-request.h0000644000175000017500000000631113034342512022556 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_REQUEST_H__ #define __INF_REQUEST_H__ #include #include G_BEGIN_DECLS #define INF_TYPE_REQUEST (inf_request_get_type()) #define INF_REQUEST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_TYPE_REQUEST, InfRequest)) #define INF_IS_REQUEST(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_TYPE_REQUEST)) #define INF_REQUEST_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), INF_TYPE_REQUEST, InfRequestInterface)) /** * InfRequestResult: * * #InfRequestResult is an opaque data type. You should only access it * via the public API functions. */ typedef struct _InfRequestResult InfRequestResult; /** * InfRequest: * * #InfRequest is an opaque data type. You should only access it * via the public API functions. */ typedef struct _InfRequest InfRequest; typedef struct _InfRequestInterface InfRequestInterface; /** * InfRequestInterface: * @finished: Default signal handler of the #InfRequest::finished signal. * @is_local: Virtual function to check whether the request is local or * remote. * * Virtual functions of the #InfRequest interface. */ struct _InfRequestInterface { /*< private >*/ GTypeInterface parent; /*< public >*/ void (*finished)(InfRequest* request, const InfRequestResult* result, const GError* error); gboolean (*is_local)(InfRequest* request); }; /** * InfRequestFunc: * @request: The #InfRequest that emits the signal. * @result: A #InfRequestResult which contains the result of the request. * @error: Error information in case the request failed, or %NULL * otherwise. * @user_data: Additional data set when the signal handler was connected. * * Signature of a signal handler for the #InfRequest::finished signal. */ typedef void(*InfRequestFunc)(InfRequest* request, const InfRequestResult* result, const GError* error, gpointer user_data); GType inf_request_get_type(void) G_GNUC_CONST; void inf_request_fail(InfRequest* request, const GError* error); void inf_request_finish(InfRequest* request, InfRequestResult* result); gboolean inf_request_is_local(InfRequest* request); G_END_DECLS #endif /* __INF_REQUEST_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-discovery.c0000644000000000000000000000013213034342512022335 xustar0030 mtime=1483851082.033718448 30 atime=1483851082.033718448 30 ctime=1488261589.052138951 libinfinity-0.7.1/libinfinity/common/inf-discovery.c0000644000175000017500000002026413034342512023073 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-discovery * @title: InfDiscovery * @short_description: Discovery of remote services * @include: libinfinity/common/inf-discovery.h * @see_also: #InfDiscoveryAvahi * @stability: Unstable * * #InfDiscovery provides a common interface for the discovery of services. * Discovered services are represented by #InfDiscoveryInfo objects * and can be used to query the name of the discovered service. * * To create a connection to the host providing a discovered service, use * inf_discovery_resolve(). */ #include G_DEFINE_INTERFACE(InfDiscovery, inf_discovery, G_TYPE_OBJECT) enum { DISCOVERED, UNDISCOVERED, LAST_SIGNAL }; static guint discovery_signals[LAST_SIGNAL]; static void inf_discovery_default_init(InfDiscoveryInterface* iface) { /** * InfDiscovery::discovered: * @discoverer: The #InfDiscovery object discovering something * @info: The #InfDiscoveryInfo describing the discovered service * * This signal is detailed. The detail is the name of the service that has * been discovered, so you can connect to * "discovered::my-service-name" if you are * only interested in a particular service. */ discovery_signals[DISCOVERED] = g_signal_new( "discovered", INF_TYPE_DISCOVERY, G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, G_STRUCT_OFFSET(InfDiscoveryInterface, discovered), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER /* InfDiscoveryInfo* */ ); /** * InfDiscovery::undiscovered: * @discoverer: The #InfDiscovery object undiscovering something * @info: The #InfDiscoveryInfo describing the undiscovered service * * This signal is emitted if a previously discovered service is no longer * available. * * This signal is detailed. The detail is the name of the service that has * been undiscovered, so you can connect to * "undiscovered::my-service-name" if you * are only interested in a particular service. */ discovery_signals[UNDISCOVERED] = g_signal_new( "undiscovered", INF_TYPE_DISCOVERY, G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED, G_STRUCT_OFFSET(InfDiscoveryInterface, undiscovered), NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER ); } /** * inf_discovery_discover: * @discovery: A #InfDiscovery. * @type: The service type to discover. * * Starts the discovery of the given service type. Whenever a service of * this type is discovered, the "discovered" signal is emitted. If the * service disappears, the "undiscovered" signal is emitted. This can be * called more than once for the same type, but only the first call has * an effect. * * Note also that implementations of #InfDiscovery might restrict the * service types that can be discovered. **/ void inf_discovery_discover(InfDiscovery* discovery, const gchar* type) { InfDiscoveryInterface* iface; g_return_if_fail(INF_IS_DISCOVERY(discovery)); g_return_if_fail(type != NULL); iface = INF_DISCOVERY_GET_IFACE(discovery); g_return_if_fail(iface->discover != NULL); iface->discover(discovery, type); } /** * inf_discovery_get_discovered: * @discovery: A #InfDiscovery. * @type: The service type of which to get discovered infos for. * * Returns a list of discovered #InfDiscoveryInfo for the given type. * * Returns: (transfer container) (element-type InfDiscoveryInfo): A newly * allocated list that needs to be freed with g_slist_free(). **/ GSList* inf_discovery_get_discovered(InfDiscovery* discovery, const gchar* type) { InfDiscoveryInterface* iface; g_return_val_if_fail(INF_IS_DISCOVERY(discovery), NULL); g_return_val_if_fail(type != NULL, NULL); iface = INF_DISCOVERY_GET_IFACE(discovery); g_return_val_if_fail(iface->get_discovered != NULL, NULL); return iface->get_discovered(discovery, type); } /** * inf_discovery_resolve: * @discovery: A #InfDiscovery. * @info: A #InfDiscoveryInfo discovered by @discovery. * @complete_func: (scope async): A callback that will be called when the * resolving process has completed. * @user_data: Extra data to pass to @complete_func and @error_func. * * Attempts to resolve @info. Resolving a #InfDiscoveryInfo means creating * a #InfXmlConnection to the publisher. The connection might not be * open when @complete_func runs. **/ void inf_discovery_resolve(InfDiscovery* discovery, InfDiscoveryInfo* info, InfDiscoveryResolvCompleteFunc complete_func, gpointer user_data) { InfDiscoveryInterface* iface; g_return_if_fail(INF_IS_DISCOVERY(discovery)); g_return_if_fail(info != NULL); iface = INF_DISCOVERY_GET_IFACE(discovery); g_return_if_fail(iface->resolve != NULL); iface->resolve(discovery, info, complete_func, user_data); } /** * inf_discovery_info_get_service_name: * @discovery: A #InfDiscovery. * @info: A #InfDiscoveryInfo discovered by @discovery. * * Returns the service name of the discovered @info. * * Returns: (transfer full): A newly allocated string. * Free with g_free(). **/ gchar* inf_discovery_info_get_service_name(InfDiscovery* discovery, InfDiscoveryInfo* info) { InfDiscoveryInterface* iface; g_return_val_if_fail(INF_IS_DISCOVERY(discovery), NULL); g_return_val_if_fail(info != NULL, NULL); iface = INF_DISCOVERY_GET_IFACE(discovery); g_return_val_if_fail(iface->info_get_service_name != NULL, NULL); return iface->info_get_service_name(discovery, info); } /** * inf_discovery_info_get_service_type: * @discovery: A #InfDiscovery. * @info: A #InfDiscoveryInfo discovered by @discovery. * * Returns the service type of the discovered @info. * * Returns: (transfer none): A string owned by @discovery. **/ const gchar* inf_discovery_info_get_service_type(InfDiscovery* discovery, InfDiscoveryInfo* info) { InfDiscoveryInterface* iface; g_return_val_if_fail(INF_IS_DISCOVERY(discovery), NULL); g_return_val_if_fail(info != NULL, NULL); iface = INF_DISCOVERY_GET_IFACE(discovery); g_return_val_if_fail(iface->info_get_service_type != NULL, NULL); return iface->info_get_service_type(discovery, info); } /** * inf_discovery_discovered: * @discovery: A #InfDiscovery. * @info: The discovered #InfDiscoveryInfo. * * Emits the "discovered" signal on @discovery. **/ void inf_discovery_discovered(InfDiscovery* discovery, InfDiscoveryInfo* info) { g_return_if_fail(INF_IS_DISCOVERY(discovery)); g_return_if_fail(info != NULL); g_signal_emit( G_OBJECT(discovery), discovery_signals[DISCOVERED], g_quark_from_string(inf_discovery_info_get_service_type(discovery, info)), info ); } /** * inf_discovery_undiscovered: * @discovery: A #InfDiscovery. * @info: The undiscovered @InfDiscoveryInfo. * * Emits the "undiscovered" signal on @discovery. **/ void inf_discovery_undiscovered(InfDiscovery* discovery, InfDiscoveryInfo* info) { g_return_if_fail(INF_IS_DISCOVERY(discovery)); g_return_if_fail(info != NULL); g_signal_emit( G_OBJECT(discovery), discovery_signals[UNDISCOVERED], g_quark_from_string(inf_discovery_info_get_service_type(discovery, info)), info ); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-ip-address.c0000644000000000000000000000013213034342512022361 xustar0030 mtime=1483851082.033718448 30 atime=1483851082.033718448 30 ctime=1488261589.060138934 libinfinity-0.7.1/libinfinity/common/inf-ip-address.c0000644000175000017500000002317513034342512023123 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-ip-address * @title: InfIpAddress * @short_description: IPv4 and IPv6 addresses * @see_also: #InfTcpConnection * @include: libinfinity/common/inf-ip-address.h * @stability: Unstable * * A #InfIpAddress represents an IPv4 or an IPv6 network address. Use * inf_ip_address_get_family() to find out the type of a specific address. **/ #include #include #ifdef G_OS_WIN32 # include # include #else # include # include # include # include # include #endif #include static const GEnumValue inf_ip_address_family_values[] = { { INF_IP_ADDRESS_IPV4, "INF_IP_ADDRESS_IPV4", "IPv4" }, { INF_IP_ADDRESS_IPV6, "INF_IP_ADDRESS_IPV6", "IPv6" }, { 0, NULL, NULL } }; struct _InfIpAddress { InfIpAddressFamily family; union { struct in_addr addr4; struct in6_addr addr6; } shared; }; INF_DEFINE_ENUM_TYPE(InfIpAddressFamily, inf_ip_address_family, inf_ip_address_family_values) G_DEFINE_BOXED_TYPE(InfIpAddress, inf_ip_address, inf_ip_address_copy, inf_ip_address_free) static InfIpAddress* inf_ip_address_new_common(InfIpAddressFamily family) { InfIpAddress* address; address = g_slice_new(InfIpAddress); address->family = family; return address; } /** * inf_ip_address_new_raw4: (constructor) * @address: An IPv4 address in network byte order. * * Creates a new IPv4 address. * * Returns: (transfer full): A new #InfIpAddress. **/ InfIpAddress* inf_ip_address_new_raw4(guint32 address) { InfIpAddress* addr; addr = inf_ip_address_new_common(INF_IP_ADDRESS_IPV4); addr->shared.addr4.s_addr = address; return addr; } /** * inf_ip_address_new_loopback4: (constructor) * * Creates a new IPv4 address that contains the local host's IP address * ("127.0.0.1"). * * Returns: (transfer full): A new #InfIpAddress. **/ InfIpAddress* inf_ip_address_new_loopback4(void) { return inf_ip_address_new_raw4(htonl(INADDR_LOOPBACK)); } /** * inf_ip_address_new_raw6: (constructor) * @address: An IPv6 address in network bype order. * * Creates a new IPv6 address. * * Returns: (transfer full): A new #InfIpAddress. **/ InfIpAddress* inf_ip_address_new_raw6(const guint8 address[16]) { InfIpAddress* addr; addr = inf_ip_address_new_common(INF_IP_ADDRESS_IPV6); memcpy(addr->shared.addr6.s6_addr, address, 16); return addr; } /** * inf_ip_address_new_loopback6: (constructor) * * Creates a new IPv6 address that contains the local host's IP address * ("::1"). * * Returns: (transfer full): A new #InfIpAddress. **/ InfIpAddress* inf_ip_address_new_loopback6(void) { return inf_ip_address_new_raw6(in6addr_loopback.s6_addr); } /** * inf_ip_address_new_from_string: (constructor) * @str: A string containing an IPv4 or IPv6 address in standard dots * notation. * * Creates a new IP address (either IPv4 or IPv6) from the given string. * * Returns: (transfer full): A new #InfIpAddress, or %NULL. **/ InfIpAddress* inf_ip_address_new_from_string(const gchar* str) { InfIpAddress* addr; #ifdef G_OS_WIN32 /* inet_pton only exists since Windows Vista, so we use * WSAStringToAddress */ union { struct sockaddr_in addr4; struct sockaddr_in6 addr6; } shared; int len; int ret; #endif addr = g_slice_new(InfIpAddress); #ifdef G_OS_WIN32 len = sizeof(struct sockaddr_in); ret = WSAStringToAddress( (char*)str, AF_INET, NULL, (struct sockaddr*)&shared.addr4, &len ); if(ret == 0) { addr->family = INF_IP_ADDRESS_IPV4; addr->shared.addr4.s_addr = shared.addr4.sin_addr.s_addr; } else { len = sizeof(struct sockaddr_in6); ret = WSAStringToAddress( (char*)str, AF_INET6, NULL, (struct sockaddr*)&shared.addr6, &len ); if(ret == 0) { addr->family = INF_IP_ADDRESS_IPV6; memcpy(addr->shared.addr6.s6_addr, shared.addr6.sin6_addr.s6_addr, 16); } else { g_slice_free(InfIpAddress, addr); addr = NULL; } } #else if(inet_pton(AF_INET, str, &addr->shared.addr4) > 0) { addr->family = INF_IP_ADDRESS_IPV4; } else if(inet_pton(AF_INET6, str, &addr->shared.addr6) > 0) { addr->family = INF_IP_ADDRESS_IPV6; } else { g_slice_free(InfIpAddress, addr); addr = NULL; } #endif return addr; } /** * inf_ip_address_copy: * @address: A #InfIpAddress. * * Creates a new #InfIpAddress that contains the same address as @address. * * Returns: A new #InfIpAddress. **/ InfIpAddress* inf_ip_address_copy(const InfIpAddress* address) { switch(address->family) { case INF_IP_ADDRESS_IPV4: return inf_ip_address_new_raw4(address->shared.addr4.s_addr); case INF_IP_ADDRESS_IPV6: return inf_ip_address_new_raw6(address->shared.addr6.s6_addr); default: g_assert_not_reached(); return NULL; } } /** * inf_ip_address_free: * @address: A #InfIpAddress. * * Frees @address. **/ void inf_ip_address_free(InfIpAddress* address) { g_slice_free(InfIpAddress, address); } /** * inf_ip_address_get_family: * @address: A #InfIpAddress. * * Returns the address family of @address. * * Returns: A #InfIpAddressFamily. **/ InfIpAddressFamily inf_ip_address_get_family(const InfIpAddress* address) { return address->family; } /** * inf_ip_address_get_raw: * @address: A #InfIpAddress. * * Returns either 32 bit (IPv4) or 128 bit (IPv6) raw address data in host * byte order of @address. * * Returns: (transfer none): The raw address. **/ gconstpointer inf_ip_address_get_raw(const InfIpAddress* address) { switch(address->family) { case INF_IP_ADDRESS_IPV4: return &address->shared.addr4; case INF_IP_ADDRESS_IPV6: return address->shared.addr6.s6_addr; default: g_assert_not_reached(); return NULL; } } /** * inf_ip_address_to_string: * @address: A #InfIpAddress. * * Returns a string representation of @address in standard dots format (like * "192.168.0.1" or "::1"). * * Returns: (transfer full): A newly-allocated string. Free with g_free(). **/ gchar* inf_ip_address_to_string(const InfIpAddress* address) { gchar* retval; #ifdef G_OS_WIN32 /* inet_ntop only exists since Windows Vista, so we use * WSAAddressToString */ union { struct sockaddr_in addr4; struct sockaddr_in6 addr6; } shared; struct sockaddr* inaddr; char dummy; DWORD addr_len; DWORD str_len; int res; #endif #ifdef G_OS_WIN32 switch(address->family) { case INF_IP_ADDRESS_IPV4: shared.addr4.sin_family = AF_INET; shared.addr4.sin_addr.s_addr = address->shared.addr4.s_addr; shared.addr4.sin_port = htons(0); inaddr = (struct sockaddr*)&shared.addr4; addr_len = sizeof(struct sockaddr_in); break; case INF_IP_ADDRESS_IPV6: shared.addr6.sin6_family = AF_INET6; memcpy(shared.addr6.sin6_addr.s6_addr, address->shared.addr6.s6_addr, 16); shared.addr6.sin6_port = htons(0); shared.addr6.sin6_flowinfo = 0; shared.addr6.sin6_scope_id = 0; inaddr = (struct sockaddr*)&shared.addr6; addr_len = sizeof(struct sockaddr_in6); break; default: g_assert_not_reached(); return NULL; } str_len = 0; res = WSAAddressToString(inaddr, addr_len, NULL, &dummy, &str_len); g_assert(res != 0); if(WSAGetLastError() != WSAEFAULT) return NULL; retval = g_malloc(str_len); res = WSAAddressToString(inaddr, addr_len, NULL, retval, &str_len); if(res < 0) { g_free(retval); return NULL; } return retval; #else switch(address->family) { case INF_IP_ADDRESS_IPV4: retval = g_malloc(INET_ADDRSTRLEN); inet_ntop(AF_INET, &address->shared.addr4, retval, INET_ADDRSTRLEN); return retval; case INF_IP_ADDRESS_IPV6: retval = g_malloc(INET6_ADDRSTRLEN); inet_ntop(AF_INET6, &address->shared.addr6, retval, INET6_ADDRSTRLEN); return retval; default: g_assert_not_reached(); return NULL; } #endif } /** * inf_ip_address_collate: * @address1: First address. * @address2: Second address. * * Compares the two addresses for sorting. * * Returns: -1 if @address1 compares before, 0 if it compares equal or * 1 if it compares after @address. **/ int inf_ip_address_collate(const InfIpAddress* address1, const InfIpAddress* address2) { if(address1->family != address2->family) { /* IPv4 compares before IPv6 */ if(address1->family == INF_IP_ADDRESS_IPV4) return -1; else return 1; } else { if(address1->family == INF_IP_ADDRESS_IPV4) { return memcmp( &address1->shared.addr4, &address2->shared.addr4, sizeof(struct in_addr) ); } else { return memcmp( &address1->shared.addr6, &address2->shared.addr6, sizeof(struct in6_addr) ); } } } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-async-operation.c0000644000000000000000000000013213034342512023441 xustar0030 mtime=1483851082.029718427 30 atime=1483851082.029718427 30 ctime=1488261589.036138987 libinfinity-0.7.1/libinfinity/common/inf-async-operation.c0000644000175000017500000002061213034342512024174 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-async-operation * @title: InfAsyncOperation * @short_description: Perform long-running operations in a separate thread * @include: libinfinity/inf-async-operation.h * @stability: Unstable * * #InfAsyncOperation is a simple mechanism to run some code in a separate * worker thread and then, once the result is computed, notify the main thread * about the result. **/ #include #include struct _InfAsyncOperation { InfIo* io; InfIoDispatch* dispatch; GThread* thread; GMutex mutex; InfAsyncOperationRunFunc run_func; InfAsyncOperationDoneFunc done_func; gpointer user_data; gpointer run_data; GDestroyNotify run_notify; }; static void inf_async_operation_dispatch(gpointer data) { InfAsyncOperation* op; op = (InfAsyncOperation*)data; g_mutex_lock(&op->mutex); op->dispatch = NULL; g_mutex_unlock(&op->mutex); if(op->done_func != NULL) op->done_func(op->run_data, op->user_data); if(op->run_notify != NULL) op->run_notify(op->run_data); op->run_data = NULL; op->run_notify = NULL; op->thread = NULL; g_mutex_clear(&op->mutex); inf_async_operation_free(op); } static gpointer inf_async_operation_thread_start(gpointer data) { InfAsyncOperation* op; op = (InfAsyncOperation*)data; op->run_func(&op->run_data, &op->run_notify, op->user_data); g_mutex_lock(&op->mutex); g_assert(op->dispatch == NULL); if(op->io != NULL) { op->dispatch = inf_io_add_dispatch( op->io, inf_async_operation_dispatch, op, NULL ); g_mutex_unlock(&op->mutex); } else { if(op->run_notify != NULL) op->run_notify(op->run_data); g_mutex_unlock(&op->mutex); g_mutex_clear(&op->mutex); g_thread_unref(op->thread); g_slice_free(InfAsyncOperation, op); } return NULL; } static void inf_async_operation_io_unref_func(gpointer user_data, GObject* where_the_object_was) { g_error( "%s", _("InfIo object was deleted without InfAsyncOperation being freed! " "This is a programming error that leaves the program in an " "inconsistent state. Therefore, the program is aborted. Please " "fix your code.") ); g_assert_not_reached(); } /** * inf_async_operation_new: * @io: The #InfIo object used to pass back the result of the operation. * @run_func: (scope async): A function to run asynchronously in a worker * thread, computing the result of the operation. * @done_func: (scope async): A function to be called in the thread of @io * once the result is available. * @user_data: Additional user data to pass to both functions. * * This function creates a new #InfAsyncOperation. The function given by * @run_func will be run asynchronously in a worker thread. Once the function * finishes, its result is passed back to the main thread defined by @io, and * @done_func is called with the computed result in the main thread. * * To actually start the asynchronous operation, call * inf_async_operation_start(). This allows to save the returned value into * a structure before starting the operation, avoiding a potential race * condition if the asynchronous function finishes quickly. * * The asynchronous operation can be canceled by calling * inf_async_operation_free() on the returned #InfAsyncOperation object. * If the operation is not cancelled and after @done_func has been called, * the operation is freed automatically and must not be freed by the caller. * The caller must also keep a reference to @io while the operation is * running. Before dropping your reference to @io, make sure to free the * asynchronous operation. When the last reference to @io is dropped, the * operation is freed automatically, since it cannot pass back its result to * the main thread anymore. * * Returns: (transfer full): A new #InfAsyncOperation. Free with * inf_async_operation_free() to cancel the operation. */ InfAsyncOperation* inf_async_operation_new(InfIo* io, InfAsyncOperationRunFunc run_func, InfAsyncOperationDoneFunc done_func, gpointer user_data) { InfAsyncOperation* op; g_return_val_if_fail(INF_IS_IO(io), NULL); g_return_val_if_fail(run_func != NULL, NULL); g_return_val_if_fail(done_func != NULL, NULL); op = g_slice_new(InfAsyncOperation); op->io = io; op->dispatch = NULL; op->thread = NULL; op->run_func = run_func; op->done_func = done_func; op->user_data = user_data; op->run_data = NULL; op->run_notify = NULL; g_object_weak_ref( G_OBJECT(io), inf_async_operation_io_unref_func, op ); return op; } /** * inf_async_operation_start: * @op: (transfer full): A #InfAsyncOperation. * @error: Location to store error information, if any. * * Starts the operation given in @op. The operation must have been created * before with inf_async_operation_new(). If the operation cannot be started, * @error is set and %FALSE is returned. In that case, the operation must not * be used anymore since it will be automatically freed. * * Returns: %TRUE on success or %FALSE if the operation could not be started. */ gboolean inf_async_operation_start(InfAsyncOperation* op, GError** error) { g_return_val_if_fail(op != NULL, FALSE); g_return_val_if_fail(op->thread == NULL, FALSE); g_mutex_init(&op->mutex); g_mutex_lock(&op->mutex); op->thread = g_thread_try_new( "InfAsyncOperation", inf_async_operation_thread_start, op, error ); if(op->thread == NULL) { g_mutex_unlock(&op->mutex); g_mutex_clear(&op->mutex); inf_async_operation_free(op); return FALSE; } g_mutex_unlock(&op->mutex); return TRUE; } /** * inf_async_operation_free: * @op: A #InfAsyncOperation. * * Frees the given asynchronous operation and cancels it if it is currently * running. This should only be called to cancel a running operation, or to * free an operation that has not been started. In all other cases, the * operation is freed automatically. */ void inf_async_operation_free(InfAsyncOperation* op) { g_return_if_fail(op != NULL); if(op->thread == NULL) { /* The async operation has not started yet, * or it has finished (dispatched) already. */ g_assert(op->io != NULL); g_object_weak_unref( G_OBJECT(op->io), inf_async_operation_io_unref_func, op ); g_slice_free(InfAsyncOperation, op); } else { g_mutex_lock(&op->mutex); g_assert(op->io != NULL); if(op->dispatch == NULL) { /* We have not dispatched yet, i.e. the worker thread is still running. * We keep the object alive, but remove the IO object, so that the * worker thread does not attempt to dispatch. This also allows to * unreference the IO object from this point onwards. The operation * object is deleted when the thread finishes. */ g_object_weak_unref( G_OBJECT(op->io), inf_async_operation_io_unref_func, op ); op->io = NULL; g_mutex_unlock(&op->mutex); } else { /* The dispatch has been set, i.e. the worker thread has finished, but * the main thread has not yet executed the dispatch function. We * cancel the dispatch and delete the operation object. */ inf_io_remove_dispatch(op->io, op->dispatch); if(op->run_notify != NULL) op->run_notify(op->run_data); g_mutex_unlock(&op->mutex); g_mutex_clear(&op->mutex); g_thread_unref(op->thread); g_slice_free(InfAsyncOperation, op); } } } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-certificate-credentials.c0000644000000000000000000000013213034342512025103 xustar0030 mtime=1483851082.029718427 30 atime=1483851082.029718427 30 ctime=1488261589.044138969 libinfinity-0.7.1/libinfinity/common/inf-certificate-credentials.c0000644000175000017500000000661313034342512025643 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-certificate-credentials * @title: InfCertificateCredentials * @short_description: Reference-counted wrapper for * #gnutls_certificate_credentials_t * @include: libinfinity/common/inf-certificate-credentials.h * @stability: Unstable * * This is a thin wrapper class for #gnutls_certificate_credentials_t. It * provides reference counting and a boxed GType for it. **/ #include G_DEFINE_BOXED_TYPE(InfCertificateCredentials, inf_certificate_credentials, inf_certificate_credentials_ref, inf_certificate_credentials_unref) struct _InfCertificateCredentials { guint ref_count; gnutls_certificate_credentials_t creds; }; /** * inf_certificate_credentials_new: * * Creates a new #InfCertificateCredentials with an initial reference count * of 1. Use inf_certificate_credentials_get() to access the underlying * #gnutls_certificate_credentials_t. * * Returns: A new #InfCertificateCredentials. Free with * inf_certificate_credentials_unref() when no longer needed. */ InfCertificateCredentials* inf_certificate_credentials_new(void) { InfCertificateCredentials* creds; creds = g_slice_new(InfCertificateCredentials); creds->ref_count = 1; gnutls_certificate_allocate_credentials(&creds->creds); return creds; } /** * inf_certificate_credentials_ref: * @creds: A #InfCertificateCredentials. * * Increases the reference count of @creds by 1. * * Returns: The passed #InfCertificateCredentials, @creds. */ InfCertificateCredentials* inf_certificate_credentials_ref(InfCertificateCredentials* creds) { g_return_val_if_fail(creds != NULL, NULL); ++creds->ref_count; return creds; } /** * inf_certificate_credentials_unref: * @creds: A #InfCertificateCredentials. * * Decreases the reference count of @creds by 1. If its reference count * reaches 0, then the #InfCertificateCredentials will be freed. */ void inf_certificate_credentials_unref(InfCertificateCredentials* creds) { g_return_if_fail(creds != NULL); if(!--creds->ref_count) { gnutls_certificate_free_credentials(creds->creds); g_slice_free(InfCertificateCredentials, creds); } } /** * inf_certificate_credentials_get: * @creds: A #InfCertificateCredentials. * * Provides access to the @creds' underlying * #gnutls_certificate_credentials_t. * * Returns: @creds' #gnutls_certificate_credentials_t. */ gnutls_certificate_credentials_t inf_certificate_credentials_get(InfCertificateCredentials* creds) { g_return_val_if_fail(creds != NULL, NULL); return creds->creds; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-io.c0000644000000000000000000000013213034342512020735 xustar0030 mtime=1483851082.033718448 30 atime=1483851082.033718448 30 ctime=1488261589.060138934 libinfinity-0.7.1/libinfinity/common/inf-io.c0000644000175000017500000002227413034342512021476 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-io * @title: InfIo * @short_description: Event loop abstraction * @include: libinfinity/common/inf-io.h * @see_also: #InfStandaloneIo * @stability: Unstable * * The #InfIo interface is used to schedule timeouts and to watch sockets for * events to occur. An actual implementation usually integrates this into the * application main loop, such as #GMainLoop. There is also a standalone * implementation, #InfStandaloneIo, that can directly be used as the * application's main loop. * * Every object in Libinfinity that needs to schedule timeouts or watches * sockets uses a InfIo to do so. This allows to use libinfinity with * different main event loops, not only Glib's one. * * #InfIo is guaranteed to be thread-safe. All functions can be called from * any thread at any time. However, all callback functions are always called * from the same thread (normally the one running the main loop). **/ #include #include typedef struct _InfIoWatchUnix InfIoWatchUnix; struct _InfIoWatchUnix { InfNativeSocket socket; gpointer user_data; GDestroyNotify notify; }; static const GFlagsValue inf_io_event_values[] = { { INF_IO_INCOMING, "INF_IO_INCOMING", "incoming" }, { INF_IO_OUTGOING, "INF_IO_OUTGOING", "outgoing" }, { INF_IO_ERROR, "INF_IO_ERROR", "error" }, { 0, NULL, NULL } }; INF_DEFINE_FLAGS_TYPE(InfIoEvent, inf_io_event, inf_io_event_values) G_DEFINE_INTERFACE(InfIo, inf_io, G_TYPE_OBJECT) static void inf_io_watch_unix_free(gpointer data) { InfIoWatchUnix* unixwatch; unixwatch = (InfIoWatchUnix*)data; unixwatch->notify(unixwatch->user_data); g_slice_free(InfIoWatchUnix, unixwatch); } static void inf_io_default_init(InfIoInterface* iface) { } /** * inf_io_add_watch: * @io: A #InfIo. * @socket: The socket to watch. * @events: Events to watch for. * @func: Function to be called when one of the events occurs. * @user_data: Extra data to pass to @func. * @notify: A #GDestroyNotify that is called when @user_data is no longer * needed, or %NULL. * * Monitors the given socket for activity and calls @func if one of the * events specified in @events occurs. * * Returns: (transfer none): A #InfIoWatch that can be used to update or * remove the watch. **/ InfIoWatch* inf_io_add_watch(InfIo* io, InfNativeSocket* socket, InfIoEvent events, InfIoWatchFunc func, gpointer user_data, GDestroyNotify notify) { InfIoInterface* iface; g_return_val_if_fail(INF_IS_IO(io), NULL); g_return_val_if_fail(socket != NULL, NULL); g_return_val_if_fail(func != NULL, NULL); iface = INF_IO_GET_IFACE(io); g_return_val_if_fail(iface->add_watch != NULL, NULL); return iface->add_watch(io, socket, events, func, user_data, notify); } #ifdef G_OS_UNIX /** * inf_io_add_watch_from_fd: * @io: A #InfIo. * @fd: The file descriptor to watch. * @events: Events to watch for. * @func: Function to be called when one of the events occurs. * @user_data: Extra data to pass to @func. * @notify: A #GDestroyNotify that is called when @user_data is no longer * needed, or %NULL. * * Monitors the given file descriptor for activity and calls @func if one of * the events specified in @events occurs. This is equivalent to * inf_io_add_watch() for a socket that represents the given file descriptor, * but takes care of the memory management of the file descriptor. This * function is especially intended for language bindings. It is only available * on unix-like operating systems. * * Returns: (transfer none): A #InfIoWatch that can be used to update or * remove the watch. **/ InfIoWatch* inf_io_add_watch_from_fd(InfIo* io, int fd, InfIoEvent events, InfIoWatchFunc func, gpointer user_data, GDestroyNotify notify) { InfIoWatchUnix* watch; watch = g_slice_new(InfIoWatchUnix); watch->socket = fd; watch->user_data = user_data; watch->notify = notify; return inf_io_add_watch( io, &watch->socket, events, func, watch, inf_io_watch_unix_free ); } #endif /** * inf_io_update_watch: * @io: A #InfIo. * @watch: The watch to update, as returned by inf_io_add_watch(). * @events: The new events to watch for. * * Changes the events that the socket bound to @watch is being watched for. * The callback of @watch will only be called if one of the newly watched for * events occurs. */ void inf_io_update_watch(InfIo* io, InfIoWatch* watch, InfIoEvent events) { InfIoInterface* iface; g_return_if_fail(INF_IS_IO(io)); g_return_if_fail(watch != NULL); iface = INF_IO_GET_IFACE(io); g_return_if_fail(iface->update_watch != NULL); iface->update_watch(io, watch, events); } /** * inf_io_remove_watch: * @io: A #InfIo. * @watch: The watch to remove, as returned by inf_io_add_watch(). * * Removes @watch from @io and releases all resources allocated for the watch. * Events are no longer looked for on the socket. */ void inf_io_remove_watch(InfIo* io, InfIoWatch* watch) { InfIoInterface* iface; g_return_if_fail(INF_IS_IO(io)); g_return_if_fail(watch != NULL); iface = INF_IO_GET_IFACE(io); g_return_if_fail(iface->remove_watch != NULL); iface->remove_watch(io, watch); } /** * inf_io_add_timeout: * @io: A #InfIo. * @msecs: Number of milliseconds after which the timeout should be elapsed. * @func: Function to be called when the timeout elapsed. * @user_data: Extra data to pass to @func. * @notify: A #GDestroyNotify that is called when @user_data is no longer * needed, or %NULL. * * Calls @func after at least @msecs milliseconds have elapsed. The timeout * is removed after it has elapsed. * * Returns: (transfer none): A timeout handle that can be used to remove * the timeout. **/ InfIoTimeout* inf_io_add_timeout(InfIo* io, guint msecs, InfIoTimeoutFunc func, gpointer user_data, GDestroyNotify notify) { InfIoInterface* iface; g_return_val_if_fail(INF_IS_IO(io), NULL); g_return_val_if_fail(func != NULL, NULL); iface = INF_IO_GET_IFACE(io); g_return_val_if_fail(iface->add_timeout != NULL, NULL); return iface->add_timeout(io, msecs, func, user_data, notify); } /** * inf_io_remove_timeout: * @io: A #InfIo. * @timeout: A timeout handle obtained from inf_io_add_timeout(). * * Removes the given timeout. **/ void inf_io_remove_timeout(InfIo* io, InfIoTimeout* timeout) { InfIoInterface* iface; g_return_if_fail(INF_IS_IO(io)); g_return_if_fail(timeout != NULL); iface = INF_IO_GET_IFACE(io); g_return_if_fail(iface->remove_timeout != NULL); iface->remove_timeout(io, timeout); } /** * inf_io_add_dispatch: * @io: A #InfIo. * @func: Function to be called when the function is dispatched. * @user_data: Extra data to pass to @func. * @notify: A #GDestroyNotify that is called when @user_data is no longer * needed, or %NULL. * * Schedules @func to be called by the thread @io runs in. This function can * be used from a different thread to communicate to @io's thread. * * Returns: (transfer none): A dispatch handle that can be used to stop the * dispatched function from being called as long as it has not yet been called. **/ InfIoDispatch* inf_io_add_dispatch(InfIo* io, InfIoDispatchFunc func, gpointer user_data, GDestroyNotify notify) { InfIoInterface* iface; g_return_val_if_fail(INF_IS_IO(io), NULL); g_return_val_if_fail(func != NULL, NULL); iface = INF_IO_GET_IFACE(io); g_return_val_if_fail(iface->add_dispatch != NULL, NULL); return iface->add_dispatch(io, func, user_data, notify); } /** * inf_io_remove_dispatch: * @io: A #InfIo. * @dispatch: A dispatch handle obtained from inf_io_add_dispatch(). * * Removes the given dispatch from @io so that it is not called. **/ void inf_io_remove_dispatch(InfIo* io, InfIoDispatch* dispatch) { InfIoInterface* iface; g_return_if_fail(INF_IS_IO(io)); g_return_if_fail(dispatch != NULL); iface = INF_IO_GET_IFACE(io); g_return_if_fail(iface->remove_dispatch != NULL); iface->remove_dispatch(io, dispatch); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-io.h0000644000000000000000000000013213034342512020742 xustar0030 mtime=1483851082.033718448 30 atime=1483851082.033718448 30 ctime=1488261588.948139179 libinfinity-0.7.1/libinfinity/common/inf-io.h0000644000175000017500000001633213034342512021501 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_IO_H__ #define __INF_IO_H__ #include #include G_BEGIN_DECLS #define INF_TYPE_IO (inf_io_get_type()) #define INF_IO(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_TYPE_IO, InfIo)) #define INF_IS_IO(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_TYPE_IO)) #define INF_IO_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), INF_TYPE_IO, InfIoInterface)) #define INF_TYPE_IO_EVENT (inf_io_event_get_type()) /** * InfIo: * * #InfIo is an opaque data type. You should only access it via the public * API functions. */ typedef struct _InfIo InfIo; typedef struct _InfIoInterface InfIoInterface; /** * InfIoWatch: * * #InfIoWatch represents a watch on a #InfNativeSocket for events to occur. * It is an opaque data type. You should only access it via the public * API functions. */ typedef struct _InfIoWatch InfIoWatch; /** * InfIoTimeout: * * #InfIoTimeout represents a timer which will call a specified function in * the future. It is an opaque data type. You should only access it via the * public API functions. */ typedef struct _InfIoTimeout InfIoTimeout; /** * InfIoDispatch: * * #InfIoDispatch represents a function to be called by the thread executing * the #InfIo object. It is an opaque data type. You should only access it * via the public API functions. */ typedef struct _InfIoDispatch InfIoDispatch; /** * InfIoEvent: * @INF_IO_INCOMING: Data can be read from the socket without blocking, or * the connection has been closed (which is the case when recv() returns 0). * @INF_IO_OUTGOING: Data can be sent without blocking. * @INF_IO_ERROR: An error with the socket occured, or the connection has * been closed. Use getsockopt() to read the %SO_ERROR option to find out what * the problem is. * * This enumeration specifies events that can be watched. */ typedef enum _InfIoEvent { INF_IO_INCOMING = 1 << 0, INF_IO_OUTGOING = 1 << 1, INF_IO_ERROR = 1 << 2 } InfIoEvent; /** * InfIoWatchFunc: * @socket: (array fixed-size=1): The socket on which an event occured. * @event: A bitmask of the events that occured. * @user_data: User-defined data specified in inf_io_add_watch(). * * Callback function that is called when an event occurs on a watched socket. */ typedef void(*InfIoWatchFunc)(InfNativeSocket* socket, InfIoEvent event, gpointer user_data); /** * InfIoTimeoutFunc: * @user_data: User-defined data specified in inf_io_add_timeout(). * * Callback function that is called when a timeout has elapsed. */ typedef void(*InfIoTimeoutFunc)(gpointer user_data); /** * InfIoDispatchFunc: * @user_data: User-defined data specified in inf_io_add_dispatch(). * * Callback function that is called when a dispatch is executed by the thread * that runs #InfIo. */ typedef void(*InfIoDispatchFunc)(gpointer user_data); /** * InfIoInterface: * @add_watch: Watches a socket for events to occur in which case @func is * called. * @update_watch: Updates a watch on a socket so that a different set of * events is watched for. * @remove_watch: Removes a watch on a socket. * @add_timeout: Schedules @func to be called at least @msecs milliseconds * in the future. * @remove_timeout: Removes a scheduled timeout again. The timeout is * removed automatically when it has elapsed, so there is no need to call * this function in that case. * @add_dispatch: Schedules @func to be called by the thread the #InfIo * runs in. * @remove_dispatch: Removes a scheduled dispatch. This can be called as long * as the scheduled function has not yet been called. * * The virtual methods of #InfIo. These allow to set up socket watches, * timeouts and function dispatchers. All of these functions need to be * thread-safe. */ struct _InfIoInterface { /*< private >*/ GTypeInterface parent; /*< public >*/ InfIoWatch* (*add_watch)(InfIo* io, InfNativeSocket* socket, InfIoEvent events, InfIoWatchFunc func, gpointer user_data, GDestroyNotify notify); void (*update_watch)(InfIo* io, InfIoWatch* watch, InfIoEvent events); void (*remove_watch)(InfIo* io, InfIoWatch* watch); InfIoTimeout* (*add_timeout)(InfIo* io, guint msecs, InfIoTimeoutFunc func, gpointer user_data, GDestroyNotify notify); void (*remove_timeout)(InfIo* io, InfIoTimeout* timeout); InfIoDispatch* (*add_dispatch)(InfIo* io, InfIoDispatchFunc func, gpointer user_data, GDestroyNotify notify); void (*remove_dispatch)(InfIo* io, InfIoDispatch* dispatch); }; GType inf_io_event_get_type(void) G_GNUC_CONST; GType inf_io_get_type(void) G_GNUC_CONST; InfIoWatch* inf_io_add_watch(InfIo* io, InfNativeSocket* socket, InfIoEvent events, InfIoWatchFunc func, gpointer user_data, GDestroyNotify notify); #ifdef G_OS_UNIX InfIoWatch* inf_io_add_watch_from_fd(InfIo* io, int fd, InfIoEvent events, InfIoWatchFunc func, gpointer user_data, GDestroyNotify notify); #endif void inf_io_update_watch(InfIo* io, InfIoWatch* watch, InfIoEvent events); void inf_io_remove_watch(InfIo* io, InfIoWatch* watch); InfIoTimeout* inf_io_add_timeout(InfIo* io, guint msecs, InfIoTimeoutFunc func, gpointer user_data, GDestroyNotify notify); void inf_io_remove_timeout(InfIo* io, InfIoTimeout* timeout); InfIoDispatch* inf_io_add_dispatch(InfIo* io, InfIoDispatchFunc func, gpointer user_data, GDestroyNotify notify); void inf_io_remove_dispatch(InfIo* io, InfIoDispatch* dispatch); G_END_DECLS #endif /* __INF_IO_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-session-proxy.h0000644000000000000000000000013213034342512023175 xustar0030 mtime=1483851082.033718448 30 atime=1483851082.033718448 30 ctime=1488261588.964139144 libinfinity-0.7.1/libinfinity/common/inf-session-proxy.h0000644000175000017500000000531313034342512023731 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_SESSION_PROXY_H__ #define __INF_SESSION_PROXY_H__ #include #include #include G_BEGIN_DECLS #define INF_TYPE_SESSION_PROXY (inf_session_proxy_get_type()) #define INF_SESSION_PROXY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_TYPE_SESSION_PROXY, InfSessionProxy)) #define INF_IS_SESSION_PROXY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_TYPE_SESSION_PROXY)) #define INF_SESSION_PROXY_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), INF_TYPE_SESSION_PROXY, InfSessionProxyInterface)) #define INF_TYPE_SESSION_PROXY_STATUS (inf_session_proxy_status_get_type()) /** * InfSessionProxy: * * #InfSessionProxy is an opaque data type. You should only access it * via the public API functions. */ typedef struct _InfSessionProxy InfSessionProxy; typedef struct _InfSessionProxyInterface InfSessionProxyInterface; /** * InfSessionProxyInterface: * @join_user: Virtual function to join a user into the proxy's session. * * Virtual functions for the #InfSessionProxy interface. */ struct _InfSessionProxyInterface { /*< private >*/ GTypeInterface parent; /* Signals */ /*< public >*/ InfRequest* (*join_user)(InfSessionProxy* proxy, guint n_params, const GParameter* params, InfRequestFunc func, gpointer user_data); }; GType inf_session_proxy_get_type(void) G_GNUC_CONST; InfRequest* inf_session_proxy_join_user(InfSessionProxy* proxy, guint n_params, const GParameter* params, InfRequestFunc func, gpointer user_data); G_END_DECLS #endif /* __INF_SESSION_PROXY_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-standalone-io.c0000644000000000000000000000013013034342512023061 xustar0029 mtime=1483851082.03771847 30 atime=1483851082.033718448 29 ctime=1488261589.08013889 libinfinity-0.7.1/libinfinity/common/inf-standalone-io.c0000644000175000017500000010014513034342512023616 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-standalone-io * @title: InfStandaloneIo * @short_description: Simple event loop implementation * @include: libinfinity/common/inf-standalone-io.h * @see_also: #InfIo * @stability: Unstable * * #InfStandaloneIo is a simple implementation of the #InfIo interface. It * implements a basic application event loop with support for listening on * sockets, scheduling timeouts and inter-thread notifications. The class * is fully thread-safe. * * This class can be perfectly used for all functions in libinfinity that * require a #InfIo object to wait for events. If, on top of that more * functionality is required, or the main loop needs to be integrated with * another library such as a UI toolkit, a custom class should be created * instead which implements the #InfIo interface. For the GTK+ toolkit, there * is #InfGtkIo in the libinfgtk library, to integrate with the Glib main * loop. */ #include #include /* TODO: Modularize the FD handling, then add epoll support */ #ifdef G_OS_WIN32 # include #else # include # include # include #endif /* !G_OS_WIN32 */ #include #ifdef G_OS_WIN32 typedef WSAEVENT InfStandaloneIoNativeEvent; typedef DWORD InfStandaloneIoPollTimeout; typedef DWORD InfStandaloneIoPollResult; static const InfStandaloneIoPollResult INF_STANDALONE_IO_POLL_TIMEOUT = WSA_WAIT_TIMEOUT; static const InfStandaloneIoPollTimeout INF_STANDALONE_IO_POLL_INFINITE = WSA_INFINITE; #define inf_standalone_io_poll(events, num_events, timeout) \ ((num_events) == 0 ? \ (Sleep(timeout), WSA_WAIT_TIMEOUT) : \ (WSAWaitForMultipleEvents(num_events, events, FALSE, timeout, TRUE))) #else typedef struct pollfd InfStandaloneIoNativeEvent; typedef int InfStandaloneIoPollTimeout; typedef int InfStandaloneIoPollResult; static const InfStandaloneIoPollResult INF_STANDALONE_IO_POLL_TIMEOUT = 0; static const InfStandaloneIoPollTimeout INF_STANDALONE_IO_POLL_INFINITE = -1; #define inf_standalone_io_poll(events, num_events, timeout) \ (poll(events, (nfds_t)num_events, timeout)) #endif struct _InfIoWatch { /* TODO: Do we actually need this? We can access the event by * priv->events[watchindex+1]. */ InfStandaloneIoNativeEvent* event; InfNativeSocket* socket; InfIoWatchFunc func; gpointer user_data; GDestroyNotify notify; /* Protection flags to avoid freeing the watch object when running * the callback */ gboolean executing; gboolean disposed; }; struct _InfIoTimeout { GTimeVal begin; guint msecs; InfIoTimeoutFunc func; gpointer user_data; GDestroyNotify notify; }; struct _InfIoDispatch { InfIoDispatchFunc func; gpointer user_data; GDestroyNotify notify; }; typedef struct _InfStandaloneIoPrivate InfStandaloneIoPrivate; struct _InfStandaloneIoPrivate { InfStandaloneIoNativeEvent* events; GMutex mutex; guint fd_size; guint fd_alloc; /* this array has fd_size-1 entries and fd_alloc-1 allocations: */ InfIoWatch** watches; GList* timeouts; GList* dispatchs; #ifndef G_OS_WIN32 int wakeup_pipe[2]; #endif gboolean polling; gboolean loop_running; }; #ifdef G_OS_WIN32 /* Mapping between WSAEventSelect's FD_ flags and libinfinity's * INF_IO flags */ typedef struct _InfStandaloneIoEventTableEntry InfStandaloneIoEventTableEntry; struct _InfStandaloneIoEventTableEntry { guint flag_val; guint flag_bit; guint io_val; }; static const InfStandaloneIoEventTableEntry inf_standalone_io_event_table[] = { { FD_READ, FD_READ_BIT, INF_IO_INCOMING }, { FD_CLOSE, FD_CLOSE_BIT, INF_IO_INCOMING }, { FD_ACCEPT, FD_ACCEPT_BIT, INF_IO_INCOMING }, { FD_WRITE, FD_WRITE_BIT, INF_IO_OUTGOING }, { FD_CONNECT, FD_CONNECT_BIT, INF_IO_OUTGOING } }; #endif #define INF_STANDALONE_IO_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INF_TYPE_STANDALONE_IO, InfStandaloneIoPrivate)) static void inf_standalone_io_io_iface_init(InfIoInterface* iface); G_DEFINE_TYPE_WITH_CODE(InfStandaloneIo, inf_standalone_io, G_TYPE_OBJECT, G_ADD_PRIVATE(InfStandaloneIo) G_IMPLEMENT_INTERFACE(INF_TYPE_IO, inf_standalone_io_io_iface_init)) static guint inf_standalone_io_timeval_diff(GTimeVal* first, GTimeVal* second) { g_assert(first->tv_sec > second->tv_sec || (first->tv_sec == second->tv_sec && first->tv_usec >= second->tv_usec)); /* Don't risk overflow, don't need to convert to signed int */ return (first->tv_sec - second->tv_sec) * 1000 + (first->tv_usec+500)/1000 - (second->tv_usec+500)/1000; } /* Run one iteration of the main loop. Call this only with the mutex locked * and a local reference added to io. */ static void inf_standalone_io_iteration_impl(InfStandaloneIo* io, InfStandaloneIoPollTimeout timeout) { InfStandaloneIoPrivate* priv; InfIoEvent events; InfStandaloneIoPollResult result; guint i; GList* item; GTimeVal current; InfIoWatch* watch; InfIoTimeout* cur_timeout; InfIoDispatch* dispatch; guint elapsed; #ifdef G_OS_WIN32 gchar* error_message; WSANETWORKEVENTS wsa_events; const InfStandaloneIoEventTableEntry* entry; #else ssize_t ret; char buf[1]; #endif priv = INF_STANDALONE_IO_PRIVATE(io); /* Find number of milliseconds to wait */ if(priv->dispatchs != NULL) { /* TODO: Don't even poll */ timeout = 0; } else { g_get_current_time(¤t); for(item = priv->timeouts; item != NULL; item = g_list_next(item)) { cur_timeout = (InfIoTimeout*)item->data; elapsed = inf_standalone_io_timeval_diff(¤t, &cur_timeout->begin); if(elapsed >= cur_timeout->msecs) { /* already elapsed */ /* TODO: Don't even poll */ timeout = 0; /* no need to check other timeouts */ break; } else { if(timeout == INF_STANDALONE_IO_POLL_INFINITE || cur_timeout->msecs - elapsed < (guint)timeout) { timeout = cur_timeout->msecs - elapsed; } } } } priv->polling = TRUE; g_mutex_unlock(&priv->mutex); result = inf_standalone_io_poll(priv->events, priv->fd_size, timeout); g_mutex_lock(&priv->mutex); priv->polling = FALSE; #ifdef G_OS_WIN32 switch(result) { case WSA_WAIT_FAILED: error_message = g_win32_error_message(WSAGetLastError()); g_warning("WSAWaitForMultipleEvents() failed: %s\n", error_message); g_free(error_message); return; case WSA_WAIT_IO_COMPLETION: return; default: break; } #else if(result == -1) { if(errno != EINTR) g_warning("poll() failed: %s\n", strerror(errno)); return; } #endif if(result == INF_STANDALONE_IO_POLL_TIMEOUT) { /* No file descriptor is active, so check whether a timeout elapsed */ g_get_current_time(¤t); for(item = priv->timeouts; item != NULL; item = g_list_next(item)) { cur_timeout = (InfIoTimeout*)item->data; elapsed = inf_standalone_io_timeval_diff(¤t, &cur_timeout->begin); if(elapsed >= cur_timeout->msecs) { priv->timeouts = g_list_delete_link(priv->timeouts, item); g_mutex_unlock(&priv->mutex); cur_timeout->func(cur_timeout->user_data); if(cur_timeout->notify) cur_timeout->notify(cur_timeout->user_data); g_slice_free(InfIoTimeout, cur_timeout); g_mutex_lock(&priv->mutex); return; } } } #ifdef G_OS_WIN32 else if(result >= WSA_WAIT_EVENT_0 && result < WSA_WAIT_EVENT_0 + priv->fd_size) { if(result == WSA_WAIT_EVENT_0) { /* wakeup call */ WSAResetEvent(priv->events[0]); } else { watch = priv->watches[result - WSA_WAIT_EVENT_0 - 1]; if(WSAEnumNetworkEvents(*watch->socket, *watch->event, &wsa_events) == SOCKET_ERROR) { error_message = g_win32_error_message(WSAGetLastError()); g_warning("WSAEnumNetworkEvents failed: %s\n", error_message); g_free(error_message); events = INF_IO_ERROR; } else { events = 0; for(i = 0; i < G_N_ELEMENTS(inf_standalone_io_event_table); ++ i) { entry = &inf_standalone_io_event_table[i]; if(wsa_events.lNetworkEvents & entry->flag_val) { events |= entry->io_val; if(wsa_events.iErrorCode[entry->flag_bit]) events |= INF_IO_ERROR; } } } /* protect from removing the watch object via * inf_io_remove_watch() when running the callback. */ watch->executing = TRUE; g_mutex_unlock(&priv->mutex); watch->func(watch->socket, events, watch->user_data); g_mutex_lock(&priv->mutex); watch->executing = FALSE; if(watch->disposed == TRUE) { g_mutex_unlock(&priv->mutex); if(watch->notify) watch->notify(watch->user_data); g_slice_free(InfIoWatch, watch); g_mutex_lock(&priv->mutex); } return; } } #else else if(result > 0) { while(result--) { for(i = 0; i < priv->fd_size; ++ i) { if(priv->events[i].revents != 0) { events = 0; if(priv->events[i].revents & POLLIN) events |= INF_IO_INCOMING; if(priv->events[i].revents & POLLOUT) events |= INF_IO_OUTGOING; /* We treat POLLPRI as error because it should not occur in * infinote. */ if(priv->events[i].revents & (POLLERR | POLLPRI | POLLHUP | POLLNVAL)) events |= INF_IO_ERROR; priv->events[i].revents = 0; if(i == 0) { /* wakeup call */ /* we were not polling for outgoing */ g_assert(~events & INF_IO_OUTGOING); if(events & INF_IO_ERROR) { /* TODO: Read error from FD? */ g_warning("Error condition on wakeup pipe"); /* TODO: Is there anything we could do here? * Try to re-establish pipe? */ } else { ret = read(priv->events[0].fd, &buf, 1); if(ret == -1) { g_warning( "read() on wakeup pipe failed: %s", strerror(errno) ); /* TODO: Is there anything we could do here? * Try to re-establish pipe? */ } else if(ret == 0) { g_warning("Wakeup pipe received EOF"); /* TODO: Is there anything we could do here? * Try to re-establish pipe? */ } else { /* this is what we send as wakeup call */ g_assert(buf[0] == 'c'); } } } else { watch = priv->watches[i-1]; /* protect from removing the watch object via * inf_io_remove_watch() when running the callback. */ watch->executing = TRUE; g_mutex_unlock(&priv->mutex); watch->func(watch->socket, events, watch->user_data); g_mutex_lock(&priv->mutex); watch->executing = FALSE; if(watch->disposed == TRUE) { g_mutex_unlock(&priv->mutex); if(watch->notify) watch->notify(watch->user_data); g_slice_free(InfIoWatch, watch); g_mutex_lock(&priv->mutex); } return; } } } } } #endif /* neither timeout nor IO fired, so try a dispatched message */ if(priv->dispatchs != NULL) { dispatch = (InfIoDispatch*)priv->dispatchs->data; priv->dispatchs = g_list_delete_link(priv->dispatchs, priv->dispatchs); g_mutex_unlock(&priv->mutex); dispatch->func(dispatch->user_data); if(dispatch->notify) dispatch->notify(dispatch->user_data); g_slice_free(InfIoDispatch, dispatch); g_mutex_lock(&priv->mutex); } } static void inf_standalone_io_init(InfStandaloneIo* io) { InfStandaloneIoPrivate* priv; #ifdef G_OS_WIN32 gchar* error_message; #endif priv = INF_STANDALONE_IO_PRIVATE(io); g_mutex_init(&priv->mutex); priv->fd_size = 0; priv->fd_alloc = 4; priv->events = g_malloc(sizeof(InfStandaloneIoNativeEvent) * priv->fd_alloc); #ifdef G_OS_WIN32 priv->events[0] = WSACreateEvent(); if(priv->events[0] == WSA_INVALID_EVENT) { error_message = g_win32_error_message(WSAGetLastError()); g_error("Failed to create wakeup event: %s", error_message); g_free(error_message); /* will not be called since g_error abort()s */ } else { ++priv->fd_size; } #else if(pipe(priv->wakeup_pipe) == -1) { g_error("Failed to create wakeup pipe: %s", strerror(errno)); } else { priv->events[0].fd = priv->wakeup_pipe[0]; priv->events[0].events = POLLIN | POLLERR; priv->events[0].revents = 0; ++priv->fd_size; } #endif priv->watches = g_malloc(sizeof(InfIoWatch*) * (priv->fd_alloc - 1) ); priv->timeouts = NULL; priv->dispatchs = NULL; priv->polling = FALSE; priv->loop_running = FALSE; } static void inf_standalone_io_finalize(GObject* object) { InfStandaloneIo* io; InfStandaloneIoPrivate* priv; guint i; GList* item; InfIoWatch* watch; InfIoTimeout* timeout; InfIoDispatch* dispatch; #ifdef G_OS_WIN32 gchar* error_message; #endif io = INF_STANDALONE_IO(object); priv = INF_STANDALONE_IO_PRIVATE(io); g_mutex_lock(&priv->mutex); for(i = 1; i < priv->fd_size; ++i) { watch = priv->watches[i - 1]; /* cannot dispose the IO while running a callback since the IO is * reffed on the stack. */ g_assert(watch->executing == FALSE); #ifdef G_OS_WIN32 if(WSAEventSelect(*watch->socket, *watch->event, 0) == SOCKET_ERROR) { error_message = g_win32_error_message(WSAGetLastError()); g_warning("WSAEventSelect() failed: %s", error_message); g_free(error_message); } #endif if(watch->notify) watch->notify(watch->user_data); g_slice_free(InfIoWatch, watch); } for(item = priv->timeouts; item != NULL; item = g_list_next(item)) { timeout = (InfIoTimeout*)item->data; if(timeout->notify) timeout->notify(timeout->user_data); g_slice_free(InfIoTimeout, timeout); } for(item = priv->dispatchs; item != NULL; item = g_list_next(item)) { dispatch = (InfIoDispatch*)item->data; if(dispatch->notify) dispatch->notify(dispatch->user_data); g_slice_free(InfIoDispatch, dispatch); } #ifdef G_OS_WIN32 for(i = 0; i < priv->fd_size; ++ i) { if(WSACloseEvent(priv->events[i]) == FALSE) { error_message = g_win32_error_message(WSAGetLastError()); g_warning("WSACloseEvent() failed: %s", error_message); g_free(error_message); } } #endif g_free(priv->events); g_free(priv->watches); g_list_free(priv->timeouts); g_list_free(priv->dispatchs); #ifndef G_OS_WIN32 if(close(priv->wakeup_pipe[0]) == -1) { g_warning( "Failed to close reading end of wakeup pipe: %s", strerror(errno) ); } if(close(priv->wakeup_pipe[1]) == -1) { g_warning( "Failed to close writing end of wakeup pipe: %s", strerror(errno) ); } #endif g_mutex_unlock(&priv->mutex); g_mutex_clear(&priv->mutex); G_OBJECT_CLASS(inf_standalone_io_parent_class)->finalize(object); } static InfIoWatch** inf_standalone_io_find_watch(InfStandaloneIo* io, InfIoWatch* watch) { InfStandaloneIoPrivate* priv; guint i; priv = INF_STANDALONE_IO_PRIVATE(io); for(i = 1; i < priv->fd_size; ++i) if(priv->watches[i-1] == watch) return &priv->watches[i-1]; return NULL; } static InfIoWatch** inf_standalone_io_find_watch_by_socket(InfStandaloneIo* io, InfNativeSocket* socket) { InfStandaloneIoPrivate* priv; guint i; priv = INF_STANDALONE_IO_PRIVATE(io); for(i = 1; i < priv->fd_size; ++i) if(priv->watches[i-1]->socket == socket) return &priv->watches[i-1]; return NULL; } static void inf_standalone_io_wakeup(InfStandaloneIo* io) { /* Wake up the main loop in case it is currently sleeping. This function is * called whenever a watch changes or a timeout or dispatch is added, so * that the new event is taken into account. */ /* Should only ever be called with the IO's mutex being locked. */ /* TODO: Turn this into a noop if called from the same thread the loop * runs in? */ InfStandaloneIoPrivate* priv; #ifndef G_OS_WIN32 char c; ssize_t ret; #else gchar* error_message; #endif priv = INF_STANDALONE_IO_PRIVATE(io); if(priv->polling) { #ifdef G_OS_WIN32 if(WSASetEvent(priv->events[0]) == FALSE) { error_message = g_win32_error_message(WSAGetLastError()); g_warning( "WSASetEvent() failed when attempting to wake up the main loop: %s", error_message ); g_free(error_message); } #else c = 'c'; ret = write(priv->wakeup_pipe[1], &c, 1); if(ret == -1) { g_warning( "write() failed when attempting to wake up the main loop: %s", strerror(errno) ); /* TODO: Is there anything we could do here? * Try to re-establish pipe? */ } else if(ret == 0) { g_warning( "Received EOF from weakup pipe when attempting to wake " "up the main loop" ); /* TODO: Is there anything we could do here? * Try to re-establish pipe? */ } #endif } } static InfIoWatch* inf_standalone_io_io_add_watch(InfIo* io, InfNativeSocket* socket, InfIoEvent events, InfIoWatchFunc func, gpointer user_data, GDestroyNotify notify) { InfStandaloneIoPrivate* priv; InfIoWatch* watch; long pevents; guint i; #ifdef G_OS_WIN32 gchar* error_message; #endif priv = INF_STANDALONE_IO_PRIVATE(io); #ifdef G_OS_WIN32 pevents = 0; if(events & INF_IO_INCOMING) pevents |= (FD_READ | FD_ACCEPT | FD_CLOSE); if(events & INF_IO_OUTGOING) pevents |= (FD_WRITE | FD_CONNECT); #else pevents = 0; if(events & INF_IO_INCOMING) pevents |= POLLIN; if(events & INF_IO_OUTGOING) pevents |= POLLOUT; if(events & INF_IO_ERROR) pevents |= (POLLERR | POLLHUP | POLLNVAL | POLLPRI); #endif g_mutex_lock(&priv->mutex); /* Watching the same socket for different events at least won't work on * Windows since WSAEventSelect cancels the effect of previous * WSAEventSelect calls for the same socket. */ if(inf_standalone_io_find_watch_by_socket(INF_STANDALONE_IO(io), socket)) { g_mutex_unlock(&priv->mutex); return NULL; } /* TODO: If we are currently polling we should not modify the fds array * array but do this after wakeup directly after the poll call. */ /* Socket is not already present, so create new watch */ if(priv->fd_size == priv->fd_alloc) { priv->fd_alloc += 4; priv->events = g_realloc( priv->events, priv->fd_alloc * sizeof(InfStandaloneIoNativeEvent) ); priv->watches = g_realloc( priv->watches, (priv->fd_alloc - 1) * sizeof(InfIoWatch*) ); /* Update event pointers, the location of the events in memory might have * changed after realloc. */ for(i = 1; i < priv->fd_size; ++i) priv->watches[i-1]->event = &priv->events[i]; } #ifdef G_OS_WIN32 priv->events[priv->fd_size] = WSACreateEvent(); if(priv->events[priv->fd_size] == WSA_INVALID_EVENT) { error_message = g_win32_error_message(WSAGetLastError()); g_warning("WSACreateEvent() failed: %s", error_message); g_free(error_message); g_mutex_unlock(&priv->mutex); return NULL; } if(WSAEventSelect(*socket, priv->events[priv->fd_size], pevents) == SOCKET_ERROR) { error_message = g_win32_error_message(WSAGetLastError()); g_warning("WSAEventSelect() failed: %s", error_message); g_free(error_message); WSACloseEvent(priv->events[priv->fd_size]); g_mutex_unlock(&priv->mutex); return NULL; } #else priv->events[priv->fd_size].fd = *socket; priv->events[priv->fd_size].events = pevents; priv->events[priv->fd_size].revents = 0; #endif watch = g_slice_new(InfIoWatch); watch->event = &priv->events[priv->fd_size]; watch->socket = socket; watch->func = func; watch->user_data = user_data; watch->notify = notify; watch->executing = FALSE; watch->disposed = FALSE; priv->watches[priv->fd_size-1] = watch; ++priv->fd_size; inf_standalone_io_wakeup(INF_STANDALONE_IO(io)); g_mutex_unlock(&priv->mutex); return watch; } static void inf_standalone_io_io_update_watch(InfIo* io, InfIoWatch* watch, InfIoEvent events) { InfStandaloneIoPrivate* priv; InfIoWatch** watch_iter; long pevents; #ifdef G_OS_WIN32 gchar* error_message; #endif priv = INF_STANDALONE_IO_PRIVATE(io); #ifdef G_OS_WIN32 pevents = 0; if(events & INF_IO_INCOMING) pevents |= (FD_READ | FD_ACCEPT | FD_CLOSE); if(events & INF_IO_OUTGOING) pevents |= (FD_WRITE | FD_CONNECT); #else pevents = 0; if(events & INF_IO_INCOMING) pevents |= POLLIN; if(events & INF_IO_OUTGOING) pevents |= POLLOUT; if(events & INF_IO_ERROR) pevents |= (POLLERR | POLLHUP | POLLNVAL | POLLPRI); #endif g_mutex_lock(&priv->mutex); watch_iter = inf_standalone_io_find_watch(INF_STANDALONE_IO(io), watch); if(watch_iter != NULL) { /* TODO: If we are currently polling we should not modify the fds array * array but do this after wakeup directly after the poll call. */ /* Update */ #ifdef G_OS_WIN32 if(WSAEventSelect(*watch->socket, *watch->event, pevents) == SOCKET_ERROR) { error_message = g_win32_error_message(WSAGetLastError()); g_warning("WSAEventSelect() failed: %s", error_message); g_free(error_message); } #else watch->event->events = pevents; #endif inf_standalone_io_wakeup(INF_STANDALONE_IO(io)); } g_mutex_unlock(&priv->mutex); } static void inf_standalone_io_io_remove_watch(InfIo* io, InfIoWatch* watch) { InfStandaloneIoPrivate* priv; InfIoWatch** watch_iter; guint index; #ifdef G_OS_WIN32 gchar* error_message; #endif priv = INF_STANDALONE_IO_PRIVATE(io); g_mutex_lock(&priv->mutex); watch_iter = inf_standalone_io_find_watch(INF_STANDALONE_IO(io), watch); if(watch_iter != NULL) { #ifdef G_OS_WIN32 if(WSAEventSelect(*watch->socket, *watch->event, 0) == SOCKET_ERROR) { error_message = g_win32_error_message(WSAGetLastError()); g_warning("WSAEventSelect() failed: %s", error_message); g_free(error_message); } if(WSACloseEvent(*watch->event) == FALSE) { error_message = g_win32_error_message(WSAGetLastError()); g_warning("WSACloseEvent() failed: %s", error_message); g_free(error_message); } #endif /* TODO: If we are currently polling we should not modify the fds array * array but do this after wakeup directly after the poll call. */ if(watch->executing) { /* The callback of the watch is currently running. We don't want to * destroy the user data while it is, so we just remove it from the * watches array, wait for the callback to return and then free the * user_data and the InfIoWatch struct. */ watch->disposed = TRUE; } else { /* Free user_data */ if(watch->notify) watch->notify(watch->user_data); g_slice_free(InfIoWatch, watch); } /* Remove watch by replacing it by the last pollfd/watch */ index = 1 + (watch_iter - priv->watches); if(index != priv->fd_size - 1) { memcpy( &priv->events[index], &priv->events[priv->fd_size - 1], sizeof(InfStandaloneIoNativeEvent) ); memcpy( &priv->watches[index - 1], &priv->watches[priv->fd_size - 2], sizeof(InfIoWatch*) ); priv->watches[index - 1]->event = &priv->events[index]; } --priv->fd_size; inf_standalone_io_wakeup(INF_STANDALONE_IO(io)); } g_mutex_unlock(&priv->mutex); } static InfIoTimeout* inf_standalone_io_io_add_timeout(InfIo* io, guint msecs, InfIoTimeoutFunc func, gpointer user_data, GDestroyNotify notify) { InfStandaloneIoPrivate* priv; InfIoTimeout* timeout; priv = INF_STANDALONE_IO_PRIVATE(io); timeout = g_slice_new(InfIoTimeout); g_get_current_time(&timeout->begin); timeout->msecs = msecs; timeout->func = func; timeout->user_data = user_data; timeout->notify = notify; g_mutex_lock(&priv->mutex); priv->timeouts = g_list_prepend(priv->timeouts, timeout); inf_standalone_io_wakeup(INF_STANDALONE_IO(io)); g_mutex_unlock(&priv->mutex); return timeout; } static void inf_standalone_io_io_remove_timeout(InfIo* io, InfIoTimeout* timeout) { InfStandaloneIoPrivate* priv; GList* item; priv = INF_STANDALONE_IO_PRIVATE(io); g_mutex_lock(&priv->mutex); item = g_list_find(priv->timeouts, timeout); if(item != NULL) { priv->timeouts = g_list_delete_link(priv->timeouts, item); g_mutex_unlock(&priv->mutex); if(timeout->notify) timeout->notify(timeout->user_data); g_slice_free(InfIoTimeout, timeout); /* No need to wake up the main loop; it might run into its timeout sooner * than necessary now, but that's OK. */ } else { g_mutex_unlock(&priv->mutex); } } static InfIoDispatch* inf_standalone_io_io_add_dispatch(InfIo* io, InfIoDispatchFunc func, gpointer user_data, GDestroyNotify notify) { InfStandaloneIoPrivate* priv; InfIoDispatch* dispatch; priv = INF_STANDALONE_IO_PRIVATE(io); dispatch = g_slice_new(InfIoDispatch); dispatch->func = func; dispatch->user_data = user_data; dispatch->notify = notify; g_mutex_lock(&priv->mutex); priv->dispatchs = g_list_prepend(priv->dispatchs, dispatch); inf_standalone_io_wakeup(INF_STANDALONE_IO(io)); g_mutex_unlock(&priv->mutex); return dispatch; } static void inf_standalone_io_io_remove_dispatch(InfIo* io, InfIoDispatch* dispatch) { InfStandaloneIoPrivate* priv; GList* item; priv = INF_STANDALONE_IO_PRIVATE(io); g_mutex_lock(&priv->mutex); item = g_list_find(priv->dispatchs, dispatch); if(item != NULL) { priv->dispatchs = g_list_delete_link(priv->dispatchs, item); g_mutex_unlock(&priv->mutex); if(dispatch->notify) dispatch->notify(dispatch->user_data); g_slice_free(InfIoDispatch, dispatch); /* No need to wake up the main loop; it might run into its timeout sooner * than necessary now, but that's OK. */ } else { g_mutex_unlock(&priv->mutex); } } static void inf_standalone_io_class_init(InfStandaloneIoClass* io_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(io_class); object_class->finalize = inf_standalone_io_finalize; } static void inf_standalone_io_io_iface_init(InfIoInterface* iface) { iface->add_watch = inf_standalone_io_io_add_watch; iface->update_watch = inf_standalone_io_io_update_watch; iface->remove_watch = inf_standalone_io_io_remove_watch; iface->add_timeout = inf_standalone_io_io_add_timeout; iface->remove_timeout = inf_standalone_io_io_remove_timeout; iface->add_dispatch = inf_standalone_io_io_add_dispatch; iface->remove_dispatch = inf_standalone_io_io_remove_dispatch; } /** * inf_standalone_io_new: (constructor) * * Creates a new #InfStandaloneIo. * * Returns: (transfer full): A new #InfStandaloneIo. Free with * g_object_unref() when no longer needed. **/ InfStandaloneIo* inf_standalone_io_new(void) { GObject* object; object = g_object_new(INF_TYPE_STANDALONE_IO, NULL); return INF_STANDALONE_IO(object); } /** * inf_standalone_io_iteration: * @io: A #InfStandaloneIo. * * Performs a single iteration of @io. The call will block until a first * event has occured. Then, it will process that event and return. **/ void inf_standalone_io_iteration(InfStandaloneIo* io) { InfStandaloneIoPrivate* priv; g_return_if_fail(INF_IS_STANDALONE_IO(io)); priv = INF_STANDALONE_IO_PRIVATE(io); g_object_ref(io); g_mutex_lock(&priv->mutex); g_return_val_if_fail(priv->polling == FALSE, g_mutex_unlock(&priv->mutex)); inf_standalone_io_iteration_impl(io, INF_STANDALONE_IO_POLL_INFINITE); g_mutex_unlock(&priv->mutex); g_object_unref(io); } /** * inf_standalone_io_iteration_timeout: * @io: A #InfStandaloneIo. * @timeout: Maximum number of milliseconds to block. * * Performs a single iteration of @io. The call will block until either an * event occured or @timeout milliseconds have elapsed. If an event occured, * the event will be processed before returning. **/ void inf_standalone_io_iteration_timeout(InfStandaloneIo* io, guint timeout) { InfStandaloneIoPrivate* priv; g_return_if_fail(INF_IS_STANDALONE_IO(io)); priv = INF_STANDALONE_IO_PRIVATE(io); g_object_ref(io); g_mutex_lock(&priv->mutex); g_return_val_if_fail(priv->polling == FALSE, g_mutex_unlock(&priv->mutex)); inf_standalone_io_iteration_impl(io, (int)timeout); g_mutex_unlock(&priv->mutex); g_object_unref(io); } /** * inf_standalone_io_loop: * @io: A #InfStandaloneIo. * * This call will cause @io to wait for events and process them, but not * return until inf_standalone_io_loop_quit() is called. **/ void inf_standalone_io_loop(InfStandaloneIo* io) { InfStandaloneIoPrivate* priv; g_return_if_fail(INF_IS_STANDALONE_IO(io)); priv = INF_STANDALONE_IO_PRIVATE(io); g_object_ref(io); g_mutex_lock(&priv->mutex); g_return_val_if_fail( priv->loop_running == FALSE, g_mutex_unlock(&priv->mutex) ); g_return_val_if_fail( priv->polling == FALSE, g_mutex_unlock(&priv->mutex) ); /* TODO: Actually we need to make sure that a previous loop() call in * another thread has exited the loop below, otherwise we will end up with * two loops running one of which is supposed to have quit. */ priv->loop_running = TRUE; while(priv->loop_running == TRUE) inf_standalone_io_iteration_impl(io, -1); g_mutex_unlock(&priv->mutex); g_object_unref(io); } /** * inf_standalone_io_loop_quit: * @io: A #InfStandaloneIo. * * Exits a loop in which @io is running through a call to * inf_standalone_io_loop(). **/ void inf_standalone_io_loop_quit(InfStandaloneIo* io) { InfStandaloneIoPrivate* priv; g_return_if_fail(INF_IS_STANDALONE_IO(io)); priv = INF_STANDALONE_IO_PRIVATE(io); g_mutex_lock(&priv->mutex); g_return_if_fail(priv->loop_running == TRUE); priv->loop_running = FALSE; inf_standalone_io_wakeup(io); g_mutex_unlock(&priv->mutex); } /** * inf_standalone_io_loop_running: * @io: A #InfStandaloneIo. * * Returns whether @io runs currently in a loop initiated with * inf_standalone_io_loop(). * * Return Value: Whether @io runs in a loop. **/ gboolean inf_standalone_io_loop_running(InfStandaloneIo* io) { InfStandaloneIoPrivate* priv; gboolean running; g_return_val_if_fail(INF_IS_STANDALONE_IO(io), FALSE); priv = INF_STANDALONE_IO_PRIVATE(io); g_mutex_lock(&priv->mutex); running = priv->loop_running; g_mutex_unlock(&priv->mutex); return running; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-init.c0000644000000000000000000000013213034342512021271 xustar0030 mtime=1483851082.033718448 30 atime=1483851082.033718448 30 ctime=1488261589.060138934 libinfinity-0.7.1/libinfinity/common/inf-init.c0000644000175000017500000000536313034342512022032 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include #include /* Get ssize_t on MSVC, required by gnutls.h */ #include #include #ifdef G_OS_WIN32 # include #endif static guint inf_init_counter = 0; extern gboolean INF_XMPP_CONNECTION_PRINT_TRAFFIC; /** * inf_init: * @error: Location to store error information, if any. * * This function initializes the libinfinity library and should be called * before any other functions of the library. The function does nothing if * it has already been called before. * * Returns: Whether the initialization was successful or not. */ gboolean inf_init(GError** error) { #ifdef G_OS_WIN32 WSADATA data; int result; gchar* error_message; #endif if(inf_init_counter == 0) { #ifdef G_OS_WIN32 result = WSAStartup(MAKEWORD(2, 2), &data); if(result != 0) { error_message = g_win32_error_message(result); g_set_error_literal( error, g_quark_from_static_string("INF_INIT_ERROR"), 0, error_message ); g_free(error_message); return FALSE; } #endif gnutls_global_init(); _inf_gettext_init(); } /* Initialize traffic debug */ if(g_getenv("LIBINFINITY_DEBUG_PRINT_TRAFFIC")) INF_XMPP_CONNECTION_PRINT_TRAFFIC = TRUE; else INF_XMPP_CONNECTION_PRINT_TRAFFIC = FALSE; ++inf_init_counter; return TRUE; } /** * inf_deinit: * * This functions deinitializes the libinfinity library. Make sure that all * objects the library provides have been freed before calling this function. * If inf_init() has been called multiple times, then inf_deinit() needs to be * called the same number of times to actually deinitialize the library. */ void inf_deinit(void) { if(--inf_init_counter == 0) { gnutls_global_deinit(); #ifdef G_OS_WIN32 WSACleanup(); #endif } } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-session.h0000644000000000000000000000013213034342512022016 xustar0030 mtime=1483851082.033718448 30 atime=1483851082.033718448 30 ctime=1488261588.960139153 libinfinity-0.7.1/libinfinity/common/inf-session.h0000644000175000017500000003277513034342512022566 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_SESSION_H__ #define __INF_SESSION_H__ #include #include #include #include #include #include #include #include G_BEGIN_DECLS #define INF_TYPE_SESSION (inf_session_get_type()) #define INF_SESSION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_TYPE_SESSION, InfSession)) #define INF_SESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INF_TYPE_SESSION, InfSessionClass)) #define INF_IS_SESSION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_TYPE_SESSION)) #define INF_IS_SESSION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INF_TYPE_SESSION)) #define INF_SESSION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INF_TYPE_SESSION, InfSessionClass)) #define INF_TYPE_SESSION_STATUS (inf_session_status_get_type()) typedef struct _InfSession InfSession; typedef struct _InfSessionClass InfSessionClass; /** * InfSessionStatus: * @INF_SESSION_PRESYNC: The session is scheduled to be synchronized from a * remote host. This can be useful if the session is needed to be present * before the actual synchronization begins. Use * inf_session_synchronize_from() to switch to * %INF_SESSION_SYNCHRONIZING. * @INF_SESSION_SYNCHRONIZING: The session is currently being synchronized * from a remote host. When done synchronizing, it will enter into * %INF_SESSION_RUNNING state. * @INF_SESSION_RUNNING: The session is running and ready to synchronize * other hosts. If a subscription group is set * (see inf_session_set_subscription_group()), then changes to the * underlying buffer are transmitted to all subscribed connections. * @INF_SESSION_CLOSED: The session is closed and can no longer be used. The * session enters this state if the synchronization fails in * %INF_SESSION_SYNCHRONIZING state or inf_session_close() is called. * * #InfSessionStatus defines in what state a session is in. */ typedef enum _InfSessionStatus { INF_SESSION_PRESYNC, INF_SESSION_SYNCHRONIZING, INF_SESSION_RUNNING, INF_SESSION_CLOSED } InfSessionStatus; /** * InfSessionSyncStatus: * @INF_SESSION_SYNC_NONE: No synchronization is ongoing. * @INF_SESSION_SYNC_IN_PROGRESS: Synchronization is currently in progress. * @INF_SESSION_SYNC_AWAITING_ACK: All synchronization data has been sent * (progress is 1.0), but we are still waiting for an acknowledgment from the * remote site. Synchronization can no longer be cancelled, but it can stiff * fail. * * #InfSessionSyncStatus represents the status of a synchronization. It is * used by inf_session_get_synchronization_status(). */ typedef enum _InfSessionSyncStatus { INF_SESSION_SYNC_NONE, INF_SESSION_SYNC_IN_PROGRESS, INF_SESSION_SYNC_AWAITING_ACK } InfSessionSyncStatus; /** * InfSessionSyncError: * @INF_SESSION_SYNC_ERROR_GOT_MESSAGE_IN_PRESYNC: Received a message * in state %INF_SESSION_PRESYNC. It is not processed because * inf_session_synchronize_from() was not yet called. * @INF_SESSION_SYNC_ERROR_UNEXPECTED_NODE: A message has been received that * was not understood. * @INF_SESSION_SYNC_ERROR_ID_NOT_PRESENT: An ID was not provided for a user * in the session. * @INF_SESSION_SYNC_ERROR_ID_IN_USE: The ID of a user is already in use by * another user. * @INF_SESSION_SYNC_ERROR_NAME_NOT_PRESENT: A name was not provided for a * user in the session. * @INF_SESSION_SYNC_ERROR_NAME_IN_USE: The name of a user is already in use * by another user. * @INF_SESSION_SYNC_ERROR_CONNECTION_CLOSED: The synchronization connection * has been closed. * @INF_SESSION_SYNC_ERROR_SENDER_CANCELLED: The sender has cancelled the * synchronization. * @INF_SESSION_SYNC_ERROR_RECEIVER_CANCELLED: The receiver has cancelled the * synchronization. * @INF_SESSION_SYNC_ERROR_UNEXPECTED_BEGIN_OF_SYNC: Received * <sync-begin/> * not a the beginning of the synchronization. * @INF_SESSION_SYNC_ERROR_NUM_MESSAGES_MISSING: The <sync-begin/> * message does not contain the number of synchronization messages to expect. * @INF_SESSION_SYNC_ERROR_UNEXPECTED_END_OF_SYNC: The <sync-end/> * message was not received at the end of the synchronization. * @INF_SESSION_SYNC_ERROR_EXPECTED_BEGIN_OF_SYNC: The <sync-begin/> * message was not received at the beginning of the synchronization. * @INF_SESSION_SYNC_ERROR_EXPECTED_END_OF_SYNC: The <sync-end/> message * was not received at the end of the synchronization. * @INF_SESSION_SYNC_ERROR_FAILED: Generic error code when no further reason * of failure is known. * * These are errors that can occur during a synchronization of a session. * Additional errors may occur depending on the session type. */ typedef enum _InfSessionSyncError { INF_SESSION_SYNC_ERROR_GOT_MESSAGE_IN_PRESYNC, INF_SESSION_SYNC_ERROR_UNEXPECTED_NODE, INF_SESSION_SYNC_ERROR_ID_NOT_PRESENT, INF_SESSION_SYNC_ERROR_ID_IN_USE, INF_SESSION_SYNC_ERROR_NAME_NOT_PRESENT, INF_SESSION_SYNC_ERROR_NAME_IN_USE, INF_SESSION_SYNC_ERROR_CONNECTION_CLOSED, INF_SESSION_SYNC_ERROR_SENDER_CANCELLED, INF_SESSION_SYNC_ERROR_RECEIVER_CANCELLED, INF_SESSION_SYNC_ERROR_UNEXPECTED_BEGIN_OF_SYNC, INF_SESSION_SYNC_ERROR_NUM_MESSAGES_MISSING, INF_SESSION_SYNC_ERROR_UNEXPECTED_END_OF_SYNC, INF_SESSION_SYNC_ERROR_EXPECTED_BEGIN_OF_SYNC, INF_SESSION_SYNC_ERROR_EXPECTED_END_OF_SYNC, INF_SESSION_SYNC_ERROR_FAILED } InfSessionSyncError; /** * InfSessionClass: * @to_xml_sync: Virtual function that saves the session within a XML * document. @parent is the root node of the document. It should create as * much nodes as possible within that root node and not in sub-nodes because * these are sent to a client and it is not allowed that other traffic is put * in between those nodes. This way, communication through the same connection * does not hang just because a large session is synchronized. * @process_xml_sync: Virtual function that is called for every node in the * XML document created by @to_xml_sync. It is supposed to reconstruct the * session content from the XML data. * @process_xml_run: Virtual function that is called for every received * message while the session is running. Return %INF_COMMUNICATION_SCOPE_GROUP * if the message is designated for all group members (see also * inf_communication_object_received() on this topic). * @get_xml_user_props: Virtual function that creates a list of * #GParameters for use with g_object_newv() from a XML node. * @set_xml_user_props: Virtual function that writes the passed user * properties into a XML node. * @validate_user_props: Virtual function that checks whether the given user * properties are valid for a user join. This prevents a user join if there is * already a user with the same name. If @exclude is not %NULL, then the * function does ignore it when validating. * @user_new: Virtual function that creates a new user object with the given * properties. * @close: Default signal handler for the #InfSession::close signal. This * cancels currently running synchronization in #InfSession. * @error: Default signal handler for the #InfSession::error signal. * @synchronization_begin: Default signal handler for the * #InfSession::synchronization-begin signal. The default handler queues the * synchronization messages. * @synchronization_progress: Default signal handler for the * #InfSession::synchronization-progress signal. * @synchronization_complete: Default signal handler for the * #InfSession::synchronization-complete signal. If the session itself got * synchronized (and did not synchronize another session), then the default * handler changes status to %INF_SESSION_RUNNING. * @synchronization_failed: Default signal handler for the * #InfSession::synchronization-failed signal. If the session itself got * synchronized (and did not synchronize another session), then the default * handler changes status to %INF_SESSION_CLOSED. * * This structure contains the virtual functions and default signal handlers * of #InfSession. */ struct _InfSessionClass { /*< private >*/ GObjectClass parent_class; /*< public >*/ /* Virtual table */ void(*to_xml_sync)(InfSession* session, xmlNodePtr parent); gboolean(*process_xml_sync)(InfSession* session, InfXmlConnection* connection, xmlNodePtr xml, GError** error); InfCommunicationScope(*process_xml_run)(InfSession* session, InfXmlConnection* connection, xmlNodePtr xml, GError** error); GArray*(*get_xml_user_props)(InfSession* session, InfXmlConnection* conn, xmlNodePtr xml); void (*set_xml_user_props)(InfSession* session, const GParameter* params, guint n_params, xmlNodePtr xml); gboolean(*validate_user_props)(InfSession* session, const GParameter* params, guint n_params, InfUser* exclude, GError** error); InfUser*(*user_new)(InfSession* session, GParameter* params, guint n_params); /* Signals */ void(*close)(InfSession* session); void(*error)(InfSession* session, InfXmlConnection* connection, xmlNodePtr xml, const GError* error); void(*synchronization_begin)(InfSession* session, InfCommunicationGroup* group, InfXmlConnection* connection); void(*synchronization_progress)(InfSession* session, InfXmlConnection* connection, gdouble percentage); void(*synchronization_complete)(InfSession* session, InfXmlConnection* connection); void(*synchronization_failed)(InfSession* session, InfXmlConnection* connection, const GError* error); }; /** * InfSession: * * #InfSession is an opaque data type. You should only access it via the * public API functions. */ struct _InfSession { /*< private >*/ GObject parent; }; const GParameter* inf_session_lookup_user_property(const GParameter* params, guint n_params, const gchar* name); GParameter* inf_session_get_user_property(GArray* array, const gchar* name); GType inf_session_status_get_type(void) G_GNUC_CONST; GType inf_session_get_type(void) G_GNUC_CONST; void inf_session_user_to_xml(InfSession* session, InfUser* user, xmlNodePtr xml); void inf_session_close(InfSession* session); InfCommunicationManager* inf_session_get_communication_manager(InfSession* session); InfBuffer* inf_session_get_buffer(InfSession* session); InfUserTable* inf_session_get_user_table(InfSession* session); InfSessionStatus inf_session_get_status(InfSession* session); InfUser* inf_session_add_user(InfSession* session, const GParameter* params, guint n_params); void inf_session_set_user_status(InfSession* session, InfUser* user, InfUserStatus status); void inf_session_synchronize_from(InfSession* session); void inf_session_synchronize_to(InfSession* session, InfCommunicationGroup* group, InfXmlConnection* connection); void inf_session_cancel_synchronization(InfSession* session, InfXmlConnection* connection); InfSessionSyncStatus inf_session_get_synchronization_status(InfSession* session, InfXmlConnection* connection); gdouble inf_session_get_synchronization_progress(InfSession* session, InfXmlConnection* connection); gboolean inf_session_has_synchronizations(InfSession* session); InfCommunicationGroup* inf_session_get_subscription_group(InfSession* session); void inf_session_set_subscription_group(InfSession* session, InfCommunicationGroup* group); void inf_session_send_to_subscriptions(InfSession* session, xmlNodePtr xml); G_END_DECLS #endif /* __INF_SESSION_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-chat-buffer.h0000644000000000000000000000013213034342512022521 xustar0030 mtime=1483851082.029718427 30 atime=1483851082.029718427 30 ctime=1488261588.940139196 libinfinity-0.7.1/libinfinity/common/inf-chat-buffer.h0000644000175000017500000001336513034342512023263 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef __INF_CHAT_BUFFER_H__ #define __INF_CHAT_BUFFER_H__ #include #include #include G_BEGIN_DECLS #define INF_TYPE_CHAT_BUFFER (inf_chat_buffer_get_type()) #define INF_CHAT_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_TYPE_CHAT_BUFFER, InfChatBuffer)) #define INF_CHAT_BUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INF_TYPE_CHAT_BUFFER, InfChatBufferClass)) #define INF_IS_CHAT_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_TYPE_CHAT_BUFFER)) #define INF_IS_CHAT_BUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INF_TYPE_CHAT_BUFFER)) #define INF_CHAT_BUFFER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INF_TYPE_CHAT_BUFFER, InfChatBufferClass)) #define INF_TYPE_CHAT_BUFFER_MESSAGE_TYPE (inf_chat_buffer_message_type_get_type()) #define INF_TYPE_CHAT_BUFFER_MESSAGE (inf_chat_buffer_message_get_type()) typedef struct _InfChatBuffer InfChatBuffer; typedef struct _InfChatBufferClass InfChatBufferClass; typedef struct _InfChatBufferMessage InfChatBufferMessage; /** * InfChatBufferMessageType: * @INF_CHAT_BUFFER_MESSAGE_NORMAL: A normal chat message. * @INF_CHAT_BUFFER_MESSAGE_EMOTE: An emote chat message (/me is doing * something). * @INF_CHAT_BUFFER_MESSAGE_USERJOIN: A user join notification. * @INF_CHAT_BUFFER_MESSAGE_USERPART: A user part notification. * * Possible chat message types. */ typedef enum _InfChatBufferMessageType { INF_CHAT_BUFFER_MESSAGE_NORMAL, INF_CHAT_BUFFER_MESSAGE_EMOTE, INF_CHAT_BUFFER_MESSAGE_USERJOIN, INF_CHAT_BUFFER_MESSAGE_USERPART } InfChatBufferMessageType; /** * InfChatBufferMessageFlags: * @INF_CHAT_BUFFER_MESSAGE_BACKLOG: The message is a backlog message, i.e. * it originated in a previous session. * * Possible chat message flags. */ typedef enum _InfChatBufferMessageFlags { INF_CHAT_BUFFER_MESSAGE_BACKLOG = 1 << 0 } InfChatBufferMessageFlags; /** * InfChatBufferMessage: * @type: The #InfChatBufferMessageType of the message. * @user: The #InfUser that issued the message. * @text: The UTF-8 encoded text of the message. * @length: The length of the message, in bytes. * @time: The time at which the message was received. * @flags: Additional flags for the message, see #InfChatBufferMessageFlags. * * Represents a chat message. */ struct _InfChatBufferMessage { InfChatBufferMessageType type; InfUser* user; gchar* text; gsize length; time_t time; InfChatBufferMessageFlags flags; }; /** * InfChatBufferClass: * @add_message: Default signal handler for the #InfChatBuffer::add-message * signal. * * This structure contains default signal handlers for #InfChatBuffer. */ struct _InfChatBufferClass { /*< private >*/ GObjectClass parent_class; /*< public >*/ void (*add_message)(InfChatBuffer* buffer, const InfChatBufferMessage* message); }; /** * InfChatBuffer: * * #InfChatBuffer is an opaque data type. You should only access it via the * public API functions. */ struct _InfChatBuffer { /*< private >*/ GObject parent; }; GType inf_chat_buffer_message_get_type(void) G_GNUC_CONST; GType inf_chat_buffer_message_type_get_type(void) G_GNUC_CONST; GType inf_chat_buffer_message_flags_get_type(void) G_GNUC_CONST; GType inf_chat_buffer_get_type(void) G_GNUC_CONST; InfChatBufferMessage* inf_chat_buffer_message_copy(const InfChatBufferMessage* message); void inf_chat_buffer_message_free(InfChatBufferMessage* message); InfChatBuffer* inf_chat_buffer_new(guint size); void inf_chat_buffer_add_message(InfChatBuffer* buffer, InfUser* by, const gchar* message, gsize length, time_t time, InfChatBufferMessageFlags flags); void inf_chat_buffer_add_emote_message(InfChatBuffer* buffer, InfUser* by, const gchar* message, gsize length, time_t time, InfChatBufferMessageFlags flags); void inf_chat_buffer_add_userjoin_message(InfChatBuffer* buffer, InfUser* user, time_t time, InfChatBufferMessageFlags flags); void inf_chat_buffer_add_userpart_message(InfChatBuffer* buffer, InfUser* user, time_t time, InfChatBufferMessageFlags flags); const InfChatBufferMessage* inf_chat_buffer_get_message(InfChatBuffer* buffer, guint n); guint inf_chat_buffer_get_n_messages(InfChatBuffer* buffer); guint inf_chat_buffer_get_size(InfChatBuffer* buffer); G_END_DECLS #endif /* __INF_CHAT_BUFFER_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-discovery-avahi.h0000644000000000000000000000013213034342512023430 xustar0030 mtime=1483851082.033718448 30 atime=1483851082.033718448 30 ctime=1488261588.944139188 libinfinity-0.7.1/libinfinity/common/inf-discovery-avahi.h0000644000175000017500000000646013034342512024170 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_DISCOVERY_AVAHI_H__ #define __INF_DISCOVERY_AVAHI_H__ #include #include #include #include /* For LIBINFINITY_HAVE_AVAHI */ #include #include #ifdef LIBINFINITY_HAVE_AVAHI G_BEGIN_DECLS #define INF_TYPE_DISCOVERY_AVAHI (inf_discovery_avahi_get_type()) #define INF_DISCOVERY_AVAHI(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_TYPE_DISCOVERY_AVAHI, InfDiscoveryAvahi)) #define INF_DISCOVERY_AVAHI_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INF_TYPE_DISCOVERY_AVAHI, InfDiscoveryAvahiClass)) #define INF_IS_DISCOVERY_AVAHI(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_TYPE_DISCOVERY_AVAHI)) #define INF_IS_DISCOVERY_AVAHI_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INF_TYPE_DISCOVERY_AVAHI)) #define INF_DISCOVERY_AVAHI_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INF_TYPE_DISCOVERY_AVAHI, InfDiscoveryAvahiClass)) typedef struct _InfDiscoveryAvahi InfDiscoveryAvahi; typedef struct _InfDiscoveryAvahiClass InfDiscoveryAvahiClass; /** * InfDiscoveryAvahiClass: * * This structure does not contain any public fields. */ struct _InfDiscoveryAvahiClass { /*< private >*/ GObjectClass parent_class; }; /** * InfDiscoveryAvahi: * * #InfDiscoveryAvahi is an opaque data type. You should only access it * via the public API functions. */ struct _InfDiscoveryAvahi { /*< private >*/ GObject parent; }; GType inf_discovery_avahi_get_type(void) G_GNUC_CONST; InfDiscoveryAvahi* inf_discovery_avahi_new(InfIo* io, InfXmppManager* manager, InfCertificateCredentials* creds, InfSaslContext* sasl_context, const gchar* sasl_mechanisms); void inf_discovery_avahi_set_security_policy(InfDiscoveryAvahi* discovery, InfXmppConnectionSecurityPolicy plcy); InfXmppConnectionSecurityPolicy inf_discovery_avahi_get_security_policy(InfDiscoveryAvahi* discovery); void inf_discovery_avahi_set_keepalive(InfDiscoveryAvahi* discovery, const InfKeepalive* keepalive); const InfKeepalive* inf_discovery_avahi_get_keepalive(InfDiscoveryAvahi* discovery); G_END_DECLS #endif /* LIBINFINITY_HAVE_AVAHI */ #endif /* __INF_DISCOVERY_AVAHI_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-browser-iter.c0000644000000000000000000000013213034342512022752 xustar0030 mtime=1483851082.029718427 30 atime=1483851082.029718427 30 ctime=1488261589.040138978 libinfinity-0.7.1/libinfinity/common/inf-browser-iter.c0000644000175000017500000000521313034342512023505 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-browser-iter * @title: InfBrowserIter * @short_description: Iterating through browsed nodes * @see_also: #InfBrowser * @include: libinfinity/common/inf-browser-iter.h * @stability: Unstable * * #InfBrowserIter is used to iterate through the nodes of a #InfBrowser. * Normally, #InfBrowserIter is allocated on the stack and * initialized by a #InfBrowser API call, such as inf_browser_get_root(). You * can also safely copy the struct by value to create a copy. It is not * necessary to free it. * * Most operations are done via the #InfBrowser API. The methods * described here could be useful to language bindings, however. * * An initialized #InfBrowserIter always points to a node within the * #InfBrowser. It stays valid as long as the node it points to is not * removed from the browser (if it is, the #InfBrowser::node-removed) signal * is emitted. **/ #include G_DEFINE_BOXED_TYPE(InfBrowserIter, inf_browser_iter, inf_browser_iter_copy, inf_browser_iter_free) /** * inf_browser_iter_copy: * @iter: A #InfBrowserIter. * * Makes a dynamically allocated copy of @iter. This should not be used by * applications because you can copy the structs by value. * * Return Value: (transfer full): A newly-allocated copy of @iter. */ InfBrowserIter* inf_browser_iter_copy(const InfBrowserIter* iter) { InfBrowserIter* new_iter; g_return_val_if_fail(iter != NULL, NULL); new_iter = g_slice_new(InfBrowserIter); *new_iter = *iter; return new_iter; } /** * inf_browser_iter_free: * @iter: A #InfBrowserIter. * * Frees a #InfBrowserIter allocated by inf_browser_iter_copy(). **/ void inf_browser_iter_free(InfBrowserIter* iter) { g_return_if_fail(iter != NULL); g_slice_free(InfBrowserIter, iter); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-simulated-connection.h0000644000000000000000000000013213034342512024457 xustar0030 mtime=1483851082.033718448 30 atime=1483851082.033718448 30 ctime=1488261588.964139144 libinfinity-0.7.1/libinfinity/common/inf-simulated-connection.h0000644000175000017500000000770113034342512025216 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_SIMULATED_CONNECTION_H__ #define __INF_SIMULATED_CONNECTION_H__ #include #include #include G_BEGIN_DECLS #define INF_TYPE_SIMULATED_CONNECTION (inf_simulated_connection_get_type()) #define INF_SIMULATED_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_TYPE_SIMULATED_CONNECTION, InfSimulatedConnection)) #define INF_SIMULATED_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INF_TYPE_SIMULATED_CONNECTION, InfSimulatedConnectionClass)) #define INF_IS_SIMULATED_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_TYPE_SIMULATED_CONNECTION)) #define INF_IS_SIMULATED_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INF_TYPE_SIMULATED_CONNECTION)) #define INF_SIMULATED_CONNECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INF_TYPE_SIMULATED_CONNECTION, InfSimulatedConnectionClass)) #define INF_TYPE_SIMULATED_CONNECTION_MODE (inf_simulated_connection_mode_get_type()) typedef struct _InfSimulatedConnection InfSimulatedConnection; typedef struct _InfSimulatedConnectionClass InfSimulatedConnectionClass; /** * InfSimulatedConnectionMode: * @INF_SIMULATED_CONNECTION_IMMEDIATE: Messages are received directly by the * target site when calling inf_xml_connection_send(). * @INF_SIMULATED_CONNECTION_DELAYED: Messages are queued, and delivered to * the target site when inf_simulated_connection_flush() is called. * @INF_SIMULATED_CONNECTION_IO_CONTROLLED: Messages are queued and delivered * once the application main loop regains control. This requires the simulated * connection to have been created with * inf_simulated_connection_new_with_io(). * * The mode of a simulated connection defines when sent messages arrive at * the target connection. */ typedef enum _InfSimulatedConnectionMode { INF_SIMULATED_CONNECTION_IMMEDIATE, INF_SIMULATED_CONNECTION_DELAYED, INF_SIMULATED_CONNECTION_IO_CONTROLLED } InfSimulatedConnectionMode; /** * InfSimulatedConnectionClass: * * This structure does not contain any public fields. */ struct _InfSimulatedConnectionClass { /*< private >*/ GObjectClass parent_class; }; /** * InfSimulatedConnection: * * #InfSimulatedConnection is an opaque data type. You should only access it * via the public API functions. */ struct _InfSimulatedConnection { /*< private >*/ GObject parent; }; GType inf_simulated_connection_mode_get_type(void) G_GNUC_CONST; GType inf_simulated_connection_get_type(void) G_GNUC_CONST; InfSimulatedConnection* inf_simulated_connection_new(void); InfSimulatedConnection* inf_simulated_connection_new_with_io(InfIo* io); void inf_simulated_connection_connect(InfSimulatedConnection* connection, InfSimulatedConnection* to); void inf_simulated_connection_set_mode(InfSimulatedConnection* connection, InfSimulatedConnectionMode mode); void inf_simulated_connection_flush(InfSimulatedConnection* connection); G_END_DECLS #endif /* __INF_SIMULATED_CONNECTION_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/common/PaxHeaders.26529/inf-user-table.h0000644000000000000000000000013013034342512022374 xustar0029 mtime=1483851082.03771847 29 atime=1483851082.03771847 30 ctime=1488261588.968139135 libinfinity-0.7.1/libinfinity/common/inf-user-table.h0000644000175000017500000001074713034342512023141 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_USER_TABLE_H__ #define __INF_USER_TABLE_H__ #include #include G_BEGIN_DECLS #define INF_TYPE_USER_TABLE (inf_user_table_get_type()) #define INF_USER_TABLE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_TYPE_USER_TABLE, InfUserTable)) #define INF_USER_TABLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INF_TYPE_USER_TABLE, InfUserTableClass)) #define INF_IS_USER_TABLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_TYPE_USER_TABLE)) #define INF_IS_USER_TABLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INF_TYPE_USER_TABLE)) #define INF_USER_TABLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INF_TYPE_USER_TABLE, InfUserTableClass)) typedef struct _InfUserTable InfUserTable; typedef struct _InfUserTableClass InfUserTableClass; /** * InfUserTableClass: * @add_user: Default signal handler for the #InfUserTable::add_user signal. * @remove_user: Default signal handler for the #InfUserTable::remove_user * signal. * @add_available_user: Default signal handler for the * #InfUserTable::add-available-user signal. * @remove_available_user: Default signal handler for the * #InfUserTable::remove-available-user signal. * @add_local_user: Default signal handler for the * #InfUserTable::add_local_user signal. * @remove_local_user: Default signal handler for the * #InfUserTable::remove_local_user signal. * * Signals for the #InfUserTable class. */ struct _InfUserTableClass { /*< private >*/ GObjectClass parent_class; /*< public >*/ void(*add_user)(InfUserTable* user_table, InfUser* user); void(*remove_user)(InfUserTable* user_table, InfUser* user); void(*add_available_user)(InfUserTable* user_table, InfUser* user); void(*remove_available_user)(InfUserTable* user_table, InfUser* user); void(*add_local_user)(InfUserTable* user_table, InfUser* user); void(*remove_local_user)(InfUserTable* user_table, InfUser* user); }; /** * InfUserTable: * * #InfUserTable is an opaque data type. You should only access it via the * public API functions. */ struct _InfUserTable { /*< private >*/ GObject parent; }; /** * InfUserTableForeachUserFunc: * @user: The #InfUser for the current iteration. * @user_data: The user_data passed to inf_user_table_foreach_user() or * inf_user_table_foreach_local_user(). * * This callback is called for every user iterated by * inf_user_table_foreach_user() or inf_user_table_foreach_local_user(). */ typedef void(*InfUserTableForeachUserFunc)(InfUser* user, gpointer user_data); GType inf_user_table_get_type(void) G_GNUC_CONST; InfUserTable* inf_user_table_new(void); void inf_user_table_add_user(InfUserTable* user_table, InfUser* user); void inf_user_table_remove_user(InfUserTable* user_table, InfUser* user); InfUser* inf_user_table_lookup_user_by_id(InfUserTable* user_table, guint id); InfUser* inf_user_table_lookup_user_by_name(InfUserTable* user_table, const gchar* name); void inf_user_table_foreach_user(InfUserTable* user_table, InfUserTableForeachUserFunc func, gpointer user_data); void inf_user_table_foreach_local_user(InfUserTable* user_table, InfUserTableForeachUserFunc func, gpointer user_data); G_END_DECLS #endif /* __INF_USER_TABLE_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/PaxHeaders.26529/inf-config.h0000644000000000000000000000013213034524101020304 xustar0030 mtime=1483909185.014924057 30 atime=1483909185.014924057 30 ctime=1488261588.988139092 libinfinity-0.7.1/libinfinity/inf-config.h0000644000175000017500000000245713034524101021046 0ustar00arminarmin00000000000000/* libinfinity/inf-config.h. Generated from inf-config.h.in by configure. */ /* infinote - Collaborative notetaking application * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /* Defines representing support for what features has been compiled into * libinfinity. All these defines are prefixed, so it is safe to be installed * and used by other packages. */ /* Whether avahi support is enabled */ #define LIBINFINITY_HAVE_AVAHI 1 /* Whether libdaemon support is enabled */ #define LIBINFINITY_HAVE_LIBDAEMON 1 /* Whether pam support is enabled */ #define LIBINFINITY_HAVE_PAM 1 libinfinity-0.7.1/libinfinity/PaxHeaders.26529/server0000644000000000000000000000013213055210725017354 xustar0030 mtime=1488261589.132138777 30 atime=1488261588.904139275 30 ctime=1488261589.132138777 libinfinity-0.7.1/libinfinity/server/0000755000175000017500000000000013055210725020163 5ustar00arminarmin00000000000000libinfinity-0.7.1/libinfinity/server/PaxHeaders.26529/infd-chat-filesystem-format.h0000644000000000000000000000013213034342512025104 xustar0030 mtime=1483851082.041718492 30 atime=1483851082.041718492 30 ctime=1488261589.000139066 libinfinity-0.7.1/libinfinity/server/infd-chat-filesystem-format.h0000644000175000017500000000376013034342512025644 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INFD_CHAT_FILESYSTEM_FORMAT_H__ #define __INFD_CHAT_FILESYSTEM_FORMAT_H__ #include #include #include G_BEGIN_DECLS /** * InfdChatFilesystemFormatError: * @INFD_CHAT_FILESYSTEM_FORMAT_ERROR_NOT_A_CHAT_SESSION: The file to be read * is not a serialized chat session. * * Errors that can occur when reading a #InfChatSession from a * #InfdFilesystemStorage. */ typedef enum _InfdTextFilesystemFormatError { INFD_CHAT_FILESYSTEM_FORMAT_ERROR_NOT_A_CHAT_SESSION } InfdChatFilesystemFormatError; gboolean infd_chat_filesystem_format_read(InfdFilesystemStorage* storage, const gchar* path, InfChatBuffer* buffer, GError** error); gboolean infd_chat_filesystem_format_write(InfdFilesystemStorage* storage, const gchar* path, InfChatBuffer* buffer, GError** error); G_END_DECLS #endif /* __INFD_CHAT_FILESYSTEM_FORMAT_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/server/PaxHeaders.26529/infd-storage.c0000644000000000000000000000013213034342512022154 xustar0030 mtime=1483851082.045718513 30 atime=1483851082.045718513 30 ctime=1488261589.128138785 libinfinity-0.7.1/libinfinity/server/infd-storage.c0000644000175000017500000002447213034342512022717 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include static const GEnumValue infd_storage_node_type_values[] = { { INFD_STORAGE_NODE_SUBDIRECTORY, "INFD_STORAGE_NODE_SUBDIRECTORY", "subdirectory" }, { INFD_STORAGE_NODE_NOTE, "INFD_STORAGE_NODE_NOTE", "note" }, { 0, NULL, NULL } }; INF_DEFINE_ENUM_TYPE(InfdStorageNodeType, infd_storage_node_type, infd_storage_node_type_values) G_DEFINE_BOXED_TYPE(InfdStorageNode, infd_storage_node, infd_storage_node_copy, infd_storage_node_free) G_DEFINE_BOXED_TYPE(InfdStorageAcl, infd_storage_acl, infd_storage_acl_copy, infd_storage_acl_free) G_DEFINE_INTERFACE(InfdStorage, infd_storage, G_TYPE_OBJECT) static void infd_storage_default_init(InfdStorageInterface* iface) { } /** * infd_storage_node_new_subdirectory: (constructor) * @path: Path to the node. * * Creates a new #InfdStorageNode with type * %INFD_STORAGE_NODE_SUBDIRECTORY and the given path. This * is most likely only going to be used by #InfdStorage * implementations. * * Returns: (transfer full): A new #InfdStorageNode. **/ InfdStorageNode* infd_storage_node_new_subdirectory(const gchar* path) { InfdStorageNode* node; g_return_val_if_fail(path != NULL, NULL); node = g_slice_new(InfdStorageNode); node->type = INFD_STORAGE_NODE_SUBDIRECTORY; node->name = g_strdup(path); return node; } /** * infd_storage_node_new_note: (constructor) * @path: Path to the node. * @identifier: Identifier of the note type, for example 'InfText' for text * notes. * * Creates a new #InfdStorageNode with type * %INFD_STORAGE_NODE_NOTE and the given path and identifier. This * is most likely only going to be used by #InfdStorage * implementations. * * Returns: (transfer full): A new #InfdStorageNode. **/ InfdStorageNode* infd_storage_node_new_note(const gchar* path, const gchar* identifier) { InfdStorageNode* node; g_return_val_if_fail(path != NULL, NULL); g_return_val_if_fail(identifier != NULL, NULL); node = g_slice_new(InfdStorageNode); node->type = INFD_STORAGE_NODE_NOTE; node->name = g_strdup(path); node->identifier = g_strdup(identifier); return node; } /** * infd_storage_node_copy: * @node: Node from which to make a copy. * * Creates a copy of a #InfdStorageNode object. * * Returns: (transfer full): A copy of @node. **/ InfdStorageNode* infd_storage_node_copy(const InfdStorageNode* node) { InfdStorageNode* new_node; g_return_val_if_fail(node != NULL, NULL); new_node = g_slice_new(InfdStorageNode); new_node->type = node->type; new_node->name = g_strdup(node->name); if(node->type == INFD_STORAGE_NODE_NOTE) new_node->identifier = g_strdup(node->identifier); return new_node; } /** * infd_storage_node_free: * @node: A #InfdStorageNode. * * Frees a #InfdStorageNode allocated with * infd_storage_node_new_subdirectory(), infd_storage_node_new_note() or * infd_storage_node_copy(). **/ void infd_storage_node_free(InfdStorageNode* node) { g_return_if_fail(node != NULL); g_free(node->name); if(node->type == INFD_STORAGE_NODE_NOTE) g_free(node->identifier); g_slice_free(InfdStorageNode, node); } /** * infd_storage_node_list_free: * @node_list: (element-type InfdStorageNode): A list of #InfdStorageNode * objects. * * Frees a singly-linked list of #InfdStorageNode as returned by * infd_storage_read_subdirectory(). **/ void infd_storage_node_list_free(GSList* node_list) { GSList* iter; GSList* next; for(iter = node_list; iter != NULL; iter = next) { next = g_slist_next(iter); infd_storage_node_free(iter->data); g_slist_free_1(iter); } } /** * infd_storage_acl_copy: * @acl: ACL settings from which to make a copy. * * Creates a copy of a #InfdStorageAcl object. * * Returns: A copy of @acl. **/ InfdStorageAcl* infd_storage_acl_copy(const InfdStorageAcl* acl) { InfdStorageAcl* new_acl; g_return_val_if_fail(acl != NULL, NULL); new_acl = g_slice_new(InfdStorageAcl); new_acl->account_id = g_strdup(acl->account_id); new_acl->mask = acl->mask; new_acl->perms = acl->perms; return new_acl; } /** * infd_storage_acl_free: * @acl: A #InfdStorageAcl. * * Frees a #InfdStorageAcl allocated with * infd_storage_acl_copy(). **/ void infd_storage_acl_free(InfdStorageAcl* acl) { g_return_if_fail(acl != NULL); g_free(acl->account_id); g_slice_free(InfdStorageAcl, acl); } /** * infd_storage_acl_list_free: * @acl_list: (element-type InfdStorageAcl): A list of #InfdStorageAcl * objects. * * Frees a singly-linked list of #InfdStorageAcl as returned by * infd_storage_read_acls(). **/ void infd_storage_acl_list_free(GSList* node_list) { GSList* iter; GSList* next; for(iter = node_list; iter != NULL; iter = next) { next = g_slist_next(iter); infd_storage_acl_free(iter->data); g_slist_free_1(iter); } } /** * infd_storage_read_subdirectory: * @storage: A #InfdStorage * @path: A path pointing to a subdirectory node. * @error: Location to store error information. * * Reads a subdirectory from the storage. Returns a list of * InfdStorageNode objects. Both the list and the objects need to * be freed by the caller via infd_storage_node_list_free(). * * Returns: (transfer full) (element-type InfdStorageNode) (allow-none): A * #GSList that contains #InfdStorageNode objects, or %NULL if either the * subdirectory is empty or an error occured. **/ GSList* infd_storage_read_subdirectory(InfdStorage* storage, const gchar* path, GError** error) { InfdStorageInterface* iface; g_return_val_if_fail(INFD_IS_STORAGE(storage), NULL); g_return_val_if_fail(path != NULL, NULL); iface = INFD_STORAGE_GET_IFACE(storage); g_return_val_if_fail(iface->read_subdirectory != NULL, NULL); return iface->read_subdirectory(storage, path, error); } /** * infd_storage_create_subdirectory: * @storage: A #InfdStorage. * @path: A path pointing to non-existing node. * @error: Location to store error information. * * Creates a new subdirectory at the given path that is initially empty. * * Returns: %TRUE on success. **/ gboolean infd_storage_create_subdirectory(InfdStorage* storage, const gchar* path, GError** error) { InfdStorageInterface* iface; g_return_val_if_fail(INFD_IS_STORAGE(storage), FALSE); g_return_val_if_fail(path != NULL, FALSE); iface = INFD_STORAGE_GET_IFACE(storage); g_return_val_if_fail(iface->create_subdirectory != NULL, FALSE); return iface->create_subdirectory(storage, path, error); } /** * infd_storage_remove_node: * @storage: A #InfdStorage * @identifier: The type of the node to remove, or %NULL to remove a * subdirectory (TODO: This shouldn't be necessary). * @path: A path pointing to an existing node. * @error: Location to store error information. * * Removes the node at path from storage. If it is a subdirectory node, all * containing nodes and subdirectory nodes are removed recursively. * * Returns: %TRUE on success. **/ gboolean infd_storage_remove_node(InfdStorage* storage, const gchar* identifier, const gchar* path, GError** error) { InfdStorageInterface* iface; g_return_val_if_fail(INFD_IS_STORAGE(storage), FALSE); g_return_val_if_fail(path != NULL, FALSE); iface = INFD_STORAGE_GET_IFACE(storage); g_return_val_if_fail(iface->remove_node != NULL, FALSE); return iface->remove_node(storage, identifier, path, error); } /** * infd_storage_read_acl: * @storage: A #InfdStorage. * @path: A path pointing to an existing node. * @error: Location to store error information, if any. * * Reads the ACL for the node at the path @path from the storage. It returns * a list of #InfdStorageAcl objects. * * Returns: (transfer full) (element-type InfdStorageAcl) (allow-none): A * possibly empty list of #InfdStorageAcl objects. Free with * infd_storage_acl_list_free() when no longer needed. */ GSList* infd_storage_read_acl(InfdStorage* storage, const gchar* path, GError** error) { InfdStorageInterface* iface; g_return_val_if_fail(INFD_IS_STORAGE(storage), NULL); g_return_val_if_fail(path != NULL, NULL); g_return_val_if_fail(error == NULL || *error == NULL, NULL); iface = INFD_STORAGE_GET_IFACE(storage); g_return_val_if_fail(iface->read_acl != NULL, NULL); return iface->read_acl(storage, path, error); } /** * infd_storage_write_acl: * @storage: A #InfdStorage. * @path: A path to an existing node. * @sheet_set: Sheets to set for the node at @path, or %NULL. * @error: Location to store error information, if any. * * Writes the ACL defined by @sheet_set into storage. If @sheet_set is %NULL * this is equivalent to an empty set. Returns %TRUE on success or %FALSE on * error. If the function fails, @error is set. * * Returns: %TRUE on success or %FALSE on error. */ gboolean infd_storage_write_acl(InfdStorage* storage, const gchar* path, const InfAclSheetSet* sheet_set, GError** error) { InfdStorageInterface* iface; g_return_val_if_fail(INFD_IS_STORAGE(storage), FALSE); g_return_val_if_fail(path != NULL, FALSE); g_return_val_if_fail(error == NULL || *error == NULL, FALSE); iface = INFD_STORAGE_GET_IFACE(storage); g_return_val_if_fail(iface->write_acl != NULL, FALSE); return iface->write_acl(storage, path, sheet_set, error); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/server/PaxHeaders.26529/infd-filesystem-storage.h0000644000000000000000000000013213034342512024343 xustar0030 mtime=1483851082.041718492 30 atime=1483851082.041718492 30 ctime=1488261589.004139056 libinfinity-0.7.1/libinfinity/server/infd-filesystem-storage.h0000644000175000017500000001015013034342512025072 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INFD_FILESYSTEM_STORAGE_H__ #define __INFD_FILESYSTEM_STORAGE_H__ #include #include #include G_BEGIN_DECLS #define INFD_TYPE_FILESYSTEM_STORAGE (infd_filesystem_storage_get_type()) #define INFD_FILESYSTEM_STORAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INFD_TYPE_FILESYSTEM_STORAGE, InfdFilesystemStorage)) #define INFD_FILESYSTEM_STORAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INFD_TYPE_FILESYSTEM_STORAGE, InfdFilesystemStorageClass)) #define INFD_IS_FILESYSTEM_STORAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INFD_TYPE_FILESYSTEM_STORAGE)) #define INFD_IS_FILESYSTEM_STORAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INFD_TYPE_FILESYSTEM_STORAGE)) #define INFD_FILESYSTEM_STORAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INFD_TYPE_FILESYSTEM_STORAGE, InfdFilesystemStorageClass)) typedef struct _InfdFilesystemStorage InfdFilesystemStorage; typedef struct _InfdFilesystemStorageClass InfdFilesystemStorageClass; typedef enum _InfdFilesystemStorageError { /* The path contains invalid characters */ INFD_FILESYSTEM_STORAGE_ERROR_INVALID_PATH, /* Failed to remove files from disk */ INFD_FILESYSTEM_STORAGE_ERROR_REMOVE_FILES, /* File has invaild format */ INFD_FILESYSTEM_STORAGE_ERROR_INVALID_FORMAT, INFD_FILESYSTEM_STORAGE_ERROR_FAILED } InfdFilesystemStorageError; struct _InfdFilesystemStorageClass { GObjectClass parent_class; }; struct _InfdFilesystemStorage { GObject parent; }; GType infd_filesystem_storage_get_type(void) G_GNUC_CONST; InfdFilesystemStorage* infd_filesystem_storage_new(const gchar* root_directory); gchar* infd_filesystem_storage_get_path(InfdFilesystemStorage* storage, const gchar* identifier, const gchar* path, GError** error); FILE* infd_filesystem_storage_open(InfdFilesystemStorage* storage, const gchar* identifier, const gchar* path, const gchar* mode, gchar** full_path, GError** error); xmlDocPtr infd_filesystem_storage_read_xml_file(InfdFilesystemStorage* storage, const gchar* identifier, const gchar* path, const gchar* toplevel_tag, GError** error); gboolean infd_filesystem_storage_write_xml_file(InfdFilesystemStorage* storage, const gchar* identifier, const gchar* path, xmlDocPtr doc, GError** error); int infd_filesystem_storage_stream_close(FILE* file); gsize infd_filesystem_storage_stream_read(FILE* file, gpointer buffer, gsize len); gsize infd_filesystem_storage_stream_write(FILE* file, gconstpointer buffer, gsize len); G_END_DECLS #endif /* __INFD_FILESYSTEM_STORAGE_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/server/PaxHeaders.26529/infd-filesystem-account-storage.h0000644000000000000000000000013213034342512025775 xustar0030 mtime=1483851082.041718492 30 atime=1483851082.041718492 30 ctime=1488261589.004139056 libinfinity-0.7.1/libinfinity/server/infd-filesystem-account-storage.h0000644000175000017500000001007113034342512026526 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INFD_FILESYSTEM_ACCOUNT_STORAGE_H__ #define __INFD_FILESYSTEM_ACCOUNT_STORAGE_H__ #include #include G_BEGIN_DECLS #define INFD_TYPE_FILESYSTEM_ACCOUNT_STORAGE (infd_filesystem_account_storage_get_type()) #define INFD_FILESYSTEM_ACCOUNT_STORAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INFD_TYPE_FILESYSTEM_ACCOUNT_STORAGE, InfdFilesystemAccountStorage)) #define INFD_FILESYSTEM_ACCOUNT_STORAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INFD_TYPE_FILESYSTEM_ACCOUNT_STORAGE, InfdFilesystemAccountStorageClass)) #define INFD_IS_FILESYSTEM_ACCOUNT_STORAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INFD_TYPE_FILESYSTEM_ACCOUNT_STORAGE)) #define INFD_IS_FILESYSTEM_ACCOUNT_STORAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INFD_TYPE_FILESYSTEM_ACCOUNT_STORAGE)) #define INFD_FILESYSTEM_ACCOUNT_STORAGE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INFD_TYPE_FILESYSTEM_ACCOUNT_STORAGE, InfdFilesystemAccountStorageClass)) typedef struct _InfdFilesystemAccountStorage InfdFilesystemAccountStorage; typedef struct _InfdFilesystemAccountStorageClass InfdFilesystemAccountStorageClass; /** * InfdFilesystemAccountStorageError: * @INFD_FILESYSTEM_ACCOUNT_STORAGE_ERROR_INVALID_FORMAT: An on-disk XML file * is not formatted correctly. * @INFD_FILESYSTEM_ACCOUNT_STORAGE_ERROR_DUPLICATE_NAME: An account name is * already in use. * @INFD_FILESYSTEM_ACCOUNT_STORAGE_ERROR_DUPLICATE_CERTIFICATE: An account * which uses the same certificate to login exists already. * @INFD_FILESYSTEM_ACCOUNT_STORAGE_ERROR_IDS_EXHAUSTED: Could not * obtain a unique account ID. * @INFD_FILESYSTEM_ACCOUNT_STORAGE_ERROR_NO_SUCH_ACCOUNT: The account with * the given ID does not exist. * * Specifies the possible error codes in the * INFD_FILESYSTEM_ACCOUNT_STORAGE_ERROR error domain. * Such errors can occur when reading the accounts file from disk. */ typedef enum _InfdFilesystemAccountStorageError { INFD_FILESYSTEM_ACCOUNT_STORAGE_ERROR_INVALID_FORMAT, INFD_FILESYSTEM_ACCOUNT_STORAGE_ERROR_DUPLICATE_NAME, INFD_FILESYSTEM_ACCOUNT_STORAGE_ERROR_DUPLICATE_CERTIFICATE, INFD_FILESYSTEM_ACCOUNT_STORAGE_ERROR_IDS_EXHAUSTED, INFD_FILESYSTEM_ACCOUNT_STORAGE_ERROR_NO_SUCH_ACCOUNT } InfdFilesystemAccountStorageError; /** * InfdFilesystemAccountStorageClass: * * This structure does not contain any public fields. */ struct _InfdFilesystemAccountStorageClass { /*< private >*/ GObjectClass parent_class; }; /** * InfdFilesystemAccountStorage: * * #InfdFilesystemAccountStorage is an opaque data type. You should only * access it via the public API functions. */ struct _InfdFilesystemAccountStorage { /*< private >*/ GObject parent; }; GType infd_filesystem_account_storage_get_type(void) G_GNUC_CONST; InfdFilesystemAccountStorage* infd_filesystem_account_storage_new(void); gboolean infd_filesystem_account_storage_set_filesystem(InfdFilesystemAccountStorage* s, InfdFilesystemStorage* fs, GError** error); G_END_DECLS #endif /* __INFD_FILESYSTEM_ACCOUNT_STORAGE_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/server/PaxHeaders.26529/infd-xmpp-server.h0000644000000000000000000000013213034342512023005 xustar0030 mtime=1483851082.045718513 30 atime=1483851082.045718513 30 ctime=1488261589.012139039 libinfinity-0.7.1/libinfinity/server/infd-xmpp-server.h0000644000175000017500000000542213034342512023542 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INFD_XMPP_SERVER_H__ #define __INFD_XMPP_SERVER_H__ #include #include #include #include /* Get ssize_t on MSVC, required by gnutls.h */ #include #include G_BEGIN_DECLS #define INFD_TYPE_XMPP_SERVER (infd_xmpp_server_get_type()) #define INFD_XMPP_SERVER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INFD_TYPE_XMPP_SERVER, InfdXmppServer)) #define INFD_XMPP_SERVER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INFD_TYPE_XMPP_SERVER, InfdXmppServerClass)) #define INFD_IS_XMPP_SERVER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INFD_TYPE_XMPP_SERVER)) #define INFD_IS_XMPP_SERVER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INFD_TYPE_XMPP_SERVER)) #define INFD_XMPP_SERVER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INFD_TYPE_XMPP_SERVER, InfdXmppServerClass)) typedef struct _InfdXmppServer InfdXmppServer; typedef struct _InfdXmppServerClass InfdXmppServerClass; struct _InfdXmppServerClass { GObjectClass parent_class; /* Signals */ void (*error)(InfdXmppServer* server, GError* error); }; struct _InfdXmppServer { GObject parent; }; GType infd_xmpp_server_get_type(void) G_GNUC_CONST; InfdXmppServer* infd_xmpp_server_new(InfdTcpServer* tcp, InfXmppConnectionSecurityPolicy policy, InfCertificateCredentials* creds, InfSaslContext* sasl_context, const gchar* sasl_mechanisms); void infd_xmpp_server_set_security_policy(InfdXmppServer* server, InfXmppConnectionSecurityPolicy policy); InfXmppConnectionSecurityPolicy infd_xmpp_server_get_security_policy(InfdXmppServer* server); G_END_DECLS #endif /* __INFD_XMPP_SERVER_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/server/PaxHeaders.26529/infd-chat-filesystem-format.c0000644000000000000000000000013213034342512025077 xustar0030 mtime=1483851082.041718492 30 atime=1483851082.041718492 30 ctime=1488261589.116138812 libinfinity-0.7.1/libinfinity/server/infd-chat-filesystem-format.c0000644000175000017500000001576213034342512025644 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:infd-chat-filesystem-format * @title: Storage of chat sessions on the file system * @short_description: Utility functions to deal with storing * #InfChatSessions in filesystem storage * @include: libinfinity/server/infd-chat-filesystem-storage.h * @see_also: #InfChatSession, #InfdFilesystemStorage * @stability: Unstable * * The functions in this section are utility functions that can be used when * implementing a #InfdNotePlugin to handle #InfChatSessions. These * functions implement reading and writing the content of an #InfChatSession * to an XML file in the storage. */ #include #include #include static GQuark infd_chat_filesystem_format_error_quark() { return g_quark_from_static_string("INFD_CHAT_FILESYSTEM_FORMAT_ERROR"); } static int infd_chat_filesystem_format_read_read_func(void* context, char* buffer, int len) { gsize res; res = infd_filesystem_storage_stream_read((FILE*)context, buffer, len); if(ferror((FILE*)context)) return -1; return (int)res; } static int infd_chat_filesystem_format_read_close_func(void* context) { return infd_filesystem_storage_stream_close((FILE*)context); } /** * infd_chat_filesystem_format_read: * @storage: A #InfdFilesystemStorage. * @path: Storage path to retrieve the session from. * @buffer: An empty #InfTextBuffer to use as the new session's buffer. * @error: Location to store error information, if any, or %NULL. * * Reads a chat session from @path in @storage. The file is expected to have * been saved with infd_chat_filesystem_format_write() before. The @buffer * parameter should be an empty #InfChatBuffer, and the document will be * written into this buffer. If the function succeeds, the buffer can be used * to create an #InfChatSession with inf_chat_session_new(). If the function * fails, %FALSE is returned and @error is set. * * Returns: %TRUE on success or %FALSE on error. */ gboolean infd_chat_filesystem_format_read(InfdFilesystemStorage* storage, const gchar* path, InfChatBuffer* buffer, GError** error) { FILE* stream; gchar* full_path; gchar* uri; xmlDocPtr doc; xmlErrorPtr xmlerror; xmlNodePtr root; xmlNodePtr child; gboolean result; g_return_val_if_fail(INFD_IS_FILESYSTEM_STORAGE(storage), FALSE); g_return_val_if_fail(path != NULL, FALSE); g_return_val_if_fail(INF_IS_CHAT_BUFFER(buffer), FALSE); g_return_val_if_fail(error == NULL || *error == NULL, FALSE); /* TODO: Use a SAX parser for better performance */ full_path = NULL; stream = infd_filesystem_storage_open( INFD_FILESYSTEM_STORAGE(storage), "InfChat", path, "r", &full_path, error ); if(stream == NULL) { g_free(full_path); return FALSE; } uri = g_filename_to_uri(full_path, NULL, error); g_free(full_path); if(uri == NULL) return FALSE; doc = xmlReadIO( infd_chat_filesystem_format_read_read_func, infd_chat_filesystem_format_read_close_func, stream, uri, "UTF-8", XML_PARSE_NOWARNING | XML_PARSE_NOERROR ); g_free(uri); if(doc == NULL) { xmlerror = xmlGetLastError(); g_set_error( error, g_quark_from_static_string("LIBXML2_PARSER_ERROR"), xmlerror->code, _("Error parsing XML in file \"%s\": [%d]: %s"), path, xmlerror->line, xmlerror->message ); result = FALSE; } else { root = xmlDocGetRootElement(doc); if(strcmp((const char*)root->name, "inf-chat-session") != 0) { g_set_error( error, infd_chat_filesystem_format_error_quark(), INFD_CHAT_FILESYSTEM_FORMAT_ERROR_NOT_A_CHAT_SESSION, _("Error processing file \"%s\": %s"), path, _("The document is not a chat session") ); result = FALSE; } else { result = TRUE; } xmlFreeDoc(doc); } if(result == FALSE) return FALSE; return TRUE; } /** * infd_chat_filesystem_format_write: * @storage: A #InfdFilesystemStorage. * @path: Storage path where to write the session to. * @buffer: The #InfChatBuffer to write. * @error: Location to store error information, if any, or %NULL. * * Writes the given buffer into the filesystem storage at @path. If * successful, the session can then be read back with * infd_chat_filesystem_format_read(). If the function fails, %FALSE is * returned and @error is set. * * Returns: %TRUE on success or %FALSE on error. */ gboolean infd_chat_filesystem_format_write(InfdFilesystemStorage* storage, const gchar* path, InfChatBuffer* buffer, GError** error) { FILE* stream; xmlDocPtr doc; xmlNodePtr root; xmlErrorPtr xmlerror; g_return_val_if_fail(INFD_IS_FILESYSTEM_STORAGE(storage), FALSE); g_return_val_if_fail(path != NULL, FALSE); g_return_val_if_fail(INF_IS_CHAT_BUFFER(buffer), FALSE); g_return_val_if_fail(error == NULL || *error == NULL, FALSE); /* Open stream before exporting buffer to XML so possible errors are * catched earlier. */ stream = infd_filesystem_storage_open( INFD_FILESYSTEM_STORAGE(storage), "InfChat", path, "w", NULL, error ); if(stream == NULL) return FALSE; root = xmlNewNode(NULL, (const xmlChar*)"inf-chat-session"); doc = xmlNewDoc((const xmlChar*)"1.0"); xmlDocSetRootElement(doc, root); /* TODO: At this point, we should tell libxml2 to use * infd_filesystem_storage_stream_write() instead of fwrite(), * to prevent C runtime mixups. */ if(xmlDocFormatDump(stream, doc, 1) == -1) { xmlerror = xmlGetLastError(); infd_filesystem_storage_stream_close(stream); xmlFreeDoc(doc); g_set_error_literal( error, g_quark_from_static_string("LIBXML2_OUTPUT_ERROR"), xmlerror->code, xmlerror->message ); return FALSE; } infd_filesystem_storage_stream_close(stream); xmlFreeDoc(doc); return TRUE; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/server/PaxHeaders.26529/infd-request.c0000644000000000000000000000013213034342512022200 xustar0030 mtime=1483851082.041718492 30 atime=1483851082.041718492 30 ctime=1488261589.124138795 libinfinity-0.7.1/libinfinity/server/infd-request.c0000644000175000017500000001436613034342512022744 0ustar00arminarmin00000000000000/* infdinote - Collaborative notetaking application * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:infd-request * @title: InfdRequest * @short_description: Asynchronous request on the server side * @include: libinfinity/server/infd-request.h * @see_also: #InfdDirectory, #InfRequest * @stability: Unstable * * #InfdRequest represents an asynchronous operation carried out on the * server side. It has the #InfdRequest:requestor property which specifies * which connection triggered the request, if any. */ #include #include #include typedef struct _InfdRequestPrivate InfdRequestPrivate; struct _InfdRequestPrivate { gchar* type; guint node_id; InfXmlConnection* requestor; gboolean finished; }; enum { PROP_0, PROP_TYPE, PROP_NODE_ID, PROP_REQUESTOR, PROP_PROGRESS }; #define INFD_REQUEST_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INFD_TYPE_REQUEST, InfdRequestPrivate)) static void infd_request_request_iface_init(InfRequestInterface* iface); G_DEFINE_TYPE_WITH_CODE(InfdRequest, infd_request, G_TYPE_OBJECT, G_ADD_PRIVATE(InfdRequest) G_IMPLEMENT_INTERFACE(INF_TYPE_REQUEST, infd_request_request_iface_init)) static void infd_request_init(InfdRequest* request) { InfdRequestPrivate* priv; priv = INFD_REQUEST_PRIVATE(request); priv->type = NULL; priv->node_id = G_MAXUINT; priv->requestor = NULL; priv->finished = FALSE; } static void infd_request_dispose(GObject* object) { InfdRequest* request; InfdRequestPrivate* priv; request = INFD_REQUEST(object); priv = INFD_REQUEST_PRIVATE(request); if(priv->requestor != NULL) { g_object_unref(priv->requestor); priv->requestor = NULL; } G_OBJECT_CLASS(infd_request_parent_class)->dispose(object); } static void infd_request_finalize(GObject* object) { InfdRequest* request; InfdRequestPrivate* priv; request = INFD_REQUEST(object); priv = INFD_REQUEST_PRIVATE(request); g_free(priv->type); G_OBJECT_CLASS(infd_request_parent_class)->finalize(object); } static void infd_request_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfdRequest* request; InfdRequestPrivate* priv; request = INFD_REQUEST(object); priv = INFD_REQUEST_PRIVATE(request); switch(prop_id) { case PROP_TYPE: g_assert(priv->type == NULL); /* construct only */ priv->type = g_value_dup_string(value); break; case PROP_NODE_ID: g_assert(priv->node_id == G_MAXUINT); /* construct only */ priv->node_id = g_value_get_uint(value); break; case PROP_REQUESTOR: g_assert(priv->requestor == NULL); /* construct only */ priv->requestor = g_value_dup_object(value); break; case PROP_PROGRESS: /* read only */ default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void infd_request_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfdRequest* request; InfdRequestPrivate* priv; request = INFD_REQUEST(object); priv = INFD_REQUEST_PRIVATE(request); switch(prop_id) { case PROP_TYPE: g_value_set_string(value, priv->type); break; case PROP_NODE_ID: g_value_set_uint(value, priv->node_id); break; case PROP_REQUESTOR: g_value_set_object(value, priv->requestor); break; case PROP_PROGRESS: if(priv->finished == TRUE) g_value_set_double(value, 1.0); else g_value_set_double(value, 0.0); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void infd_request_request_finished(InfRequest* request, const InfRequestResult* result, const GError* error) { InfdRequestPrivate* priv; priv = INFD_REQUEST_PRIVATE(request); priv->finished = TRUE; g_object_notify(G_OBJECT(request), "progress"); } static gboolean infd_request_request_is_local(InfRequest* request) { InfdRequestPrivate* priv; priv = INFD_REQUEST_PRIVATE(request); if(priv->requestor != NULL) return FALSE; return TRUE; } static void infd_request_class_init(InfdRequestClass* request_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(request_class); object_class->dispose = infd_request_dispose; object_class->finalize = infd_request_finalize; object_class->set_property = infd_request_set_property; object_class->get_property = infd_request_get_property; g_object_class_install_property( object_class, PROP_REQUESTOR, g_param_spec_object( "requestor", "Requestor", "The connection making the request", INF_TYPE_XML_CONNECTION, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_NODE_ID, g_param_spec_uint( "node-id", "Node ID", "The ID of the node affected by the request", 0, G_MAXUINT, G_MAXUINT, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_override_property(object_class, PROP_TYPE, "type"); g_object_class_override_property(object_class, PROP_PROGRESS, "progress"); } static void infd_request_request_iface_init(InfRequestInterface* iface) { iface->finished = infd_request_request_finished; iface->is_local = infd_request_request_is_local; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/server/PaxHeaders.26529/infd-xml-server.c0000644000000000000000000000013213034342512022614 xustar0030 mtime=1483851082.045718513 30 atime=1483851082.045718513 30 ctime=1488261589.132138777 libinfinity-0.7.1/libinfinity/server/infd-xml-server.c0000644000175000017500000000601313034342512023346 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include static const GEnumValue infd_xml_server_status_values[] = { { INFD_XML_SERVER_CLOSED, "INFD_XML_SERVER_CLOSED", "closed" }, { INFD_XML_SERVER_CLOSING, "INFD_XML_SERVER_CLOSING", "closing" }, { INFD_XML_SERVER_OPEN, "INFD_XML_SERVER_OPEN", "open" }, { INFD_XML_SERVER_OPENING, "INFD_XML_SERVER_OPENING", "opening" }, { 0, NULL, NULL } }; INF_DEFINE_ENUM_TYPE(InfdXmlServerStatus, infd_xml_server_status, infd_xml_server_status_values) G_DEFINE_INTERFACE(InfdXmlServer, infd_xml_server, G_TYPE_OBJECT) enum { NEW_CONNECTION, LAST_SIGNAL }; static guint server_signals[LAST_SIGNAL]; static void infd_xml_server_default_init(InfdXmlServerInterface* iface) { server_signals[NEW_CONNECTION] = g_signal_new( "new-connection", INFD_TYPE_XML_SERVER, G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfdXmlServerInterface, new_connection), NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, INF_TYPE_XML_CONNECTION ); g_object_interface_install_property( iface, g_param_spec_enum( "status", "XmlServer Status", "The status of the server", INFD_TYPE_XML_SERVER_STATUS, INFD_XML_SERVER_CLOSED, G_PARAM_READABLE ) ); } /** * infd_xml_server_close: * @server: A #InfdXmlServer. * * Closes @server. **/ void infd_xml_server_close(InfdXmlServer* server) { InfdXmlServerInterface* iface; g_return_if_fail(INFD_IS_XML_SERVER(server)); iface = INFD_XML_SERVER_GET_IFACE(server); g_return_if_fail(iface->close); iface->close(server); } /** * infd_xml_server_new_connection: * @server: A #InfdXmlServer. * @connection: A #InfXmlConnection. * * Emits the "new-connection" signal on @server. **/ void infd_xml_server_new_connection(InfdXmlServer* server, InfXmlConnection* connection) { g_return_if_fail(INFD_IS_XML_SERVER(server)); g_return_if_fail(INF_IS_XML_CONNECTION(connection)); g_signal_emit( G_OBJECT(server), server_signals[NEW_CONNECTION], 0, connection ); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/server/PaxHeaders.26529/infd-note-plugin.h0000644000000000000000000000013213034342512022756 xustar0030 mtime=1483851082.041718492 30 atime=1483851082.041718492 30 ctime=1488261589.004139056 libinfinity-0.7.1/libinfinity/server/infd-note-plugin.h0000644000175000017500000000553313034342512023516 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INFD_NOTE_PLUGIN_H__ #define __INFD_NOTE_PLUGIN_H__ #include #include #include #include #include #include G_BEGIN_DECLS /* TODO: GTypeModule stuff? */ typedef InfSession*(*InfdNotePluginSessionNew)(InfIo*, InfCommunicationManager*, InfSessionStatus, InfCommunicationGroup*, InfXmlConnection*, const char*, gpointer); typedef InfSession*(*InfdNotePluginSessionRead)(InfdStorage*, InfIo*, InfCommunicationManager*, const gchar*, gpointer, GError**); typedef gboolean(*InfdNotePluginSessionWrite)(InfdStorage*, InfSession*, const gchar*, gpointer, GError**); typedef struct _InfdNotePlugin InfdNotePlugin; struct _InfdNotePlugin { gpointer user_data; /* The typename of the storage backend this plugin can be used with, such * as InfdFilesystemStorage. */ const gchar* storage_type; /* The note type this plugin handles, such as InfText */ const gchar* note_type; InfdNotePluginSessionNew session_new; InfdNotePluginSessionRead session_read; InfdNotePluginSessionWrite session_write; }; G_END_DECLS #endif /* __INFD_NOTE_PLUGIN_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/server/PaxHeaders.26529/infd-session-proxy.h0000644000000000000000000000013213034342512023357 xustar0030 mtime=1483851082.045718513 30 atime=1483851082.045718513 30 ctime=1488261589.008139048 libinfinity-0.7.1/libinfinity/server/infd-session-proxy.h0000644000175000017500000000736213034342512024121 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INFD_SESSION_PROXY_H__ #define __INFD_SESSION_PROXY_H__ #include #include G_BEGIN_DECLS #define INFD_TYPE_SESSION_PROXY (infd_session_proxy_get_type()) #define INFD_SESSION_PROXY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INFD_TYPE_SESSION_PROXY, InfdSessionProxy)) #define INFD_SESSION_PROXY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INFD_TYPE_SESSION_PROXY, InfdSessionProxyClass)) #define INFD_IS_SESSION_PROXY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INFD_TYPE_SESSION_PROXY)) #define INFD_IS_SESSION_PROXY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INFD_TYPE_SESSION_PROXY)) #define INFD_SESSION_PROXY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INFD_TYPE_SESSION_PROXY, InfdSessionProxyClass)) typedef struct _InfdSessionProxy InfdSessionProxy; typedef struct _InfdSessionProxyClass InfdSessionProxyClass; /** * InfdSessionProxyClass: * @add_subscription: Default signal handler for the * #InfdSessionProxy::add-subscription signal. * @remove_subscription: Default signal handler for the * #InfdSessionProxy::remove-subscription signal. * @reject_user_join: Default signal handler for the * #InfdSessionProxy::reject-user-join signal. * * This structure contains the default signal handlers of the * #InfdSessionProxy class. */ struct _InfdSessionProxyClass { /*< private >*/ GObjectClass parent_class; /*< public >*/ /* Signals */ void (*add_subscription)(InfdSessionProxy* proxy, InfXmlConnection* connection, guint seq_id); void (*remove_subscription)(InfdSessionProxy* proxy, InfXmlConnection* connection); gboolean (*reject_user_join)(InfdSessionProxy* proxy, InfXmlConnection* connection, const GArray* user_properties, InfUser* rejoin_user); }; /** * InfdSessionProxy: * * #InfdSessionProxy is an opaque data type. You should only access it via the * public API functions. */ struct _InfdSessionProxy { /*< private >*/ GObject parent; }; GType infd_session_proxy_get_type(void) G_GNUC_CONST; void infd_session_proxy_subscribe_to(InfdSessionProxy* proxy, InfXmlConnection* connection, guint seq_id, gboolean synchronize); void infd_session_proxy_unsubscribe(InfdSessionProxy* proxy, InfXmlConnection* connection); gboolean infd_session_proxy_has_subscriptions(InfdSessionProxy* proxy); gboolean infd_session_proxy_is_subscribed(InfdSessionProxy* proxy, InfXmlConnection* connection); gboolean infd_session_proxy_is_idle(InfdSessionProxy* proxy); G_END_DECLS #endif /* __INFD_SESSION_PROXY_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/server/PaxHeaders.26529/infd-progress-request.c0000644000000000000000000000013213034342512024042 xustar0030 mtime=1483851082.041718492 30 atime=1483851082.041718492 30 ctime=1488261589.124138795 libinfinity-0.7.1/libinfinity/server/infd-progress-request.c0000644000175000017500000001400513034342512024574 0ustar00arminarmin00000000000000/* infdinote - Collaborative notetaking application * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:infd-progress-request * @title: InfdProgressRequest * @short_description: Watch progress of node exploration * @include: libinfinity/server/infd-progress-request.h * @see_also: #InfRequest, #InfdRequest, #InfdDirectory * @stability: Unstable * * This class represents a request which consists of multiple steps and * for which progress on the overall operation is reported. */ #include typedef struct _InfdProgressRequestPrivate InfdProgressRequestPrivate; struct _InfdProgressRequestPrivate { guint current; guint total; gboolean initiated; }; enum { PROP_0, PROP_CURRENT, PROP_TOTAL, PROP_PROGRESS }; #define INFD_PROGRESS_REQUEST_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INFD_TYPE_PROGRESS_REQUEST, InfdProgressRequestPrivate)) G_DEFINE_TYPE_WITH_CODE(InfdProgressRequest, infd_progress_request, INFD_TYPE_REQUEST, G_ADD_PRIVATE(InfdProgressRequest)) static void infd_progress_request_init(InfdProgressRequest* request) { InfdProgressRequestPrivate* priv; priv = INFD_PROGRESS_REQUEST_PRIVATE(request); priv->current = 0; priv->total = 0; priv->initiated = FALSE; } static void infd_progress_request_finalize(GObject* object) { InfdProgressRequest* request; InfdProgressRequestPrivate* priv; request = INFD_PROGRESS_REQUEST(object); priv = INFD_PROGRESS_REQUEST_PRIVATE(request); G_OBJECT_CLASS(infd_progress_request_parent_class)->finalize(object); } static void infd_progress_request_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfdProgressRequest* request; InfdProgressRequestPrivate* priv; request = INFD_PROGRESS_REQUEST(object); priv = INFD_PROGRESS_REQUEST_PRIVATE(request); switch(prop_id) { case PROP_TOTAL: case PROP_CURRENT: case PROP_PROGRESS: /* readonly */ default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void infd_progress_request_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfdProgressRequest* progress_request; InfdProgressRequestPrivate* priv; gboolean finished; progress_request = INFD_PROGRESS_REQUEST(object); priv = INFD_PROGRESS_REQUEST_PRIVATE(progress_request); switch(prop_id) { case PROP_TOTAL: g_value_set_uint(value, priv->total); break; case PROP_CURRENT: g_value_set_uint(value, priv->current); break; case PROP_PROGRESS: if(priv->initiated == FALSE) g_value_set_double(value, 0.0); else if(priv->total == 0) g_value_set_double(value, 1.0); else g_value_set_double(value, (double)priv->current / (double)priv->total); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void infd_progress_request_class_init(InfdProgressRequestClass* request_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(request_class); object_class->finalize = infd_progress_request_finalize; object_class->set_property = infd_progress_request_set_property; object_class->get_property = infd_progress_request_get_property; g_object_class_install_property( object_class, PROP_CURRENT, g_param_spec_uint( "current", "Current", "The current number of finished operations", 0, G_MAXUINT, 0, G_PARAM_READABLE ) ); g_object_class_install_property( object_class, PROP_TOTAL, g_param_spec_uint( "total", "Total", "The total number of operations", 0, G_MAXUINT, 0, G_PARAM_READABLE ) ); g_object_class_override_property(object_class, PROP_PROGRESS, "progress"); } /** * infd_progress_request_initiated: * @request: A #InfdProgressRequest. * @total: The total number of operations. * * Initiates the request. A progress request is considered initiated as soon * as the total number of operations is known. **/ void infd_progress_request_initiated(InfdProgressRequest* request, guint total) { InfdProgressRequestPrivate* priv; g_return_if_fail(INFD_IS_PROGRESS_REQUEST(request)); priv = INFD_PROGRESS_REQUEST_PRIVATE(request); g_return_if_fail(priv->initiated == FALSE); priv->total = total; priv->initiated = TRUE; g_object_notify(G_OBJECT(request), "total"); if(priv->total == 0) g_object_notify(G_OBJECT(request), "progress"); } /** * infd_progress_request_progress: * @request: A #InfdProgressRequest. * * Indicates that one more operation has been finished and changes the * #InfdProgressRequest:current property accordingly. **/ void infd_progress_request_progress(InfdProgressRequest* request) { InfdProgressRequestPrivate* priv; g_return_if_fail(INFD_IS_PROGRESS_REQUEST(request)); priv = INFD_PROGRESS_REQUEST_PRIVATE(request); g_return_if_fail(priv->current < priv->total); ++priv->current; g_object_notify(G_OBJECT(request), "current"); g_object_notify(G_OBJECT(request), "progress"); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/server/PaxHeaders.26529/infd-filesystem-account-storage.c0000644000000000000000000000013213034342512025770 xustar0030 mtime=1483851082.041718492 30 atime=1483851082.041718492 30 ctime=1488261589.120138803 libinfinity-0.7.1/libinfinity/server/infd-filesystem-account-storage.c0000644000175000017500000013211213034342512026522 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:infd-filesystem-account-storage * @short_description: Standalone account storage backend * @see_also: #InfdAccountStorage, #InfdDirectory * @include: libinfinity/server/infd-filesystem-account-storage.h * @stability: Unstable * * This class implements the #InfdAccountStorage interface via an underlying * #InfdFilesystemStorage. It uses the "root-directory" of that * underlying storage to store an XML file there which contains the account * information. * * This is a simple implementation of an account storage which keeps all * accounts read from the file in memory. When you have more than a thousand * accounts or so you should start thinking of using a more sophisticated * account storage, for example a database backend. **/ #include #include #include #include #include #include #include #include #include typedef struct _InfdFilesystemAccountStorageAccountInfo InfdFilesystemAccountStorageAccountInfo; struct _InfdFilesystemAccountStorageAccountInfo { InfAclAccountId id; gchar* name; gchar** certificates; guint n_certificates; gchar* password_salt; gchar* password_hash; gint64 first_seen; gint64 last_seen; }; typedef struct _InfdFilesystemAccountStoragePrivate InfdFilesystemAccountStoragePrivate; struct _InfdFilesystemAccountStoragePrivate { InfdFilesystemStorage* filesystem; GHashTable* accounts; /* by ID */ GHashTable* accounts_by_certificate; /* by certificate DN */ GHashTable* accounts_by_name; /* by name */ /* Note that we require names to be unique */ }; enum { PROP_0, PROP_FILESYSTEM_STORAGE }; #define INFD_FILESYSTEM_ACCOUNT_STORAGE_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INFD_TYPE_FILESYSTEM_ACCOUNT_STORAGE, InfdFilesystemAccountStoragePrivate)) static void infd_filesystem_account_storage_account_storage_iface_init(InfdAccountStorageInterface* iface); G_DEFINE_TYPE_WITH_CODE(InfdFilesystemAccountStorage, infd_filesystem_account_storage, G_TYPE_OBJECT, G_ADD_PRIVATE(InfdFilesystemAccountStorage) G_IMPLEMENT_INTERFACE(INFD_TYPE_ACCOUNT_STORAGE, infd_filesystem_account_storage_account_storage_iface_init)) static GQuark infd_filesystem_account_storage_error_quark(void) { return g_quark_from_static_string("INFD_FILESYSTEM_ACCOUNT_STORAGE_ERROR"); } static void infd_filesystem_account_storage_account_info_free(gpointer ptr) { InfdFilesystemAccountStorageAccountInfo* info; guint i; info = (InfdFilesystemAccountStorageAccountInfo*)ptr; g_free(info->name); for(i = 0; i < info->n_certificates; ++i) g_free(info->certificates[i]); g_free(info->certificates); g_free(info->password_salt); g_free(info->password_hash); g_slice_free(InfdFilesystemAccountStorageAccountInfo, info); } static InfdFilesystemAccountStorageAccountInfo* infd_filesystem_account_storage_account_info_from_xml(xmlNodePtr xml, GError** error) { InfdFilesystemAccountStorageAccountInfo* info; xmlChar* id; xmlChar* name; InfAclAccountId account_id; GError* local_error; gboolean has_first_seen; gdouble first_seen; gboolean has_last_seen; gdouble last_seen; xmlChar* password_salt; xmlChar* password_hash; gnutls_datum_t datum; size_t hash_len; int res; gchar* binary_salt; gchar* binary_hash; xmlNodePtr child; GPtrArray* certificate_array; guint i; g_return_val_if_fail(xml != NULL, NULL); g_return_val_if_fail(error == NULL || *error == NULL, NULL); local_error = NULL; has_first_seen = inf_xml_util_get_attribute_double( xml, "first-seen", &first_seen, &local_error ); if(local_error != NULL) { g_propagate_error(error, local_error); return NULL; } has_last_seen = inf_xml_util_get_attribute_double( xml, "last-seen", &last_seen, &local_error ); if(local_error != NULL) { g_propagate_error(error, local_error); return NULL; } id = inf_xml_util_get_attribute_required(xml, "id", error); if(id == NULL) return NULL; account_id = inf_acl_account_id_from_string((const gchar*)id); xmlFree(id); name = inf_xml_util_get_attribute_required(xml, "name", error); if(name == NULL) return NULL; password_salt = inf_xml_util_get_attribute(xml, "password-salt"); password_hash = inf_xml_util_get_attribute(xml, "password-hash"); if( (password_salt != NULL && password_hash == NULL) || (password_salt == NULL && password_hash != NULL)) { g_set_error_literal( error, infd_filesystem_account_storage_error_quark(), INFD_FILESYSTEM_ACCOUNT_STORAGE_ERROR_INVALID_FORMAT, _("If one of \"password-hash\" or \"password-salt\" is provided, the " "other must be provided as well.") ); if(password_salt != NULL) xmlFree(password_salt); if(password_hash != NULL) xmlFree(password_hash); xmlFree(name); return NULL; } if(password_salt != NULL && password_hash != NULL) { datum.data = password_salt; datum.size = strlen(password_salt); hash_len = 32; binary_salt = g_malloc(hash_len); res = gnutls_hex_decode(&datum, binary_salt, &hash_len); xmlFree(password_salt); if(hash_len != 32) { g_set_error_literal( error, infd_filesystem_account_storage_error_quark(), INFD_FILESYSTEM_ACCOUNT_STORAGE_ERROR_INVALID_FORMAT, _("The length of the password salt is incorrect, it should " "be 32 bytes") ); xmlFree(password_hash); g_free(binary_salt); return NULL; } else if(res != GNUTLS_E_SUCCESS) { inf_gnutls_set_error(error, res); xmlFree(password_hash); g_free(binary_salt); xmlFree(name); return NULL; } datum.data = password_hash; datum.size = strlen(password_hash); hash_len = gnutls_hash_get_len(GNUTLS_DIG_SHA256); binary_hash = g_malloc(hash_len); res = gnutls_hex_decode(&datum, binary_hash, &hash_len); xmlFree(password_hash); if(hash_len != gnutls_hash_get_len(GNUTLS_DIG_SHA256)) { g_set_error( error, infd_filesystem_account_storage_error_quark(), INFD_FILESYSTEM_ACCOUNT_STORAGE_ERROR_INVALID_FORMAT, _("The length of the password hash is incorrect, it should be " "%u bytes"), (unsigned int)gnutls_hash_get_len(GNUTLS_DIG_SHA256) ); g_free(binary_salt); g_free(binary_hash); xmlFree(name); return NULL; } else if(res != GNUTLS_E_SUCCESS) { inf_gnutls_set_error(error, res); g_free(binary_salt); g_free(binary_hash); xmlFree(name); return NULL; } } else { binary_salt = NULL; binary_hash = NULL; if(password_salt != NULL) xmlFree(password_salt); if(password_hash != NULL) xmlFree(password_hash); } certificate_array = g_ptr_array_new(); for(child = xml->children; child != NULL; child = child->next) { if(child->type != XML_ELEMENT_NODE) continue; if(strcmp((const char*)child->name, "certificate") == 0) g_ptr_array_add(certificate_array, xmlNodeGetContent(child)); } info = g_slice_new(InfdFilesystemAccountStorageAccountInfo); info->id = account_id; info->name = g_strdup((const gchar*)name); xmlFree(name); info->certificates = g_malloc(sizeof(gchar*) * certificate_array->len); for(i = 0; i < certificate_array->len; ++i) { info->certificates[i] = g_strdup(certificate_array->pdata[i]); xmlFree(certificate_array->pdata[i]); } info->n_certificates = certificate_array->len; g_ptr_array_free(certificate_array, TRUE); info->password_salt = binary_salt; info->password_hash = binary_hash; if(has_first_seen == TRUE) info->first_seen = first_seen * 1e6; else info->first_seen = 0; if(has_last_seen == TRUE) info->last_seen = last_seen * 1e6; else info->last_seen = 0; return info; } static void infd_filesystem_account_storage_account_info_to_xml( const InfdFilesystemAccountStorageAccountInfo* info, xmlNodePtr xml) { guint i; gnutls_datum_t datum; size_t out_size; gchar* out; int res; g_return_if_fail(info != NULL); g_return_if_fail(xml != NULL); inf_xml_util_set_attribute( xml, "id", inf_acl_account_id_to_string(info->id) ); inf_xml_util_set_attribute(xml, "name", info->name); for(i = 0; i < info->n_certificates; ++i) { xmlNewChild( xml, NULL, (const xmlChar*)"certificate", (const xmlChar*)info->certificates[i] ); } if(info->password_salt != NULL) { datum.data = info->password_salt; datum.size = 32; res = gnutls_hex_encode(&datum, NULL, &out_size); g_assert(res == GNUTLS_E_SHORT_MEMORY_BUFFER); out = g_malloc(out_size + 1); res = gnutls_hex_encode(&datum, out, &out_size); g_assert(res == GNUTLS_E_SUCCESS); out[out_size] = '\0'; inf_xml_util_set_attribute(xml, "password-salt", out); g_free(out); } if(info->password_hash != NULL) { datum.data = info->password_hash; datum.size = gnutls_hash_get_len(GNUTLS_DIG_SHA256); res = gnutls_hex_encode(&datum, NULL, &out_size); g_assert(res == GNUTLS_E_SHORT_MEMORY_BUFFER); out = g_malloc(out_size + 1); res = gnutls_hex_encode(&datum, out, &out_size); g_assert(res == GNUTLS_E_SUCCESS); out[out_size] = '\0'; inf_xml_util_set_attribute(xml, "password-hash", out); g_free(out); } if(info->first_seen != 0) { inf_xml_util_set_attribute_double( xml, "first-seen", info->first_seen / 1e6 ); } if(info->last_seen != 0) { inf_xml_util_set_attribute_double( xml, "last-seen", info->last_seen / 1e6 ); } } void infd_filesystem_account_storage_account_info_update_time( InfdFilesystemAccountStorageAccountInfo* info) { GTimeVal timeval; gint64 current_time; g_get_current_time(&timeval); current_time = (gint64)timeval.tv_sec * 1000000 + timeval.tv_usec; if(info->first_seen == 0) info->first_seen = current_time; info->last_seen = current_time; } static gchar* infd_filesystem_account_storage_generate_salt(GError** error) { gchar* salt; int res; salt = g_malloc(32); res = gnutls_rnd(GNUTLS_RND_RANDOM, salt, 32); if(res != GNUTLS_E_SUCCESS) { g_free(salt); inf_gnutls_set_error(error, res); return NULL; } return salt; } static gchar* infd_filesystem_account_storage_hash_password(const gchar* password, const gchar* salt, GError** error) { guint password_len; gchar* salted_password; gchar* hash; int res; password_len = strlen(password); salted_password = g_malloc(32 + password_len); memcpy(salted_password, salt, 16); memcpy(salted_password + 16, password, password_len); memcpy(salted_password + 16 + password_len, salt + 16, 16); hash = g_malloc(gnutls_hash_get_len(GNUTLS_DIG_SHA256)); res = gnutls_hash_fast( GNUTLS_DIG_SHA256, salted_password, 32 + password_len, hash ); g_free(salted_password); if(res != GNUTLS_E_SUCCESS) { g_free(hash); inf_gnutls_set_error(error, res); return FALSE; } return hash; } static GHashTable* infd_filesystem_account_storage_load_file(InfdFilesystemStorage* storage, GError** error) { GHashTable* table; GError* local_error; xmlDocPtr doc; xmlNodePtr root; xmlNodePtr child; InfdFilesystemAccountStorageAccountInfo* info; gpointer id_ptr; table = g_hash_table_new_full( NULL, NULL, NULL, infd_filesystem_account_storage_account_info_free ); local_error = NULL; doc = infd_filesystem_storage_read_xml_file( storage, "xml", "/accounts", "inf-acl-account-list", &local_error ); if(local_error != NULL) { if(local_error->domain == G_FILE_ERROR && local_error->code == G_FILE_ERROR_NOENT) { /* The account file does not exist. This is not an error, but just means * the account list is empty. */ g_error_free(local_error); return table; } g_propagate_error(error, local_error); g_hash_table_destroy(table); return NULL; } root = xmlDocGetRootElement(doc); for(child = root->children; child != NULL; child = child->next) { if(child->type != XML_ELEMENT_NODE) continue; if(strcmp((const char*)child->name, "account") == 0) { info = infd_filesystem_account_storage_account_info_from_xml( child, error ); if(info == NULL) { g_hash_table_destroy(table); return NULL; } id_ptr = INF_ACL_ACCOUNT_ID_TO_POINTER(info->id); if(g_hash_table_lookup(table, id_ptr) != NULL) { g_set_error( error, infd_filesystem_account_storage_error_quark(), INFD_FILESYSTEM_ACCOUNT_STORAGE_ERROR_INVALID_FORMAT, _("Duplicate account ID \"%s\" in file \"%s\""), inf_acl_account_id_to_string(info->id), doc->name ); g_hash_table_destroy(table); return NULL; } g_hash_table_insert(table, id_ptr, info); } } xmlFreeDoc(doc); return table; } /* Given an accounts table, this fills the reverse lookup tables */ static gboolean infd_filesystem_account_storage_xref_account_table(GHashTable* accounts, GHashTable* by_certificate, GHashTable* by_name, GError** error) { GHashTableIter hash_iter; gpointer value; InfdFilesystemAccountStorageAccountInfo* info; InfdFilesystemAccountStorageAccountInfo* other_info; guint i; g_hash_table_iter_init(&hash_iter, accounts); while(g_hash_table_iter_next(&hash_iter, NULL, &value)) { info = (InfdFilesystemAccountStorageAccountInfo*)value; if(info->name != NULL) { other_info = g_hash_table_lookup(by_name, info->name); if(other_info != NULL) { g_set_error( error, infd_filesystem_account_storage_error_quark(), INFD_FILESYSTEM_ACCOUNT_STORAGE_ERROR_DUPLICATE_NAME, _("Accounts \"%s\" and \"%s\" have the same name. This is not " "supported by InfdFilesystemAccountStorage."), inf_acl_account_id_to_string(other_info->id), inf_acl_account_id_to_string(info->id) ); return FALSE; } g_hash_table_insert(by_name, info->name, info); } for(i = 0; i < info->n_certificates; ++i) { other_info = g_hash_table_lookup(by_certificate, info->certificates[i]); if(other_info != NULL) { g_set_error( error, infd_filesystem_account_storage_error_quark(), INFD_FILESYSTEM_ACCOUNT_STORAGE_ERROR_DUPLICATE_CERTIFICATE, _("Accounts \"%s\" and \"%s\" have the same certificate with " "DN=%s. This is not supported by InfdFilesystemAccountStorage."), inf_acl_account_id_to_string(other_info->id), inf_acl_account_id_to_string(info->id), info->certificates[i] ); return FALSE; } g_hash_table_insert(by_certificate, info->certificates[i], info); } } return TRUE; } static gboolean infd_filesystem_account_storage_store_file(InfdFilesystemStorage* storage, GHashTable* table, GError** error) { xmlNodePtr root; xmlNodePtr child; GHashTableIter hash_iter; gpointer value; InfdFilesystemAccountStorageAccountInfo* info; xmlDocPtr doc; gboolean result; root = xmlNewNode(NULL, (const xmlChar*)"inf-acl-account-list"); g_hash_table_iter_init(&hash_iter, table); while(g_hash_table_iter_next(&hash_iter, NULL, &value)) { info = (InfdFilesystemAccountStorageAccountInfo*)value; child = xmlNewChild(root, NULL, (const xmlChar*)"account", NULL); infd_filesystem_account_storage_account_info_to_xml(info, child); } doc = xmlNewDoc((const xmlChar*)"1.0"); xmlDocSetRootElement(doc, root); result = infd_filesystem_storage_write_xml_file( storage, "xml", "accounts", doc, error ); xmlFreeDoc(doc); return result; } static gboolean infd_filesystem_account_storage_set_filesystem_impl( InfdFilesystemAccountStorage* s, InfdFilesystemStorage* fs, GError** error) { InfdFilesystemAccountStoragePrivate* priv; gboolean success; GHashTable* old_accounts; GHashTable* old_accounts_by_name; GHashTable* old_accounts_by_certificate; GHashTable* new_accounts; GHashTable* new_accounts_by_name; GHashTable* new_accounts_by_certificate; GHashTableIter hash_iter; gpointer id_ptr; gpointer value; InfdFilesystemAccountStorageAccountInfo* info; InfAclAccount notify_account; priv = INFD_FILESYSTEM_ACCOUNT_STORAGE_PRIVATE(s); if(priv->filesystem == fs) return TRUE; /* Load the new accounts */ new_accounts = infd_filesystem_account_storage_load_file(fs, error); if(new_accounts == NULL) return FALSE; new_accounts_by_certificate = g_hash_table_new(g_str_hash, g_str_equal); new_accounts_by_name = g_hash_table_new(g_str_hash, g_str_equal); success = infd_filesystem_account_storage_xref_account_table( new_accounts, new_accounts_by_certificate, new_accounts_by_name, error ); if(success == FALSE) { g_hash_table_destroy(new_accounts_by_certificate); g_hash_table_destroy(new_accounts_by_name); g_hash_table_destroy(new_accounts); return FALSE; } if(priv->filesystem != NULL) g_object_unref(priv->filesystem); priv->filesystem = fs; if(fs != NULL) g_object_ref(fs); /* TODO: We should connect to notify::root-directory, and if the root * directory changes, re-load the file and update our accounts, emitting * signals for removed and added accounts. */ /* Okay, new account table is consistent. */ old_accounts = priv->accounts; old_accounts_by_name = priv->accounts_by_name; old_accounts_by_certificate = priv->accounts_by_certificate; priv->accounts = new_accounts; priv->accounts_by_name = new_accounts_by_name; priv->accounts_by_certificate = new_accounts_by_certificate; /* Notify about changed accounts */ g_hash_table_iter_init(&hash_iter, old_accounts); while(g_hash_table_iter_next(&hash_iter, &id_ptr, &value)) { info = (InfdFilesystemAccountStorageAccountInfo*)value; if(g_hash_table_lookup(new_accounts, id_ptr) == NULL) { notify_account.id = info->id; notify_account.name = info->name; infd_account_storage_account_removed( INFD_ACCOUNT_STORAGE(s), ¬ify_account ); } } g_hash_table_iter_init(&hash_iter, new_accounts); while(g_hash_table_iter_next(&hash_iter, &id_ptr, &value)) { info = (InfdFilesystemAccountStorageAccountInfo*)value; if(g_hash_table_lookup(old_accounts, id_ptr) == NULL) { notify_account.id = info->id; notify_account.name = info->name; infd_account_storage_account_added( INFD_ACCOUNT_STORAGE(s), ¬ify_account ); } } g_hash_table_destroy(old_accounts_by_certificate); g_hash_table_destroy(old_accounts_by_name); g_hash_table_destroy(old_accounts); return TRUE; } /* Note this does no collission checks */ static void infd_filesystem_account_storage_add_info( InfdFilesystemAccountStorage* storage, InfdFilesystemAccountStorageAccountInfo* info) { InfdFilesystemAccountStoragePrivate* priv; guint i; priv = INFD_FILESYSTEM_ACCOUNT_STORAGE_PRIVATE(storage); g_hash_table_insert( priv->accounts, INF_ACL_ACCOUNT_ID_TO_POINTER(info->id), info ); g_hash_table_insert(priv->accounts_by_name, info->name, info); for(i = 0; i < info->n_certificates; ++i) { g_hash_table_insert( priv->accounts_by_certificate, info->certificates[i], info ); } } static void infd_filesystem_account_storage_remove_info( InfdFilesystemAccountStorage* storage, InfdFilesystemAccountStorageAccountInfo* info) { InfdFilesystemAccountStoragePrivate* priv; guint i; priv = INFD_FILESYSTEM_ACCOUNT_STORAGE_PRIVATE(storage); for(i = 0; i < info->n_certificates; ++i) g_hash_table_remove(priv->accounts_by_certificate, info->certificates[i]); g_hash_table_remove(priv->accounts_by_name, info->name); g_hash_table_steal(priv->accounts, INF_ACL_ACCOUNT_ID_TO_POINTER(info->id)); } static void infd_filesystem_account_storage_init(InfdFilesystemAccountStorage* storage) { InfdFilesystemAccountStoragePrivate* priv; priv = INFD_FILESYSTEM_ACCOUNT_STORAGE_PRIVATE(storage); priv->filesystem = NULL; priv->accounts = g_hash_table_new_full( NULL, NULL, NULL, infd_filesystem_account_storage_account_info_free ); priv->accounts_by_certificate = g_hash_table_new( g_str_hash, g_str_equal ); priv->accounts_by_name = g_hash_table_new( g_str_hash, g_str_equal ); } static void infd_filesystem_account_storage_dispose(GObject* object) { InfdFilesystemAccountStorage* storage; InfdFilesystemAccountStoragePrivate* priv; storage = INFD_FILESYSTEM_ACCOUNT_STORAGE(object); priv = INFD_FILESYSTEM_ACCOUNT_STORAGE_PRIVATE(storage); if(priv->filesystem != NULL) { g_object_unref(priv->filesystem); priv->filesystem = NULL; } G_OBJECT_CLASS(infd_filesystem_account_storage_parent_class)->dispose(object); } static void infd_filesystem_account_storage_finalize(GObject* object) { InfdFilesystemAccountStorage* storage; InfdFilesystemAccountStoragePrivate* priv; storage = INFD_FILESYSTEM_ACCOUNT_STORAGE(object); priv = INFD_FILESYSTEM_ACCOUNT_STORAGE_PRIVATE(storage); g_hash_table_destroy(priv->accounts_by_name); g_hash_table_destroy(priv->accounts_by_certificate); g_hash_table_destroy(priv->accounts); G_OBJECT_CLASS(infd_filesystem_account_storage_parent_class)->finalize(object); } static void infd_filesystem_account_storage_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfdFilesystemAccountStorage* storage; InfdFilesystemAccountStoragePrivate* priv; GError* error; storage = INFD_FILESYSTEM_ACCOUNT_STORAGE(object); priv = INFD_FILESYSTEM_ACCOUNT_STORAGE_PRIVATE(storage); switch(prop_id) { case PROP_FILESYSTEM_STORAGE: error = NULL; infd_filesystem_account_storage_set_filesystem_impl( storage, INFD_FILESYSTEM_STORAGE(g_value_get_object(value)), &error ); if(error != NULL) { g_warning( _("Failed to read accounts from filesystem: %s"), error->message ); g_error_free(error); } break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void infd_filesystem_account_storage_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfdFilesystemAccountStorage* storage; InfdFilesystemAccountStoragePrivate* priv; storage = INFD_FILESYSTEM_ACCOUNT_STORAGE(object); priv = INFD_FILESYSTEM_ACCOUNT_STORAGE_PRIVATE(storage); switch(prop_id) { case PROP_FILESYSTEM_STORAGE: g_value_set_object(value, G_OBJECT(priv->filesystem)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static InfdAccountStorageSupport infd_filesystem_account_storage_get_support(InfdAccountStorage* storage) { /* We support everything. Note that we don't do notifications, since the * account storage cannot be modified externally (if the file is modified * we don't pick it up). The only point where we make notifications is when * the underlying filesystem is changed. */ return INFD_ACCOUNT_STORAGE_SUPPORT_NOTIFICATION | INFD_ACCOUNT_STORAGE_SUPPORT_LIST_ACCOUNTS | INFD_ACCOUNT_STORAGE_SUPPORT_ADD_ACCOUNT | INFD_ACCOUNT_STORAGE_SUPPORT_REMOVE_ACCOUNT | INFD_ACCOUNT_STORAGE_SUPPORT_CERTIFICATE_LOGIN | INFD_ACCOUNT_STORAGE_SUPPORT_PASSWORD_LOGIN | INFD_ACCOUNT_STORAGE_SUPPORT_CERTIFICATE_CHANGE | INFD_ACCOUNT_STORAGE_SUPPORT_PASSWORD_CHANGE; } static InfAclAccount* infd_filesystem_account_storage_lookup_accounts(InfdAccountStorage* s, const InfAclAccountId* ids, guint n_accounts, GError** error) { InfdFilesystemAccountStorage* storage; InfdFilesystemAccountStoragePrivate* priv; InfAclAccount* result; guint i; InfdFilesystemAccountStorageAccountInfo* info; storage = INFD_FILESYSTEM_ACCOUNT_STORAGE(s); priv = INFD_FILESYSTEM_ACCOUNT_STORAGE_PRIVATE(storage); result = g_malloc(sizeof(InfAclAccount) * n_accounts); for(i = 0; i < n_accounts; ++i) { info = g_hash_table_lookup( priv->accounts, INF_ACL_ACCOUNT_ID_TO_POINTER(ids[i]) ); if(info != NULL) { result[i].id = ids[i]; result[i].name = g_strdup(info->name); } else { result[i].id = 0; result[i].name = NULL; } } return result; } static InfAclAccount* infd_filesystem_account_storage_lookup_accounts_by_name(InfdAccountStorage* s, const gchar* name, guint* n_accounts, GError** error) { InfdFilesystemAccountStorage* storage; InfdFilesystemAccountStoragePrivate* priv; InfdFilesystemAccountStorageAccountInfo* info; InfAclAccount* result; storage = INFD_FILESYSTEM_ACCOUNT_STORAGE(s); priv = INFD_FILESYSTEM_ACCOUNT_STORAGE_PRIVATE(storage); info = g_hash_table_lookup(priv->accounts_by_name, name); if(info == NULL) { *n_accounts = 0; return NULL; } *n_accounts = 1; result = g_malloc(sizeof(InfAclAccount)); result->id = info->id; result->name = g_strdup(info->name); return result; } static InfAclAccount* infd_filesystem_account_storage_list_accounts(InfdAccountStorage* s, guint* n_accounts, GError** error) { InfdFilesystemAccountStorage* storage; InfdFilesystemAccountStoragePrivate* priv; GHashTableIter hash_iter; gpointer value; InfdFilesystemAccountStorageAccountInfo* info; InfAclAccount* result; guint index; storage = INFD_FILESYSTEM_ACCOUNT_STORAGE(s); priv = INFD_FILESYSTEM_ACCOUNT_STORAGE_PRIVATE(storage); *n_accounts = g_hash_table_size(priv->accounts); if(*n_accounts == 0) return NULL; result = g_malloc( (*n_accounts) * sizeof(InfAclAccount)); index = 0; g_hash_table_iter_init(&hash_iter, priv->accounts); while(g_hash_table_iter_next(&hash_iter, NULL, &value)) { info = (InfdFilesystemAccountStorageAccountInfo*)value; result[index].id = info->id; result[index].name = g_strdup(info->name); ++index; } g_assert(index == *n_accounts); return result; } static InfAclAccountId infd_filesystem_account_storage_add_account(InfdAccountStorage* s, const gchar* name, gnutls_x509_crt_t* certs, guint n_certs, const gchar* password, GError** error) { InfdFilesystemAccountStorage* storage; InfdFilesystemAccountStoragePrivate* priv; InfdFilesystemAccountStorageAccountInfo* info; guint i; gchar* dn; gchar* fingerprint; gchar* password_salt; gchar* password_hash; gchar* id_str; InfAclAccountId id; gboolean success; storage = INFD_FILESYSTEM_ACCOUNT_STORAGE(s); priv = INFD_FILESYSTEM_ACCOUNT_STORAGE_PRIVATE(storage); /* Validity checks: */ info = g_hash_table_lookup(priv->accounts_by_name, name); if(info != NULL) { g_set_error( error, infd_filesystem_account_storage_error_quark(), INFD_FILESYSTEM_ACCOUNT_STORAGE_ERROR_DUPLICATE_NAME, _("There is already an account with name \"%s\""), name ); return 0; } if(strlen(name) > 48) { g_set_error_literal( error, infd_filesystem_account_storage_error_quark(), INFD_FILESYSTEM_ACCOUNT_STORAGE_ERROR_INVALID_FORMAT, _("The account name is too long") ); return 0; } for(i = 0; i < n_certs; ++i) { dn = inf_cert_util_get_dn(certs[i]); info = g_hash_table_lookup(priv->accounts_by_certificate, dn); if(info != NULL) { g_set_error( error, infd_filesystem_account_storage_error_quark(), INFD_FILESYSTEM_ACCOUNT_STORAGE_ERROR_DUPLICATE_CERTIFICATE, _("There is already an account with a certificate with DN=\"%s\""), dn ); g_free(dn); return 0; } g_free(dn); /* Also check for the fingerprint, in case some old directories still * use fingerprints. */ fingerprint = inf_cert_util_get_fingerprint(certs[i], GNUTLS_DIG_SHA256); info = g_hash_table_lookup(priv->accounts_by_certificate, fingerprint); if(info != NULL) { g_set_error( error, infd_filesystem_account_storage_error_quark(), INFD_FILESYSTEM_ACCOUNT_STORAGE_ERROR_DUPLICATE_CERTIFICATE, _("There is already an account with a " "certificate with fingerprint=\"%s\""), fingerprint ); g_free(fingerprint); return 0; } g_free(fingerprint); } if(password != NULL) { password_salt = infd_filesystem_account_storage_generate_salt(error); if(password_salt == NULL) return 0; password_hash = infd_filesystem_account_storage_hash_password( password, password_salt, error ); if(password_hash == NULL) { g_free(password_salt); return 0; } } else { password_salt = NULL; password_hash = NULL; } /* Okay, create the account. First, choose an ID */ for(i = 0; i < 10000; ++i) { id_str = g_strdup_printf("fs:user:%s:%x", name, g_random_int()); if(g_hash_table_lookup(priv->accounts, id_str) == NULL) break; g_free(id_str); id_str = NULL; } if(id_str == NULL) { g_set_error( error, infd_filesystem_account_storage_error_quark(), INFD_FILESYSTEM_ACCOUNT_STORAGE_ERROR_IDS_EXHAUSTED, _("Could not generate a unique ID for account with name \"%s\""), name ); g_free(password_hash); g_free(password_salt); return 0; } id = inf_acl_account_id_from_string(id_str); g_free(id_str); info = g_slice_new(InfdFilesystemAccountStorageAccountInfo); info->id = id; info->name = g_strdup(name); info->certificates = g_malloc(sizeof(gchar*) * n_certs); info->n_certificates = n_certs; for(i = 0; i < n_certs; ++i) info->certificates[i] = inf_cert_util_get_dn(certs[i]); info->password_salt = password_salt; info->password_hash = password_hash; info->first_seen = 0; info->last_seen = 0; infd_filesystem_account_storage_add_info(storage, info); success = infd_filesystem_account_storage_store_file( priv->filesystem, priv->accounts, error ); if(success == FALSE) { infd_filesystem_account_storage_remove_info(storage, info); infd_filesystem_account_storage_account_info_free(info); return 0; } return info->id; } static gboolean infd_filesystem_account_storage_remove_account(InfdAccountStorage* s, InfAclAccountId account, GError** error) { InfdFilesystemAccountStorage* storage; InfdFilesystemAccountStoragePrivate* priv; InfdFilesystemAccountStorageAccountInfo* info; guint i; gboolean success; storage = INFD_FILESYSTEM_ACCOUNT_STORAGE(s); priv = INFD_FILESYSTEM_ACCOUNT_STORAGE_PRIVATE(storage); info = g_hash_table_lookup( priv->accounts, INF_ACL_ACCOUNT_ID_TO_POINTER(account) ); if(info == NULL) { g_set_error( error, infd_filesystem_account_storage_error_quark(), INFD_FILESYSTEM_ACCOUNT_STORAGE_ERROR_NO_SUCH_ACCOUNT, _("There is no such account with ID \"%s\""), inf_acl_account_id_to_string(account) ); return FALSE; } infd_filesystem_account_storage_remove_info(storage, info); success = infd_filesystem_account_storage_store_file( priv->filesystem, priv->accounts, error ); if(success == FALSE) { infd_filesystem_account_storage_add_info(storage, info); return FALSE; } infd_filesystem_account_storage_account_info_free(info); return TRUE; } static InfAclAccountId infd_filesystem_account_storage_login_by_certificate(InfdAccountStorage* s, gnutls_x509_crt_t cert, GError** error) { InfdFilesystemAccountStorage* storage; InfdFilesystemAccountStoragePrivate* priv; InfdFilesystemAccountStorageAccountInfo* info; gchar* dn; gchar* fingerprint; guint i; storage = INFD_FILESYSTEM_ACCOUNT_STORAGE(s); priv = INFD_FILESYSTEM_ACCOUNT_STORAGE_PRIVATE(storage); dn = inf_cert_util_get_dn(cert); info = g_hash_table_lookup(priv->accounts_by_certificate, dn); if(info == NULL) { /* If we could not find any certificate with the given DN, then check the * key fingerprint. In an earlier version, we identified users by key and * not by DN, so not to break existing directories, we also need to check * the key fingerprint. If we have a positive match, then we also replace * the fingerprint by the DN of the certificate to silently migrate to DN * everywhere. */ fingerprint = inf_cert_util_get_fingerprint(cert, GNUTLS_DIG_SHA256); info = g_hash_table_lookup(priv->accounts_by_certificate, fingerprint); if(info != NULL) { /* Replace the fingerprint by the DN. Note there is no collision here, * because otherwise we would have found the certificate by DN eralier */ g_hash_table_remove(priv->accounts_by_certificate, fingerprint); g_hash_table_insert(priv->accounts_by_certificate, dn, info); for(i = 0; i < info->n_certificates; ++i) { if(strcmp(info->certificates[i], fingerprint) == 0) { g_free(info->certificates[i]); info->certificates[i] = dn; dn = NULL; break; } } g_assert(i < info->n_certificates); } g_free(fingerprint); } g_free(dn); if(info == NULL) return 0; infd_filesystem_account_storage_account_info_update_time(info); /* Try to save the fingerprint/DN and time change to disk, but if it does * not work, that's okay for now, we still keep the login functional. */ infd_filesystem_account_storage_store_file( priv->filesystem, priv->accounts, NULL ); return info->id; } static InfAclAccountId infd_filesystem_account_storage_login_by_password(InfdAccountStorage* s, const gchar* username, const gchar* password, GError** error) { InfdFilesystemAccountStorage* storage; InfdFilesystemAccountStoragePrivate* priv; InfdFilesystemAccountStorageAccountInfo* info; gchar* hash; gchar cmp; guint i; storage = INFD_FILESYSTEM_ACCOUNT_STORAGE(s); priv = INFD_FILESYSTEM_ACCOUNT_STORAGE_PRIVATE(storage); info = g_hash_table_lookup(priv->accounts_by_name, username); if(info == NULL || info->password_hash == NULL || info->password_salt == NULL) { return 0; } hash = infd_filesystem_account_storage_hash_password( password, info->password_salt, error ); if(hash == NULL) return 0; /* length-independent string compare */ cmp = 0; for(i = 0; i < gnutls_hash_get_len(GNUTLS_DIG_SHA256); ++i) cmp |= (info->password_hash[i] ^ hash[i]); g_free(hash); if(cmp != 0) return 0; infd_filesystem_account_storage_account_info_update_time(info); /* Try to save the fingerprint/DN and time change to disk, but if it does * not work, that's okay for now, we still keep the login functional. */ infd_filesystem_account_storage_store_file( priv->filesystem, priv->accounts, NULL ); return info->id; } static gboolean infd_filesystem_account_storage_set_certificate(InfdAccountStorage* s, InfAclAccountId account, gnutls_x509_crt_t* certs, guint n_certs, GError** error) { InfdFilesystemAccountStorage* storage; InfdFilesystemAccountStoragePrivate* priv; InfdFilesystemAccountStorageAccountInfo* info; InfdFilesystemAccountStorageAccountInfo* cert_info; guint i; gchar* dn; gchar** old_certificates; guint old_n_certificates; gboolean success; storage = INFD_FILESYSTEM_ACCOUNT_STORAGE(s); priv = INFD_FILESYSTEM_ACCOUNT_STORAGE_PRIVATE(storage); info = g_hash_table_lookup( priv->accounts, INF_ACL_ACCOUNT_ID_TO_POINTER(account) ); if(info == NULL) { g_set_error( error, infd_filesystem_account_storage_error_quark(), INFD_FILESYSTEM_ACCOUNT_STORAGE_ERROR_NO_SUCH_ACCOUNT, _("There is no such account with ID \"%s\""), inf_acl_account_id_to_string(account) ); return FALSE; } for(i = 0; i < n_certs; ++i) { dn = inf_cert_util_get_dn(certs[i]); cert_info = g_hash_table_lookup(priv->accounts_by_certificate, dn); if(cert_info != NULL && cert_info != info) { g_set_error( error, infd_filesystem_account_storage_error_quark(), INFD_FILESYSTEM_ACCOUNT_STORAGE_ERROR_DUPLICATE_CERTIFICATE, _("The certificate with DN=%s is already in use by another account"), dn ); g_free(dn); return FALSE; } g_free(dn); } old_certificates = info->certificates; old_n_certificates = info->n_certificates; if(n_certs > 0) { info->certificates = g_malloc(sizeof(gchar*) * n_certs); info->n_certificates = n_certs; for(i = 0; i < n_certs; ++i) info->certificates[i] = inf_cert_util_get_dn(certs[i]); } else { info->certificates = NULL; info->n_certificates = 0; } /* We have not updated the accounts_by_certificate table yet, but before we * do so, we write the accounts file -- if that files, we need to * rollback */ success = infd_filesystem_account_storage_store_file( priv->filesystem, priv->accounts, NULL ); if(success == FALSE) { for(i = 0; i < n_certs; ++i) g_free(info->certificates[i]); g_free(info->certificates); info->certificates = old_certificates; info->n_certificates = old_n_certificates; return FALSE; } for(i = 0; i < old_n_certificates; ++i) { g_hash_table_remove(priv->accounts_by_certificate, old_certificates[i]); g_free(old_certificates[i]); } g_free(old_certificates); for(i = 0; i < n_certs; ++i) { g_hash_table_insert( priv->accounts_by_certificate, info->certificates[i], info ); } return TRUE; } static gboolean infd_filesystem_account_storage_set_password(InfdAccountStorage* s, InfAclAccountId account, const gchar* password, GError** error) { InfdFilesystemAccountStorage* storage; InfdFilesystemAccountStoragePrivate* priv; InfdFilesystemAccountStorageAccountInfo* info; gchar* password_hash; gchar* password_salt; gchar* old_hash; gchar* old_salt; gboolean success; info = g_hash_table_lookup( priv->accounts, INF_ACL_ACCOUNT_ID_TO_POINTER(account) ); if(info == NULL) { g_set_error( error, infd_filesystem_account_storage_error_quark(), INFD_FILESYSTEM_ACCOUNT_STORAGE_ERROR_NO_SUCH_ACCOUNT, _("There is no such account with ID \"%s\""), inf_acl_account_id_to_string(account) ); return FALSE; } if(password != NULL) { password_salt = infd_filesystem_account_storage_generate_salt(error); if(password_salt == NULL) return FALSE; password_hash = infd_filesystem_account_storage_hash_password( password, password_salt, error ); if(password_hash == NULL) { g_free(password_salt); return FALSE; } } else { password_salt = NULL; password_hash = NULL; } old_hash = info->password_hash; old_salt = info->password_salt; info->password_hash = password_hash; info->password_salt = password_salt; /* Try to write the updated password to disk */ success = infd_filesystem_account_storage_store_file( priv->filesystem, priv->accounts, NULL ); if(success == FALSE) { /* rollback */ info->password_hash = old_hash; info->password_salt = old_salt; g_free(password_hash); g_free(password_salt); return FALSE; } g_free(old_hash); g_free(old_salt); return TRUE; } static void infd_filesystem_account_storage_class_init( InfdFilesystemAccountStorageClass* filesystem_account_storage_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(filesystem_account_storage_class); object_class->dispose = infd_filesystem_account_storage_dispose; object_class->finalize = infd_filesystem_account_storage_finalize; object_class->set_property = infd_filesystem_account_storage_set_property; object_class->get_property = infd_filesystem_account_storage_get_property; g_object_class_install_property( object_class, PROP_FILESYSTEM_STORAGE, g_param_spec_object( "filesystem-storage", "Filesystem Storage", "The filesystem storage which to use the store the accounts file", INFD_TYPE_FILESYSTEM_STORAGE, G_PARAM_READWRITE ) ); } static void infd_filesystem_account_storage_account_storage_iface_init( InfdAccountStorageInterface* iface) { iface->get_support = infd_filesystem_account_storage_get_support; iface->lookup_accounts = infd_filesystem_account_storage_lookup_accounts; iface->lookup_accounts_by_name = infd_filesystem_account_storage_lookup_accounts_by_name; iface->list_accounts = infd_filesystem_account_storage_list_accounts; iface->add_account = infd_filesystem_account_storage_add_account; iface->remove_account = infd_filesystem_account_storage_remove_account; iface->login_by_certificate = infd_filesystem_account_storage_login_by_certificate; iface->login_by_password = infd_filesystem_account_storage_login_by_password; iface->set_certificate = infd_filesystem_account_storage_set_certificate; iface->set_password = infd_filesystem_account_storage_set_password; iface->account_added = NULL; iface->account_removed = NULL; } /** * infd_filesystem_account_storage_new: (constructor) * * Creates a new #InfdFilesystemAccountStorage that stores its account list as * a file in the filesystem. Use * infd_filesystem_account_storage_set_filesystem() to set the underlying * #InfdFilesystemStorage object. * * Returns: (transfer full): A new #InfdFilesystemAccountStorage. **/ InfdFilesystemAccountStorage* infd_filesystem_account_storage_new(void) { GObject* object; object = g_object_new( INFD_TYPE_FILESYSTEM_ACCOUNT_STORAGE, NULL ); return INFD_FILESYSTEM_ACCOUNT_STORAGE(object); } /** * infd_filesystem_account_storage_set_filesystem: * @s: A #InfdFilesystemAccountStorage. * @fs: The underlying #InfdFilesystemStorage to use. * @error: Location for error information, if any, or %NULL. * * Uses @fs as the underlying #InfdFilesystemStorage for @s. The * #InfdFilesystemStorage:root-directory property specifies where the account * list is stored. * * If an error occurs while loading the account list, the function returns * %FALSE and @error is set. * * Returns: %TRUE on success or %FALSE on error. */ gboolean infd_filesystem_account_storage_set_filesystem(InfdFilesystemAccountStorage* s, InfdFilesystemStorage* fs, GError** error) { return infd_filesystem_account_storage_set_filesystem_impl(s, fs, error); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/server/PaxHeaders.26529/infd-server-pool.h0000644000000000000000000000013213034342512022772 xustar0030 mtime=1483851082.045718513 30 atime=1483851082.045718513 30 ctime=1488261589.008139048 libinfinity-0.7.1/libinfinity/server/infd-server-pool.h0000644000175000017500000000670013034342512023527 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INFD_SERVER_POOL_H__ #define __INFD_SERVER_POOL_H__ #include #include #include #include #include G_BEGIN_DECLS #define INFD_TYPE_SERVER_POOL (infd_server_pool_get_type()) #define INFD_SERVER_POOL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INFD_TYPE_SERVER_POOL, InfdServerPool)) #define INFD_SERVER_POOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INFD_TYPE_SERVER_POOL, InfdServerPoolClass)) #define INFD_IS_SERVER_POOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INFD_TYPE_SERVER_POOL)) #define INFD_IS_SERVER_POOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INFD_TYPE_SERVER_POOL)) #define INFD_SERVER_POOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INFD_TYPE_SERVER_POOL, InfdServerPoolClass)) typedef struct _InfdServerPool InfdServerPool; typedef struct _InfdServerPoolClass InfdServerPoolClass; /** * InfdServerPoolClass: * * This structure does not contain any public fields. */ struct _InfdServerPoolClass { /*< private >*/ GObjectClass parent_class; }; /** * InfdServerPool: * * #InfdServerPool is an opaque data type. You should only access it via the * public API functions. */ struct _InfdServerPool { /*< private >*/ GObject parent; }; /** * InfdServerPoolForeachServerFunc: * @server: The currently iterated server. * @user_data: Additional data passed to infd_server_pool_foreach_server(). * * This is the callback signature of the callback passed to * infd_server_pool_foreach_server(). */ typedef void(*InfdServerPoolForeachServerFunc)(InfdXmlServer* server, gpointer user_data); GType infd_server_pool_get_type(void) G_GNUC_CONST; InfdServerPool* infd_server_pool_new(InfdDirectory* directory); void infd_server_pool_add_server(InfdServerPool* server_pool, InfdXmlServer* server); void infd_server_pool_add_local_publisher(InfdServerPool* server_pool, InfdXmppServer* server, InfLocalPublisher* publisher); void infd_server_pool_remove_server(InfdServerPool* server_pool, InfdXmlServer* server); void infd_server_pool_foreach_server(InfdServerPool* server_pool, InfdServerPoolForeachServerFunc func, gpointer user_data); G_END_DECLS #endif /* __INFD_SERVER_POOL_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/server/PaxHeaders.26529/infd-tcp-server.c0000644000000000000000000000013213034342512022602 xustar0030 mtime=1483851082.045718513 30 atime=1483851082.045718513 30 ctime=1488261589.128138785 libinfinity-0.7.1/libinfinity/server/infd-tcp-server.c0000644000175000017500000005244613034342512023347 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include #include #include #include #include #include #ifndef G_OS_WIN32 # include # include # include # include # include # include # include # include #else # include #endif static const GEnumValue infd_tcp_server_status_values[] = { { INFD_TCP_SERVER_CLOSED, "INFD_TCP_SERVER_CLOSED", "closed" }, { INFD_TCP_SERVER_OPEN, "INFD_TCP_SERVER_OPEN", "open" }, { 0, NULL, NULL } }; typedef struct _InfdTcpServerPrivate InfdTcpServerPrivate; struct _InfdTcpServerPrivate { InfIo* io; InfIoWatch* watch; InfNativeSocket socket; InfdTcpServerStatus status; InfIpAddress* local_address; guint local_port; InfKeepalive keepalive; }; enum { PROP_0, PROP_IO, PROP_STATUS, PROP_LOCAL_ADDRESS, PROP_LOCAL_PORT, PROP_KEEPALIVE }; enum { NEW_CONNECTION, ERROR_, /* ERROR is a #define on WIN32 */ LAST_SIGNAL }; #define INFD_TCP_SERVER_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INFD_TYPE_TCP_SERVER, InfdTcpServerPrivate)) static guint tcp_server_signals[LAST_SIGNAL]; INF_DEFINE_ENUM_TYPE(InfdTcpServerStatus, infd_tcp_server_status, infd_tcp_server_status_values) G_DEFINE_TYPE_WITH_CODE(InfdTcpServer, infd_tcp_server, G_TYPE_OBJECT, G_ADD_PRIVATE(InfdTcpServer)) /* TODO: The following functions are merely copied from inf-tcp-connection.c. * Probably they should belong into some inf-net-util.c file in * libinfinity/common. */ static void infd_tcp_server_addr_info(InfNativeSocket socket, gboolean local, InfIpAddress** address, guint* port) { union { struct sockaddr in_generic; struct sockaddr_in in; struct sockaddr_in6 in6; } native_addr; socklen_t len; len = sizeof(native_addr); if(local == TRUE) getsockname(socket, &native_addr.in_generic, &len); else getpeername(socket, &native_addr.in_generic, &len); switch(native_addr.in_generic.sa_family) { case AF_INET: if(address != NULL) *address = inf_ip_address_new_raw4(native_addr.in.sin_addr.s_addr); if(port != NULL) *port = ntohs(native_addr.in.sin_port); break; case AF_INET6: if(address != NULL) *address = inf_ip_address_new_raw6(native_addr.in6.sin6_addr.s6_addr); if(port != NULL) *port = ntohs(native_addr.in6.sin6_port); break; default: g_assert_not_reached(); break; } } static void infd_tcp_server_system_error(InfdTcpServer* server, int code) { GError* error; error = NULL; inf_native_socket_make_error(code, &error); g_signal_emit(G_OBJECT(server), tcp_server_signals[ERROR_], 0, error); g_error_free(error); } static void infd_tcp_server_io(InfNativeSocket* socket, InfIoEvent events, gpointer user_data) { InfdTcpServer* server; InfdTcpServerPrivate* priv; socklen_t len; InfNativeSocket new_socket; int errcode; InfTcpConnection* connection; GError* error; union { struct sockaddr in_generic; struct sockaddr_in in; struct sockaddr_in6 in6; } native_addr; InfIpAddress* address; guint port; server = INFD_TCP_SERVER(user_data); priv = INFD_TCP_SERVER_PRIVATE(server); g_object_ref(G_OBJECT(server)); if(events & INF_IO_ERROR) { len = sizeof(int); #ifdef G_OS_WIN32 getsockopt(priv->socket, SOL_SOCKET, SO_ERROR, (char*)&errcode, &len); #else getsockopt(priv->socket, SOL_SOCKET, SO_ERROR, &errcode, &len); #endif /* TODO: Verify that we get senseful error codes here */ infd_tcp_server_system_error(server, errcode); } else if(events & INF_IO_INCOMING) { do { /* Note that we do not do anything with native_addr and len. This is * currently only for debugging purposes since there seemingly was a * case where accept returned a valid but socket and errno was set to * EAGAIN (which might have been resulted from a previous call however * since the errno = 0 line was not there yet before that either). * I hope to get some more information this way in case this occurs * again. */ #ifndef G_OS_WIN32 errno = 0; #endif len = sizeof(native_addr); new_socket = accept(priv->socket, &native_addr.in_generic, &len); errcode = INF_NATIVE_SOCKET_LAST_ERROR; if(new_socket == INVALID_SOCKET && errcode != INF_NATIVE_SOCKET_EINTR && errcode != INF_NATIVE_SOCKET_EAGAIN) { infd_tcp_server_system_error(server, errcode); } else if(new_socket != INVALID_SOCKET) { switch(native_addr.in_generic.sa_family) { case AF_INET: address = inf_ip_address_new_raw4(native_addr.in.sin_addr.s_addr); port = ntohs(native_addr.in.sin_port); break; case AF_INET6: address = inf_ip_address_new_raw6(native_addr.in6.sin6_addr.s6_addr); port = ntohs(native_addr.in6.sin6_port); break; default: g_assert_not_reached(); break; } error = NULL; connection = _inf_tcp_connection_accepted( priv->io, new_socket, address, port, &priv->keepalive, &error ); /* _inf_tcp_connection_accepted() takes ownership of address */ if(connection != NULL) { g_signal_emit( G_OBJECT(server), tcp_server_signals[NEW_CONNECTION], 0, connection ); g_object_unref(connection); } else { g_signal_emit( G_OBJECT(server), tcp_server_signals[ERROR_], 0, error ); g_error_free(error); closesocket(new_socket); } } } while( (new_socket != INVALID_SOCKET || (new_socket == INVALID_SOCKET && errcode == INF_NATIVE_SOCKET_EINTR)) && (priv->socket != INVALID_SOCKET)); } g_object_unref(G_OBJECT(server)); } static void infd_tcp_server_init(InfdTcpServer* server) { InfdTcpServerPrivate* priv; priv = INFD_TCP_SERVER_PRIVATE(server); priv->io = NULL; priv->socket = INVALID_SOCKET; priv->status = INFD_TCP_SERVER_CLOSED; priv->local_address = NULL; priv->local_port = 0; priv->keepalive.mask = 0; } static void infd_tcp_server_dispose(GObject* object) { InfdTcpServer* server; InfdTcpServerPrivate* priv; server = INFD_TCP_SERVER(object); priv = INFD_TCP_SERVER_PRIVATE(server); if(priv->status != INFD_TCP_SERVER_CLOSED) infd_tcp_server_close(server); if(priv->io != NULL) { g_object_unref(G_OBJECT(priv->io)); priv->io = NULL; } G_OBJECT_CLASS(infd_tcp_server_parent_class)->dispose(object); } static void infd_tcp_server_finalize(GObject* object) { InfdTcpServer* server; InfdTcpServerPrivate* priv; server = INFD_TCP_SERVER(object); priv = INFD_TCP_SERVER_PRIVATE(server); if(priv->local_address != NULL) inf_ip_address_free(priv->local_address); G_OBJECT_CLASS(infd_tcp_server_parent_class)->finalize(object); } static void infd_tcp_server_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfdTcpServer* server; InfdTcpServerPrivate* priv; server = INFD_TCP_SERVER(object); priv = INFD_TCP_SERVER_PRIVATE(server); switch(prop_id) { case PROP_IO: g_assert(priv->status == INFD_TCP_SERVER_CLOSED); if(priv->io != NULL) g_object_unref(G_OBJECT(priv->io)); priv->io = INF_IO(g_value_dup_object(value)); break; case PROP_LOCAL_ADDRESS: g_assert(priv->status == INFD_TCP_SERVER_CLOSED); if(priv->local_address != NULL) inf_ip_address_free(priv->local_address); priv->local_address = (InfIpAddress*)g_value_dup_boxed(value); break; case PROP_LOCAL_PORT: g_assert(priv->status == INFD_TCP_SERVER_CLOSED); priv->local_port = g_value_get_uint(value); break; case PROP_KEEPALIVE: g_assert(g_value_get_boxed(value) != NULL); priv->keepalive = *(const InfKeepalive*)g_value_get_boxed(value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void infd_tcp_server_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfdTcpServer* server; InfdTcpServerPrivate* priv; server = INFD_TCP_SERVER(object); priv = INFD_TCP_SERVER_PRIVATE(server); switch(prop_id) { case PROP_IO: g_value_set_object(value, G_OBJECT(priv->io)); break; case PROP_STATUS: g_value_set_enum(value, priv->status); break; case PROP_LOCAL_ADDRESS: g_value_set_static_boxed(value, priv->local_address); break; case PROP_LOCAL_PORT: g_value_set_uint(value, priv->local_port); break; case PROP_KEEPALIVE: g_value_set_boxed(value, &priv->keepalive); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void infd_tcp_server_error(InfdTcpServer* server, GError* error) { InfdTcpServerPrivate* priv; priv = INFD_TCP_SERVER_PRIVATE(server); if(priv->status == INFD_TCP_SERVER_OPEN) { g_assert(priv->watch != NULL); inf_io_remove_watch(priv->io, priv->watch); priv->watch = NULL; } if(priv->socket != INVALID_SOCKET) { closesocket(priv->socket); priv->socket = INVALID_SOCKET; } if(priv->status != INFD_TCP_SERVER_CLOSED) { priv->status = INFD_TCP_SERVER_CLOSED; g_object_notify(G_OBJECT(server), "status"); } } static void infd_tcp_server_class_init(InfdTcpServerClass* tcp_server_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(tcp_server_class); object_class->dispose = infd_tcp_server_dispose; object_class->finalize = infd_tcp_server_finalize; object_class->set_property = infd_tcp_server_set_property; object_class->get_property = infd_tcp_server_get_property; tcp_server_class->new_connection = NULL; tcp_server_class->error = infd_tcp_server_error; g_object_class_install_property( object_class, PROP_IO, g_param_spec_object( "io", "IO", "I/O handler", INF_TYPE_IO, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_STATUS, g_param_spec_enum( "status", "Status", "Status of the TCP server", INFD_TYPE_TCP_SERVER_STATUS, INFD_TCP_SERVER_CLOSED, G_PARAM_READABLE ) ); g_object_class_install_property( object_class, PROP_LOCAL_ADDRESS, g_param_spec_boxed( "local-address", "Local address", "Address to bind to", INF_TYPE_IP_ADDRESS, G_PARAM_READWRITE ) ); g_object_class_install_property( object_class, PROP_LOCAL_PORT, g_param_spec_uint( "local-port", "Local port", "Port to bind to", 0, 65535, 0, G_PARAM_READWRITE ) ); g_object_class_install_property( object_class, PROP_KEEPALIVE, g_param_spec_boxed( "keepalive", "Keepalive", "Keepalive settings for accepted connections", INF_TYPE_KEEPALIVE, G_PARAM_READWRITE ) ); tcp_server_signals[NEW_CONNECTION] = g_signal_new( "new-connection", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfdTcpServerClass, new_connection), NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, INF_TYPE_TCP_CONNECTION ); tcp_server_signals[ERROR_] = g_signal_new( "error", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfdTcpServerClass, error), NULL, NULL, g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE, 1, G_TYPE_ERROR ); } /** * infd_tcp_server_bind: * @server: A #InfdTcpServer. * @error: Location to store error information, if any. * * Binds the server to the address and port given by the * #InfdTcpServer:local-address and #InfdTcpServer:local-port properties. If * the former is %NULL, it will bind on all interfaces on IPv4. If the latter * is 0, a random available port will be assigned. If the function fails, * %FALSE is returned and an error is set. * * @server must be in %INFD_TCP_SERVER_CLOSED state for this function to be * called. * * Returns: %TRUE on success, or %FALSE if an error occured. */ gboolean infd_tcp_server_bind(InfdTcpServer* server, GError** error) { InfdTcpServerPrivate* priv; union { struct sockaddr_in in; struct sockaddr_in6 in6; } native_address; struct sockaddr* addr; socklen_t addrlen; #if !defined(G_OS_WIN32) && defined(HAVE_SO_REUSEADDR) int value; #endif g_return_val_if_fail(INFD_IS_TCP_SERVER(server), FALSE); priv = INFD_TCP_SERVER_PRIVATE(server); g_return_val_if_fail(priv->status == INFD_TCP_SERVER_CLOSED, FALSE); if(priv->local_address == NULL) { priv->socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); addr = (struct sockaddr*)&native_address.in; addrlen = sizeof(struct sockaddr_in); native_address.in.sin_addr.s_addr = INADDR_ANY; native_address.in.sin_family = AF_INET; native_address.in.sin_port = htons(priv->local_port); } else { switch(inf_ip_address_get_family(priv->local_address)) { case INF_IP_ADDRESS_IPV4: priv->socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); addr = (struct sockaddr*)&native_address.in; addrlen = sizeof(struct sockaddr_in); memcpy( &native_address.in.sin_addr, inf_ip_address_get_raw(priv->local_address), sizeof(struct in_addr) ); native_address.in.sin_family = AF_INET; native_address.in.sin_port = htons(priv->local_port); break; case INF_IP_ADDRESS_IPV6: priv->socket = socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP); addr = (struct sockaddr*)&native_address.in6; addrlen = sizeof(struct sockaddr_in6); memcpy( &native_address.in6.sin6_addr, inf_ip_address_get_raw(priv->local_address), sizeof(struct in6_addr) ); native_address.in6.sin6_family = AF_INET6; native_address.in6.sin6_port = htons(priv->local_port); native_address.in6.sin6_flowinfo = 0; native_address.in6.sin6_scope_id = 0; break; default: g_assert_not_reached(); break; } } if(priv->socket == INVALID_SOCKET) { inf_native_socket_make_error(INF_NATIVE_SOCKET_LAST_ERROR, error); return FALSE; } #if !defined(G_OS_WIN32) && defined(HAVE_SO_REUSEADDR) /* Allow fast restarts of servers by enabling SO_REUSEADDR */ value = 1; if(setsockopt(priv->socket, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(int)) == -1) { inf_native_socket_make_error(INF_NATIVE_SOCKET_LAST_ERROR, error); closesocket(priv->socket); priv->socket = INVALID_SOCKET; return FALSE; } #endif if(bind(priv->socket, addr, addrlen) == -1) { inf_native_socket_make_error(INF_NATIVE_SOCKET_LAST_ERROR, error); closesocket(priv->socket); priv->socket = INVALID_SOCKET; return FALSE; } g_object_freeze_notify(G_OBJECT(server)); /* Is assigned a few lines below, but notifications are frozen currently * anyway... this saves us a temporary variable here. */ if(priv->local_port == 0) g_object_notify(G_OBJECT(server), "local-port"); if(priv->local_address != NULL) { infd_tcp_server_addr_info( priv->socket, TRUE, NULL, &priv->local_port ); } else { infd_tcp_server_addr_info( priv->socket, TRUE, &priv->local_address, &priv->local_port ); g_object_notify(G_OBJECT(server), "local-address"); } g_object_notify(G_OBJECT(server), "local-port"); priv->status = INFD_TCP_SERVER_BOUND; g_object_notify(G_OBJECT(server), "status"); g_object_thaw_notify(G_OBJECT(server)); return TRUE; } /** * infd_tcp_server_open: * @server: A #InfdTcpServer. * @error: Location to store error information. * * Attempts to open @server. This means binding its local address and port * if not already (see infd_tcp_server_bind()) and accepting incoming * connections. * * @server needs to be in %INFD_TCP_SERVER_CLOSED or %INFD_TCP_SERVER_BOUND * status for this function to be called. If @server's status is * %INFD_TCP_SERVER_CLOSED, then infd_tcp_server_bind() is called before * actually opening the server. * * Returns: %TRUE on success, or %FALSE if an error occured. **/ gboolean infd_tcp_server_open(InfdTcpServer* server, GError** error) { InfdTcpServerPrivate* priv; gboolean was_bound; #ifdef G_OS_WIN32 u_long argp; #else int result; #endif g_return_val_if_fail(INFD_IS_TCP_SERVER(server), FALSE); priv = INFD_TCP_SERVER_PRIVATE(server); g_return_val_if_fail(priv->io != NULL, FALSE); g_return_val_if_fail(priv->status != INFD_TCP_SERVER_OPEN, FALSE); g_assert(priv->watch == NULL); g_object_freeze_notify(G_OBJECT(server)); was_bound = (priv->status != INFD_TCP_SERVER_CLOSED); if(!was_bound) { if(!infd_tcp_server_bind(server, error)) { g_object_thaw_notify(G_OBJECT(server)); return FALSE; } } /* TODO: Should move this code to InfNativeSocket, so that it can be * shared with InfTcpConnection */ #ifndef G_OS_WIN32 result = fcntl(priv->socket, F_GETFL); if(result == -1) { inf_native_socket_make_error(INF_NATIVE_SOCKET_LAST_ERROR, error); if(!was_bound) infd_tcp_server_close(server); g_object_thaw_notify(G_OBJECT(server)); return FALSE; } if(fcntl(priv->socket, F_SETFL, result | O_NONBLOCK) == -1) { inf_native_socket_make_error(INF_NATIVE_SOCKET_LAST_ERROR, error); if(!was_bound) infd_tcp_server_close(server); g_object_thaw_notify(G_OBJECT(server)); return FALSE; } #else argp = 1; if(ioctlsocket(priv->socket, FIONBIO, &argp) != 0) { inf_native_socket_make_error(INF_NATIVE_SOCKET_LAST_ERROR, error); if(!was_bound) infd_tcp_server_close(server); g_object_thaw_notify(G_OBJECT(server)); return FALSE; } #endif if(listen(priv->socket, 5) == -1) { inf_native_socket_make_error(INF_NATIVE_SOCKET_LAST_ERROR, error); if(!was_bound) infd_tcp_server_close(server); g_object_thaw_notify(G_OBJECT(server)); return FALSE; } priv->watch = inf_io_add_watch( priv->io, &priv->socket, INF_IO_INCOMING | INF_IO_ERROR, infd_tcp_server_io, server, NULL ); priv->status = INFD_TCP_SERVER_OPEN; g_object_notify(G_OBJECT(server), "status"); g_object_thaw_notify(G_OBJECT(server)); return TRUE; } /** * infd_tcp_server_close: * @server: A #InfdTcpServer. * * Closes a TCP server that is open or bound. **/ void infd_tcp_server_close(InfdTcpServer* server) { InfdTcpServerPrivate* priv; g_return_if_fail(INFD_IS_TCP_SERVER(server)); priv = INFD_TCP_SERVER_PRIVATE(server); g_return_if_fail(priv->status != INFD_TCP_SERVER_CLOSED); if(priv->status == INFD_TCP_SERVER_OPEN) { g_assert(priv->watch != NULL); inf_io_remove_watch(priv->io, priv->watch); priv->watch = NULL; } closesocket(priv->socket); priv->socket = INVALID_SOCKET; priv->status = INFD_TCP_SERVER_CLOSED; g_object_notify(G_OBJECT(server), "status"); } /** * infd_tcp_server_set_keepalive: * @server: A #InfdTcpServer. * @keepalive: The keepalive settings for accepted connections. * * Sets the keepalive settings for new connections accepted by the server. */ void infd_tcp_server_set_keepalive(InfdTcpServer* server, const InfKeepalive* keepalive) { g_return_if_fail(INFD_IS_TCP_SERVER(server)); g_return_if_fail(keepalive != NULL); INFD_TCP_SERVER_PRIVATE(server)->keepalive = *keepalive; } /** * infd_tcp_server_get_keepalive: * @server: A #InfdTcpServer. * * Obtains the current keepalive settings for accepted connections. * * Returns: A #InfKeepalive representing the keepalive configuration for * accepted connections, owned by @server. */ const InfKeepalive* infd_tcp_server_get_keepalive(InfdTcpServer* server) { g_return_val_if_fail(INFD_IS_TCP_SERVER(server), NULL); return &INFD_TCP_SERVER_PRIVATE(server)->keepalive; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/server/PaxHeaders.26529/infd-account-storage.c0000644000000000000000000000013213034342512023606 xustar0030 mtime=1483851082.041718492 30 atime=1483851082.041718492 30 ctime=1488261589.116138812 libinfinity-0.7.1/libinfinity/server/infd-account-storage.c0000644000175000017500000005734313034342512024354 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:infd-account-storage * @title: InfdAccountStorage * @short_description: Interface to user account database * @include: libinfinity/server/infd-account-storage.h * @see_also: #InfdDirectory, #InfdFilesystemAccountStorage * @stability: Unstable * * #InfdAccountStorage provides an interface for #InfdDirectory to access a * database of user accounts. It provides methods to list and lookup available * accounts, and to add and remove accounts. * * Each account is uniquely identified by an account ID, #InfAclAccount.id, * and is assigned a human-readable name, #InfAclAccount.name. Typically, most * operations can be performed with the ID, and for example permissions for * users are stored by refering to the account ID in #InfdDirectory. The * authentication storage can be used to look up a name for the ID, and it is * responsible for storing the account information permanantly. * * Interface implementations do not need to support every operation provided * by the API of this interface, however if they support a certain operation, * #InfdDirectory takes advantage of it. The only required operation is to be * able to look up an account name by its ID, and the reverse lookup, i.e. * find all accounts with a given name. The * #InfdAccountStorageInterface.get_support() function returns a bitmask of the * supported operations. * * Implementations of this interface can couple the available accounts to * various external sources, such as SQL databases, LDAP or PAM. * Libinfinity also provides a standalone implementation of this interface, * which stores the account list as a file in the file system, see * #InfdFilesystemAccountStorage. */ #include #include #include #include static const GFlagsValue infd_account_storage_support_values[] = { { INFD_ACCOUNT_STORAGE_SUPPORT_NOTIFICATION, "INFD_ACCOUNT_STORAGE_SUPPORT_NOTIFICATION", "notification" }, { INFD_ACCOUNT_STORAGE_SUPPORT_LIST_ACCOUNTS, "INFD_ACCOUNT_STORAGE_SUPPORT_LIST_ACCOUNTS", "list-accounts" }, { INFD_ACCOUNT_STORAGE_SUPPORT_ADD_ACCOUNT, "INFD_ACCOUNT_STORAGE_SUPPORT_ADD_ACCOUNT", "add-account" }, { INFD_ACCOUNT_STORAGE_SUPPORT_REMOVE_ACCOUNT, "INFD_ACCOUNT_STORAGE_SUPPORT_REMOVE_ACCOUNT", "remove-account" }, { INFD_ACCOUNT_STORAGE_SUPPORT_CERTIFICATE_LOGIN, "INFD_ACCOUNT_STORAGE_SUPPORT_CERTIFICATE_LOGIN", "certificate-login" }, { INFD_ACCOUNT_STORAGE_SUPPORT_PASSWORD_LOGIN, "INFD_ACCOUNT_STORAGE_SUPPORT_PASSWORD_LOGIN", "password-login" }, { INFD_ACCOUNT_STORAGE_SUPPORT_CERTIFICATE_CHANGE, "INFD_ACCOUNT_STORAGE_SUPPORT_CERTIFICATE_CHANGE", "certificate-change" }, { INFD_ACCOUNT_STORAGE_SUPPORT_PASSWORD_CHANGE, "INFD_ACCOUNT_STORAGE_SUPPORT_PASSWORD_CHANGE", "password-change" }, { 0, NULL, NULL } }; INF_DEFINE_FLAGS_TYPE(InfdAccountStorageSupport, infd_account_storage_support, infd_account_storage_support_values) G_DEFINE_INTERFACE(InfdAccountStorage, infd_account_storage, G_TYPE_OBJECT) enum { ACCOUNT_ADDED, ACCOUNT_REMOVED, LAST_SIGNAL }; static guint account_storage_signals[LAST_SIGNAL]; static void infd_account_storage_default_init(InfdAccountStorageInterface* iface) { /** * InfdAccountStorage::account-added: * @storage: The #InfdAccountStorage emitting the signal. * @info: The #InfAclAccount containing the account ID and account name * of the added account. * * This signal is emitted whenever an account has been added to the * account storage. However, the signal is only emitted if the storage * implementations supports the %INFD_ACCOUNT_STORAGE_SUPPORT_NOTIFICATION * support flag. */ account_storage_signals[ACCOUNT_ADDED] = g_signal_new( "account-added", INFD_TYPE_ACCOUNT_STORAGE, G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfdAccountStorageInterface, account_added), NULL, NULL, g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE, 1, INF_TYPE_ACL_ACCOUNT | G_SIGNAL_TYPE_STATIC_SCOPE ); /** * InfdAccountStorage::account-removed: * @storage: The #InfdAccountStorage emitting the signal. * @info: The #InfAclAccount containing the account ID and account name * of the removed account. * * This signal is emitted whenever an account has been permanently removed * from the storage. However, the signal is only emitted if the storage * implementations supports the %INFD_ACCOUNT_STORAGE_SUPPORT_NOTIFICATION * support flag. */ account_storage_signals[ACCOUNT_REMOVED] = g_signal_new( "account-removed", INFD_TYPE_ACCOUNT_STORAGE, G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfdAccountStorageInterface, account_removed), NULL, NULL, g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE, 1, INF_TYPE_ACL_ACCOUNT | G_SIGNAL_TYPE_STATIC_SCOPE ); } /** * infd_account_storage_get_support: * @storage: A #InfdAccountStorage. * * Returns a bitmask of operations supported by the account storage backend. * If unsupported operations are attempted on @storage, an @error with code * %INF_DIRECTORY_ERROR_OPERATION_UNSUPPORTED will be generated. * * Returns: A bitmask of supported operations. */ InfdAccountStorageSupport infd_account_storage_get_support(InfdAccountStorage* storage) { InfdAccountStorageInterface* iface; g_return_val_if_fail(INFD_IS_ACCOUNT_STORAGE(storage), 0); iface = INFD_ACCOUNT_STORAGE_GET_IFACE(storage); g_return_val_if_fail(iface->get_support != NULL, 0); return iface->get_support(storage); } /** * infd_account_storage_supports: * @storage: A #InfdAccountStorage. * @support: A bitmask of operations to test. * * Checks whether support for all operations specified in @support is * available for @storage. This is equivalent to calling * infd_account_storage_get_support() and testing the returned value for * containing the bits in @support. * * Returns: %TRUE if all operations in @support are supported or %FALSE * otherwise. */ gboolean infd_account_storage_supports(InfdAccountStorage* storage, InfdAccountStorageSupport support) { InfdAccountStorageSupport available_support; available_support = infd_account_storage_get_support(storage); if( (available_support & support) != support) return FALSE; return TRUE; } /** * infd_account_storage_lookup_accounts: * @storage: A #InfdAccountStorage. * @accounts: (array length=n_accounts): An array of #InfAclAccountIds * to look up. * @n_accounts: The number of elements in @accounts. * @error: Location to store error information, if any, or %NULL. * * Looks up the #InfAclAccount structure for all IDs present in @accounts. * The return value is an array of #InfAclAccount structures which is in the * same order as the @accounts array. If an element in the output array has * the #InfAclAccount.id field set to 0, it means that the account with the * corresponding ID in the @accounts array does not exist in @storage. * * Returns: (array length=n_accounts) (transfer full): An array of * #InfAclAccount structures with @n_accounts entries. Free with * inf_acl_account_array_free(). */ InfAclAccount* infd_account_storage_lookup_accounts(InfdAccountStorage* storage, const InfAclAccountId* accounts, guint n_accounts, GError** error) { InfdAccountStorageInterface* iface; g_return_val_if_fail(INFD_IS_ACCOUNT_STORAGE(storage), NULL); g_return_val_if_fail(accounts != NULL, NULL); g_return_val_if_fail(n_accounts > 0, NULL); g_return_val_if_fail(error == NULL || *error == NULL, NULL); iface = INFD_ACCOUNT_STORAGE_GET_IFACE(storage); g_return_val_if_fail(iface->lookup_accounts != NULL, NULL); return iface->lookup_accounts(storage, accounts, n_accounts, error); } /** * infd_account_storage_lookup_accounts_by_name: * @storage: A #InfdAccountStorage. * @name: The name to look up. * @n_accounts: (out): An output parameter holding the number of returned * accounts. * @error: Location to store error information, if any, or %NULL. * * This function performs the "reverse" lookup: Given an account * name, the function returns an array with all accounts that have this name. * Many backends make sure that there cannot be duplicated names, in which * case this can at most return one account, however in principle accounts * with the same name are supported. * * If there is no account with the given name, the function returns %NULL and * sets @n_accounts to 0. If an error occurs, %NULL is returned, @n_accounts * is undefined, and @error is set. Therefore, to reliably find out whether a * lookup error occured or this is no account with the given name, a non-%NULL * error pointer should be passed and checked after the function call. * * Returns: (array length=n_accounts) (transfer full): An array of * #InfAclAccount structures with length @n_accounts, or %NULL on error * or when @n_accounts is 0 or @error is set. Free with * inf_acl_account_array_free(). */ InfAclAccount* infd_account_storage_lookup_accounts_by_name(InfdAccountStorage* storage, const gchar* name, guint* n_accounts, GError** error) { InfdAccountStorageInterface* iface; g_return_val_if_fail(INFD_IS_ACCOUNT_STORAGE(storage), NULL); g_return_val_if_fail(name != NULL, NULL); g_return_val_if_fail(n_accounts != NULL, NULL); g_return_val_if_fail(error == NULL || *error == NULL, NULL); iface = INFD_ACCOUNT_STORAGE_GET_IFACE(storage); g_return_val_if_fail(iface->lookup_accounts_by_name != NULL, NULL); return iface->lookup_accounts_by_name(storage, name, n_accounts, error); } /** * infd_account_storage_list_accounts: * @storage: A #InfdAccountStorage. * @n_accounts: (out): An output parameter holding the number of accounts * in @storage. * @error: Location to store error information, if any, or %NULL. * * Returns an array of all accounts in @storage. The length of the array * is stored in the output parameter @n_accounts. The functions returns %NULL * and sets @n_accounts to 0 if there are no accounts in @storage. If there is * an error, the function returns %NULL, @n_accounts is undefined, and @error * is set. Therefore, to reliably find out whether an error occurred or * whether there are really no accounts present, a non-%NULL error pointer * should be passed and checked after the function call. * * Note that this function might not be supported by the backend. See * infd_account_storage_get_support(). * * Returns: (array length=n_accounts) (allow-none) (transfer full): An array * of #InfAclAccount structures with length @n_accounts, or %NULL if * @n_accounts is 0 or @error is set. Free with * inf_acl_account_array_free(). */ InfAclAccount* infd_account_storage_list_accounts(InfdAccountStorage* storage, guint* n_accounts, GError** error) { InfdAccountStorageInterface* iface; g_return_val_if_fail(INFD_IS_ACCOUNT_STORAGE(storage), NULL); g_return_val_if_fail(n_accounts != NULL, NULL); g_return_val_if_fail(error == NULL || *error == NULL, NULL); iface = INFD_ACCOUNT_STORAGE_GET_IFACE(storage); if(iface->list_accounts == NULL) { g_set_error_literal( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_OPERATION_UNSUPPORTED, _("The account backend does not support acount listing") ); return NULL; } return iface->list_accounts(storage, n_accounts, error); } /** * infd_account_storage_add_account: * @storage: A #InfdAccountStorage. * @name: The name of the new account. * @certs: (array length=n_certs) (allow-none): An array of certificates that * can be used to login to the new account, or %NULL. * @n_certs: The length of the certificate array. * @password: (allow-none): A password that can be used to login to the * new account, or %NULL. * @error: Location to store error information, if any, or %NULL. * * Adds a new account to @storage. The account will have the given name. The * account ID is determined by the storage backend and if the operation is * successful it is returned. * * If the operation does not support storing certificates and/or passwords, * the function will fail if @certs or @password are not set to %NULL, * respectively. Note also that this function might not be supported at all * by the backend. See infd_account_storage_get_support(). * * Returns: (transfer full): The #InfAclAccountId of the added account, or 0 * on error. */ InfAclAccountId infd_account_storage_add_account(InfdAccountStorage* storage, const gchar* name, gnutls_x509_crt_t* certs, guint n_certs, const gchar* password, GError** error) { InfdAccountStorageInterface* iface; g_return_val_if_fail(INFD_IS_ACCOUNT_STORAGE(storage), 0); g_return_val_if_fail(name != NULL, 0); g_return_val_if_fail(certs == NULL || n_certs > 0, 0); g_return_val_if_fail(error == NULL || *error == NULL, 0); iface = INFD_ACCOUNT_STORAGE_GET_IFACE(storage); if(iface->add_account == NULL) { g_set_error_literal( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_OPERATION_UNSUPPORTED, _("The account backend does not support adding accounts") ); return 0; } return iface->add_account(storage, name, certs, n_certs, password, error); } /** * infd_account_storage_remove_account: * @storage: A #InfdAccountStorage. * @account: The ID of the account to remove. * @error: Location to store error information, if any, or %NULL. * * Removes the account with the given ID from @storage. * * Note that this function might not be supported by the backend. See * infd_account_storage_get_support(). * * Returns: %TRUE on success or %FALSE on error. */ gboolean infd_account_storage_remove_account(InfdAccountStorage* storage, InfAclAccountId account, GError** error) { InfdAccountStorageInterface* iface; g_return_val_if_fail(INFD_IS_ACCOUNT_STORAGE(storage), FALSE); g_return_val_if_fail(account != 0, FALSE); g_return_val_if_fail(error == NULL || *error == NULL, FALSE); iface = INFD_ACCOUNT_STORAGE_GET_IFACE(storage); if(iface->remove_account == NULL) { g_set_error_literal( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_OPERATION_UNSUPPORTED, _("The account backend does not support removing accounts") ); return FALSE; } return iface->remove_account(storage, account, error); } /** * infd_account_storage_login_by_certificate: * @storage: A #InfdAccountStorage. * @cert: The certificate presented by the client. * @error: Location to store error information, if any, or %NULL. * * This function returns the ID of the account which belongs to the given * client certificate. If there is no such account on an error occurs, * the function returns 0, and, in the case of an error, @error is set as * well. * * Note that this function might not be supported by the backend. See * infd_account_storage_get_support(). * * Returns: (transfer full): The account ID of the account associated to * @cert, or 0 on error or if there is no such account. */ InfAclAccountId infd_account_storage_login_by_certificate(InfdAccountStorage* storage, gnutls_x509_crt_t cert, GError** error) { InfdAccountStorageInterface* iface; g_return_val_if_fail(INFD_IS_ACCOUNT_STORAGE(storage), 0); g_return_val_if_fail(cert != 0, 0); g_return_val_if_fail(error == NULL || *error == NULL, 0); iface = INFD_ACCOUNT_STORAGE_GET_IFACE(storage); if(iface->login_by_certificate == NULL) { g_set_error_literal( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_OPERATION_UNSUPPORTED, _("The account backend does not support logging in with a certificate") ); return 0; } return iface->login_by_certificate(storage, cert, error); } /** * infd_account_storage_login_by_password: * @storage: A #InfdAccountStorage. * @username: The username of the account to log into. * @password: The password of the corresponding account. * @error: Location to store error information, if any. * * This function returns the account ID which matches to the given username * and password. If there is no such account or if the password is incorrect, * the function returns 0. If an error occurs, the function returns 0 and * @error is set. * * Note that when the password is incorrect, @error is not set. It is only set * if there was an internal error and the login procedure could not be carried * out due to technical reasons, such as a database outage. * * Note that this function might not be supported by the backend. See * infd_account_storage_get_support(). * * Returns: (transfer full): The account ID of the account associated to * @username if @password is correct, or 0 otherwise. */ InfAclAccountId infd_account_storage_login_by_password(InfdAccountStorage* storage, const gchar* username, const gchar* password, GError** error) { InfdAccountStorageInterface* iface; g_return_val_if_fail(INFD_IS_ACCOUNT_STORAGE(storage), 0); g_return_val_if_fail(username != 0, 0); g_return_val_if_fail(password != 0, 0); g_return_val_if_fail(error == NULL || *error == NULL, 0); iface = INFD_ACCOUNT_STORAGE_GET_IFACE(storage); if(iface->login_by_password == NULL) { g_set_error_literal( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_OPERATION_UNSUPPORTED, _("The account backend does not support logging in with a password") ); return 0; } return iface->login_by_password(storage, username, password, error); } /** * infd_account_storage_set_certificate: * @storage: A #InfdAccountStorage. * @account: The ID of the account whose certificate to set. * @certs: (array length=n_certs) (allow-none): An array of certificates, * or %NULL if n_certs is 0. * @n_certs: The number of certificates in the certificate array. * @error: Location to store error information, if any. * * Changes the certificate(s) associated to the account with ID @account. * All certificates that are currently associated to it are removed, and the * given certificates are associated instead. If @n_certs is 0, there will * be no associated certificates and login by certificate will be disabled * for @account. * * Note that this function might not be supported by the backend. See * infd_account_storage_get_support(). * * Returns: %TRUE if the operation was successful or %FALSE if an error * occured. */ gboolean infd_account_storage_set_certificate(InfdAccountStorage* storage, InfAclAccountId account, gnutls_x509_crt_t* certs, guint n_certs, GError** error) { InfdAccountStorageInterface* iface; g_return_val_if_fail(INFD_IS_ACCOUNT_STORAGE(storage), FALSE); g_return_val_if_fail(account != 0, FALSE); g_return_val_if_fail(certs != NULL || n_certs == 0, FALSE); g_return_val_if_fail(error == NULL || *error == NULL, FALSE); iface = INFD_ACCOUNT_STORAGE_GET_IFACE(storage); if(iface->set_certificate == NULL) { g_set_error_literal( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_OPERATION_UNSUPPORTED, _("The account backend does not support changing the certificate") ); return FALSE; } return iface->set_certificate(storage, account, certs, n_certs, error); } /** * infd_account_storage_set_password: * @storage: A #InfdAccountStorage. * @account: The ID of the account whose password to change. * @password: The new password for the account, or %NULL. * @error: Location to store error information, if any, or %NULL. * * Changes the password for the account with the given ID. If this call * succeeds, the new password will have to be provided to * infd_account_storage_login_by_password() for the login to succeed. If * @password is %NULL, the password will be unset and login by password * will no longer be possible. * * Note that this function might not be supported by the backend. See * infd_account_storage_get_support(). * * Returns: %TRUE on success or %FALSE on error. */ gboolean infd_account_storage_set_password(InfdAccountStorage* storage, InfAclAccountId account, const gchar* password, GError** error) { InfdAccountStorageInterface* iface; g_return_val_if_fail(INFD_IS_ACCOUNT_STORAGE(storage), FALSE); g_return_val_if_fail(account != 0, FALSE); g_return_val_if_fail(error == NULL || *error == NULL, FALSE); iface = INFD_ACCOUNT_STORAGE_GET_IFACE(storage); if(iface->set_password == NULL) { g_set_error_literal( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_OPERATION_UNSUPPORTED, _("The account backend does not support changing the password") ); return FALSE; } return iface->set_password(storage, account, password, error); } /** * infd_account_storage_account_added: * @storage: A #InfdAccountStorage. * @account: The #InfAclAccount that was added to the storage. * * Emits the #InfdAccountStorage::account-added signal on @storage. This * should only be used by interface implementations. */ void infd_account_storage_account_added(InfdAccountStorage* storage, const InfAclAccount* account) { g_return_if_fail(INFD_IS_ACCOUNT_STORAGE(storage)); g_return_if_fail(account != NULL); g_return_if_fail( infd_account_storage_supports( storage, INFD_ACCOUNT_STORAGE_SUPPORT_NOTIFICATION ) ); g_signal_emit( G_OBJECT(storage), account_storage_signals[ACCOUNT_ADDED], 0, account ); } /** * infd_account_storage_account_removed: * @storage: A #InfdAccountStorage. * @account: The #InfAclAccount with the account information for the removed * account. * * Emits the #InfdAccountStorage::account-removed signal on @storage. This * should only be used by interface implementations. */ void infd_account_storage_account_removed(InfdAccountStorage* storage, const InfAclAccount* account) { g_return_if_fail(INFD_IS_ACCOUNT_STORAGE(storage)); g_return_if_fail(account != NULL); g_return_if_fail( infd_account_storage_supports( storage, INFD_ACCOUNT_STORAGE_SUPPORT_NOTIFICATION ) ); g_signal_emit( G_OBJECT(storage), account_storage_signals[ACCOUNT_REMOVED], 0, account ); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/server/PaxHeaders.26529/infd-storage.h0000644000000000000000000000013213034342512022161 xustar0030 mtime=1483851082.045718513 30 atime=1483851082.045718513 30 ctime=1488261589.012139039 libinfinity-0.7.1/libinfinity/server/infd-storage.h0000644000175000017500000001177513034342512022726 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INFD_STORAGE_H__ #define __INFD_STORAGE_H__ #include #include G_BEGIN_DECLS #define INFD_TYPE_STORAGE (infd_storage_get_type()) #define INFD_STORAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INFD_TYPE_STORAGE, InfdStorage)) #define INFD_IS_STORAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INFD_TYPE_STORAGE)) #define INFD_STORAGE_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), INFD_TYPE_STORAGE, InfdStorageInterface)) #define INFD_TYPE_STORAGE_NODE_TYPE (infd_storage_node_type_get_type()) #define INFD_TYPE_STORAGE_NODE (infd_storage_node_get_type()) #define INFD_TYPE_STORAGE_ACL (infd_storage_acl_get_type()) typedef struct _InfdStorage InfdStorage; typedef struct _InfdStorageInterface InfdStorageInterface; typedef enum _InfdStorageNodeType { INFD_STORAGE_NODE_SUBDIRECTORY, INFD_STORAGE_NODE_NOTE } InfdStorageNodeType; typedef struct _InfdStorageNode InfdStorageNode; struct _InfdStorageNode { InfdStorageNodeType type; gchar* name; gchar* identifier; /* Only set when type == INFD_STORAGE_NODE_NOTE */ }; typedef struct _InfdStorageAcl InfdStorageAcl; struct _InfdStorageAcl { gchar* account_id; InfAclMask mask; InfAclMask perms; }; struct _InfdStorageInterface { GTypeInterface parent; /* All these calls are supposed to be synchronous, e.g. completly perform * the required task. Some day, we could implement asynchronous * behaviour in InfdDirectory (e.g. it caches operations and executes * them via the storage in the background). */ /* Virtual Table */ GSList* (*read_subdirectory)(InfdStorage* storage, const gchar* path, GError** error); gboolean (*create_subdirectory)(InfdStorage* storage, const gchar* path, GError** error); /* TODO: Remove the identifier here */ gboolean (*remove_node)(InfdStorage* storage, const gchar* identifier, const gchar* path, GError** error); /* TODO: Add further methods to copy, move and expunge nodes */ GSList* (*read_acl)(InfdStorage* storage, const gchar* path, GError** error); gboolean (*write_acl)(InfdStorage* storage, const gchar* path, const InfAclSheetSet* sheet_set, GError** error); }; GType infd_storage_node_type_get_type(void) G_GNUC_CONST; GType infd_storage_node_get_type(void) G_GNUC_CONST; GType infd_storage_acl_get_type(void) G_GNUC_CONST; GType infd_storage_get_type(void) G_GNUC_CONST; InfdStorageNode* infd_storage_node_new_subdirectory(const gchar* path); InfdStorageNode* infd_storage_node_new_note(const gchar* path, const gchar* identifier); InfdStorageNode* infd_storage_node_copy(const InfdStorageNode* node); void infd_storage_node_free(InfdStorageNode* node); void infd_storage_node_list_free(GSList* node_list); InfdStorageAcl* infd_storage_acl_copy(const InfdStorageAcl* acl); void infd_storage_acl_free(InfdStorageAcl* acl); void infd_storage_acl_list_free(GSList* acl_list); GSList* infd_storage_read_subdirectory(InfdStorage* storage, const gchar* path, GError** error); gboolean infd_storage_create_subdirectory(InfdStorage* storage, const gchar* path, GError** error); gboolean infd_storage_remove_node(InfdStorage* storage, const gchar* identifier, const gchar* path, GError** error); GSList* infd_storage_read_acl(InfdStorage* storage, const gchar* path, GError** error); gboolean infd_storage_write_acl(InfdStorage* storage, const gchar* path, const InfAclSheetSet* sheet_set, GError** error); G_END_DECLS #endif /* __INFD_STORAGE_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/server/PaxHeaders.26529/infd-xmpp-server.c0000644000000000000000000000013213034342512023000 xustar0030 mtime=1483851082.045718513 30 atime=1483851082.045718513 30 ctime=1488261589.132138777 libinfinity-0.7.1/libinfinity/server/infd-xmpp-server.c0000644000175000017500000004745613034342512023552 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include #include #include #include /* Some Windows header #defines ERROR for no good */ #ifdef G_OS_WIN32 # ifdef ERROR # undef ERROR # endif #endif typedef enum InfdXmppServerStatus_ { INFD_XMPP_SERVER_CLOSED, INFD_XMPP_SERVER_OPEN } InfdXmppServerStatus; typedef struct _InfdXmppServerPrivate InfdXmppServerPrivate; struct _InfdXmppServerPrivate { InfdTcpServer* tcp; InfdXmppServerStatus status; gchar* local_hostname; InfXmppConnectionSecurityPolicy security_policy; InfCertificateCredentials* tls_creds; InfSaslContext* sasl_context; InfSaslContext* sasl_own_context; gchar* sasl_mechanisms; }; enum { PROP_0, PROP_TCP, PROP_LOCAL_HOSTNAME, PROP_CREDENTIALS, PROP_SASL_CONTEXT, PROP_SASL_MECHANISMS, PROP_SECURITY_POLICY, /* Overridden from XML server */ PROP_STATUS }; enum { ERROR, LAST_SIGNAL }; #define INFD_XMPP_SERVER_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INFD_TYPE_XMPP_SERVER, InfdXmppServerPrivate)) static guint xmpp_server_signals[LAST_SIGNAL]; static void infd_xmpp_server_xml_server_iface_init(InfdXmlServerInterface* iface); G_DEFINE_TYPE_WITH_CODE(InfdXmppServer, infd_xmpp_server, G_TYPE_OBJECT, G_ADD_PRIVATE(InfdXmppServer) G_IMPLEMENT_INTERFACE(INFD_TYPE_XML_SERVER, infd_xmpp_server_xml_server_iface_init)) static void infd_xmpp_server_new_connection_cb(InfdTcpServer* tcp_server, InfTcpConnection* tcp_connection, gpointer user_data) { InfdXmppServer* xmpp_server; InfdXmppServerPrivate* priv; InfXmppConnection* xmpp_connection; InfIpAddress* addr; gchar* addr_str; xmpp_server = INFD_XMPP_SERVER(user_data); priv = INFD_XMPP_SERVER_PRIVATE(xmpp_server); /* TODO: We could perform a reverse DNS lookup to find the client hostname * here. */ g_object_get(G_OBJECT(tcp_connection), "remote-address", &addr, NULL); addr_str = inf_ip_address_to_string(addr); inf_ip_address_free(addr); xmpp_connection = inf_xmpp_connection_new( tcp_connection, INF_XMPP_CONNECTION_SERVER, priv->local_hostname, addr_str, priv->security_policy, priv->tls_creds, priv->sasl_context, priv->sasl_own_context != NULL ? "ANONYMOUS" : priv->sasl_mechanisms ); g_free(addr_str); /* We could, alternatively, keep the connection around until authentication * has completed and emit the new_connection signal after that, to guarantee * that the connection is open when new_connection is emitted. */ infd_xml_server_new_connection( INFD_XML_SERVER(xmpp_server), INF_XML_CONNECTION(xmpp_connection) ); g_object_unref(G_OBJECT(xmpp_connection)); } static void infd_xmpp_server_error_cb(InfdTcpServer* tcp_server, GError* error, gpointer user_data) { g_signal_emit( G_OBJECT(user_data), xmpp_server_signals[ERROR], 0, error ); } static void infd_xmpp_server_notify_status_cb(InfdTcpServer* tcp_server, GParamSpec* pspec, gpointer user_data) { InfdXmppServer* xmpp; InfdXmppServerPrivate* priv; InfdTcpServerStatus status; xmpp = INFD_XMPP_SERVER(user_data); priv = INFD_XMPP_SERVER_PRIVATE(xmpp); g_object_get(G_OBJECT(tcp_server), "status", &status, NULL); switch(status) { case INFD_TCP_SERVER_CLOSED: case INFD_TCP_SERVER_BOUND: if(priv->status != INFD_XMPP_SERVER_CLOSED) { priv->status = INFD_XMPP_SERVER_CLOSED; g_object_notify(G_OBJECT(xmpp), "status"); } break; case INFD_TCP_SERVER_OPEN: if(priv->status != INFD_XMPP_SERVER_OPEN) { priv->status = INFD_XMPP_SERVER_OPEN; g_object_notify(G_OBJECT(xmpp), "status"); } break; default: g_assert_not_reached(); break; } } static void infd_xmpp_server_sasl_cb(InfSaslContextSession* session, Gsasl_property property, gpointer session_data, gpointer user_data) { InfdXmppServer* xmpp; InfdXmppServerPrivate* priv; xmpp = INFD_XMPP_SERVER(user_data); priv = INFD_XMPP_SERVER_PRIVATE(xmpp); switch(property) { case GSASL_ANONYMOUS_TOKEN: inf_sasl_context_session_set_property( session, GSASL_ANONYMOUS_TOKEN, priv->local_hostname ); inf_sasl_context_session_continue(session, GSASL_OK); break; case GSASL_VALIDATE_ANONYMOUS: /* Authentaction always successful */ inf_sasl_context_session_continue(session, GSASL_OK); break; default: /* This is only used when using built-in SASL context, and this one * only supports anonymous authentication. */ g_assert_not_reached(); inf_sasl_context_session_continue(session, GSASL_NO_CALLBACK); break; } } /* Set own SASL context based on whether an external one is given or not */ static void infd_xmpp_server_setup_own_sasl_context(InfdXmppServer* xmpp) { InfdXmppServerPrivate* priv; priv = INFD_XMPP_SERVER_PRIVATE(xmpp); g_assert(priv->sasl_own_context == NULL); if(priv->sasl_context == NULL && priv->tcp != NULL) { /* Failure does not matter too much because every XMPP connection will * generate an own SASL context in this case, and error out if that * fails again. */ priv->sasl_own_context = inf_sasl_context_new(NULL); if(priv->sasl_own_context != NULL) { priv->sasl_context = priv->sasl_own_context; inf_sasl_context_ref(priv->sasl_context); inf_sasl_context_set_callback( priv->sasl_context, infd_xmpp_server_sasl_cb, xmpp, NULL ); g_object_notify(G_OBJECT(xmpp), "sasl-context"); } } } static void infd_xmpp_server_set_tcp(InfdXmppServer* xmpp, InfdTcpServer* tcp) { InfdXmppServerPrivate* priv; InfdTcpServerStatus tcp_status; priv = INFD_XMPP_SERVER_PRIVATE(xmpp); g_object_freeze_notify(G_OBJECT(xmpp)); if(priv->tcp != NULL) { g_object_get(G_OBJECT(priv->tcp), "status", &tcp_status, NULL); /* This will cause a notify that will adjust the XMPP status later */ if(tcp_status != INFD_TCP_SERVER_CLOSED) infd_tcp_server_close(priv->tcp); /* TODO: Make sure there are no connections with sasl_own_context out * there anymore because otherwise the SASL callback might access an * invalid InfdServer pointer once we get finalized. */ /* TODO: Or, give data associated with the SASL context its own * life cycle. Should be easy given that it has a destroy notify. */ if(priv->sasl_own_context != NULL) { inf_sasl_context_unref(priv->sasl_own_context); priv->sasl_own_context = NULL; } inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->tcp), G_CALLBACK(infd_xmpp_server_new_connection_cb), xmpp ); inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->tcp), G_CALLBACK(infd_xmpp_server_error_cb), xmpp ); inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->tcp), G_CALLBACK(infd_xmpp_server_notify_status_cb), xmpp ); g_object_unref(G_OBJECT(priv->tcp)); } priv->tcp = tcp; if(tcp != NULL) { g_object_ref(G_OBJECT(tcp)); g_signal_connect( G_OBJECT(tcp), "new-connection", G_CALLBACK(infd_xmpp_server_new_connection_cb), xmpp ); g_signal_connect( G_OBJECT(tcp), "error", G_CALLBACK(infd_xmpp_server_error_cb), xmpp ); g_signal_connect( G_OBJECT(tcp), "notify::status", G_CALLBACK(infd_xmpp_server_notify_status_cb), xmpp ); g_object_get(G_OBJECT(tcp), "status", &tcp_status, NULL); switch(tcp_status) { case INFD_TCP_SERVER_CLOSED: case INFD_TCP_SERVER_BOUND: g_assert(priv->status == INFD_XMPP_SERVER_CLOSED); break; case INFD_TCP_SERVER_OPEN: priv->status = INFD_XMPP_SERVER_OPEN; g_object_notify(G_OBJECT(xmpp), "status"); break; default: g_assert_not_reached(); break; } } infd_xmpp_server_setup_own_sasl_context(xmpp); g_object_thaw_notify(G_OBJECT(xmpp)); } static void infd_xmpp_server_init(InfdXmppServer* xmpp) { InfdXmppServerPrivate* priv; priv = INFD_XMPP_SERVER_PRIVATE(xmpp); priv->tcp = NULL; priv->status = INFD_XMPP_SERVER_CLOSED; priv->local_hostname = g_strdup(g_get_host_name()); priv->security_policy = INF_XMPP_CONNECTION_SECURITY_ONLY_UNSECURED; priv->tls_creds = NULL; priv->sasl_context = NULL; priv->sasl_own_context = NULL; priv->sasl_mechanisms = NULL; } static void infd_xmpp_server_dispose(GObject* object) { InfdXmppServer* xmpp; InfdXmppServerPrivate* priv; xmpp = INFD_XMPP_SERVER(object); priv = INFD_XMPP_SERVER_PRIVATE(xmpp); if(priv->status != INFD_XMPP_SERVER_CLOSED) infd_xml_server_close(INFD_XML_SERVER(xmpp)); infd_xmpp_server_set_tcp(xmpp, NULL); if(priv->sasl_own_context != NULL) { inf_sasl_context_unref(priv->sasl_own_context); priv->sasl_own_context = NULL; } if(priv->sasl_context != NULL) { inf_sasl_context_unref(priv->sasl_context); priv->sasl_context = NULL; } if(priv->tls_creds != NULL) { inf_certificate_credentials_unref(priv->tls_creds); priv->tls_creds = NULL; } G_OBJECT_CLASS(infd_xmpp_server_parent_class)->dispose(object); } static void infd_xmpp_server_finalize(GObject* object) { InfdXmppServer* xmpp; InfdXmppServerPrivate* priv; xmpp = INFD_XMPP_SERVER(object); priv = INFD_XMPP_SERVER_PRIVATE(xmpp); g_free(priv->local_hostname); g_free(priv->sasl_mechanisms); G_OBJECT_CLASS(infd_xmpp_server_parent_class)->finalize(object); } static void infd_xmpp_server_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfdXmppServer* xmpp; InfdXmppServerPrivate* priv; xmpp = INFD_XMPP_SERVER(object); priv = INFD_XMPP_SERVER_PRIVATE(xmpp); switch(prop_id) { case PROP_TCP: infd_xmpp_server_set_tcp( xmpp, INFD_TCP_SERVER(g_value_get_object(value)) ); break; case PROP_LOCAL_HOSTNAME: g_free(priv->local_hostname); priv->local_hostname = g_value_dup_string(value); if(priv->local_hostname == NULL) priv->local_hostname = g_strdup(g_get_host_name()); break; case PROP_CREDENTIALS: if(priv->tls_creds != NULL) inf_certificate_credentials_unref(priv->tls_creds); priv->tls_creds = g_value_dup_boxed(value); break; case PROP_SASL_CONTEXT: if(priv->sasl_own_context != NULL) { inf_sasl_context_unref(priv->sasl_own_context); priv->sasl_own_context = NULL; } if(priv->sasl_context != NULL) inf_sasl_context_unref(priv->sasl_context); priv->sasl_context = g_value_dup_boxed(value); infd_xmpp_server_setup_own_sasl_context(xmpp); break; case PROP_SASL_MECHANISMS: g_free(priv->sasl_mechanisms); priv->sasl_mechanisms = g_value_dup_string(value); break; case PROP_SECURITY_POLICY: infd_xmpp_server_set_security_policy(xmpp, g_value_get_enum(value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void infd_xmpp_server_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfdXmppServer* xmpp; InfdXmppServerPrivate* priv; xmpp = INFD_XMPP_SERVER(object); priv = INFD_XMPP_SERVER_PRIVATE(xmpp); switch(prop_id) { case PROP_STATUS: switch(priv->status) { case INFD_XMPP_SERVER_CLOSED: g_value_set_enum(value, INFD_XML_SERVER_CLOSED); break; case INFD_XMPP_SERVER_OPEN: g_value_set_enum(value, INFD_XML_SERVER_OPEN); break; default: g_assert_not_reached(); break; } break; case PROP_TCP: g_value_set_object(value, priv->tcp); break; case PROP_LOCAL_HOSTNAME: g_value_set_string(value, priv->local_hostname); break; case PROP_CREDENTIALS: g_value_set_boxed(value, priv->tls_creds); break; case PROP_SASL_CONTEXT: g_value_set_boxed(value, priv->sasl_context); break; case PROP_SASL_MECHANISMS: g_value_set_string(value, priv->sasl_mechanisms); break; case PROP_SECURITY_POLICY: g_value_set_enum(value, priv->security_policy); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void infd_xmpp_server_xml_server_close(InfdXmlServer* xml) { InfdXmppServerPrivate* priv; priv = INFD_XMPP_SERVER_PRIVATE(xml); g_return_if_fail(priv->status != INFD_XMPP_SERVER_CLOSED); switch(priv->status) { case INFD_XMPP_SERVER_OPEN: /* This will cause a status notify that will adjust the XMPP status */ infd_tcp_server_close(priv->tcp); break; case INFD_XMPP_SERVER_CLOSED: default: g_assert_not_reached(); break; } } static void infd_xmpp_server_class_init(InfdXmppServerClass* xmpp_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(xmpp_class); object_class->dispose = infd_xmpp_server_dispose; object_class->finalize = infd_xmpp_server_finalize; object_class->set_property = infd_xmpp_server_set_property; object_class->get_property = infd_xmpp_server_get_property; xmpp_class->error = NULL; g_object_class_install_property( object_class, PROP_TCP, g_param_spec_object( "tcp-server", "TCP server", "Underlaying TCP server", INFD_TYPE_TCP_SERVER, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_LOCAL_HOSTNAME, g_param_spec_string( "local-hostname", "Local hostname", "Hostname of the server", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_CREDENTIALS, g_param_spec_boxed( "credentials", "Credentials", "The certificate credentials for GnuTLS", INF_TYPE_CERTIFICATE_CREDENTIALS, G_PARAM_READWRITE | G_PARAM_CONSTRUCT ) ); g_object_class_install_property( object_class, PROP_SASL_CONTEXT, g_param_spec_boxed( "sasl-context", "SASL context", "The SASL context used for authentaction", INF_TYPE_SASL_CONTEXT, G_PARAM_READWRITE | G_PARAM_CONSTRUCT ) ); g_object_class_install_property( object_class, PROP_SASL_MECHANISMS, g_param_spec_string( "sasl-mechanisms", "SASL mechanisms", "The SASL mechanisms offered to the client for authentication", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT ) ); g_object_class_install_property( object_class, PROP_SECURITY_POLICY, g_param_spec_enum( "security-policy", "Security policy", "Whether to offer or require TLS", INF_TYPE_XMPP_CONNECTION_SECURITY_POLICY, INF_XMPP_CONNECTION_SECURITY_ONLY_UNSECURED, G_PARAM_READWRITE | G_PARAM_CONSTRUCT ) ); g_object_class_override_property(object_class, PROP_STATUS, "status"); xmpp_server_signals[ERROR] = g_signal_new( "error", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfdXmppServerClass, error), NULL, NULL, g_cclosure_marshal_VOID__BOXED, G_TYPE_NONE, 1, G_TYPE_ERROR ); } static void infd_xmpp_server_xml_server_iface_init(InfdXmlServerInterface* iface) { iface->close = infd_xmpp_server_xml_server_close; } /** * infd_xmpp_server_new: (constructor) * @tcp: A #InfdTcpServer. * @policy: The initial security policy. * @creds: Certificate credentials used to secure any communication. * @sasl_context: A SASL context used for authentication. * @sasl_mechanisms: A whitespace-sparated list of SASL mechanisms. * * Creates a new #InfdXmppServer with @tcp as underlaying TCP server object. * No attempt is being made to open @tcp, if it is not already open. When a * new connection comes in, the XMPP server creates a XMPP connection that * may be used to communicate with the client. Note however that the * resulting connection will be in status OPENING until authentication has * completed. * * If @policy is %INF_XMPP_CONNECTION_SECURITY_ONLY_UNSECURED, then @creds may * be %NULL. If @creds is non-%NULL nevertheless, then it is possible to change * the security policy later using infd_xmpp_server_set_security_policy(). * @creds can also be changed later while the server is running. So just set * valid credentials before changing @policy to allow TLS. * * If @sasl_context is %NULL, the server uses a built-in context that only * supports ANONYMOUS authentication. If @sasl_context is not %NULL, then * @sasl_mechanisms specifies the mechanisms offered to clients. If * @sasl_mechanisms is %NULL, then all available mechanims will be offered. * If @sasl_context is %NULL, then this parameter is ignored. * * Return Value: (transfer full): A new #InfdXmppServer. **/ InfdXmppServer* infd_xmpp_server_new(InfdTcpServer* tcp, InfXmppConnectionSecurityPolicy policy, InfCertificateCredentials* creds, InfSaslContext* sasl_context, const gchar* sasl_mechanisms) { GObject* object; g_return_val_if_fail(INFD_IS_TCP_SERVER(tcp), NULL); g_return_val_if_fail( policy == INF_XMPP_CONNECTION_SECURITY_ONLY_UNSECURED || creds != NULL, NULL ); object = g_object_new( INFD_TYPE_XMPP_SERVER, "tcp-server", tcp, "credentials", creds, "security-policy", policy, "sasl-context", sasl_context, "sasl-mechanisms", sasl_mechanisms, NULL ); return INFD_XMPP_SERVER(object); } /** * infd_xmpp_server_set_security_policy: * @server: A #InfdXmppServer. * @policy: The new security policy. * * Sets the security policy for newly accepted #InfXmppConnections. * Does not already established connections. */ void infd_xmpp_server_set_security_policy(InfdXmppServer* server, InfXmppConnectionSecurityPolicy policy) { InfdXmppServerPrivate* priv; g_return_if_fail(INFD_IS_XMPP_SERVER(server)); priv = INFD_XMPP_SERVER_PRIVATE(server); if(policy != priv->security_policy) { g_return_if_fail( policy == INF_XMPP_CONNECTION_SECURITY_ONLY_UNSECURED || priv->tls_creds != NULL ); priv->security_policy = policy; g_object_notify(G_OBJECT(server), "security-policy"); } } /** * infd_xmpp_server_get_security_policy: * @server: A #InfdXmppServer. * * Returns the current security policy for newly accepted * #InfXmppConnections. * * Returns: The current security policy. */ InfXmppConnectionSecurityPolicy infd_xmpp_server_get_security_policy(InfdXmppServer* server) { g_return_val_if_fail( INFD_IS_XMPP_SERVER(server), INF_XMPP_CONNECTION_SECURITY_BOTH_PREFER_TLS ); return INFD_XMPP_SERVER_PRIVATE(server)->security_policy; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/server/PaxHeaders.26529/infd-directory.c0000644000000000000000000000013213055210615022515 xustar0030 mtime=1488261517.900288579 30 atime=1488261517.900288579 30 ctime=1488261589.120138803 libinfinity-0.7.1/libinfinity/server/infd-directory.c0000644000175000017500000112511113055210615023251 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:infd-directory * @short_description: Directory of published documents * @see_also: #InfcBrowser, #InfdStorage * @include: libinfinity/server/infd-directory.h * @stability: Unstable * * The #InfdDirectory manages a directory of documents. An item in the * directory is also called "node". A node may either be a * subdirectory or a document (also called "note"). Notes may be of * different type - there may be plain text notes, rich text notes, * graphics notes, etc. * * #InfdStorage defines where the directory structure and the notes are read * from and how they are permanently stored. **/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include typedef enum _InfdDirectoryNodeType { INFD_DIRECTORY_NODE_SUBDIRECTORY, INFD_DIRECTORY_NODE_NOTE, INFD_DIRECTORY_NODE_UNKNOWN, } InfdDirectoryNodeType; typedef struct _InfdDirectoryNode InfdDirectoryNode; struct _InfdDirectoryNode { InfdDirectoryNode* parent; InfdDirectoryNode* prev; InfdDirectoryNode* next; InfAclSheetSet* acl; GSList* acl_connections; InfdDirectoryNodeType type; guint id; gchar* name; union { struct { /* Running session, or NULL */ InfdSessionProxy* session; /* Session type */ const InfdNotePlugin* plugin; /* Timeout to save the session when inactive for some time */ InfIoTimeout* save_timeout; /* Whether we hold a weak reference or a strong reference on session */ gboolean weakref; } note; struct { /* Note type */ GQuark type; } unknown; struct { /* List of connections that have this folder open and have to be * notified if something happens with it. */ GSList* connections; /* First child node */ InfdDirectoryNode* child; /* Whether we requested the node already from the background storage. * This is required because the nodes field may be NULL due to an empty * subdirectory or due to an unexplored subdirectory. */ gboolean explored; } subdir; } shared; }; typedef struct _InfdDirectorySessionSaveTimeoutData InfdDirectorySessionSaveTimeoutData; struct _InfdDirectorySessionSaveTimeoutData { InfdDirectory* directory; InfdDirectoryNode* node; }; typedef struct _InfdDirectorySyncIn InfdDirectorySyncIn; struct _InfdDirectorySyncIn { InfdDirectory* directory; InfdDirectoryNode* parent; guint node_id; gchar* name; InfAclSheetSet* sheet_set; const InfdNotePlugin* plugin; InfdSessionProxy* proxy; InfdRequest* request; }; typedef enum _InfdDirectorySubreqType { INFD_DIRECTORY_SUBREQ_CHAT, INFD_DIRECTORY_SUBREQ_SESSION, INFD_DIRECTORY_SUBREQ_ADD_NODE, INFD_DIRECTORY_SUBREQ_SYNC_IN, INFD_DIRECTORY_SUBREQ_SYNC_IN_SUBSCRIBE } InfdDirectorySubreqType; /* Subscription request */ typedef struct _InfdDirectorySubreq InfdDirectorySubreq; struct _InfdDirectorySubreq { InfdDirectorySubreqType type; InfXmlConnection* connection; /* TODO: Should maybe go to shared as CHAT is not using this: */ guint node_id; union { struct { InfdSessionProxy* session; InfdRequest* request; } session; struct { InfdDirectoryNode* parent; InfCommunicationHostedGroup* group; const InfdNotePlugin* plugin; gchar* name; InfAclSheetSet* sheet_set; /* TODO: Isn't group already present in proxy? */ InfdSessionProxy* proxy; InfdRequest* request; } add_node; struct { InfdDirectoryNode* parent; InfCommunicationHostedGroup* synchronization_group; InfCommunicationHostedGroup* subscription_group; const InfdNotePlugin* plugin; gchar* name; InfAclSheetSet* sheet_set; /* TODO: Aren't the groups already present in proxy? */ InfdSessionProxy* proxy; InfdRequest* request; } sync_in; } shared; }; typedef struct _InfdDirectoryConnectionInfo InfdDirectoryConnectionInfo; struct _InfdDirectoryConnectionInfo { guint seq_id; InfAclAccountId account_id; }; typedef struct _InfdDirectoryTransientAccount InfdDirectoryTransientAccount; struct _InfdDirectoryTransientAccount { InfAclAccount account; gchar* dn; }; typedef struct _InfdDirectoryPrivate InfdDirectoryPrivate; struct _InfdDirectoryPrivate { InfIo* io; InfdStorage* storage; InfdAccountStorage* account_storage; InfCommunicationManager* communication_manager; InfCommunicationHostedGroup* group; gnutls_x509_privkey_t private_key; InfCertificateChain* certificate; GHashTable* plugins; /* Registered plugins */ GHashTable* connections; /* Connection infos */ InfdDirectoryTransientAccount* transient_accounts; guint n_transient_accounts; guint node_counter; GHashTable* nodes; /* Mapping from id to node */ InfdDirectoryNode* root; InfAclSheetSet* orig_root_acl; /* in case root->acl is altered */ GSList* sync_ins; GSList* subscription_requests; InfdSessionProxy* chat_session; }; enum { PROP_0, PROP_IO, PROP_STORAGE, PROP_ACCOUNT_STORAGE, PROP_COMMUNICATION_MANAGER, PROP_PRIVATE_KEY, PROP_CERTIFICATE, /* read only */ PROP_CHAT_SESSION, PROP_STATUS }; enum { CONNECTION_ADDED, CONNECTION_REMOVED, LAST_SIGNAL }; static const unsigned int DAYS = 24 * 60 * 60; #define INFD_DIRECTORY_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INFD_TYPE_DIRECTORY, InfdDirectoryPrivate)) /* These make sure that the node iter points to is contained in directory */ #define infd_directory_return_if_iter_fail(directory, iter) \ g_return_if_fail( \ g_hash_table_lookup( \ INFD_DIRECTORY_PRIVATE(INFD_DIRECTORY(directory))->nodes, \ GUINT_TO_POINTER((iter)->node_id) \ ) == (iter)->node \ ) #define infd_directory_return_val_if_iter_fail(directory, iter, val) \ g_return_val_if_fail( \ g_hash_table_lookup( \ INFD_DIRECTORY_PRIVATE(INFD_DIRECTORY(directory))->nodes, \ GUINT_TO_POINTER((iter)->node_id) \ ) == (iter)->node, \ val \ ) /* These make sure that node is a subdirectory node */ #define infd_directory_return_if_subdir_fail(node) \ g_return_if_fail( \ ((InfdDirectoryNode*)node)->type == INFD_DIRECTORY_NODE_SUBDIRECTORY \ ) #define infd_directory_return_val_if_subdir_fail(node, val) \ g_return_val_if_fail( \ ((InfdDirectoryNode*)node)->type == INFD_DIRECTORY_NODE_SUBDIRECTORY, \ val \ ) #define GBOOLEAN_TO_POINTER(boolean) \ (GUINT_TO_POINTER( (boolean) ? 2 : 1)) #define GPOINTER_TO_BOOLEAN(boolean) \ ((gboolean) ((GPOINTER_TO_UINT(boolean) == 2) ? TRUE : FALSE)) static guint directory_signals[LAST_SIGNAL]; static GQuark infd_directory_node_id_quark; /* Time a session needs to be idle before it is unloaded from RAM */ /* TODO: This should be a property: */ static const guint INFD_DIRECTORY_SAVE_TIMEOUT = 60000; static void infd_directory_communication_object_iface_init(InfCommunicationObjectInterface* iface); static void infd_directory_browser_iface_init(InfBrowserInterface* iface); G_DEFINE_TYPE_WITH_CODE(InfdDirectory, infd_directory, G_TYPE_OBJECT, G_ADD_PRIVATE(InfdDirectory) G_IMPLEMENT_INTERFACE(INF_COMMUNICATION_TYPE_OBJECT, infd_directory_communication_object_iface_init) G_IMPLEMENT_INTERFACE(INF_TYPE_BROWSER, infd_directory_browser_iface_init)) /* * Path handling. */ /* Returns the complete path to this node in the given GString */ static void infd_directory_node_get_path_string(InfdDirectoryNode* node, GString* string) { g_return_if_fail(node != NULL); g_return_if_fail(string != NULL); if(node->parent != NULL) { /* Each node except the root node has a name */ g_assert(node->name != NULL); /* Make sure to not recurse if our parent is the root node because * this would add an additional slash */ if(node->parent->parent != NULL) infd_directory_node_get_path_string(node->parent, string); g_string_append_c(string, '/'); g_string_append(string, node->name); } else { /* This node has no parent, so it is the root node */ g_assert(node->name == NULL); g_string_append_c(string, '/'); } } static void infd_directory_node_get_path(InfdDirectoryNode* node, gchar** path, gsize* len) { GString* str; g_return_if_fail(node != NULL); g_return_if_fail(path != NULL); str = g_string_sized_new(128); infd_directory_node_get_path_string(node, str); *path = str->str; if(len != NULL) *len = str->len; g_string_free(str, FALSE); } static void infd_directory_node_make_path(InfdDirectoryNode* node, const gchar* name, gchar** path, gsize* len) { GString* str; g_return_if_fail(node != NULL); g_return_if_fail(name != NULL); g_return_if_fail(path != NULL); str = g_string_sized_new(128); infd_directory_node_get_path_string(node, str); if(node->parent != NULL) g_string_append_c(str, '/'); g_string_append(str, name); *path = str->str; if(len != NULL) *len = str->len; g_string_free(str, FALSE); } /* * Save timeout */ /* Required by infd_directory_session_save_timeout_func() */ static void infd_directory_node_unlink_session(InfdDirectory* directory, InfdDirectoryNode* node, InfdRequest* request); static void infd_directory_session_save_timeout_data_free(gpointer data) { g_slice_free(InfdDirectorySessionSaveTimeoutData, data); } static void infd_directory_session_save_timeout_func(gpointer user_data) { InfdDirectorySessionSaveTimeoutData* timeout_data; InfdDirectoryPrivate* priv; GError* error; gchar* path; gboolean result; InfSession* session; timeout_data = (InfdDirectorySessionSaveTimeoutData*)user_data; g_assert(timeout_data->node->type == INFD_DIRECTORY_NODE_NOTE); g_assert(timeout_data->node->shared.note.save_timeout != NULL); priv = INFD_DIRECTORY_PRIVATE(timeout_data->directory); error = NULL; infd_directory_node_get_path(timeout_data->node, &path, NULL); g_object_get( G_OBJECT(timeout_data->node->shared.note.session), "session", &session, NULL ); /* TODO: Only write if the buffer modified-flag is set */ result = timeout_data->node->shared.note.plugin->session_write( priv->storage, session, path, timeout_data->node->shared.note.plugin->user_data, &error ); g_object_unref(session); /* TODO: Unset modified flag of buffer if result == TRUE */ /* The timeout is removed automatically after it has elapsed */ timeout_data->node->shared.note.save_timeout = NULL; if(result == FALSE) { g_warning( _("Failed to save note \"%s\": %s\n\nKeeping it in memory. Another " "save attempt will be made when the server is shut down."), path, error->message ); g_error_free(error); } else { infd_directory_node_unlink_session( timeout_data->directory, timeout_data->node, NULL ); } g_free(path); } static void infd_directory_start_session_save_timeout(InfdDirectory* directory, InfdDirectoryNode* node) { InfdDirectoryPrivate* priv; InfdDirectorySessionSaveTimeoutData* timeout_data; priv = INFD_DIRECTORY_PRIVATE(directory); timeout_data = g_slice_new(InfdDirectorySessionSaveTimeoutData); timeout_data->directory = directory; timeout_data->node = node; if(priv->storage != NULL) { node->shared.note.save_timeout = inf_io_add_timeout( priv->io, INFD_DIRECTORY_SAVE_TIMEOUT, infd_directory_session_save_timeout_func, timeout_data, infd_directory_session_save_timeout_data_free ); } } static void infd_directory_session_weak_ref_cb(gpointer data, GObject* where_the_object_was) { InfdDirectoryNode* node; node = (InfdDirectoryNode*)data; g_assert(G_OBJECT(node->shared.note.session) == where_the_object_was); g_assert(node->shared.note.weakref == TRUE); g_assert(node->shared.note.save_timeout == NULL); node->shared.note.session = NULL; node->shared.note.weakref = FALSE; } static void infd_directory_session_idle_notify_cb(GObject* object, GParamSpec* pspec, gpointer user_data) { InfdDirectory* directory; InfdDirectoryPrivate* priv; gpointer node_id; InfdDirectoryNode* node; directory = INFD_DIRECTORY(user_data); priv = INFD_DIRECTORY_PRIVATE(directory); node_id = g_object_get_qdata(object, infd_directory_node_id_quark); node = g_hash_table_lookup(priv->nodes, node_id); g_assert(node != NULL); /* Drop session from memory if it remains idle */ if(infd_session_proxy_is_idle(INFD_SESSION_PROXY(object))) { if(node->shared.note.weakref == FALSE && node->shared.note.save_timeout == NULL) { infd_directory_start_session_save_timeout(directory, node); } } else { /* If a session becomes non-idle again then strong-ref it */ if(node->shared.note.weakref == TRUE) { g_object_ref(node->shared.note.session); g_assert(node->shared.note.save_timeout == NULL); node->shared.note.weakref = FALSE; g_object_weak_unref( G_OBJECT(node->shared.note.session), infd_directory_session_weak_ref_cb, node ); } else if(node->shared.note.save_timeout != NULL) { inf_io_remove_timeout(priv->io, node->shared.note.save_timeout); node->shared.note.save_timeout = NULL; } } } static gboolean infd_directory_session_reject_user_join_cb(InfdSessionProxy* proxy, InfXmlConnection* connection, const GArray* user_properties, InfUser* rejoin_user, gpointer user_data) { InfdDirectory* directory; InfdDirectoryPrivate* priv; gpointer node_id; InfdDirectoryNode* node; InfdDirectoryConnectionInfo* info; InfBrowserIter iter; InfAclMask check_mask; gboolean result; directory = INFD_DIRECTORY(user_data); priv = INFD_DIRECTORY_PRIVATE(directory); node_id = g_object_get_qdata(G_OBJECT(proxy), infd_directory_node_id_quark); node = g_hash_table_lookup(priv->nodes, node_id); g_assert(node != NULL); /* ACL cannot prevent local users from joining */ if(connection != NULL) { info = g_hash_table_lookup(priv->connections, connection); g_assert(info != NULL); iter.node_id = node->id; iter.node = node; inf_acl_mask_set1(&check_mask, INF_ACL_CAN_JOIN_USER); result = inf_browser_check_acl( INF_BROWSER(directory), &iter, info->account_id, &check_mask, NULL ); /* Reject the user join if the permission is not set. */ if(result == FALSE) return TRUE; } return FALSE; } /* Releases a session fully from the directory. This is not normally needed * because if we don't need a session anymore we still keep a weak reference * to it around, in case we need to recover it later. When nobody is holding * a strong reference to it anymore we clear the pointer in * infd_directory_session_weak_ref_cb(). The only point where this function * is being called is when a node with an active session is removed from the * directory. */ static void infd_directory_release_session(InfdDirectory* directory, InfdDirectoryNode* node, InfdSessionProxy* session) { InfdDirectoryPrivate* priv; priv = INFD_DIRECTORY_PRIVATE(directory); g_assert(node->type == INFD_DIRECTORY_NODE_NOTE); g_assert(node->shared.note.session == session); if(node->shared.note.save_timeout != NULL) { inf_io_remove_timeout(priv->io, node->shared.note.save_timeout); node->shared.note.save_timeout = NULL; } inf_signal_handlers_disconnect_by_func( G_OBJECT(session), G_CALLBACK(infd_directory_session_idle_notify_cb), directory ); inf_signal_handlers_disconnect_by_func( G_OBJECT(session), G_CALLBACK(infd_directory_session_reject_user_join_cb), directory ); g_object_set_qdata( G_OBJECT(session), infd_directory_node_id_quark, NULL ); if(node->shared.note.weakref == TRUE) { g_object_weak_unref( G_OBJECT(session), infd_directory_session_weak_ref_cb, node ); } else { g_object_unref(session); } node->shared.note.session = NULL; node->shared.note.weakref = FALSE; } /* * ACLs */ static void infd_directory_announce_acl_account(InfdDirectory* directory, const InfAclAccount* account, InfXmlConnection* except) { InfdDirectoryPrivate* priv; InfBrowser* browser; xmlNodePtr xml; InfBrowserIter iter; InfAclMask mask; GHashTableIter hash_iter; gpointer key; gpointer value; InfXmlConnection* connection; InfdDirectoryConnectionInfo* conn_info; InfAclAccountId account_id; priv = INFD_DIRECTORY_PRIVATE(directory); browser = INF_BROWSER(directory); xml = xmlNewNode(NULL, (const xmlChar*)"add-acl-account"); inf_acl_account_to_xml(account, xml); iter.node = priv->root; iter.node_id = priv->root->id; inf_acl_mask_set1(&mask, INF_ACL_CAN_QUERY_ACCOUNT_LIST); /* Send to all connections that have the INF_ACL_CAN_QUERY_ACCOUNT_LIST * permission. */ g_hash_table_iter_init(&hash_iter, priv->connections); while(g_hash_table_iter_next(&hash_iter, &key, &value)) { connection = INF_XML_CONNECTION(key); conn_info = (InfdDirectoryConnectionInfo*)value; account_id = conn_info->account_id; g_assert(account_id != 0); if(inf_browser_check_acl(browser, &iter, account_id, &mask, NULL) && connection != except) { inf_communication_group_send_message( INF_COMMUNICATION_GROUP(priv->group), connection, xmlCopyNode(xml, 1) ); } } inf_browser_acl_account_added(INF_BROWSER(directory), account, NULL); xmlFreeNode(xml); } /* acl_connections is a list of connections which have queried the full ACL. * It can be NULL in which case only the default sheet and the sheet for that * particular connection are sent. */ static gboolean infd_directory_acl_sheets_to_xml_for_connection(InfdDirectory* directory, GSList* acl_connections, const InfAclSheetSet* sheets, InfXmlConnection* connection, xmlNodePtr xml) { InfdDirectoryPrivate* priv; InfdDirectoryConnectionInfo* info; guint written_sheets; InfAclSheet selected_sheets[2]; InfAclSheetSet set; InfAclAccountId default_id; guint i; priv = INFD_DIRECTORY_PRIVATE(directory); if(g_slist_find(acl_connections, connection) != NULL) { if(sheets->n_sheets > 0) inf_acl_sheet_set_to_xml(sheets, xml); written_sheets = sheets->n_sheets; } else { /* Otherwise, add only the sheets for the user itself and the default * sheet. */ info = g_hash_table_lookup(priv->connections, connection); g_assert(info != NULL); default_id = inf_acl_account_id_from_string("default"); written_sheets = 0; for(i = 0; i < sheets->n_sheets && written_sheets < 2; ++i) { if(sheets->sheets[i].account == default_id || sheets->sheets[i].account == info->account_id) { selected_sheets[written_sheets] = sheets->sheets[i]; ++written_sheets; } } if(written_sheets > 0) { set.own_sheets = NULL; set.sheets = selected_sheets; set.n_sheets = written_sheets; inf_acl_sheet_set_to_xml(&set, xml); } } if(written_sheets == 0) return FALSE; return TRUE; } static void infd_directory_announce_acl_sheets_for_connection(InfdDirectory* directory, const InfdDirectoryNode* nd, const InfAclSheetSet* shts, InfXmlConnection* conn) { InfdDirectoryPrivate* priv; gboolean has_sheets; xmlNodePtr xml; gboolean any_sheets; priv = INFD_DIRECTORY_PRIVATE(directory); xml = xmlNewNode(NULL, (const xmlChar*)"set-acl"); any_sheets = infd_directory_acl_sheets_to_xml_for_connection( directory, nd->acl_connections, shts, conn, xml ); if(any_sheets == TRUE) { inf_xml_util_set_attribute_uint(xml, "id", nd->id); inf_communication_group_send_message( INF_COMMUNICATION_GROUP(priv->group), conn, xml ); } else { xmlFreeNode(xml); } } static void infd_directory_announce_acl_sheets(InfdDirectory* directory, InfdDirectoryNode* node, InfdRequest* request, const InfAclSheetSet* sheet_set, InfXmlConnection* except) { InfdDirectoryPrivate* priv; xmlNodePtr xml; GList* connection_list; GSList* local_connection_list; GList* item; GSList* local_item; InfBrowserIter iter; priv = INFD_DIRECTORY_PRIVATE(directory); /* Go through all connections that see this node, i.e. have explored the * parent node. To those connections we need to send an ACL update. */ if(node->parent == NULL) { connection_list = g_hash_table_get_keys(priv->connections); for(item = connection_list; item != NULL; item = g_list_next(item)) { if(item->data != except) { infd_directory_announce_acl_sheets_for_connection( directory, node, sheet_set, INF_XML_CONNECTION(item->data) ); } } g_list_free(connection_list); } else { local_connection_list = node->parent->shared.subdir.connections; for(local_item = local_connection_list; local_item != NULL; local_item = g_slist_next(local_item)) { if(local_item->data != except) { infd_directory_announce_acl_sheets_for_connection( directory, node, sheet_set, INF_XML_CONNECTION(local_item->data) ); } } } iter.node_id = node->id; iter.node = node; inf_browser_acl_changed( INF_BROWSER(directory), &iter, sheet_set, INF_REQUEST(request) ); } static InfAclAccountId infd_directory_get_account_for_certificate(InfdDirectory* directory, gnutls_x509_crt_t cert, GError** error) { InfdDirectoryPrivate* priv; gboolean supports_login_by_certificate; priv = INFD_DIRECTORY_PRIVATE(directory); supports_login_by_certificate = FALSE; if(priv->account_storage != NULL) { supports_login_by_certificate = infd_account_storage_supports( priv->account_storage, INFD_ACCOUNT_STORAGE_SUPPORT_CERTIFICATE_LOGIN ); } /* Don't create an error */ if(!supports_login_by_certificate) return 0; return infd_account_storage_login_by_certificate( priv->account_storage, cert, error ); } static InfAclAccountId infd_directory_login_by_certificate(InfdDirectory* directory, InfXmlConnection* connection) { InfdDirectoryPrivate* priv; InfCertificateChain* chain; InfAclAccountId login_id; gchar* dn; guint i; GError* error; priv = INFD_DIRECTORY_PRIVATE(directory); g_object_get(G_OBJECT(connection), "remote-certificate", &chain, NULL); login_id = 0; if(chain != NULL) { error = NULL; dn = inf_cert_util_get_dn( inf_certificate_chain_get_own_certificate(chain) ); for(i = 0; i < priv->n_transient_accounts; ++i) { if(priv->transient_accounts[i].dn != NULL) { if(strcmp(priv->transient_accounts[i].dn, dn) == 0) { login_id = priv->transient_accounts[i].account.id; break; } } } if(login_id == 0) { login_id = infd_directory_get_account_for_certificate( directory, inf_certificate_chain_get_own_certificate(chain), &error ); if(error != NULL) { dn = inf_cert_util_get_dn( inf_certificate_chain_get_own_certificate(chain) ); g_warning( _("Failed to login client \"%s\" by certificate: %s"), dn, error->message ); g_error_free(error); } } g_free(dn); inf_certificate_chain_unref(chain); } /* No client certificate provided, or certificate not registered with any * account: Fall back to default user. */ if(login_id == 0) login_id = inf_acl_account_id_from_string("default"); return login_id; } static void infd_directory_write_acl_at_path(InfdDirectory* directory, const gchar* path, const InfAclSheetSet* acl) { InfdDirectoryPrivate* priv; InfBrowserIter iter; GError* error; priv = INFD_DIRECTORY_PRIVATE(directory); /* Write the changed ACL into the storage */ if(priv->storage != NULL) { error = NULL; /* TODO: Don't write sheets for transient accounts. It does not make much * difference, because the transient user account is not stored, so the * sheet will be rejected anyway when it is read from disk next time. */ infd_storage_write_acl(priv->storage, path, acl, &error); if(error != NULL) { g_warning( _("Failed to write ACL for node \"%s\": %s\nThe new ACL is applied " "but will be lost after a server re-start. This is a possible " "security problem. Please fix the problem with the storage!"), path, error->message ); g_error_free(error); } } } static void infd_directory_write_acl(InfdDirectory* directory, InfdDirectoryNode* node) { InfdDirectoryPrivate* priv; InfBrowserIter iter; InfAclSheetSet* acl; gchar* path; priv = INFD_DIRECTORY_PRIVATE(directory); /* Write the changed ACL into the storage */ if(priv->storage != NULL) { infd_directory_node_get_path(node, &path, NULL); /* In case this is the root node, store the original non-altered ACL. This * allows to keep certain permissions at the original value, even if they * are disabled in the current configuration. */ acl = node->acl; if(node == priv->root) acl = priv->orig_root_acl; infd_directory_write_acl_at_path(directory, path, acl); g_free(path); } } /* This function removes ACL sheets from sheet_set that do not belong to * any known user. Known users are given in the verify_accounts hash table, * and if lookup_if_not_cached is set to TRUE, then accounts not found in * the hash table are looked up from the account storage, and the hash table * is updated with the lookup result. * * The returned sheet set is NULL if no changes were made, or a sheet set * containing all changed sheets. If report_changed_sheets is FALSE, the * function always returns NULL. */ static InfAclSheetSet* infd_directory_verify_acl(InfdDirectory* directory, InfAclSheetSet* sheet_set, GHashTable* verify_accounts, gboolean lookup_if_not_cached, gboolean report_changed_sheets) { InfdDirectoryPrivate* priv; GArray* to_be_looked_up; gboolean is_cached; gpointer cache_result; guint i, j; InfAclSheetSet* changed_sheets; InfAclSheet* sheet; InfAclAccount* accounts; InfAclAccountId account_id; GError* error; priv = INFD_DIRECTORY_PRIVATE(directory); g_assert(verify_accounts != NULL || lookup_if_not_cached == TRUE); g_assert(sheet_set->n_sheets == 0 || sheet_set->own_sheets != NULL); changed_sheets = NULL; to_be_looked_up = NULL; for(i = 0; i < sheet_set->n_sheets; ) { if(verify_accounts != NULL) { is_cached = g_hash_table_lookup_extended( verify_accounts, INF_ACL_ACCOUNT_ID_TO_POINTER(sheet_set->sheets[i].account), NULL, &cache_result ); } else { is_cached = FALSE; } if(is_cached == TRUE) { if(GPOINTER_TO_BOOLEAN(cache_result) == FALSE) { account_id = sheet_set->sheets[i].account; inf_acl_sheet_set_remove_sheet(sheet_set, &sheet_set->own_sheets[i]); if(report_changed_sheets) { if(changed_sheets == NULL) changed_sheets = inf_acl_sheet_set_new(); sheet = inf_acl_sheet_set_add_sheet(changed_sheets, account_id); inf_acl_mask_clear(&sheet->mask); } } else { ++i; } } else { /* Did not find in the cache */ if(lookup_if_not_cached) { /* Check transient accounts */ for(j = 0; j < priv->n_transient_accounts; ++j) { if(priv->transient_accounts[j].account.id == sheet_set->sheets[i].account) { if(verify_accounts != NULL) { g_hash_table_insert( verify_accounts, INF_ACL_ACCOUNT_ID_TO_POINTER(sheet_set->sheets[i].account), GBOOLEAN_TO_POINTER(TRUE) ); } break; } } if(j < priv->n_transient_accounts) { ++i; } else { if(priv->account_storage != NULL) { /* Not a transient account either, so look up from storage */ if(to_be_looked_up == NULL) { to_be_looked_up = g_array_new( FALSE, FALSE, sizeof(InfAclAccountId) ); } g_array_append_val(to_be_looked_up, sheet_set->sheets[i].account); ++i; } else { /* We do not have an account storage, so the account does * definitely not exist */ account_id = sheet_set->sheets[i].account; inf_acl_sheet_set_remove_sheet( sheet_set, &sheet_set->own_sheets[i] ); if(report_changed_sheets) { if(changed_sheets == NULL) changed_sheets = inf_acl_sheet_set_new(); sheet = inf_acl_sheet_set_add_sheet(changed_sheets, account_id); inf_acl_mask_clear(&sheet->mask); } } } } } } /* Look up the missing pieces */ if(to_be_looked_up != NULL) { error = NULL; accounts = infd_account_storage_lookup_accounts( priv->account_storage, (InfAclAccountId*)to_be_looked_up->data, to_be_looked_up->len, &error ); if(error != NULL) { /* If an error occurred, keep the sheet set as it is, i.e. don't * remove anything, just in case. */ g_warning( _("Failed to look up accounts in account storage: %s"), error->message ); g_error_free(error); } else { for(i = 0; i < to_be_looked_up->len; ++i) { account_id = accounts[i].id; if(account_id == 0) { /* Not found, remove from sheet set */ account_id = g_array_index(to_be_looked_up, InfAclAccountId, i); sheet = inf_acl_sheet_set_find_sheet(sheet_set, account_id); g_assert(sheet != NULL); inf_acl_sheet_set_remove_sheet(sheet_set, sheet); if(report_changed_sheets) { if(changed_sheets == NULL) changed_sheets = inf_acl_sheet_set_new(); sheet = inf_acl_sheet_set_add_sheet(changed_sheets, account_id); inf_acl_mask_clear(&sheet->mask); } if(verify_accounts != NULL) { g_hash_table_insert( verify_accounts, INF_ACL_ACCOUNT_ID_TO_POINTER(account_id), GBOOLEAN_TO_POINTER(FALSE) ); } } else { /* Found */ if(verify_accounts != NULL) { g_hash_table_insert( verify_accounts, INF_ACL_ACCOUNT_ID_TO_POINTER(account_id), GBOOLEAN_TO_POINTER(TRUE) ); } } } inf_acl_account_array_free(accounts, to_be_looked_up->len); } g_array_free(to_be_looked_up, TRUE); } return changed_sheets; } static void infd_directory_verify_acl_for_node(InfdDirectory* directory, InfdDirectoryNode* node, GHashTable* verify_accounts, gboolean lookup_if_not_cached) { InfdDirectoryPrivate* priv; InfdDirectoryNode* child; InfAclSheetSet* removed_sheets; InfBrowserIter iter; priv = INFD_DIRECTORY_PRIVATE(directory); if(node->type == INFD_DIRECTORY_NODE_SUBDIRECTORY && node->shared.subdir.explored == TRUE) { for(child = node->shared.subdir.child; child != NULL; child = child->next) { infd_directory_verify_acl_for_node( directory, child, verify_accounts, lookup_if_not_cached ); } } if(node->acl != NULL) { removed_sheets = infd_directory_verify_acl( directory, node->acl, verify_accounts, lookup_if_not_cached, TRUE ); if(node == priv->root) { infd_directory_verify_acl( directory, priv->orig_root_acl, verify_accounts, lookup_if_not_cached, FALSE ); } if(removed_sheets != NULL) { iter.node = node; iter.node_id = node->id; inf_browser_acl_changed( INF_BROWSER(directory), &iter, removed_sheets, NULL ); inf_acl_sheet_set_free(removed_sheets); infd_directory_write_acl(directory, node); } } } static void infd_directory_verify_all_acls(InfdDirectory* directory, GHashTable* verify_accounts, gboolean lookup_if_not_cached) { InfdDirectoryPrivate* priv; GSList* item; InfdDirectorySyncIn* sync_in; InfdDirectorySubreq* subreq; InfAclSheetSet* acl; GHashTable* own_table; own_table = NULL; if(verify_accounts == NULL) { own_table = g_hash_table_new(NULL, NULL); verify_accounts = own_table; } priv = INFD_DIRECTORY_PRIVATE(directory); infd_directory_verify_acl_for_node( directory, priv->root, verify_accounts, lookup_if_not_cached ); /* Remove ACL sheet from sync-ins and subscription requests. */ for(item = priv->sync_ins; item != NULL; item = item->next) { sync_in = (InfdDirectorySyncIn*)item->data; if(sync_in->sheet_set != NULL) { infd_directory_verify_acl( directory, sync_in->sheet_set, verify_accounts, lookup_if_not_cached, FALSE ); } } for(item = priv->subscription_requests; item != NULL; item = item->next) { subreq = (InfdDirectorySubreq*)item->data; switch(subreq->type) { case INFD_DIRECTORY_SUBREQ_CHAT: case INFD_DIRECTORY_SUBREQ_SESSION: acl = NULL; break; case INFD_DIRECTORY_SUBREQ_ADD_NODE: acl = subreq->shared.add_node.sheet_set; break; case INFD_DIRECTORY_SUBREQ_SYNC_IN: case INFD_DIRECTORY_SUBREQ_SYNC_IN_SUBSCRIBE: acl = subreq->shared.sync_in.sheet_set; break; default: g_assert_not_reached(); break; } if(acl != NULL) { infd_directory_verify_acl( directory, acl, verify_accounts, lookup_if_not_cached, FALSE ); } } if(own_table != NULL) g_hash_table_destroy(own_table); } /* node can be NULL. If node is not NULL, additional sheets are returned * which correspond to erasure of the current ACL for the node. This allows * the ACL change to be performed atomically on the node. * * The verify_accounts table is a cache when verifying whether the accounts * present in the sheet exist or not. */ static InfAclSheetSet* infd_directory_read_acl(InfdDirectory* directory, const gchar* path, InfdDirectoryNode* node, GHashTable* verify_accounts, GError** error) { InfdDirectoryPrivate* priv; InfBrowserIter iter; GError* local_error; GSList* acl; GSList* item; InfdStorageAcl* storage_acl; InfAclSheetSet* sheet_set; InfAclSheet* sheet; InfAclAccountId account_id; InfAclSheetSet* verify_sheets; priv = INFD_DIRECTORY_PRIVATE(directory); g_assert(priv->storage != NULL); local_error = NULL; acl = infd_storage_read_acl(priv->storage, path, &local_error); if(local_error != NULL) { g_propagate_error(error, local_error); return FALSE; } /* If there are any ACLs set already for this node, then clear them. This * should usually not happen because we only call this function for new * nodes, but it can happen when the storage is changed on the fly and the * root node changes. */ if(node != NULL && node->acl != NULL) { sheet_set = inf_acl_sheet_set_get_clear_sheets(node->acl); } else { sheet_set = inf_acl_sheet_set_new(); } for(item = acl; item != NULL; item = g_slist_next(item)) { storage_acl = (InfdStorageAcl*)item->data; account_id = inf_acl_account_id_from_string(storage_acl->account_id); sheet = inf_acl_sheet_set_add_sheet(sheet_set, account_id); sheet->mask = storage_acl->mask; sheet->perms = storage_acl->perms; } infd_storage_acl_list_free(acl); if(priv->account_storage != NULL) { verify_sheets = infd_directory_verify_acl( directory, sheet_set, verify_accounts, TRUE, TRUE ); if(verify_sheets != NULL) { /* We do not need to make signal emissions here, since the ACL has just * been read. However, if verify_sheets is not equal to zero, then * sheets have been removed from the set, and we want to write the * updated set to storage. */ infd_directory_write_acl_at_path(directory, path, sheet_set); inf_acl_sheet_set_free(verify_sheets); } } return sheet_set; } static void infd_directory_report_support(InfdDirectory* directory, gboolean* add_account, gboolean* remove_account) { InfdDirectoryPrivate* priv; gboolean supports_add_account; gboolean supports_remove_account; InfdAccountStorageSupport support; priv = INFD_DIRECTORY_PRIVATE(directory); supports_add_account = FALSE; supports_remove_account = FALSE; if(priv->account_storage != NULL) { support = infd_account_storage_get_support(priv->account_storage); if(support & INFD_ACCOUNT_STORAGE_SUPPORT_ADD_ACCOUNT) if(priv->private_key != NULL && priv->certificate != NULL) supports_add_account = TRUE; if(support & INFD_ACCOUNT_STORAGE_SUPPORT_REMOVE_ACCOUNT) supports_remove_account = TRUE; } if(add_account != NULL) *add_account = supports_add_account; if(remove_account != NULL) *remove_account = supports_remove_account; } /* Change the given sheet set such that if we don't support account creation * or removal, it is disabled in sheet_set. Return FALSE if sheet_set had to * be changed. */ static gboolean infd_directory_report_support_in_sheets(InfdDirectory* directory, InfAclSheetSet* sheet_set) { gboolean supports_remove_account; gboolean supports_add_account; gboolean unaltered; guint i; InfAclSheet* sheet; InfAclMask tmp_mask; g_assert(sheet_set->n_sheets == 0 || sheet_set->own_sheets != NULL); infd_directory_report_support( directory, &supports_add_account, &supports_remove_account ); unaltered = TRUE; for(i = 0; i < sheet_set->n_sheets; ++i) { sheet = &sheet_set->own_sheets[i]; if(supports_add_account == FALSE && inf_acl_mask_has(&sheet->mask, INF_ACL_CAN_CREATE_ACCOUNT) && inf_acl_mask_has(&sheet->perms, INF_ACL_CAN_CREATE_ACCOUNT)) { /* Remove the INF_ACL_CAN_CREATE_ACCOUNT flag */ inf_acl_mask_set1(&tmp_mask, INF_ACL_CAN_CREATE_ACCOUNT); inf_acl_mask_neg(&tmp_mask, &tmp_mask); inf_acl_mask_and(&sheet->perms, &tmp_mask, &sheet->perms); unaltered = FALSE; } if(supports_remove_account == FALSE && inf_acl_mask_has(&sheet->mask, INF_ACL_CAN_REMOVE_ACCOUNT) && inf_acl_mask_has(&sheet->perms, INF_ACL_CAN_REMOVE_ACCOUNT)) { /* Remove the INF_ACL_CAN_REMOVE_ACCOUNT flag */ inf_acl_mask_set1(&tmp_mask, INF_ACL_CAN_REMOVE_ACCOUNT); inf_acl_mask_neg(&tmp_mask, &tmp_mask); inf_acl_mask_and(&sheet->perms, &tmp_mask, &sheet->perms); unaltered = FALSE; } } return unaltered; } static void infd_directory_update_root_acl(InfdDirectory* directory) { InfdDirectoryPrivate* priv; InfAclSheetSet* copy_set; InfAclSheetSet* merge_sheets; guint i; gboolean include_sheet; const InfAclSheet* new_sheet; const InfAclSheet* cur_sheet; InfAclSheet* merge_sheet; InfAclMask cur_perms; InfAclMask new_perms; priv = INFD_DIRECTORY_PRIVATE(directory); copy_set = inf_acl_sheet_set_copy(priv->orig_root_acl); infd_directory_report_support_in_sheets(directory, copy_set); /* We will now update root->acl to copy_set. Below we construct a * sheet set which contains the differences. */ merge_sheets = inf_acl_sheet_set_new(); for(i = 0; i < copy_set->n_sheets; ++i) { include_sheet = TRUE; new_sheet = ©_set->sheets[i]; cur_sheet = inf_acl_sheet_set_find_const_sheet( priv->root->acl, new_sheet->account ); g_assert(cur_sheet != NULL); if(inf_acl_mask_equal(&new_sheet->mask, &cur_sheet->mask)) { inf_acl_mask_and(&cur_sheet->perms, &cur_sheet->mask, &cur_perms); inf_acl_mask_and(&new_sheet->perms, &new_sheet->mask, &new_perms); if(inf_acl_mask_equal(&cur_perms, &new_perms)) include_sheet = FALSE; } /* The sheet has changed */ if(include_sheet) { merge_sheet = inf_acl_sheet_set_add_sheet( merge_sheets, new_sheet->account ); merge_sheet->mask = new_sheet->mask; merge_sheet->perms = new_sheet->perms; } } /* We make use of the fact that there are the same sheets in * priv->orig_root_acl and priv->root->acl. */ if(merge_sheets->n_sheets > 0) { inf_acl_sheet_set_free(priv->root->acl); priv->root->acl = copy_set; infd_directory_announce_acl_sheets( directory, priv->root, NULL, merge_sheets, NULL ); } else { inf_acl_sheet_set_free(copy_set); } inf_acl_sheet_set_free(merge_sheets); } static void infd_directory_read_root_acl(InfdDirectory* directory) { InfdDirectoryPrivate* priv; InfAclAccountId default_id; InfAclSheetSet* sheet_set; InfAclSheet* default_sheet; InfAclSheet* sheet; InfAclMask default_mask; InfAclMask tmp_mask; GError* error; priv = INFD_DIRECTORY_PRIVATE(directory); error = NULL; sheet_set = infd_directory_read_acl( directory, "/", priv->root, NULL, &error ); /* Will be reset below: */ if(priv->orig_root_acl != NULL) inf_acl_sheet_set_free(priv->orig_root_acl); default_id = inf_acl_account_id_from_string("default"); if(error != NULL) { g_assert(sheet_set == NULL); g_warning( _("Failed to read the ACL for the root node: %s\n" "In order not to compromise security all permissions have been " "revoked for all users. The infinote server is likely not very " "usable in this configuration, so please check the storage " "system, fix the problem and re-start the server."), error->message ); g_error_free(error); /* Clear all existing sheets and add one sheet for the default user which * prohibits everything. */ if(priv->root->acl != NULL) sheet_set = inf_acl_sheet_set_get_clear_sheets(priv->root->acl); else sheet_set = inf_acl_sheet_set_new(); default_sheet = inf_acl_sheet_set_add_sheet(sheet_set, default_id); default_sheet->mask = INF_ACL_MASK_ALL; inf_acl_mask_clear(&default_sheet->perms); /* Make sure this "revoke-everything" sheet is not written to disk. */ priv->root->acl = inf_acl_sheet_set_merge_sheets( priv->root->acl, sheet_set ); if(priv->root->acl != NULL) priv->orig_root_acl = inf_acl_sheet_set_copy(priv->root->acl); else priv->orig_root_acl = NULL; infd_directory_announce_acl_sheets( directory, priv->root, NULL, /* TODO: make a request for this? */ sheet_set, NULL ); } else { /* Make sure there are permissions for the default user defined. If there * are not, use sensible default permissions. */ default_sheet = inf_acl_sheet_set_add_sheet(sheet_set, default_id); default_mask = default_sheet->mask; inf_acl_mask_neg(&default_mask, &tmp_mask); inf_acl_mask_and(&tmp_mask, &INF_ACL_MASK_DEFAULT, &tmp_mask); inf_acl_mask_or(&default_sheet->perms, &tmp_mask, &default_sheet->perms); default_sheet->mask = INF_ACL_MASK_ALL; /* Set original ACL as read from disk */ if(priv->root->acl != NULL) priv->orig_root_acl = inf_acl_sheet_set_copy(priv->root->acl); else priv->orig_root_acl = NULL; /* Note that the sheets array already includes sheets that clear the * existing ACL. */ priv->orig_root_acl = inf_acl_sheet_set_merge_sheets( priv->orig_root_acl, sheet_set ); /* For the actual permissions to use, remove the CAN_ADD_ACCOUNT * permission if we do not have a certificate set or if it is not * supported by the backend. */ infd_directory_report_support_in_sheets(directory, sheet_set); priv->root->acl = inf_acl_sheet_set_merge_sheets( priv->root->acl, sheet_set ); infd_directory_announce_acl_sheets( directory, priv->root, NULL, /* TODO: make a request for this? */ sheet_set, NULL ); inf_acl_mask_and(&default_mask, &INF_ACL_MASK_ALL, &default_mask); if(!inf_acl_mask_equal(&default_mask, &INF_ACL_MASK_ALL)) infd_directory_write_acl(directory, priv->root); } inf_acl_sheet_set_free(sheet_set); } /* * Node construction and removal */ /* Creates the subscription group for a node, named "InfSession_%u", %u being * the node id (which should be unique). */ static InfCommunicationHostedGroup* infd_directory_create_subscription_group(InfdDirectory* directory, guint node_id) { InfdDirectoryPrivate* priv; InfCommunicationHostedGroup* group; gchar* group_name; /* TODO: For the moment, there only exist central methods anyway. In the * long term, this should probably be a property, though. */ static const gchar* const methods[] = { "central", NULL }; priv = INFD_DIRECTORY_PRIVATE(directory); group_name = g_strdup_printf("InfSession_%u", node_id); group = inf_communication_manager_open_group( priv->communication_manager, group_name, methods ); g_free(group_name); return group; } static InfdSessionProxy* infd_directory_create_session_proxy_with_group(InfdDirectory* directory, InfSession* session, InfCommunicationHostedGroup* g) { InfdDirectoryPrivate* priv; InfdSessionProxy* proxy; priv = INFD_DIRECTORY_PRIVATE(directory); g_assert( inf_communication_group_get_target(INF_COMMUNICATION_GROUP(g)) == NULL ); proxy = INFD_SESSION_PROXY( g_object_new( INFD_TYPE_SESSION_PROXY, "io", priv->io, "session", session, "subscription-group", g, NULL ) ); inf_communication_group_set_target( INF_COMMUNICATION_GROUP(g), INF_COMMUNICATION_OBJECT(proxy) ); return proxy; } static InfdSessionProxy* infd_directory_create_session_proxy(InfdDirectory* directory, const InfdNotePlugin* plugin, InfSessionStatus status, InfCommunicationHostedGroup* sync_g, InfXmlConnection* sync_conn, InfCommunicationHostedGroup* sub_g, const char* path) { InfdDirectoryPrivate* priv; InfSession* session; InfdSessionProxy* proxy; g_assert(sub_g != NULL); priv = INFD_DIRECTORY_PRIVATE(directory); session = plugin->session_new( priv->io, priv->communication_manager, status, INF_COMMUNICATION_GROUP(sync_g), sync_conn, path, plugin->user_data ); proxy = infd_directory_create_session_proxy_with_group( directory, session, sub_g ); g_object_unref(session); if(sync_g != NULL && sync_g != sub_g) { inf_communication_group_set_target( INF_COMMUNICATION_GROUP(sync_g), INF_COMMUNICATION_OBJECT(proxy) ); } return proxy; } /* Called after a session proxy has been created for a newly added node. * It attempts to store the node in the storage. If it cannot be stored, the * function fails and unrefs the proxy. */ static gboolean infd_directory_session_proxy_ensure(InfdDirectory* directory, InfdDirectoryNode* parent, const gchar* name, const InfdNotePlugin* plugin, InfdSessionProxy* proxy, GError** error) { InfdDirectoryPrivate* priv; gchar* path; InfSession* session; gboolean ret; InfCommunicationGroup* sub_group; InfCommunicationGroup* sync_group; priv = INFD_DIRECTORY_PRIVATE(directory); g_object_get(G_OBJECT(proxy), "session", &session, NULL); if(priv->storage != NULL) { /* Save session initially */ infd_directory_node_make_path(parent, name, &path, NULL); ret = plugin->session_write( priv->storage, session, path, plugin->user_data, error ); g_free(path); /* Unset modified flag since we just wrote the buffer contents into * storage. */ if(ret == TRUE) inf_buffer_set_modified(inf_session_get_buffer(session), FALSE); } else { ret = TRUE; } if(ret == FALSE) { /* Reset communication groups for the proxy, to avoid a warning at * final unref. Due do this failing the groups are very likely going to be * unrefed as well any time soon. */ sub_group = inf_session_get_subscription_group(session); inf_communication_group_set_target(sub_group, NULL); g_object_get(G_OBJECT(session), "sync-group", &sync_group, NULL); if(sync_group != NULL && sync_group != sub_group) inf_communication_group_set_target(sync_group, NULL); if(sync_group != NULL) g_object_unref(sync_group); g_object_unref(proxy); } g_object_unref(session); return ret; } /* Links a InfdSessionProxy with a InfdDirectoryNode */ static void infd_directory_node_link_session(InfdDirectory* directory, InfdDirectoryNode* node, InfdRequest* request, InfdSessionProxy* proxy) { InfdDirectoryPrivate* priv; InfBrowserIter iter; priv = INFD_DIRECTORY_PRIVATE(directory); g_assert(node->type == INFD_DIRECTORY_NODE_NOTE); g_assert(node->shared.note.session == NULL || (node->shared.note.session == proxy && node->shared.note.weakref == TRUE)); iter.node = node; iter.node_id = node->id; inf_browser_subscribe_session( INF_BROWSER(directory), &iter, INF_SESSION_PROXY(proxy), INF_REQUEST(request) ); } static void infd_directory_node_unlink_session(InfdDirectory* directory, InfdDirectoryNode* node, InfdRequest* request) { InfdDirectoryPrivate* priv; InfBrowserIter iter; priv = INFD_DIRECTORY_PRIVATE(directory); g_assert(node->type == INFD_DIRECTORY_NODE_NOTE); g_assert(node->shared.note.session != NULL); g_assert(node->shared.note.weakref == FALSE); iter.node = node; iter.node_id = node->id; inf_browser_unsubscribe_session( INF_BROWSER(directory), &iter, INF_SESSION_PROXY(node->shared.note.session), INF_REQUEST(request) ); } /* Notes are saved into the storage when save_notes is TRUE. */ static void infd_directory_node_unlink_child_sessions(InfdDirectory* directory, InfdDirectoryNode* node, InfdRequest* request, gboolean save_notes) { InfdDirectoryPrivate* priv; InfdDirectoryNode* child; gchar* path; GError* error; InfSession* session; priv = INFD_DIRECTORY_PRIVATE(directory); switch(node->type) { case INFD_DIRECTORY_NODE_SUBDIRECTORY: if(node->shared.subdir.explored == TRUE) { for(child = node->shared.subdir.child; child != NULL; child = child->next) { infd_directory_node_unlink_child_sessions( directory, child, request, save_notes ); } } break; case INFD_DIRECTORY_NODE_NOTE: if(node->shared.note.session != NULL) { if(save_notes) { infd_directory_node_get_path(node, &path, NULL); error = NULL; if(priv->storage != NULL) { g_object_get( G_OBJECT(node->shared.note.session), "session", &session, NULL ); node->shared.note.plugin->session_write( priv->storage, session, path, node->shared.note.plugin->user_data, &error ); g_object_unref(session); } /* TODO: Unset modified flag of buffer if result == TRUE */ if(error != NULL) { /* There is not really anything we could do about it here. Of * course, any application should save the sessions explicitely * before shutting the directory down, so that it has the chance to * cancel the shutdown if the session could not be saved. */ /* TODO: We could try saving the session somewhere in /tmp, for * example via to_xml_sync. */ g_warning( _("Could not write session \"%s\" to storage: %s\n\nAll changes " "since the document das been saved are lost."), path, error->message ); g_error_free(error); } g_free(path); } if(node->shared.note.weakref == FALSE) infd_directory_node_unlink_session(directory, node, request); } break; case INFD_DIRECTORY_NODE_UNKNOWN: /* Nothing to do */ break; default: g_assert_not_reached(); break; } } static void infd_directory_node_link(InfdDirectoryNode* node, InfdDirectoryNode* parent) { g_return_if_fail(node != NULL); g_return_if_fail(parent != NULL); infd_directory_return_if_subdir_fail(parent); node->prev = NULL; if(parent->shared.subdir.child != NULL) { parent->shared.subdir.child->prev = node; node->next = parent->shared.subdir.child; } else { node->next = NULL; } parent->shared.subdir.child = node; } static void infd_directory_node_unlink(InfdDirectoryNode* node) { g_return_if_fail(node != NULL); g_return_if_fail(node->parent != NULL); if(node->prev != NULL) { node->prev->next = node->next; } else { g_assert(node->parent->type == INFD_DIRECTORY_NODE_SUBDIRECTORY); node->parent->shared.subdir.child = node->next; } if(node->next != NULL) node->next->prev = node->prev; } /* This function takes ownership of name. If write_acl the ACL is written to * the storage. This should be used for newly created nodes, but for nodes * read from storage it should be false, since it is pointless to write * the ACL again. */ static InfdDirectoryNode* infd_directory_node_new_common(InfdDirectory* directory, InfdDirectoryNode* parent, InfdDirectoryNodeType type, guint node_id, gchar* name, const InfAclSheetSet* sheet_set, gboolean write_acl) { InfdDirectoryPrivate* priv; InfdDirectoryNode* node; InfBrowserIter iter; priv = INFD_DIRECTORY_PRIVATE(directory); g_assert( g_hash_table_lookup(priv->nodes, GUINT_TO_POINTER(node_id)) == NULL ); node = g_slice_new(InfdDirectoryNode); node->parent = parent; node->type = type; node->id = node_id; node->name = name; node->acl = NULL; node->acl_connections = NULL; if(sheet_set != NULL) { node->acl = inf_acl_sheet_set_merge_sheets(node->acl, sheet_set); if(write_acl == TRUE) infd_directory_write_acl(directory, node); } if(parent != NULL) { infd_directory_node_link(node, parent); } else { node->prev = NULL; node->next = NULL; } g_hash_table_insert(priv->nodes, GUINT_TO_POINTER(node->id), node); return node; } static InfdDirectoryNode* infd_directory_node_new_subdirectory(InfdDirectory* directory, InfdDirectoryNode* parent, guint node_id, gchar* name, const InfAclSheetSet* sheet_set, gboolean write_acl) { InfdDirectoryNode* node; node = infd_directory_node_new_common( directory, parent, INFD_DIRECTORY_NODE_SUBDIRECTORY, node_id, name, sheet_set, write_acl ); node->shared.subdir.connections = NULL; node->shared.subdir.child = NULL; node->shared.subdir.explored = FALSE; return node; } static InfdDirectoryNode* infd_directory_node_new_note(InfdDirectory* directory, InfdDirectoryNode* parent, guint node_id, gchar* name, const InfAclSheetSet* sheet_set, gboolean write_acl, const InfdNotePlugin* plugin) { InfdDirectoryNode* node; node = infd_directory_node_new_common( directory, parent, INFD_DIRECTORY_NODE_NOTE, node_id, name, sheet_set, write_acl ); node->shared.note.session = NULL; node->shared.note.plugin = plugin; node->shared.note.save_timeout = NULL; node->shared.note.weakref = FALSE; return node; } static InfdDirectoryNode* infd_directory_node_new_unknown(InfdDirectory* directory, InfdDirectoryNode* parent, guint node_id, gchar* name, const InfAclSheetSet* sheet_set, gboolean write_acl, const gchar* note_type) { InfdDirectoryNode* node; node = infd_directory_node_new_common( directory, parent, INFD_DIRECTORY_NODE_UNKNOWN, node_id, name, sheet_set, write_acl ); node->shared.unknown.type = g_quark_from_string(note_type); return node; } /* Required by infd_directory_node_free() */ static void infd_directory_remove_sync_in(InfdDirectory* directory, InfdDirectorySyncIn* sync_in); static void infd_directory_remove_subreq(InfdDirectory* directory, InfdDirectorySubreq* request); static void infd_directory_node_free(InfdDirectory* directory, InfdDirectoryNode* node) { InfdDirectoryPrivate* priv; InfBrowserIter iter; gboolean removed; GSList* item; GSList* next; InfdDirectorySyncIn* sync_in; InfdDirectorySubreq* request; g_return_if_fail(INFD_IS_DIRECTORY(directory)); g_return_if_fail(node != NULL); priv = INFD_DIRECTORY_PRIVATE(directory); switch(node->type) { case INFD_DIRECTORY_NODE_SUBDIRECTORY: g_slist_free(node->shared.subdir.connections); /* Free child nodes */ if(node->shared.subdir.explored == TRUE) { while(node->shared.subdir.child != NULL) { infd_directory_node_free(directory, node->shared.subdir.child); } } break; case INFD_DIRECTORY_NODE_NOTE: /* Sessions must have been explicitely unlinked before; we might still * have weak references though. */ g_assert(node->shared.note.session == NULL || node->shared.note.weakref == TRUE); if(node->shared.note.session != NULL) { infd_directory_release_session( directory, node, node->shared.note.session ); } break; case INFD_DIRECTORY_NODE_UNKNOWN: /* Nothing to do */ break; default: g_assert_not_reached(); break; } if(node->parent != NULL) infd_directory_node_unlink(node); g_slist_free(node->acl_connections); /* Only clear ACL table after unlink, so that ACL has effect until the very * moment where the node does not exist anymore, to avoid possible races. */ if(node->acl != NULL) inf_acl_sheet_set_free(node->acl); /* Remove sync-ins whose parent is gone */ for(item = priv->sync_ins; item != NULL; item = next) { next = item->next; sync_in = (InfdDirectorySyncIn*)item->data; if(sync_in->parent == node) infd_directory_remove_sync_in(directory, sync_in); } for(item = priv->subscription_requests; item != NULL; item = next) { next = item->next; request = (InfdDirectorySubreq*)item->data; switch(request->type) { case INFD_DIRECTORY_SUBREQ_CHAT: break; case INFD_DIRECTORY_SUBREQ_SESSION: /* Keep subscription requests whose parent is gone. They will be * released upon client reply. */ /*if(request->node_id == node->id) infd_directory_remove_subreq(directory, request);*/ break; case INFD_DIRECTORY_SUBREQ_ADD_NODE: if(request->shared.add_node.parent->id == node->id) request->shared.add_node.parent = NULL; break; case INFD_DIRECTORY_SUBREQ_SYNC_IN: case INFD_DIRECTORY_SUBREQ_SYNC_IN_SUBSCRIBE: if(request->shared.sync_in.parent->id == node->id) request->shared.sync_in.parent = NULL; break; default: g_assert_not_reached(); break; } } removed = g_hash_table_remove(priv->nodes, GUINT_TO_POINTER(node->id)); g_assert(removed == TRUE); g_free(node->name); g_slice_free(InfdDirectoryNode, node); } static void infd_directory_node_remove_connection(InfdDirectoryNode* node, InfXmlConnection* connection) { InfdDirectoryNode* child; GSList* item; g_assert(node->type == INFD_DIRECTORY_NODE_SUBDIRECTORY); g_assert(node->shared.subdir.explored == TRUE); item = g_slist_find(node->shared.subdir.connections, connection); /* Note that if the connection is not in this node's connection list, * then it cannot be in a child's list either. */ if(item != NULL) { node->shared.subdir.connections = g_slist_delete_link( node->shared.subdir.connections, item ); if(node->shared.subdir.explored == TRUE) { for(child = node->shared.subdir.child; child != NULL; child = child->next) { if(child->type == INFD_DIRECTORY_NODE_SUBDIRECTORY && child->shared.subdir.explored == TRUE) { infd_directory_node_remove_connection(child, connection); } } } else { g_assert(node->shared.subdir.connections == NULL); } } /* Remove the connection from ACL connections of ourselves and all * children. Do not recurse, since the recursion has taken place * in the loop above only for explored subdirectories. */ node->acl_connections = g_slist_remove(node->acl_connections, connection); for(child = node->shared.subdir.child; child != NULL; child = child->next) { child->acl_connections = g_slist_remove( child->acl_connections, connection ); } } /* * Permission enforcement */ /* Return the permissions needed to create a new node */ static void infd_directory_get_add_node_permissions(InfdDirectory* directory, InfAclMask* out, gboolean subdirectory, gboolean initial_subscribe, gboolean sync_in, const InfAclSheetSet* sheet_set) { if(subdirectory) inf_acl_mask_set1(out, INF_ACL_CAN_ADD_SUBDIRECTORY); else inf_acl_mask_set1(out, INF_ACL_CAN_ADD_DOCUMENT); if(initial_subscribe == TRUE) inf_acl_mask_or1(out, INF_ACL_CAN_SUBSCRIBE_SESSION); if(sync_in == TRUE) inf_acl_mask_or1(out, INF_ACL_CAN_SYNC_IN); if(sheet_set != NULL && sheet_set->n_sheets > 0) inf_acl_mask_or1(out, INF_ACL_CAN_SET_ACL); } /* Enforces the ACL on the given node. If the exploration permission is no * longer given for this node, then explorations and subscriptions are also * removed from all children. Returns whether node is still explored by * the connection. * * Note this function does not enforce all ACLs recursively! */ static gboolean infd_directory_enforce_single_acl(InfdDirectory* directory, InfXmlConnection* connection, InfdDirectoryNode* node, gboolean is_explored) { InfdDirectoryPrivate* priv; InfdDirectoryConnectionInfo* info; InfAclAccountId account; InfBrowser* browser; InfBrowserIter iter; InfAclMask mask; xmlNodePtr child_xml; InfdDirectoryNode* child; InfdSessionProxy* proxy; GSList* item; GSList* next; InfdDirectorySubreq* subreq; InfdDirectorySyncIn* sync_in; InfXmlConnection* sync_in_connection; gboolean retval; priv = INFD_DIRECTORY_PRIVATE(directory); info = g_hash_table_lookup(priv->connections, connection); g_assert(info != NULL); account = info->account_id; browser = INF_BROWSER(directory); iter.node = node; iter.node_id = node->id; retval = TRUE; if(node->type == INFD_DIRECTORY_NODE_SUBDIRECTORY) { if(g_slist_find(node->shared.subdir.connections, connection) != NULL) { /* Remove exploration if new account does not have permission, or * if one of the parent folders is no longer explored */ inf_acl_mask_set1(&mask, INF_ACL_CAN_EXPLORE_NODE); if(!is_explored || !inf_browser_check_acl(browser, &iter, account, &mask, NULL)) { node->shared.subdir.connections = g_slist_remove(node->shared.subdir.connections, connection); retval = FALSE; /* If there are subscription requests to create a node into this node * from this connection, then mark them as canceled, so that we don't * create the node in handle_subscribe_ack(). The client might * actually create the node if it does not register the new ACL early * enough, but that's okay because it removes it again as * soon as it does. */ for(item = priv->subscription_requests; item != NULL; item = next) { next = item->next; subreq = (InfdDirectorySubreq*)item->data; switch(subreq->type) { case INFD_DIRECTORY_SUBREQ_CHAT: case INFD_DIRECTORY_SUBREQ_SESSION: break; case INFD_DIRECTORY_SUBREQ_ADD_NODE: if(subreq->connection == connection) if(subreq->shared.add_node.parent->id == node->id) subreq->shared.add_node.parent = NULL; break; case INFD_DIRECTORY_SUBREQ_SYNC_IN: case INFD_DIRECTORY_SUBREQ_SYNC_IN_SUBSCRIBE: if(subreq->connection == connection) if(subreq->shared.sync_in.parent->id == node->id) subreq->shared.sync_in.parent = NULL; break; default: g_assert_not_reached(); break; } } /* Remove sync-ins whose parent is gone */ for(item = priv->sync_ins; item != NULL; item = next) { next = item->next; sync_in = (InfdDirectorySyncIn*)item->data; g_object_get( G_OBJECT(sync_in->request), "requestor", &sync_in_connection, NULL ); if(sync_in_connection == connection && sync_in->parent == node) infd_directory_remove_sync_in(directory, sync_in); g_object_unref(sync_in_connection); } for(child = node->shared.subdir.child; child != NULL; child = child->next) { infd_directory_enforce_single_acl( directory, connection, child, FALSE ); } } } else { retval = FALSE; } } else { retval = FALSE; if(node->type == INFD_DIRECTORY_NODE_NOTE) { proxy = node->shared.note.session; if(proxy != NULL) { if(infd_session_proxy_is_subscribed(proxy, connection)) { /* Remove subscription if no longer allowed, or if parent directory * is no longer explored */ inf_acl_mask_set1(&mask, INF_ACL_CAN_SUBSCRIBE_SESSION); if(!is_explored || !inf_browser_check_acl(browser, &iter, account, &mask, NULL)) { infd_session_proxy_unsubscribe(proxy, connection); } else { /* TODO: Remove joined users if join-user * permissions are no longer granted. */ } } } } } if(g_slist_find(node->acl_connections, connection) != NULL) { inf_acl_mask_set1(&mask, INF_ACL_CAN_QUERY_ACL); if(!is_explored || !inf_browser_check_acl(browser, &iter, account, &mask, NULL)) { node->acl_connections = g_slist_remove(node->acl_connections, connection); } } return retval; } /* Enforce ACL for the given node and all its children for info. If * reply_xml is set, then fill it with information about ACL for all * nodes for info's account. This is used when a connection is * switching accounts. */ static void infd_directory_enforce_acl(InfdDirectory* directory, InfXmlConnection* conn, InfdDirectoryNode* node, xmlNodePtr reply_xml) { InfdDirectoryPrivate* priv; InfdDirectoryNode* child; InfdDirectoryConnectionInfo* info; InfAclAccountId account; const InfAclSheet* sheet; xmlNodePtr child_xml; priv = INFD_DIRECTORY_PRIVATE(directory); info = g_hash_table_lookup(priv->connections, conn); g_assert(info != NULL); account = info->account_id; if(infd_directory_enforce_single_acl(directory, conn, node, TRUE) == TRUE) { g_assert(node->type == INFD_DIRECTORY_NODE_SUBDIRECTORY); for(child = node->shared.subdir.child; child != NULL; child = child->next) { infd_directory_enforce_acl(directory, conn, child, reply_xml); } } /* If this node has ACLs set for the new account, then add this to the * reply XML, so that the remote host knows its own permissions * on the node */ if(reply_xml != NULL) { if(node->acl != NULL) { /* TODO: This is only necessary if the client has not queried the * full ACL for this node. */ sheet = inf_acl_sheet_set_find_const_sheet(node->acl, account); if(sheet != NULL) { child_xml = xmlNewChild(reply_xml, NULL, (const xmlChar*)"acl", NULL); inf_xml_util_set_attribute_uint(child_xml, "node-id", node->id); inf_acl_sheet_perms_to_xml(&sheet->mask, &sheet->perms, child_xml); } } } } static InfdDirectoryTransientAccount* infd_directory_lookup_transient_account(InfdDirectory* directory, InfAclAccountId account) { InfdDirectoryPrivate* priv; guint i; priv = INFD_DIRECTORY_PRIVATE(directory); for(i = 0; i < priv->n_transient_accounts; ++i) if(priv->transient_accounts[i].account.id == account) return &priv->transient_accounts[i]; return NULL; } static InfAclAccount* infd_directory_lookup_account(InfdDirectory* directory, InfAclAccountId account, guint* transient_index, GError** error) { InfdDirectoryPrivate* priv; InfdDirectoryTransientAccount* transient; InfAclAccount* result; InfAclAccount* result_copy; guint i; priv = INFD_DIRECTORY_PRIVATE(directory); transient = infd_directory_lookup_transient_account(directory, account); if(transient != NULL) { if(transient_index != NULL) *transient_index = transient - priv->transient_accounts; return inf_acl_account_copy(&transient->account); } result = NULL; if(priv->account_storage != NULL) { result = infd_account_storage_lookup_accounts( priv->account_storage, &account, 1, error ); if(result == NULL) return NULL; } if(result == NULL || result[0].id == 0) { if(result != NULL) inf_acl_account_array_free(result, 1); return NULL; } if(transient_index != NULL) *transient_index = priv->n_transient_accounts; /* Note that the return value that we got from * infd_account_storage_lookup_accounts() is actually an array, and * therefore needs to be freed with inf_acl_account_array_free(). However, * we only return a single account that we want to be freed with * inf_acl_account_free(). Therefore, we are making a copy here -- note * that the two free functions are in fact different if GSlice is enabled, * since an array of InfAclAccounts in allocated with g_malloc, while a * single InfAclAccount is allocated with GSlice. */ result_copy = inf_acl_account_copy(result); inf_acl_account_array_free(result, 1); return result_copy; } static InfAclAccountId infd_directory_lookup_account_by_name(InfdDirectory* directory, const gchar* name, GError** error) { InfdDirectoryPrivate* priv; InfAclAccount* accounts; guint n_accounts; guint i; GError* local_error; InfAclAccountId account_id; priv = INFD_DIRECTORY_PRIVATE(directory); for(i = 0; i < priv->n_transient_accounts; ++i) if(priv->transient_accounts[i].account.name != NULL) if(strcmp(name, priv->transient_accounts[i].account.name) == 0) return priv->transient_accounts[i].account.id; account_id = 0; if(priv->account_storage != NULL) { local_error = NULL; accounts = infd_account_storage_lookup_accounts_by_name( priv->account_storage, name, &n_accounts, &local_error ); if(local_error != NULL) { g_propagate_error(error, local_error); return 0; } if(n_accounts > 0) { account_id = accounts[0].id; inf_acl_account_array_free(accounts, n_accounts); } } return account_id; } static void infd_directory_change_acl_account(InfdDirectory* directory, InfXmlConnection* connection, const InfAclAccount* account) { InfdDirectoryPrivate* priv; InfdDirectoryConnectionInfo* info; InfAclAccountId default_id; gboolean is_default_account; xmlNodePtr xml; priv = INFD_DIRECTORY_PRIVATE(directory); /* Set new account */ info = g_hash_table_lookup(priv->connections, connection); g_assert(info != NULL); if(info->account_id == account->id) return; info->account_id = account->id; /* Check whether we need to transfer ACLs for the new account to the * connection. */ default_id = inf_acl_account_id_from_string("default"); is_default_account = FALSE; if(account->id == default_id) is_default_account = TRUE; xml = xmlNewNode(NULL, (const xmlChar*)"change-acl-account"); inf_acl_account_to_xml(account, xml); /* Enforce the ACLs of the new account on the connection. While * we do this, we also fill in the ACL sheets for all nodes of the * new connection, to be transferred. */ infd_directory_enforce_acl( directory, connection, priv->root, is_default_account ? NULL : xml ); /* Send to client */ inf_communication_group_send_message( INF_COMMUNICATION_GROUP(priv->group), connection, xml ); } static gnutls_x509_crt_t infd_directory_create_certificate_from_crq(InfdDirectory* directory, gnutls_x509_crq_t crq, guint64 validity, GError** error) { InfdDirectoryPrivate* priv; gnutls_x509_crt_t cert; int res; guint64 timestamp; gchar serial_buffer[5]; priv = INFD_DIRECTORY_PRIVATE(directory); if(priv->certificate == NULL || priv->private_key == NULL) { g_set_error_literal( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_OPERATION_UNSUPPORTED, _("Server does not support issuing certificates") ); return NULL; } res = gnutls_x509_crt_init(&cert); if(res != GNUTLS_E_SUCCESS) { inf_gnutls_set_error(error, res); return NULL; } res = gnutls_x509_crt_set_crq(cert, crq); if(res != GNUTLS_E_SUCCESS) { gnutls_x509_crt_deinit(cert); inf_gnutls_set_error(error, res); return NULL; } timestamp = time(NULL); serial_buffer[4] = (timestamp ) & 0xff; serial_buffer[3] = (timestamp >> 8) & 0xff; serial_buffer[2] = (timestamp >> 16) & 0xff; serial_buffer[1] = (timestamp >> 24) & 0xff; serial_buffer[0] = (timestamp >> 32) & 0xff; res = gnutls_x509_crt_set_serial(cert, serial_buffer, 5); if(res != GNUTLS_E_SUCCESS) { gnutls_x509_crt_deinit(cert); inf_gnutls_set_error(error, res); return NULL; } /* Set the activation time a bit in the past, so that if the client * checks the certificate and has its clock slightly offset it doesn't * find the certificate invalid. */ res = gnutls_x509_crt_set_activation_time(cert, timestamp - DAYS / 10); if(res != GNUTLS_E_SUCCESS) { gnutls_x509_crt_deinit(cert); inf_gnutls_set_error(error, res); return NULL; } res = gnutls_x509_crt_set_expiration_time(cert, timestamp + validity); if(res != GNUTLS_E_SUCCESS) { gnutls_x509_crt_deinit(cert); inf_gnutls_set_error(error, res); return NULL; } res = gnutls_x509_crt_set_basic_constraints(cert, 0, -1); if(res != GNUTLS_E_SUCCESS) { gnutls_x509_crt_deinit(cert); inf_gnutls_set_error(error, res); return NULL; } res = gnutls_x509_crt_set_key_usage(cert, GNUTLS_KEY_DIGITAL_SIGNATURE); if(res != GNUTLS_E_SUCCESS) { gnutls_x509_crt_deinit(cert); inf_gnutls_set_error(error, res); return NULL; } res = gnutls_x509_crt_set_version(cert, 3); if(res != GNUTLS_E_SUCCESS) { gnutls_x509_crt_deinit(cert); inf_gnutls_set_error(error, res); return NULL; } /* The certificate is now set up, we can sign it. */ res = gnutls_x509_crt_sign2( cert, inf_certificate_chain_get_own_certificate(priv->certificate), priv->private_key, GNUTLS_DIG_SHA256, 0 ); if(res != GNUTLS_E_SUCCESS) { gnutls_x509_crt_deinit(cert); inf_gnutls_set_error(error, res); return NULL; } return cert; } static gchar* infd_directory_account_name_from_certificate(gnutls_x509_crt_t cert, GError** error) { gchar* name; /* Check that a common name is set in the certificate. Without a common * name, we cannot associate the certificate to an account. */ name = inf_cert_util_get_dn_by_oid(cert, GNUTLS_OID_X520_COMMON_NAME, 0); if(name == NULL || name[0] == '\0') { g_set_error_literal( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_INVALID_CERTIFICATE, _("The certificate request has no common name set") ); g_free(name); return NULL; } return name; } static void infd_directory_account_storage_account_added_cb(InfdAccountStorage* storage, const InfAclAccount* acc, gpointer user_data); static void infd_directory_account_storage_account_removed_cb(InfdAccountStorage* storage, const InfAclAccount* acc, gpointer user_data); static InfAclAccountId infd_directory_create_acl_account_with_certificates(InfdDirectory* directory, const gchar* account_name, gboolean transient, gnutls_x509_crt_t* certs, guint n_certs, InfXmlConnection* conn, GError** error) { InfdDirectoryPrivate* priv; gchar* transient_id_str; InfAclAccountId account_id; InfdDirectoryTransientAccount* transient_account; InfAclAccount* account; InfAclAccount announce_account; priv = INFD_DIRECTORY_PRIVATE(directory); if(transient == TRUE) { /* Transient accounts only support one certificate at the moment */ g_assert(n_certs <= 1); transient_id_str = g_strdup_printf("_transient:%s", account_name); account_id = inf_acl_account_id_from_string(transient_id_str); g_free(transient_id_str); transient_account = infd_directory_lookup_transient_account(directory, account_id); if(transient_account != NULL) { g_set_error( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_DUPLICATE_ACCOUNT, _("There is already a transient account with name \"%s\""), account_name ); return 0; } priv->transient_accounts = g_realloc( priv->transient_accounts, (priv->n_transient_accounts + 1) * sizeof(InfdDirectoryTransientAccount) ); transient_account = &priv->transient_accounts[priv->n_transient_accounts]; account = &transient_account->account; ++priv->n_transient_accounts; account->id = account_id; account->name = g_strdup(account_name); transient_account->dn = NULL; if(n_certs > 0) transient_account->dn = inf_cert_util_get_dn(certs[0]); } else if(priv->account_storage != NULL) { /* Note that we cannot rely on the account storage to provide proper * notifications when adding the account to the storage, since * implementation are not required to support notifications. Therefore, * block our signal handlers and then announce explicitly. */ inf_signal_handlers_block_by_func( G_OBJECT(priv->account_storage), G_CALLBACK(infd_directory_account_storage_account_added_cb), directory ); account_id = infd_account_storage_add_account( priv->account_storage, account_name, certs, n_certs, NULL, error ); inf_signal_handlers_unblock_by_func( G_OBJECT(priv->account_storage), G_CALLBACK(infd_directory_account_storage_account_added_cb), directory ); if(account_id == 0) return 0; announce_account.id = account_id; announce_account.name = (gchar*)account_name; account = &announce_account; } else { g_set_error_literal( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_OPERATION_UNSUPPORTED, _("This server does not support creating accounts") ); return 0; } infd_directory_announce_acl_account(directory, account, conn); return account_id; } /* If connection is set, make sure to send reply to this connection, * even if it would normally not be notified. Don't actually remove, just * announce and cleanup data structures. */ static void infd_directory_cleanup_acl_account(InfdDirectory* directory, const InfAclAccount* account, gboolean cleanup_acls, InfXmlConnection* connection, const gchar* seq, InfdRequest* request) { InfdDirectoryPrivate* priv; InfdDirectoryConnectionInfo* info; InfAclAccountId account_id; InfAclAccountId default_id; InfBrowser* browser; InfBrowserIter iter; InfAclMask mask; GHashTableIter hash_iter; gpointer key; gpointer value; GHashTable* table; GSList* notify_connections; GSList* item; xmlNodePtr xml; priv = INFD_DIRECTORY_PRIVATE(directory); account_id = account->id; default_id = inf_acl_account_id_from_string("default"); g_assert(account_id != default_id); browser = INF_BROWSER(directory); iter.node = priv->root; iter.node_id = priv->root->id; inf_acl_mask_set1(&mask, INF_ACL_CAN_QUERY_ACCOUNT_LIST); /* First, demote all connections with this account to the default account, * and make a list of connections that need to be notified about the removed * account. */ notify_connections = NULL; g_hash_table_iter_init(&hash_iter, priv->connections); while(g_hash_table_iter_next(&hash_iter, &key, &value)) { info = (InfdDirectoryConnectionInfo*)value; if(info->account_id == account_id) { info->account_id = inf_acl_account_id_from_string("default"); infd_directory_enforce_acl( directory, (InfXmlConnection*)key, priv->root, NULL ); notify_connections = g_slist_prepend(notify_connections, key); } else { if(inf_browser_check_acl(browser, &iter, account_id, &mask, NULL)) { /* Notify if CAN_QUERY_ACCOUNT_LIST permission is set */ notify_connections = g_slist_prepend(notify_connections, key); } } } if(cleanup_acls == TRUE) { /* Next, remove this account from all ACL sheets. Note that we do not do * this for sheets that we do not have explored yet. The permissions will * be dropped automatically as soon as the node is explored. Note that * this is a bit of a security issue at the moment: if an account with the * previous ID is re-created, then the existing permissions of * non-explored nodes are taken for the new account. Therefore, account * storage backends should try hard to always produce unique IDs. */ table = g_hash_table_new(NULL, NULL); g_hash_table_insert( table, INF_ACL_ACCOUNT_ID_TO_POINTER(account_id), GBOOLEAN_TO_POINTER(FALSE) ); infd_directory_verify_all_acls(directory, table, FALSE); g_hash_table_destroy(table); } /* Then, send requests */ if(connection != NULL) if(g_slist_find(notify_connections, connection) == NULL) notify_connections = g_slist_prepend(notify_connections, connection); if(notify_connections != NULL) { xml = xmlNewNode(NULL, (const xmlChar*)"remove-acl-account"); inf_xml_util_set_attribute( xml, "id", inf_acl_account_id_to_string(account_id) ); if(seq != NULL) inf_xml_util_set_attribute(xml, "seq", seq); for(item = notify_connections; item != NULL; item = item->next) { inf_communication_group_send_message( INF_COMMUNICATION_GROUP(priv->group), (InfXmlConnection*)item->data, (item->next == NULL) ? xml : xmlCopyNode(xml, 1) ); } } g_slist_free(notify_connections); /* Then, make callback */ if(request != NULL) { inf_request_finish( INF_REQUEST(request), inf_request_result_make_remove_acl_account( INF_BROWSER(directory), account ) ); } inf_browser_acl_account_removed( INF_BROWSER(directory), account, NULL ); } static gboolean infd_directory_remove_acl_account(InfdDirectory* directory, InfAclAccountId account_id, InfXmlConnection* connection, const gchar* seq, InfdRequest* request, GError** error) { InfdDirectoryPrivate* priv; InfAclAccountId default_id; InfAclAccount* account; GError* local_error; guint transient_index; gboolean account_removed; priv = INFD_DIRECTORY_PRIVATE(directory); default_id = inf_acl_account_id_from_string("default"); if(account_id == default_id) { g_set_error_literal( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_NO_SUCH_ACCOUNT, _("The default account cannot be removed") ); return FALSE; } local_error = NULL; account = infd_directory_lookup_account( directory, account_id, &transient_index, &local_error ); if(local_error != NULL) { g_propagate_error(error, local_error); return FALSE; } if(account == NULL) { g_set_error( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_NO_SUCH_ACCOUNT, _("There is no such account with ID \"%s\""), inf_acl_account_id_to_string(account_id) ); return FALSE; } if(transient_index < priv->n_transient_accounts) { /* Remove a transient account */ g_free(priv->transient_accounts[transient_index].account.name); g_free(priv->transient_accounts[transient_index].dn); priv->transient_accounts[transient_index] = priv->transient_accounts[priv->n_transient_accounts - 1]; priv->transient_accounts = g_realloc( priv->transient_accounts, (priv->n_transient_accounts - 1) * sizeof(InfdDirectoryTransientAccount) ); --priv->n_transient_accounts; } else if(priv->account_storage != NULL) { /* Note that we cannot rely on the account storage to provide proper * notifications when adding the account to the storage, since * implementation are not required to support notifications. Therefore, * block our signal handlers and then announce explicitly. */ inf_signal_handlers_block_by_func( G_OBJECT(priv->account_storage), G_CALLBACK(infd_directory_account_storage_account_removed_cb), directory ); account_removed = infd_account_storage_remove_account( priv->account_storage, account_id, error ); inf_signal_handlers_unblock_by_func( G_OBJECT(priv->account_storage), G_CALLBACK(infd_directory_account_storage_account_removed_cb), directory ); if(account_removed == FALSE) return FALSE; } else { g_set_error_literal( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_OPERATION_UNSUPPORTED, _("This server does not support removing accounts") ); return FALSE; } infd_directory_cleanup_acl_account( directory, account, TRUE, connection, seq, request ); inf_acl_account_free(account); return TRUE; } /* * Node synchronization. */ static xmlNodePtr infd_directory_node_desc_register_to_xml(const gchar* node_name, guint node_id, InfdDirectoryNode* parent, const gchar* plugin_type, const gchar* name) { xmlNodePtr xml; xml = xmlNewNode(NULL, (const xmlChar*)node_name); inf_xml_util_set_attribute_uint(xml, "id", node_id); inf_xml_util_set_attribute_uint(xml, "parent", parent->id); inf_xml_util_set_attribute(xml, "name", name); inf_xml_util_set_attribute(xml, "type", plugin_type); return xml; } /* Creates XML request to tell someone about a new node */ static xmlNodePtr infd_directory_node_register_to_xml(InfdDirectoryNode* node) { const InfdNotePlugin* plugin; const gchar* plugin_type; g_assert(node->parent != NULL); switch(node->type) { case INFD_DIRECTORY_NODE_SUBDIRECTORY: plugin_type = "InfSubdirectory"; break; case INFD_DIRECTORY_NODE_NOTE: plugin_type = node->shared.note.plugin->note_type; break; case INFD_DIRECTORY_NODE_UNKNOWN: plugin_type = g_quark_to_string(node->shared.unknown.type); break; default: g_assert_not_reached(); break; } return infd_directory_node_desc_register_to_xml( "add-node", node->id, node->parent, plugin_type, node->name ); } /* Creates XML request to tell someone about a removed node */ static xmlNodePtr infd_directory_node_unregister_to_xml(InfdDirectoryNode* node) { xmlNodePtr xml; gchar id_buf[16]; sprintf(id_buf, "%u", node->id); xml = xmlNewNode(NULL, (const xmlChar*)"remove-node"); xmlNewProp(xml, (const xmlChar*)"id", (const xmlChar*)id_buf); return xml; } static gboolean infd_directory_make_seq(InfdDirectory* directory, InfXmlConnection* connection, xmlNodePtr xml, gchar** seq, GError** error) { InfdDirectoryPrivate* priv; InfdDirectoryConnectionInfo* info; GError* local_error; guint seq_num; priv = INFD_DIRECTORY_PRIVATE(directory); local_error = NULL; if(!inf_xml_util_get_attribute_uint(xml, "seq", &seq_num, &local_error)) { if(local_error) { g_propagate_error(error, local_error); return FALSE; } *seq = NULL; return TRUE; } info = g_hash_table_lookup(priv->connections, connection); g_assert(info != NULL); *seq = g_strdup_printf("%u/%u", info->seq_id, seq_num); return TRUE; } /* Announces the presence of a new node. This is not done in * infd_directory_node_new because we do not want to do this for all * nodes we create (namely not for the root node). */ static void infd_directory_node_register(InfdDirectory* directory, InfdDirectoryNode* node, InfdRequest* request, InfXmlConnection* except, const gchar* seq) { InfdDirectoryPrivate* priv; InfBrowserIter iter; InfdDirectoryConnectionInfo* info; xmlNodePtr xml; xmlNodePtr copy_xml; GSList* item; priv = INFD_DIRECTORY_PRIVATE(directory); iter.node_id = node->id; iter.node = node; inf_browser_node_added( INF_BROWSER(directory), &iter, INF_REQUEST(request) ); xml = infd_directory_node_register_to_xml(node); if(seq != NULL) inf_xml_util_set_attribute(xml, "seq", seq); for(item = node->parent->shared.subdir.connections; item != NULL; item = g_slist_next(item)) { if(item->data != except) { info = g_hash_table_lookup(priv->connections, item->data); g_assert(info != NULL); copy_xml = xmlCopyNode(xml, 1); if(node->acl != NULL) { infd_directory_acl_sheets_to_xml_for_connection( directory, node->acl_connections, node->acl, INF_XML_CONNECTION(item->data), copy_xml ); } inf_communication_group_send_message( INF_COMMUNICATION_GROUP(priv->group), INF_XML_CONNECTION(item->data), copy_xml ); } } xmlFreeNode(xml); } /* Announces that a node is removed. Again, this is not done in * infd_directory_node_free because we do not want to do this for * every subnode if a subdirectory is freed. */ static void infd_directory_node_unregister(InfdDirectory* directory, InfdDirectoryNode* node, InfdRequest* request, const gchar* seq) { InfdDirectoryPrivate* priv; InfBrowserIter iter; xmlNodePtr xml; GSList* item; priv = INFD_DIRECTORY_PRIVATE(directory); iter.node_id = node->id; iter.node = node; inf_browser_node_removed( INF_BROWSER(directory), &iter, INF_REQUEST(request) ); xml = infd_directory_node_unregister_to_xml(node); if(seq != NULL) inf_xml_util_set_attribute(xml, "seq", seq); for(item = node->parent->shared.subdir.connections; item != NULL; item = g_slist_next(item)) { inf_communication_group_send_message( INF_COMMUNICATION_GROUP(priv->group), INF_XML_CONNECTION(item->data), xmlCopyNode(xml, 1) ); } xmlFreeNode(xml); } static gboolean infd_directory_node_name_equal(const gchar* name1, const gchar* name2) { gchar* f1 = g_utf8_casefold(name1, -1); gchar* f2 = g_utf8_casefold(name2, -1); gboolean result = (g_utf8_collate(f1, f2) == 0); g_free(f2); g_free(f1); return result; } /* * Sync-In */ static void infd_directory_sync_in_synchronization_failed_cb(InfSession* session, InfXmlConnection* connection, const GError* error, gpointer user_data) { /* Synchronization failed. We simply remove the sync-in. There is no further * notification required since the synchronization failed on the remote site * as well. */ InfdDirectorySyncIn* sync_in; InfdRequest* request; sync_in = (InfdDirectorySyncIn*)user_data; request = sync_in->request; g_object_ref(request); infd_directory_remove_sync_in(sync_in->directory, sync_in); inf_request_fail(INF_REQUEST(request), error); g_object_unref(request); } static void infd_directory_sync_in_synchronization_complete_cb(InfSession* session, InfXmlConnection* conn, gpointer user_data) { /* Synchronization done. We can now safely create the node in the directory * tree. */ InfdDirectorySyncIn* sync_in; InfdDirectory* directory; const InfdNotePlugin* plugin; InfdDirectoryPrivate* priv; InfdDirectoryNode* node; InfBrowserIter iter; InfBrowserIter parent; InfdRequest* request; InfdSessionProxy* proxy; gchar* path; gboolean ret; GError* error; sync_in = (InfdDirectorySyncIn*)user_data; directory = sync_in->directory; plugin = sync_in->plugin; priv = INFD_DIRECTORY_PRIVATE(directory); node = infd_directory_node_new_note( directory, sync_in->parent, sync_in->node_id, sync_in->name, sync_in->sheet_set, TRUE, sync_in->plugin ); sync_in->name = NULL; /* Don't free, we passed ownership */ request = sync_in->request; g_object_ref(request); proxy = sync_in->proxy; g_object_ref(proxy); parent.node_id = sync_in->parent->id; parent.node = sync_in->parent; infd_directory_remove_sync_in(directory, sync_in); /* Don't send to conn since the completed synchronization already lets the * remote site know that the node was inserted. */ infd_directory_node_register(directory, node, request, conn, NULL); infd_directory_node_link_session(directory, node, request, proxy); /* Save session initially */ infd_directory_node_get_path(node, &path, NULL); error = NULL; if(priv->storage != NULL) { ret = plugin->session_write( priv->storage, session, path, plugin->user_data, &error ); } else { ret = TRUE; } if(ret == FALSE) { /* Note that while indeed this may fail in theory we have already * (successfully) written the session before we started the sync-in, so * the name of the node is accepted by the storage backend. */ g_warning( _("Session \"%s\" could not be saved: %s\nAnother attempt will " "be made when the session is unused for a while or the server is " "shut down."), path, error->message ); g_error_free(error); } g_free(path); iter.node_id = node->id; iter.node = node; inf_request_finish( INF_REQUEST(request), inf_request_result_make_add_node(INF_BROWSER(directory), &parent, &iter) ); g_object_unref(request); } static InfdDirectorySyncIn* infd_directory_add_sync_in(InfdDirectory* directory, InfdDirectoryNode* parent, InfdRequest* request, guint node_id, const gchar* name, const InfAclSheetSet* sheet_set, const InfdNotePlugin* plugin, InfdSessionProxy* proxy) { InfdDirectoryPrivate* priv; InfdDirectorySyncIn* sync_in; InfSession* session; priv = INFD_DIRECTORY_PRIVATE(directory); sync_in = g_slice_new(InfdDirectorySyncIn); sync_in->directory = directory; sync_in->parent = parent; sync_in->node_id = node_id; sync_in->name = g_strdup(name); if(sheet_set != NULL) sync_in->sheet_set = inf_acl_sheet_set_copy(sheet_set); else sync_in->sheet_set = NULL; sync_in->plugin = plugin; sync_in->proxy = proxy; sync_in->request = request; g_object_ref(sync_in->proxy); g_object_ref(sync_in->request); g_object_get(G_OBJECT(proxy), "session", &session, NULL); /* Connect after the default handler, so that the session status has changed * before our callbacks are called. This makes sure that the session status * is RUNNING when we emit the "subscribe-session" signal. */ g_signal_connect_after( G_OBJECT(session), "synchronization-failed", G_CALLBACK(infd_directory_sync_in_synchronization_failed_cb), sync_in ); g_signal_connect_after( G_OBJECT(session), "synchronization-complete", G_CALLBACK(infd_directory_sync_in_synchronization_complete_cb), sync_in ); g_object_unref(session); priv->sync_ins = g_slist_prepend(priv->sync_ins, sync_in); return sync_in; } static void infd_directory_remove_sync_in(InfdDirectory* directory, InfdDirectorySyncIn* sync_in) { InfdDirectoryPrivate* priv; InfSession* session; priv = INFD_DIRECTORY_PRIVATE(directory); g_object_get(G_OBJECT(sync_in->proxy), "session", &session, NULL); inf_signal_handlers_disconnect_by_func( G_OBJECT(session), G_CALLBACK(infd_directory_sync_in_synchronization_failed_cb), sync_in ); inf_signal_handlers_disconnect_by_func( G_OBJECT(session), G_CALLBACK(infd_directory_sync_in_synchronization_complete_cb), sync_in ); g_object_unref(session); /* This cancels the synchronization: */ g_object_unref(sync_in->proxy); /* TODO: Fail request with a cancelled error? */ g_object_unref(sync_in->request); if(sync_in->sheet_set != NULL) inf_acl_sheet_set_free(sync_in->sheet_set); g_free(sync_in->name); g_slice_free(InfdDirectorySyncIn, sync_in); priv->sync_ins = g_slist_remove(priv->sync_ins, sync_in); } static InfdDirectorySyncIn* infd_directory_find_sync_in_by_name(InfdDirectory* directory, InfdDirectoryNode* parent, const gchar* name) { InfdDirectoryPrivate* priv; GSList* item; InfdDirectorySyncIn* sync_in; priv = INFD_DIRECTORY_PRIVATE(directory); for(item = priv->sync_ins; item != NULL; item = item->next) { sync_in = (InfdDirectorySyncIn*)item->data; if(sync_in->parent == parent && infd_directory_node_name_equal(sync_in->name, name) == TRUE) { return sync_in; } } return NULL; } /* * Subscription requests. */ static InfdDirectorySubreq* infd_directory_add_subreq_common(InfdDirectory* directory, InfdDirectorySubreqType type, InfXmlConnection* connection, guint node_id) { InfdDirectoryPrivate* priv; InfdDirectorySubreq* request; priv = INFD_DIRECTORY_PRIVATE(directory); request = g_slice_new(InfdDirectorySubreq); request->type = type; request->connection = connection; request->node_id = node_id; priv->subscription_requests = g_slist_prepend(priv->subscription_requests, request); return request; } static InfdDirectorySubreq* infd_directory_add_subreq_chat(InfdDirectory* directory, InfXmlConnection* connection) { InfdDirectorySubreq* request; request = infd_directory_add_subreq_common( directory, INFD_DIRECTORY_SUBREQ_CHAT, connection, 0 ); return request; } static InfdDirectorySubreq* infd_directory_add_subreq_session(InfdDirectory* directory, InfXmlConnection* connection, InfdRequest* request, guint node_id, InfdSessionProxy* proxy) { InfdDirectorySubreq* subreq; subreq = infd_directory_add_subreq_common( directory, INFD_DIRECTORY_SUBREQ_SESSION, connection, node_id ); subreq->shared.session.session = proxy; /* take ownership */ subreq->shared.session.request = request; if(request != NULL) g_object_ref(request); return subreq; } static InfdDirectorySubreq* infd_directory_add_subreq_add_node(InfdDirectory* directory, InfXmlConnection* connection, InfCommunicationHostedGroup* group, InfdRequest* request, InfdDirectoryNode* parent, guint node_id, const gchar* name, const InfAclSheetSet* sheet_set, const InfdNotePlugin* plugin, InfSession* session, GError** error) { InfdDirectorySubreq* subreq; InfdSessionProxy* proxy; gchar* path; gboolean ensured; if(session != NULL) { proxy = infd_directory_create_session_proxy_with_group( directory, session, group ); } else { infd_directory_node_make_path(parent, name, &path, NULL); proxy = infd_directory_create_session_proxy( directory, plugin, INF_SESSION_RUNNING, NULL, NULL, group, path ); g_free(path); } ensured = infd_directory_session_proxy_ensure( directory, parent, name, plugin, proxy, error ); if(ensured == FALSE) return NULL; subreq = infd_directory_add_subreq_common( directory, INFD_DIRECTORY_SUBREQ_ADD_NODE, connection, node_id ); subreq->shared.add_node.parent = parent; subreq->shared.add_node.group = group; subreq->shared.add_node.plugin = plugin; subreq->shared.add_node.name = g_strdup(name); if(sheet_set != NULL) subreq->shared.add_node.sheet_set = inf_acl_sheet_set_copy(sheet_set); else subreq->shared.add_node.sheet_set = NULL; subreq->shared.add_node.proxy = proxy; subreq->shared.add_node.request = request; g_object_ref(request); g_object_ref(group); return subreq; } static InfdDirectorySubreq* infd_directory_add_subreq_sync_in(InfdDirectory* directory, InfXmlConnection* connection, InfCommunicationHostedGroup* sync_group, InfCommunicationHostedGroup* sub_group, InfdRequest* request, InfdDirectoryNode* parent, guint node_id, const gchar* name, const InfAclSheetSet* sheet_set, const InfdNotePlugin* plugin, GError** error) { InfdDirectorySubreq* subreq; InfdSessionProxy* proxy; gchar* path; gboolean ensured; infd_directory_node_make_path(parent, name, &path, NULL); /* Keep proxy in PRESYNC state, until we have the confirmation from the * remote site that the chosen method is OK and we can go on. */ proxy = infd_directory_create_session_proxy( directory, plugin, INF_SESSION_PRESYNC, sync_group, connection, sub_group, path ); g_free(path); ensured = infd_directory_session_proxy_ensure( directory, parent, name, plugin, proxy, error ); if(ensured == FALSE) return NULL; subreq = infd_directory_add_subreq_common( directory, sync_group == sub_group ? INFD_DIRECTORY_SUBREQ_SYNC_IN_SUBSCRIBE : INFD_DIRECTORY_SUBREQ_SYNC_IN, connection, node_id ); subreq->shared.sync_in.parent = parent; subreq->shared.sync_in.synchronization_group = sync_group; subreq->shared.sync_in.subscription_group = sub_group; subreq->shared.sync_in.plugin = plugin; subreq->shared.sync_in.name = g_strdup(name); if(sheet_set != NULL) subreq->shared.sync_in.sheet_set = inf_acl_sheet_set_copy(sheet_set); else subreq->shared.sync_in.sheet_set = NULL; subreq->shared.sync_in.proxy = proxy; subreq->shared.sync_in.request = request; g_object_ref(request); g_object_ref(sync_group); g_object_ref(sub_group); return subreq; } static void infd_directory_free_subreq(InfdDirectorySubreq* request) { switch(request->type) { case INFD_DIRECTORY_SUBREQ_CHAT: break; case INFD_DIRECTORY_SUBREQ_SESSION: g_object_unref(request->shared.session.session); if(request->shared.session.request != NULL) g_object_unref(request->shared.session.request); break; case INFD_DIRECTORY_SUBREQ_ADD_NODE: g_free(request->shared.add_node.name); if(request->shared.add_node.sheet_set != NULL) inf_acl_sheet_set_free(request->shared.add_node.sheet_set); g_object_unref(request->shared.add_node.group); g_object_unref(request->shared.add_node.proxy); /* TODO: Fail with some cancelled error? */ g_object_unref(request->shared.add_node.request); break; case INFD_DIRECTORY_SUBREQ_SYNC_IN: case INFD_DIRECTORY_SUBREQ_SYNC_IN_SUBSCRIBE: g_free(request->shared.sync_in.name); if(request->shared.sync_in.sheet_set != NULL) inf_acl_sheet_set_free(request->shared.sync_in.sheet_set); g_object_unref(request->shared.sync_in.synchronization_group); g_object_unref(request->shared.sync_in.subscription_group); g_object_unref(request->shared.sync_in.proxy); /* TODO: Fail with some cancelled error? */ g_object_unref(request->shared.sync_in.request); break; default: g_assert_not_reached(); break; } g_slice_free(InfdDirectorySubreq, request); } static void infd_directory_unlink_subreq(InfdDirectory* directory, InfdDirectorySubreq* request) { InfdDirectoryPrivate* priv; priv = INFD_DIRECTORY_PRIVATE(directory); priv->subscription_requests = g_slist_remove(priv->subscription_requests, request); } static void infd_directory_remove_subreq(InfdDirectory* directory, InfdDirectorySubreq* request) { infd_directory_unlink_subreq(directory, request); infd_directory_free_subreq(request); } static InfdDirectorySubreq* infd_directory_find_subreq_by_node_id(InfdDirectory* directory, InfdDirectorySubreqType type, guint node_id) { InfdDirectoryPrivate* priv; GSList* item; InfdDirectorySubreq* subreq; priv = INFD_DIRECTORY_PRIVATE(directory); for(item = priv->subscription_requests; item != NULL; item = item->next) { subreq = (InfdDirectorySubreq*)item->data; if(subreq->type == type && subreq->node_id == node_id) return subreq; } return NULL; } static InfdDirectorySubreq* infd_directory_find_subreq_by_name(InfdDirectory* directory, InfdDirectoryNode* parent, const gchar* name) { InfdDirectoryPrivate* priv; GSList* item; InfdDirectorySubreq* request; priv = INFD_DIRECTORY_PRIVATE(directory); for(item = priv->subscription_requests; item != NULL; item = item->next) { request = (InfdDirectorySubreq*)item->data; switch(request->type) { case INFD_DIRECTORY_SUBREQ_CHAT: case INFD_DIRECTORY_SUBREQ_SESSION: /* These don't occupy names */ break; case INFD_DIRECTORY_SUBREQ_ADD_NODE: if(request->shared.add_node.parent == parent && infd_directory_node_name_equal(request->shared.add_node.name, name)) { return request; } break; case INFD_DIRECTORY_SUBREQ_SYNC_IN: case INFD_DIRECTORY_SUBREQ_SYNC_IN_SUBSCRIBE: if(request->shared.sync_in.parent == parent && infd_directory_node_name_equal(request->shared.sync_in.name, name)) { return request; } break; default: g_assert_not_reached(); break; } } return NULL; } /* * Directory tree operations. */ static InfdDirectoryNode* infd_directory_node_find_child_by_name(InfdDirectoryNode* parent, const gchar* name) { InfdDirectoryNode* node; infd_directory_return_val_if_subdir_fail(parent, NULL); for(node = parent->shared.subdir.child; node != NULL; node = node->next) if(infd_directory_node_name_equal(node->name, name)) return node; return NULL; } /* Checks whether a node with the given name can be created in the given * parent directory. */ static gboolean infd_directory_node_is_name_available(InfdDirectory* directory, InfdDirectoryNode* parent, const gchar* name, GError** error) { gboolean has_sensible_character = FALSE; const gchar* p; for (p = name; *p != '\0'; p = g_utf8_next_char(p)) { if(!g_unichar_isprint(*p)) { g_set_error( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_INVALID_NAME, _("Name \"%s\" is an invalid name: contains non-printable characters"), name ); return FALSE; } else if(!g_unichar_isspace(*p)) { has_sensible_character = TRUE; } } if(!has_sensible_character) { g_set_error( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_INVALID_NAME, _("Name \"%s\" is an invalid name: contains only space characters"), name ); return FALSE; } if(strchr(name, '/') != NULL) { g_set_error( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_INVALID_NAME, _("Name \"%s\" is an invalid name: contains \"/\""), name ); return FALSE; } if(infd_directory_node_find_child_by_name(parent, name) != NULL || infd_directory_find_sync_in_by_name(directory, parent, name) != NULL || infd_directory_find_subreq_by_name(directory, parent, name) != NULL) { g_set_error( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_NODE_EXISTS, _("A node with name \"%s\" exists already"), name ); return FALSE; } return TRUE; } static gboolean infd_directory_node_explore(InfdDirectory* directory, InfdDirectoryNode* node, InfdProgressRequest* request, GError** error) { InfdDirectoryPrivate* priv; InfdStorageNode* storage_node; InfdDirectoryNode* new_node; InfBrowserIter iter; InfdNotePlugin* plugin; GError* local_error; GSList* list; InfAclSheetSet* sheet_set; GPtrArray* acls; GHashTable* verify_table; GSList* item; gchar* path; gsize len; gsize node_len; gsize sep_len; gsize path_len; guint index; priv = INFD_DIRECTORY_PRIVATE(directory); g_assert(priv->storage != NULL); g_assert(node->type == INFD_DIRECTORY_NODE_SUBDIRECTORY); g_assert(node->shared.subdir.explored == FALSE); local_error = NULL; infd_directory_node_get_path(node, &path, &len); list = infd_storage_read_subdirectory(priv->storage, path, &local_error); if(local_error != NULL) { g_free(path); if(request != NULL) inf_request_fail(INF_REQUEST(request), local_error); g_propagate_error(error, local_error); return FALSE; } /* First pass: Count the total number of items and read the ACLs for each * node. If there is a problem reading the ACL for one node, cancel the * full exploration. */ path_len = len; acls = g_ptr_array_sized_new(16); verify_table = g_hash_table_new(NULL, NULL); for(item = list; item != NULL; item = g_slist_next(item)) { storage_node = (InfdStorageNode*)item->data; /* Construct the storage path for this node */ node_len = strlen(storage_node->name); sep_len = 1; if(path[len - 1] == '/') sep_len = 0; if(len + sep_len + node_len < path_len) { path_len = len + sep_len + node_len; path = g_realloc(path, path_len + sep_len); } if(sep_len > 0) path[len] = '/'; memcpy(path + len + sep_len, storage_node->name, node_len + 1); /* Read ACL */ sheet_set = infd_directory_read_acl( directory, path, NULL, verify_table, &local_error ); if(local_error != NULL) { for(index = 0; index < acls->len; ++index) inf_acl_sheet_set_free(g_ptr_array_index(acls, index)); g_ptr_array_free(acls, TRUE); g_hash_table_destroy(verify_table); infd_storage_node_list_free(list); g_free(path); if(request != NULL) inf_request_fail(INF_REQUEST(request), local_error); g_propagate_error(error, local_error); return FALSE; } g_ptr_array_add(acls, sheet_set); } g_hash_table_destroy(verify_table); node->shared.subdir.explored = TRUE; g_free(path); if(request != NULL) infd_progress_request_initiated(request, acls->len); /* Second pass, fill the directory tree */ index = 0; for(item = list, index = 0; item != NULL; item = g_slist_next(item), ++index) { storage_node = (InfdStorageNode*)item->data; sheet_set = (InfAclSheetSet*)g_ptr_array_index(acls, index); new_node = NULL; switch(storage_node->type) { case INFD_STORAGE_NODE_SUBDIRECTORY: new_node = infd_directory_node_new_subdirectory( directory, node, priv->node_counter++, g_strdup(storage_node->name), sheet_set, FALSE ); break; case INFD_STORAGE_NODE_NOTE: /* TODO: Currently we ignore notes of unknown type. Perhaps we should * report some error. */ plugin = g_hash_table_lookup(priv->plugins, storage_node->identifier); if(plugin != NULL) { new_node = infd_directory_node_new_note( directory, node, priv->node_counter++, g_strdup(storage_node->name), sheet_set, FALSE, plugin ); } else { new_node = infd_directory_node_new_unknown( directory, node, priv->node_counter++, g_strdup(storage_node->name), sheet_set, FALSE, storage_node->identifier ); } break; default: g_assert_not_reached(); break; } inf_acl_sheet_set_free(sheet_set); if(new_node != NULL) { /* Announce the new node. In most cases, this does nothing on the * network because there are no connections that have this node open * (otherwise, we would already have explored the node earlier). * However, if the background storage is replaced by a new one, the root * folder of the new storage will be explored immediately (see below in * infd_directory_set_storage()) and there might still be connections * interesting in root folder changes (because they opened the root * folder from the old storage). Also, local users might be interested * in the new node. */ infd_directory_node_register( directory, new_node, INFD_REQUEST(request), NULL, NULL ); } if(request != NULL) infd_progress_request_progress(request); } g_ptr_array_free(acls, TRUE); if(request != NULL) { iter.node_id = node->id; iter.node = node; inf_request_finish( INF_REQUEST(request), inf_request_result_make_explore_node(INF_BROWSER(directory), &iter) ); } infd_storage_node_list_free(list); return TRUE; } static InfdDirectoryNode* infd_directory_node_add_subdirectory(InfdDirectory* directory, InfdDirectoryNode* parent, InfdRequest* request, const gchar* name, const InfAclSheetSet* sheet_set, InfXmlConnection* connection, const gchar* seq, GError** error) { InfdDirectoryPrivate* priv; InfdDirectoryNode* node; gboolean result; gchar* path; GError* local_error; InfBrowserIter parent_iter; InfBrowserIter iter; g_assert(parent->type == INFD_DIRECTORY_NODE_SUBDIRECTORY); g_assert(parent->shared.subdir.explored == TRUE); g_assert(request != NULL); priv = INFD_DIRECTORY_PRIVATE(directory); local_error = NULL; node = NULL; infd_directory_node_is_name_available( directory, parent, name, &local_error ); if(local_error == NULL) { infd_directory_node_make_path(parent, name, &path, NULL); if(priv->storage != NULL) result = infd_storage_create_subdirectory(priv->storage, path, error); else result = TRUE; g_free(path); if(result == TRUE) { node = infd_directory_node_new_subdirectory( directory, parent, priv->node_counter++, g_strdup(name), sheet_set, TRUE ); node->shared.subdir.explored = TRUE; infd_directory_node_register(directory, node, request, NULL, seq); parent_iter.node_id = parent->id; parent_iter.node = parent; iter.node_id = node->id; iter.node = node; inf_request_finish( INF_REQUEST(request), inf_request_result_make_add_node( INF_BROWSER(directory), &parent_iter, &iter ) ); } } if(local_error != NULL) { g_assert(node == NULL); inf_request_fail(INF_REQUEST(request), local_error); g_propagate_error(error, local_error); } return node; } static gboolean infd_directory_node_add_note(InfdDirectory* directory, InfdDirectoryNode* parent, InfdRequest* request, const gchar* name, const InfAclSheetSet* sheet_set, const InfdNotePlugin* plugin, InfSession* session, InfXmlConnection* connection, gboolean subscribe_connection, const char* seq, GError** error) { InfdDirectoryPrivate* priv; InfdDirectoryNode* node; guint node_id; InfCommunicationHostedGroup* group; xmlNodePtr xml; xmlNodePtr child; const gchar* method; InfdDirectorySubreq* subreq; InfdSessionProxy* proxy; gchar* path; gboolean ensured; GError* local_error; InfBrowserIter parent_iter; InfBrowserIter iter; priv = INFD_DIRECTORY_PRIVATE(directory); g_assert(parent->type == INFD_DIRECTORY_NODE_SUBDIRECTORY); g_assert(parent->shared.subdir.explored == TRUE); g_assert(request != NULL); local_error = NULL; infd_directory_node_is_name_available( directory, parent, name, &local_error ); if(local_error == NULL) { node_id = priv->node_counter++; group = infd_directory_create_subscription_group(directory, node_id); if(subscribe_connection == TRUE) { /* Note that if session is non-zero at this point, the remote site has * to know the contents of the session. It is not synchronized * automatically. * Note also though this is in principle supported by the code, there is * currently no case that calls this function with non-zero session and * subscribe_connection set. */ subreq = infd_directory_add_subreq_add_node( directory, connection, group, request, parent, node_id, name, sheet_set, plugin, session, error ); if(subreq != NULL) { xml = infd_directory_node_desc_register_to_xml( "add-node", node_id, parent, plugin->note_type, name ); inf_xml_util_set_attribute(xml, "seq", seq); if(sheet_set != NULL) { infd_directory_acl_sheets_to_xml_for_connection( directory, NULL, sheet_set, connection, xml ); } child = xmlNewChild(xml, NULL, (const xmlChar*)"subscribe", NULL); inf_xml_util_set_attribute( child, "group", inf_communication_group_get_name(INF_COMMUNICATION_GROUP(group)) ); method = inf_communication_group_get_method_for_connection( INF_COMMUNICATION_GROUP(group), connection ); /* "central" method should always be available */ g_assert(method != NULL); inf_xml_util_set_attribute(child, "method", method); inf_communication_group_send_message( INF_COMMUNICATION_GROUP(priv->group), connection, xml ); } } else { if(session != NULL) { proxy = infd_directory_create_session_proxy_with_group( directory, session, group ); } else { infd_directory_node_make_path(parent, name, &path, NULL); proxy = infd_directory_create_session_proxy( directory, plugin, INF_SESSION_RUNNING, NULL, NULL, group, path ); g_free(path); } ensured = infd_directory_session_proxy_ensure( directory, parent, name, plugin, proxy, &local_error ); if(ensured == TRUE) { node = infd_directory_node_new_note( directory, parent, node_id, g_strdup(name), sheet_set, TRUE, plugin ); infd_directory_node_register(directory, node, request, NULL, seq); infd_directory_node_link_session(directory, node, request, proxy); g_object_unref(proxy); parent_iter.node_id = parent->id; parent_iter.node = parent; iter.node_id = node->id; iter.node = node; inf_request_finish( INF_REQUEST(request), inf_request_result_make_add_node( INF_BROWSER(directory), &parent_iter, &iter ) ); } } g_object_unref(group); } if(local_error != NULL) { inf_request_fail(INF_REQUEST(request), local_error); g_propagate_error(error, local_error); return FALSE; } return TRUE; } static gboolean infd_directory_node_add_sync_in(InfdDirectory* directory, InfdDirectoryNode* parent, InfdRequest* request, const gchar* name, const InfAclSheetSet* sheet_set, const InfdNotePlugin* plugin, InfXmlConnection* sync_conn, gboolean subscribe_sync_conn, const gchar *seq, GError** error) { InfdDirectoryPrivate* priv; InfCommunicationHostedGroup* subscription_group; InfCommunicationHostedGroup* synchronization_group; guint node_id; gchar* sync_group_name; const gchar* method; InfdDirectorySubreq* subreq; xmlNodePtr xml; xmlNodePtr child; GError* local_error; /* Synchronization is always between only two peers, so central method * is enough. */ static const gchar* const sync_methods[] = { "central", NULL }; priv = INFD_DIRECTORY_PRIVATE(directory); g_assert(parent->type == INFD_DIRECTORY_NODE_SUBDIRECTORY); g_assert(parent->shared.subdir.explored == TRUE); local_error = NULL; infd_directory_node_is_name_available( directory, parent, name, &local_error ); if(local_error == NULL) { node_id = priv->node_counter++; subscription_group = infd_directory_create_subscription_group(directory, node_id); if(subscribe_sync_conn == TRUE) { synchronization_group = subscription_group; g_object_ref(synchronization_group); } else { sync_group_name = g_strdup_printf("InfSession_SyncIn_%u", node_id); synchronization_group = inf_communication_manager_open_group( priv->communication_manager, sync_group_name, sync_methods ); g_free(sync_group_name); } method = inf_communication_group_get_method_for_connection( INF_COMMUNICATION_GROUP(synchronization_group), sync_conn ); /* "central" should always be available */ g_assert(method != NULL); subreq = infd_directory_add_subreq_sync_in( directory, sync_conn, synchronization_group, subscription_group, request, parent, node_id, name, sheet_set, plugin, error ); if(subreq != NULL) { xml = infd_directory_node_desc_register_to_xml( "sync-in", node_id, parent, plugin->note_type, name ); if(sheet_set != NULL) { infd_directory_acl_sheets_to_xml_for_connection( directory, NULL, sheet_set, sync_conn, xml ); } inf_xml_util_set_attribute( xml, "group", inf_communication_group_get_name( INF_COMMUNICATION_GROUP(synchronization_group) ) ); inf_xml_util_set_attribute(xml, "method", method); if(seq != NULL) inf_xml_util_set_attribute(xml, "seq", seq); if(subscribe_sync_conn == TRUE) { /* Note that if subscribe_sync_conn is set, then sync_group is the * same as the subscription group, so we don't need to query the * subscription group here. */ child = xmlNewChild(xml, NULL, (const xmlChar*)"subscribe", NULL); inf_xml_util_set_attribute(child, "method", method); inf_xml_util_set_attribute( child, "group", inf_communication_group_get_name( INF_COMMUNICATION_GROUP(subscription_group) ) ); } inf_communication_group_send_message( INF_COMMUNICATION_GROUP(priv->group), sync_conn, xml ); } g_object_unref(synchronization_group); g_object_unref(subscription_group); } if(local_error != NULL) { inf_request_fail(INF_REQUEST(request), local_error); g_propagate_error(error, local_error); return FALSE; } return TRUE; } static gboolean infd_directory_node_remove(InfdDirectory* directory, InfdDirectoryNode* node, InfdRequest* request, const gchar* seq, GError** error) { InfdDirectoryPrivate* priv; gchar* path; InfBrowserIter iter; GError* local_error; const gchar* note_type; priv = INFD_DIRECTORY_PRIVATE(directory); /* Cannot remove the root node */ /* TODO: Move the error check here so we have same error checking for * local and remote requests. */ g_assert(node->parent != NULL); g_assert(request != NULL); local_error = NULL; if(priv->storage != NULL) { infd_directory_node_get_path(node, &path, NULL); switch(node->type) { case INFD_DIRECTORY_NODE_SUBDIRECTORY: note_type = NULL; break; case INFD_DIRECTORY_NODE_NOTE: note_type = node->shared.note.plugin->note_type; break; case INFD_DIRECTORY_NODE_UNKNOWN: note_type = g_quark_to_string(node->shared.unknown.type); break; default: g_assert_not_reached(); break; } infd_storage_remove_node( priv->storage, note_type, path, &local_error ); g_free(path); } iter.node_id = node->id; iter.node = node; if(local_error != NULL) { inf_request_fail(INF_REQUEST(request), local_error); g_propagate_error(error, local_error); return FALSE; } else { inf_request_finish( INF_REQUEST(request), inf_request_result_make_remove_node(INF_BROWSER(directory), &iter) ); /* Need to unlink child sessions explicitely before unregistering, so * remove-session is emitted before node-removed. Don't save changes since * we just removed the note anyway. */ infd_directory_node_unlink_child_sessions( directory, node, request, FALSE ); infd_directory_node_unregister(directory, node, request, seq); infd_directory_node_free(directory, node); return TRUE; } } /* Returns the session for the given node. This does not link the session * (if it isn't already). This means that the next time this function is * called, the session will be created again if you don't link it yourself, * or if you don't create a subscription request for it. Unref the result. */ static InfdSessionProxy* infd_directory_node_make_session(InfdDirectory* directory, InfdDirectoryNode* node, GError** error) { InfdDirectoryPrivate* priv; InfSession* session; GSList* item; InfdDirectorySubreq* subreq; InfCommunicationHostedGroup* group; InfdSessionProxy* proxy; gchar* path; g_assert(node->type == INFD_DIRECTORY_NODE_NOTE); priv = INFD_DIRECTORY_PRIVATE(directory); /* Make sure the session is not already created */ g_assert(node->shared.note.session == NULL || node->shared.note.weakref == TRUE); g_assert( infd_directory_find_subreq_by_node_id( directory, INFD_DIRECTORY_SUBREQ_SESSION, node->id ) == NULL ); /* Note the session might only be weak-refed in which case we re-use it */ if(node->shared.note.session != NULL) { proxy = node->shared.note.session; g_object_ref(proxy); return proxy; } /* If we don't have a background storage then all nodes are in memory */ g_assert(priv->storage != NULL); infd_directory_node_get_path(node, &path, NULL); session = node->shared.note.plugin->session_read( priv->storage, priv->io, priv->communication_manager, path, node->shared.note.plugin->user_data, error ); g_free(path); if(session == NULL) return NULL; /* Buffer might have been marked as modified while reading the session, but * as we just read it from the storage, we don't consider it modified. */ inf_buffer_set_modified(inf_session_get_buffer(session), FALSE); group = infd_directory_create_subscription_group(directory, node->id); proxy = infd_directory_create_session_proxy_with_group( directory, session, group ); g_object_unref(group); g_object_unref(session); return proxy; } /* * Network command handling. */ static gboolean infd_directory_verify_sheet_set(InfdDirectory* directory, const InfAclSheetSet* sheet_set, GError** error) { InfAclSheetSet* changed_sheets; InfAclSheetSet* copy; /* TODO: infd_directory_verify_acl() should be able to operate such that * it leaves the passed-in sheet set unmodified, and so that it just * returns TRUE or FALSE depending on whether changes are needed. */ copy = inf_acl_sheet_set_copy(sheet_set); inf_acl_sheet_set_sink(copy); changed_sheets = infd_directory_verify_acl( directory, copy, NULL, TRUE, TRUE ); inf_acl_sheet_set_free(copy); if(changed_sheets != NULL) { g_assert(changed_sheets->n_sheets > 0); g_set_error( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_NO_SUCH_ACCOUNT, "There is no such account with ID \"%s\"", inf_acl_account_id_to_string(changed_sheets->sheets[0].account) ); inf_acl_sheet_set_free(changed_sheets); return FALSE; } return TRUE; } static InfAclSheetSet* infd_directory_sheet_set_from_xml(InfdDirectory* directory, xmlNodePtr xml, GError** error) { InfAclSheetSet* sheet_set; GError* local_error; local_error = NULL; sheet_set = inf_acl_sheet_set_from_xml(xml, &local_error); if(local_error != NULL) { g_propagate_error(error, local_error); return NULL; } if(sheet_set != NULL) { if(infd_directory_verify_sheet_set(directory, sheet_set, error) != TRUE) { inf_acl_sheet_set_free(sheet_set); return NULL; } } return sheet_set; } static gboolean infd_directory_check_auth(InfdDirectory* directory, InfdDirectoryNode* node, InfXmlConnection* connection, const InfAclMask* mask, GError** error) { InfdDirectoryPrivate* priv; InfdDirectoryConnectionInfo* info; InfBrowserIter iter; gboolean result; priv = INFD_DIRECTORY_PRIVATE(directory); info = g_hash_table_lookup(priv->connections, connection); g_assert(info != NULL); iter.node_id = node->id; iter.node = node; result = inf_browser_check_acl( INF_BROWSER(directory), &iter, info->account_id, mask, NULL ); if(result == FALSE) { g_set_error_literal( error, inf_request_error_quark(), INF_REQUEST_ERROR_NOT_AUTHORIZED, _("Permission denied") ); return FALSE; } return TRUE; } static InfAclAccountId infd_directory_create_acl_account_with_certificate(InfdDirectory* directory, const gchar* account_name, gnutls_x509_crt_t cert, InfXmlConnection* conn, GError** error) { InfdDirectoryPrivate* priv; InfAclAccountId existing; GError* local_error; InfAclMask perms; InfdDirectoryTransientAccount* transient; gchar* dn; gboolean success; priv = INFD_DIRECTORY_PRIVATE(directory); local_error = NULL; existing = infd_directory_lookup_account_by_name( directory, account_name, &local_error ); if(local_error != NULL) { g_propagate_error(error, local_error); return 0; } inf_acl_mask_set1(&perms, INF_ACL_CAN_CREATE_ACCOUNT); if(existing != 0) inf_acl_mask_or1(&perms, INF_ACL_CAN_OVERRIDE_ACCOUNT); if(!infd_directory_check_auth(directory, priv->root, conn, &perms, error)) return 0; /* If there is a certificate with the same name, replace its * certificates with the new certificate. */ if(existing != 0) { transient = infd_directory_lookup_transient_account(directory, existing); if(transient != NULL) { g_free(transient->dn); transient->dn = inf_cert_util_get_dn(cert); } else { g_assert(priv->account_storage != NULL); success = infd_account_storage_set_certificate( priv->account_storage, existing, &cert, 1, error ); if(success == FALSE) existing = 0; } } else { existing = infd_directory_create_acl_account_with_certificates( directory, account_name, FALSE, &cert, 1, conn, error ); } return existing; } static void infd_directory_send_welcome_message(InfdDirectory* directory, InfXmlConnection* connection) { InfdDirectoryPrivate* priv; xmlNodePtr xml; xmlNodePtr plugins; xmlNodePtr child; InfAclAccountId default_id; InfAclAccount* account; GHashTableIter iter; gpointer value; const InfdNotePlugin* plugin; InfdDirectoryConnectionInfo* info; const InfAclSheetSet* sheet_set; GError* local_error; priv = INFD_DIRECTORY_PRIVATE(directory); xml = xmlNewNode(NULL, (const xmlChar*) "welcome"); inf_xml_util_set_attribute( xml, "protocol-version", inf_protocol_get_version() ); info = g_hash_table_lookup(priv->connections, connection); g_assert(info != NULL); inf_xml_util_set_attribute_uint(xml, "sequence-id", info->seq_id); plugins = xmlNewChild(xml, NULL, (const xmlChar*) "note-plugins", NULL); g_hash_table_iter_init(&iter, priv->plugins); while(g_hash_table_iter_next(&iter, NULL, &value)) { plugin = (const InfdNotePlugin*)value; child = xmlNewChild(plugins, NULL, (const xmlChar*) "note-plugin", NULL); inf_xml_util_set_attribute(child, "type", plugin->note_type); } default_id = inf_acl_account_id_from_string("default"); if(info->account_id != default_id) { local_error = NULL; account = infd_directory_lookup_account( directory, info->account_id, NULL, &local_error ); if(local_error != NULL) { g_warning( _("Failed to look up account: %s. Logging out user..."), local_error->message ); g_error_free(local_error); } if(account == NULL) { info->account_id = default_id; } else { child = xmlNewChild(xml, NULL, (const xmlChar*)"account", NULL); inf_acl_account_to_xml(account, child); inf_acl_account_free(account); } } /* Add default ACL for the root node */ infd_directory_acl_sheets_to_xml_for_connection( directory, priv->root->acl_connections, priv->root->acl, connection, xml ); inf_communication_group_send_message( INF_COMMUNICATION_GROUP(priv->group), connection, xml ); } static InfdDirectorySubreq* infd_directory_get_subreq_from_xml(InfdDirectory* directory, InfXmlConnection* connection, xmlNodePtr xml, GError** error) { InfdDirectoryPrivate* priv; guint node_id; gboolean has_node; GSList* item; InfdDirectorySubreq* request; priv = INFD_DIRECTORY_PRIVATE(directory); has_node = inf_xml_util_get_attribute_uint( xml, "id", &node_id, error ); if(has_node == FALSE) { /* subscription requests without node ID are for server chat */ for(item = priv->subscription_requests; item != NULL; item = item->next) { request = (InfdDirectorySubreq*)item->data; if(request->type == INFD_DIRECTORY_SUBREQ_CHAT) return request; } g_set_error_literal( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_NO_SUCH_SUBSCRIPTION_REQUEST, _("No subscription request for the server chat") ); } else { for(item = priv->subscription_requests; item != NULL; item = item->next) { request = (InfdDirectorySubreq*)item->data; if(request->type != INFD_DIRECTORY_SUBREQ_CHAT && request->connection == connection && request->node_id == node_id) { return request; } } g_set_error( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_NO_SUCH_SUBSCRIPTION_REQUEST, _("No subscription request with ID %u"), node_id ); } return NULL; } static InfdDirectoryNode* infd_directory_get_node_from_xml(InfdDirectory* directory, xmlNodePtr xml, const gchar* attrib, GError** error) { InfdDirectoryPrivate* priv; InfdDirectoryNode* node; guint node_id; gboolean has_node; priv = INFD_DIRECTORY_PRIVATE(directory); has_node = inf_xml_util_get_attribute_uint_required( xml, attrib, &node_id, error ); if(has_node == FALSE) return NULL; node = g_hash_table_lookup(priv->nodes, GUINT_TO_POINTER(node_id)); if(node == NULL) { g_set_error_literal( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_NO_SUCH_NODE, inf_directory_strerror(INF_DIRECTORY_ERROR_NO_SUCH_NODE) ); return NULL; } /* TODO: Verify that the connection has explored this node */ return node; } static InfdDirectoryNode* infd_directory_get_node_from_xml_typed(InfdDirectory* directory, xmlNodePtr xml, const gchar* attrib, InfdDirectoryNodeType type, GError** error) { InfdDirectoryNode* node; node = infd_directory_get_node_from_xml(directory, xml, attrib, error); if(node != NULL && node->type != type) { switch(type) { case INFD_DIRECTORY_NODE_SUBDIRECTORY: g_set_error( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_NOT_A_SUBDIRECTORY, _("Node with ID \"%u\" is not a subdirectory node"), node->id ); return NULL; case INFD_DIRECTORY_NODE_NOTE: if(node->type == INFD_DIRECTORY_NODE_UNKNOWN) { g_set_error( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_NOTE_TYPE_UNSUPPORTED, _("Node with ID \"%u\" has unsupported type \"%s\""), node->id, g_quark_to_string(node->shared.unknown.type) ); } else { g_set_error( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_NOT_A_NOTE, _("Node with ID \"%u\" is not a leaf node"), node->id ); } return NULL; case INFD_DIRECTORY_NODE_UNKNOWN: g_assert_not_reached(); /* TODO: Needs to be implemented */ break; default: g_assert_not_reached(); return NULL; } } return node; } static gboolean infd_directory_handle_explore_node(InfdDirectory* directory, InfXmlConnection* connection, const xmlNodePtr xml, GError** error) { InfdDirectoryPrivate* priv; InfdDirectoryNode* node; InfAclMask perms; GSList* item; InfdProgressRequest* request; InfBrowserIter iter; GError* local_error; InfdDirectoryNode* child; xmlNodePtr reply_xml; gchar* seq; guint total; const InfAclSheetSet* sheet_set; priv = INFD_DIRECTORY_PRIVATE(directory); node = infd_directory_get_node_from_xml_typed( directory, xml, "id", INFD_DIRECTORY_NODE_SUBDIRECTORY, error ); if(node == NULL) return FALSE; inf_acl_mask_set1(&perms, INF_ACL_CAN_EXPLORE_NODE); if(!infd_directory_check_auth(directory, node, connection, &perms, error)) return FALSE; if(node->shared.subdir.explored == FALSE) { request = INFD_PROGRESS_REQUEST( g_object_new( INFD_TYPE_PROGRESS_REQUEST, "type", "explore-node", "node-id", node->id, "requestor", connection, NULL ) ); iter.node_id = node->id; iter.node = node; inf_browser_begin_request( INF_BROWSER(directory), &iter, INF_REQUEST(request) ); local_error = NULL; infd_directory_node_explore(directory, node, request, &local_error); g_object_unref(request); if(local_error != NULL) { g_propagate_error(error, local_error); return FALSE; } } if(g_slist_find(node->shared.subdir.connections, connection) != NULL) { g_set_error_literal( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_ALREADY_EXPLORED, inf_directory_strerror(INF_DIRECTORY_ERROR_ALREADY_EXPLORED) ); return FALSE; } if(!infd_directory_make_seq(directory, connection, xml, &seq, error)) return FALSE; total = 0; for(child = node->shared.subdir.child; child != NULL; child = child->next) ++ total; reply_xml = xmlNewNode(NULL, (const xmlChar*)"explore-begin"); inf_xml_util_set_attribute_uint(reply_xml, "total", total); if(seq != NULL) inf_xml_util_set_attribute(reply_xml, "seq", seq); inf_communication_group_send_message( INF_COMMUNICATION_GROUP(priv->group), connection, reply_xml ); for(child = node->shared.subdir.child; child != NULL; child = child->next) { reply_xml = infd_directory_node_register_to_xml(child); if(seq != NULL) inf_xml_util_set_attribute(reply_xml, "seq", seq); if(child->acl != NULL) { infd_directory_acl_sheets_to_xml_for_connection( directory, child->acl_connections, child->acl, connection, reply_xml ); } inf_communication_group_send_message( INF_COMMUNICATION_GROUP(priv->group), connection, reply_xml ); } reply_xml = xmlNewNode(NULL, (const xmlChar*)"explore-end"); if(seq != NULL) inf_xml_util_set_attribute(reply_xml, "seq", seq); inf_communication_group_send_message( INF_COMMUNICATION_GROUP(priv->group), connection, reply_xml ); /* Remember that this connection explored that node so that it gets * notified when changes occur. */ node->shared.subdir.connections = g_slist_prepend( node->shared.subdir.connections, connection ); g_free(seq); return TRUE; } static gboolean infd_directory_handle_add_node(InfdDirectory* directory, InfXmlConnection* connection, const xmlNodePtr xml, GError** error) { InfdDirectoryPrivate* priv; InfdDirectoryNode* parent; InfBrowserIter parent_iter; InfdDirectoryNode* node; GError* local_error; InfAclSheetSet* sheet_set; InfAclMask perms; InfdNotePlugin* plugin; InfdRequest* request; xmlChar* name; xmlChar* type; gchar* seq; xmlNodePtr child; gboolean perform_sync_in; gboolean subscribe_sync_conn; gboolean is_subdirectory; gboolean node_added; priv = INFD_DIRECTORY_PRIVATE(directory); parent = infd_directory_get_node_from_xml_typed( directory, xml, "parent", INFD_DIRECTORY_NODE_SUBDIRECTORY, error ); if(parent == NULL) return FALSE; local_error = NULL; sheet_set = infd_directory_sheet_set_from_xml(directory, xml, &local_error); if(local_error != NULL) { g_propagate_error(error, local_error); return FALSE; } type = inf_xml_util_get_attribute_required(xml, "type", error); if(type == NULL) { if(sheet_set != NULL) inf_acl_sheet_set_free(sheet_set); return FALSE; } if(strcmp((const gchar*)type, "InfSubdirectory") == 0) is_subdirectory = TRUE; else is_subdirectory = FALSE; /* Check for sync-in/subscribe flags */ perform_sync_in = subscribe_sync_conn = FALSE; for(child = xml->children; child != NULL; child = child->next) { if(strcmp((const char*)child->name, "sync-in") == 0) perform_sync_in = TRUE; else if(strcmp((const char*)child->name, "subscribe") == 0) subscribe_sync_conn = TRUE; } infd_directory_get_add_node_permissions( directory, &perms, is_subdirectory, subscribe_sync_conn, perform_sync_in, sheet_set ); if(!infd_directory_check_auth(directory, parent, connection, &perms, error)) { if(sheet_set != NULL) inf_acl_sheet_set_free(sheet_set); xmlFree(type); return FALSE; } if(is_subdirectory == TRUE) { /* No plugin because we want to create a directory */ plugin = NULL; xmlFree(type); /* TODO: Error if perform_sync_in or subscribe are set. Actually we * could interpret subscribe as initially explored... */ } else { plugin = g_hash_table_lookup(priv->plugins, (const gchar*)type); xmlFree(type); if(plugin == NULL) { if(sheet_set != NULL) inf_acl_sheet_set_free(sheet_set); g_set_error_literal( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_TYPE_UNKNOWN, inf_directory_strerror(INF_DIRECTORY_ERROR_TYPE_UNKNOWN) ); return FALSE; } } if(!infd_directory_make_seq(directory, connection, xml, &seq, error)) { if(sheet_set != NULL) inf_acl_sheet_set_free(sheet_set); return FALSE; } name = inf_xml_util_get_attribute_required(xml, "name", error); if(name == NULL) { if(sheet_set != NULL) inf_acl_sheet_set_free(sheet_set); g_free(seq); return FALSE; } request = INFD_REQUEST( g_object_new( INFD_TYPE_REQUEST, "type", "add-node", "node-id", parent->id, "requestor", connection, NULL ) ); parent_iter.node_id = parent->id; parent_iter.node = parent; inf_browser_begin_request( INF_BROWSER(directory), &parent_iter, INF_REQUEST(request) ); if(plugin == NULL) { node = infd_directory_node_add_subdirectory( directory, parent, request, (const gchar*)name, sheet_set, connection, seq, error ); if(node == NULL) node_added = FALSE; else node_added = TRUE; } else { if(perform_sync_in == FALSE) { node_added = infd_directory_node_add_note( directory, parent, request, (const gchar*)name, sheet_set, plugin, NULL, connection, subscribe_sync_conn, seq, error ); } else { node_added = infd_directory_node_add_sync_in( directory, parent, request, (const char*)name, sheet_set, plugin, connection, subscribe_sync_conn, seq, error ); /* Note: The sync-in can still fail for various reasons. Maybe the * client doesn't support the communication method, the synchronization * fails or the parent folder is removed. */ } } g_object_unref(request); if(sheet_set != NULL) inf_acl_sheet_set_free(sheet_set); xmlFree(name); g_free(seq); return node_added; } static gboolean infd_directory_handle_remove_node(InfdDirectory* directory, InfXmlConnection* connection, const xmlNodePtr xml, GError** error) { InfdDirectoryNode* node; gchar* seq; InfdRequest* request; InfBrowserIter iter; gboolean result; InfdDirectoryNode* up; InfAclMask perms; node = infd_directory_get_node_from_xml(directory, xml, "id", error); if(node == NULL) return FALSE; if(node->parent == NULL) { g_set_error_literal( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_ROOT_NODE_REMOVE_ATTEMPT, _("The root node cannot be removed") ); return FALSE; } else { /* Check the remove node permission on the parent node */ up = node->parent; inf_acl_mask_set1(&perms, INF_ACL_CAN_REMOVE_NODE); if(!infd_directory_check_auth(directory, up, connection, &perms, error)) return FALSE; if(!infd_directory_make_seq(directory, connection, xml, &seq, error)) return FALSE; request = INFD_REQUEST( g_object_new( INFD_TYPE_REQUEST, "type", "remove-node", "node-id", node->id, "requestor", connection, NULL ) ); iter.node_id = node->id; iter.node = node; inf_browser_begin_request( INF_BROWSER(directory), &iter, INF_REQUEST(request) ); result = infd_directory_node_remove(directory, node, request, seq, error); g_object_unref(request); return result; } } static gboolean infd_directory_handle_subscribe_session(InfdDirectory* directory, InfXmlConnection* connection, xmlNodePtr xml, GError** error) { InfdDirectoryPrivate* priv; InfdDirectoryNode* node; InfAclMask perms; GSList* item; InfdDirectorySubreq* subreq; InfdSessionProxy* proxy; InfBrowserIter iter; InfdRequest* request; InfCommunicationGroup* group; const gchar* method; gchar* seq; xmlNodePtr reply_xml; GError* local_error; priv = INFD_DIRECTORY_PRIVATE(directory); node = infd_directory_get_node_from_xml_typed( directory, xml, "id", INFD_DIRECTORY_NODE_NOTE, error ); if(node == NULL) return FALSE; inf_acl_mask_set1(&perms, INF_ACL_CAN_SUBSCRIBE_SESSION); if(!infd_directory_check_auth(directory, node, connection, &perms, error)) return FALSE; /* TODO: Bail if this connection is either currently being synchronized to * or is already subscribed */ request = NULL; proxy = NULL; /* Check if there exists already a session in a subreq */ for(item = priv->subscription_requests; item != NULL; item = item->next) { subreq = (InfdDirectorySubreq*)item->data; if(subreq->type == INFD_DIRECTORY_SUBREQ_SESSION && subreq->node_id == node->id) { if(subreq->connection == connection) { g_set_error_literal( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_ALREADY_SUBSCRIBED, inf_directory_strerror(INF_DIRECTORY_ERROR_ALREADY_SUBSCRIBED) ); return FALSE; } else { request = subreq->shared.session.request; proxy = subreq->shared.session.session; } } } if(node->shared.note.session != NULL && node->shared.note.weakref == FALSE) { g_assert(proxy == NULL || proxy == node->shared.note.session); proxy = node->shared.note.session; } if(!infd_directory_make_seq(directory, connection, xml, &seq, error)) return FALSE; /* Make a new request if there is no request yet and we don't have a proxy * already. If we do have a proxy, then we don't have to read anything from * storage. */ if(request == NULL && proxy == NULL) { request = INFD_REQUEST( g_object_new( INFD_TYPE_REQUEST, "type", "subscribe-session", "node-id", node->id, "requestor", connection, NULL ) ); iter.node_id = node->id; iter.node = node; inf_browser_begin_request( INF_BROWSER(directory), &iter, INF_REQUEST(request) ); } else if(request != NULL) { g_object_ref(request); } /* In case we don't have a proxy already, create a new one */ if(proxy == NULL) { local_error = NULL; proxy = infd_directory_node_make_session(directory, node, &local_error); if(proxy == NULL) { /* Only if we have already a proxy we could not have a request here */ g_assert(request != NULL); inf_request_fail(INF_REQUEST(request), local_error); g_object_unref(request); g_free(seq); g_propagate_error(error, local_error); return FALSE; } } else { g_object_ref(proxy); } g_object_get(G_OBJECT(proxy), "subscription-group", &group, NULL); method = inf_communication_group_get_method_for_connection( group, connection ); /* We should always be able to fallback to "central" */ g_assert(method != NULL); /* Reply that subscription was successful (so far, synchronization may * still fail) and tell identifier. */ reply_xml = xmlNewNode(NULL, (const xmlChar*)"subscribe-session"); xmlNewProp( reply_xml, (const xmlChar*)"group", (const xmlChar*)inf_communication_group_get_name(group) ); xmlNewProp( reply_xml, (const xmlChar*)"method", (const xmlChar*)method ); g_object_unref(group); inf_xml_util_set_attribute_uint(reply_xml, "id", node->id); if(seq != NULL) inf_xml_util_set_attribute(reply_xml, "seq", seq); /* This gives ownership of proxy to the subscription request */ infd_directory_add_subreq_session( directory, connection, request, node->id, proxy ); if(request != NULL) g_object_unref(request); inf_communication_group_send_message( INF_COMMUNICATION_GROUP(priv->group), connection, reply_xml ); g_free(seq); return TRUE; } static gboolean infd_directory_handle_save_session(InfdDirectory* directory, InfXmlConnection* connection, const xmlNodePtr xml, GError** error) { InfdDirectoryPrivate* priv; InfdDirectoryNode* node; xmlNodePtr reply_xml; gchar* path; gchar* seq; InfSession* session; gboolean result; priv = INFD_DIRECTORY_PRIVATE(directory); if(priv->storage == NULL) { g_set_error_literal( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_NO_STORAGE, _("No background storage available") ); return FALSE; } /* TODO: Don't do anything if buffer is not modified */ /* TODO: Authentication, we could also allow specific connections to save * without being subscribed. */ node = infd_directory_get_node_from_xml_typed( directory, xml, "id", INFD_DIRECTORY_NODE_NOTE, error ); if(node->shared.note.session == NULL || !infd_session_proxy_is_subscribed(node->shared.note.session, connection)) { g_set_error_literal( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_UNSUBSCRIBED, _("The requesting connection is not subscribed to the session") ); return FALSE; } /* We only need this if we are saving asynchronously: */ /* TODO: Which we should do, of course. */ #if 0 reply_xml = xmlNewNode(NULL, (const xmlChar*)"session-save-in-progress"); seq_attr = xmlGetProp(xml, (const xmlChar*)"seq"); if(seq_attr != NULL) { xmlNewProp(reply_xml, (const xmlChar*)"seq", seq_attr); xmlFree(seq_attr); } inf_connection_manager_group_send_to_connection( priv->group, connection, reply_xml ); #endif infd_directory_node_get_path(node, &path, NULL); g_object_get( G_OBJECT(node->shared.note.session), "session", &session, NULL ); /* TODO: Make a request */ result = node->shared.note.plugin->session_write( priv->storage, session, path, node->shared.note.plugin->user_data, error ); g_object_unref(session); /* TODO: unset modified flag of buffer if result == TRUE */ /* The timeout should only be set when there aren't any connections * subscribed, however we just made sure that the connection the request * comes from is subscribed. */ g_assert(node->shared.note.save_timeout == NULL); g_free(path); if(result == FALSE) return FALSE; if(!infd_directory_make_seq(directory, connection, xml, &seq, error)) return FALSE; reply_xml = xmlNewNode(NULL, (const xmlChar*)"session-saved"); if(seq != NULL) inf_xml_util_set_attribute(reply_xml, "seq", seq); inf_communication_group_send_message( INF_COMMUNICATION_GROUP(priv->group), connection, reply_xml ); g_free(seq); return TRUE; } static gboolean infd_directory_handle_subscribe_chat(InfdDirectory* directory, InfXmlConnection* connection, xmlNodePtr xml, GError** error) { InfdDirectoryPrivate* priv; InfCommunicationGroup* group; const gchar* method; gchar* seq; xmlNodePtr reply_xml; InfdDirectoryNode* node; InfAclMask perms; priv = INFD_DIRECTORY_PRIVATE(directory); /* TODO: Bail if this connection is either currently being synchronized to * or is already subscribed */ /* TODO: Bail if a subscription request for this connection is pending. */ if(priv->chat_session == NULL) { g_set_error_literal( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_CHAT_DISABLED, _("The chat is disabled") ); return FALSE; } node = priv->root; inf_acl_mask_set1(&perms, INF_ACL_CAN_SUBSCRIBE_CHAT); if(!infd_directory_check_auth(directory, node, connection, &perms, error)) return FALSE; if(!infd_directory_make_seq(directory, connection, xml, &seq, error)) return FALSE; g_object_get( G_OBJECT(priv->chat_session), "subscription-group", &group, NULL ); method = inf_communication_group_get_method_for_connection( group, connection ); /* We should always be able to fallback to "central" */ g_assert(method != NULL); /* Reply that subscription was successful (so far, synchronization may * still fail) and tell identifier. */ reply_xml = xmlNewNode(NULL, (const xmlChar*)"subscribe-chat"); xmlNewProp( reply_xml, (const xmlChar*)"group", (const xmlChar*)inf_communication_group_get_name(group) ); xmlNewProp( reply_xml, (const xmlChar*)"method", (const xmlChar*)method ); g_object_unref(group); if(seq) inf_xml_util_set_attribute(reply_xml, "seq", seq); infd_directory_add_subreq_chat(directory, connection); inf_communication_group_send_message( INF_COMMUNICATION_GROUP(priv->group), connection, reply_xml ); g_free(seq); return TRUE; } static gboolean infd_directory_handle_create_acl_account(InfdDirectory* directory, InfXmlConnection* connection, xmlNodePtr xml, GError** error) { InfdDirectoryPrivate* priv; xmlNodePtr child; int res; gnutls_datum_t crq_text; gnutls_x509_crq_t crq; gnutls_x509_crt_t cert; gnutls_x509_crt_t* certs; guint n_certs; guint i; gchar* cert_buffer; gchar* seq; xmlNodePtr reply_xml; gchar* name; InfAclAccountId account_id; InfAclAccount account; priv = INFD_DIRECTORY_PRIVATE(directory); crq_text.data = NULL; for(child = xml->children; child != NULL; child = child->next) { if(child->type != XML_ELEMENT_NODE) continue; if(strcmp((const char*)child->name, "crq") == 0) { if(child->children != NULL && child->children->type == XML_TEXT_NODE) { crq_text.data = (char*)child->children->content; crq_text.size = strlen(crq_text.data); } } } if(crq_text.data == NULL) { g_set_error_literal( error, inf_request_error_quark(), INF_REQUEST_ERROR_NO_SUCH_ATTRIBUTE, _("No certificate request provided") ); return FALSE; } /* TODO: Some of the code below should be moved to inf-cert-util */ res = gnutls_x509_crq_init(&crq); if(res != GNUTLS_E_SUCCESS) { inf_gnutls_set_error(error, res); return FALSE; } res = gnutls_x509_crq_import(crq, &crq_text, GNUTLS_X509_FMT_PEM); if(res != GNUTLS_E_SUCCESS) { gnutls_x509_crq_deinit(crq); inf_gnutls_set_error(error, res); return FALSE; } res = gnutls_x509_crq_verify(crq, 0); if(res != GNUTLS_E_SUCCESS) { gnutls_x509_crq_deinit(crq); inf_gnutls_set_error(error, res); return FALSE; } /* OK, so now we have a good certificate request in front of us. Now, go * ahead, create the certificate and sign it with the server's key. */ cert = infd_directory_create_certificate_from_crq( directory, crq, 365 * DAYS, error ); gnutls_x509_crq_deinit(crq); if(cert == NULL) return FALSE; /* Export the certificate to PEM format and send it back to the client */ g_assert(priv->certificate != NULL); n_certs = inf_certificate_chain_get_n_certificates(priv->certificate) + 1; certs = g_malloc(n_certs * sizeof(gnutls_x509_crt_t)); for(i = 0; i < n_certs - 1; ++i) { certs[i + 1] = inf_certificate_chain_get_nth_certificate(priv->certificate, i); } certs[0] = cert; cert_buffer = inf_cert_util_write_certificate_mem(certs, n_certs, error); g_free(certs); if(cert_buffer == NULL) return FALSE; /* Create seq */ if(!infd_directory_make_seq(directory, connection, xml, &seq, error)) { g_free(cert_buffer); gnutls_x509_crt_deinit(cert); return FALSE; } /* Check permissions */ name = infd_directory_account_name_from_certificate(cert, error); if(name == NULL) { g_free(cert_buffer); gnutls_x509_crt_deinit(cert); g_free(seq); return FALSE; } /* At this point, the request is validated and nothing can fail anymore, * except the account creation itself. */ /* Create account. This function checks permissions of the connection. */ account_id = infd_directory_create_acl_account_with_certificate( directory, name, cert, connection, error ); gnutls_x509_crt_deinit(cert); if(account_id == 0) { g_free(name); g_free(seq); g_free(cert_buffer); return FALSE; } reply_xml = xmlNewNode(NULL, (const xmlChar*)"create-acl-account"); child = xmlNewChild(reply_xml, NULL, (const xmlChar*)"certificate", NULL); xmlNodeAddContent(child, (const xmlChar*)cert_buffer); g_free(cert_buffer); if(seq != NULL) inf_xml_util_set_attribute(reply_xml, "seq", seq); g_free(seq); account.id = account_id; account.name = name; inf_acl_account_to_xml(&account, reply_xml); g_free(name); inf_communication_group_send_message( INF_COMMUNICATION_GROUP(priv->group), connection, reply_xml ); return TRUE; } static gboolean infd_directory_handle_remove_acl_account(InfdDirectory* directory, InfXmlConnection* connection, xmlNodePtr xml, GError** error) { InfdDirectoryPrivate* priv; xmlChar* xml_id; InfAclAccountId account_id; gchar* seq; gboolean result; InfdDirectoryNode* node; InfAclMask perms; priv = INFD_DIRECTORY_PRIVATE(directory); node = priv->root; inf_acl_mask_set1(&perms, INF_ACL_CAN_REMOVE_ACCOUNT); if(!infd_directory_check_auth(directory, node, connection, &perms, error)) return FALSE; xml_id = inf_xml_util_get_attribute_required(xml, "id", error); if(xml_id == NULL) return FALSE; account_id = inf_acl_account_id_from_string((const gchar*)xml_id); xmlFree(xml_id); if(!infd_directory_make_seq(directory, connection, xml, &seq, error)) return FALSE; result = infd_directory_remove_acl_account( directory, account_id, connection, seq, NULL, error ); g_free(seq); return result; } static gboolean infd_directory_handle_query_acl_account_list(InfdDirectory* directory, InfXmlConnection* connection, const xmlNodePtr xml, GError** error) { InfdDirectoryPrivate* priv; InfdDirectoryNode* node; InfdDirectoryConnectionInfo* conn_info; InfAclMask perms; gchar* seq; GError* local_error; GSList* item; xmlNodePtr reply_xml; gboolean notifications_enabled; guint known_accounts; InfAclAccount* accounts; guint n_accounts; InfAclAccountId default_id; const InfAclAccount* account; guint i; priv = INFD_DIRECTORY_PRIVATE(directory); conn_info = g_hash_table_lookup(priv->connections, connection); g_assert(conn_info != NULL); node = priv->root; inf_acl_mask_set1(&perms, INF_ACL_CAN_QUERY_ACCOUNT_LIST); if(!infd_directory_check_auth(directory, node, connection, &perms, error)) return FALSE; if(!infd_directory_make_seq(directory, connection, xml, &seq, error)) return FALSE; local_error = NULL; if(priv->account_storage != NULL) { accounts = infd_account_storage_list_accounts( priv->account_storage, &n_accounts, &local_error ); if(local_error != NULL) { g_propagate_error(error, local_error); g_free(seq); return FALSE; } } else { accounts = NULL; n_accounts = 0; } reply_xml = xmlNewNode(NULL, (const xmlChar*)"acl-account-list-begin"); notifications_enabled = TRUE; if(priv->account_storage != NULL) { notifications_enabled = infd_account_storage_supports( priv->account_storage, INFD_ACCOUNT_STORAGE_SUPPORT_NOTIFICATION ); } inf_xml_util_set_attribute_uint( reply_xml, "notifications-enabled", (notifications_enabled == TRUE) ? 1 : 0 ); /* Count the number of accounts already known by the client, to correctly * calculate the number of accounts to be transferred. */ default_id = inf_acl_account_id_from_string("default"); if(conn_info->account_id != default_id) known_accounts = 2; else known_accounts = 1; g_assert(n_accounts + priv->n_transient_accounts >= known_accounts); inf_xml_util_set_attribute_uint( reply_xml, "total", n_accounts + priv->n_transient_accounts - known_accounts ); if(seq != NULL) inf_xml_util_set_attribute(reply_xml, "seq", seq); inf_communication_group_send_message( INF_COMMUNICATION_GROUP(priv->group), connection, reply_xml ); for(i = 0; i < priv->n_transient_accounts + n_accounts; ++i) { if(i < priv->n_transient_accounts) account = &priv->transient_accounts[i].account; else account = &accounts[i - priv->n_transient_accounts]; /* Ignore accounts already known by the client: Its own account and the * default account. */ if(account->id != default_id && account->id != conn_info->account_id) { reply_xml = xmlNewNode(NULL, (const xmlChar*)"add-acl-account"); inf_acl_account_to_xml(account, reply_xml); if(seq != NULL) inf_xml_util_set_attribute(reply_xml, "seq", seq); inf_communication_group_send_message( INF_COMMUNICATION_GROUP(priv->group), connection, reply_xml ); } } inf_acl_account_array_free(accounts, n_accounts); reply_xml = xmlNewNode(NULL, (const xmlChar*)"acl-account-list-end"); if(seq != NULL) inf_xml_util_set_attribute(reply_xml, "seq", seq); inf_communication_group_send_message( INF_COMMUNICATION_GROUP(priv->group), connection, reply_xml ); g_free(seq); return TRUE; } static gboolean infd_directory_handle_lookup_acl_accounts(InfdDirectory* directory, InfXmlConnection* connection, const xmlNodePtr xml, GError** error) { InfdDirectoryPrivate* priv; InfdDirectoryNode* node; InfAclMask perms; InfAclAccountId default_id; gchar* seq; xmlNodePtr reply_xml; xmlNodePtr reply_child; xmlNodePtr child; const gchar* content; InfAclAccountId id; const gchar* name; InfdDirectoryTransientAccount* transient; InfAclAccount* account; InfAclAccount* accounts; guint n_accounts; guint i; GArray* to_be_looked_up; GError* local_error; priv = INFD_DIRECTORY_PRIVATE(directory); /* ACL account lookup needs INF_ACL_CAN_QUERY_ACCOUNT_LIST permissions */ node = priv->root; inf_acl_mask_set1(&perms, INF_ACL_CAN_QUERY_ACCOUNT_LIST); if(!infd_directory_check_auth(directory, node, connection, &perms, error)) return FALSE; if(!infd_directory_make_seq(directory, connection, xml, &seq, error)) return FALSE; reply_xml = xmlNewNode(NULL, (const xmlChar*)"lookup-acl-accounts"); if(seq != NULL) inf_xml_util_set_attribute(reply_xml, "seq", seq); g_free(seq); /* TODO: Try to avoid duplicates in the following */ default_id = inf_acl_account_id_from_string("default"); to_be_looked_up = g_array_new(FALSE, FALSE, sizeof(InfAclAccountId)); for(child = xml->children; child != NULL; child = child->next) { if(child->type != XML_ELEMENT_NODE) continue; if(strcmp((const char*)child->name, "id") == 0) { /* Lookup by ID: Try transient directly, otherwise collect in * lookup array -- do bulk lookup afterwards. */ content = NULL; if(child->children != NULL && child->children->type == XML_TEXT_NODE) content = (const gchar*)child->children->content; id = inf_acl_account_id_from_string(content); if(id != 0 && id != default_id) { transient = infd_directory_lookup_transient_account(directory, id); if(transient != NULL) { reply_child = xmlNewChild( reply_xml, NULL, (const xmlChar*)"account", NULL ); inf_acl_account_to_xml(&transient->account, reply_child); } else { g_array_append_val(to_be_looked_up, id); } } } else if(strcmp((const char*)child->name, "name") == 0) { /* Lookup by name: Lookup both transient and storage here, * the InfdAccountStorage interface does not provide bulk lookup of * names at the moment. */ name = NULL; if(child->children != NULL && child->children->type == XML_TEXT_NODE) name = (const gchar*)child->children->content; if(name != NULL && *name != '\0') { if(priv->account_storage != NULL) { local_error = NULL; accounts = infd_account_storage_lookup_accounts_by_name( priv->account_storage, name, &n_accounts, &local_error ); if(local_error != NULL) { xmlFreeNode(reply_xml); g_array_free(to_be_looked_up, TRUE); g_propagate_error(error, local_error); return FALSE; } } else { accounts = NULL; n_accounts = 0; } for(i = 0; i < priv->n_transient_accounts + n_accounts; ++i) { if(i < priv->n_transient_accounts) account = &priv->transient_accounts[i].account; else account = &accounts[i - priv->n_transient_accounts]; if(i >= priv->n_transient_accounts || (account->name != NULL && strcmp(account->name, name) == 0)) { reply_child = xmlNewChild( reply_xml, NULL, (const xmlChar*)"account", NULL ); inf_acl_account_to_xml(account, reply_child); } } if(accounts != NULL) inf_acl_account_array_free(accounts, n_accounts); } } } /* Now, look up all remaining IDs */ if(priv->account_storage != NULL && to_be_looked_up->len > 0) { local_error = NULL; accounts = infd_account_storage_lookup_accounts( priv->account_storage, (InfAclAccountId*)to_be_looked_up->data, to_be_looked_up->len, &local_error ); if(local_error != NULL) { xmlFreeNode(reply_xml); g_array_free(to_be_looked_up, TRUE); g_propagate_error(error, local_error); return FALSE; } for(i = 0; i < to_be_looked_up->len; ++i) { if(accounts[i].id != 0) { reply_child = xmlNewChild( reply_xml, NULL, (const xmlChar*)"account", NULL ); inf_acl_account_to_xml(&accounts[i], reply_child); } } inf_acl_account_array_free(accounts, to_be_looked_up->len); } g_array_free(to_be_looked_up, TRUE); inf_communication_group_send_message( INF_COMMUNICATION_GROUP(priv->group), connection, reply_xml ); return TRUE; } static gboolean infd_directory_handle_query_acl(InfdDirectory* directory, InfXmlConnection* connection, const xmlNodePtr xml, GError** error) { InfdDirectoryPrivate* priv; InfdDirectoryNode* node; InfAclMask perms; gchar* seq; const InfAclSheetSet* sheet_set; xmlNodePtr reply_xml; priv = INFD_DIRECTORY_PRIVATE(directory); node = infd_directory_get_node_from_xml( directory, xml, "id", error ); if(node == NULL) return FALSE; if(g_slist_find(node->acl_connections, connection) != NULL) { g_set_error_literal( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_ACL_ALREADY_QUERIED, _("The ACL for this node has already been queried") ); return FALSE; } inf_acl_mask_set1(&perms, INF_ACL_CAN_QUERY_ACL); if(!infd_directory_check_auth(directory, node, connection, &perms, error)) return FALSE; if(!infd_directory_make_seq(directory, connection, xml, &seq, error)) return FALSE; /* Add to ACL connections here so that * infd_directory_acl_sheets_to_xml_for_connection() will send the full * ACL, and not only the default sheet. */ node->acl_connections = g_slist_prepend(node->acl_connections, connection); reply_xml = xmlNewNode(NULL, (const xmlChar*)"set-acl"); inf_xml_util_set_attribute_uint(reply_xml, "id", node->id); if(seq != NULL) inf_xml_util_set_attribute(reply_xml, "seq", seq); if(node->acl != NULL) { infd_directory_acl_sheets_to_xml_for_connection( directory, node->acl_connections, node->acl, connection, reply_xml ); } inf_communication_group_send_message( INF_COMMUNICATION_GROUP(priv->group), connection, reply_xml ); g_free(seq); return TRUE; } static gboolean infd_directory_handle_set_acl(InfdDirectory* directory, InfXmlConnection* connection, const xmlNodePtr xml, GError** error) { InfdDirectoryPrivate* priv; InfdDirectoryNode* node; InfAclMask perms; gchar* seq; GError* local_error; InfAclSheetSet* sheet_set; InfdRequest* request; InfBrowserIter iter; InfAclAccountId default_id; const InfAclSheet* default_sheet; const InfAclSheet* account_sheet; GHashTableIter conn_iter; gpointer key; gpointer value; InfXmlConnection* conn; InfdDirectoryConnectionInfo* info; xmlNodePtr reply_xml; guint i; const InfAclSheet* sheet; priv = INFD_DIRECTORY_PRIVATE(directory); node = infd_directory_get_node_from_xml( directory, xml, "id", error ); if(node == NULL) return FALSE; if(g_slist_find(node->acl_connections, connection) == NULL) { g_set_error_literal( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_ACL_NOT_QUERIED, _("The ACL for this node has not been queried yet") ); return FALSE; } inf_acl_mask_set1(&perms, INF_ACL_CAN_SET_ACL); if(!infd_directory_check_auth(directory, node, connection, &perms, error)) return FALSE; /* TODO: Introduce inf_acl_sheet_set_from_xml_required */ local_error = NULL; sheet_set = infd_directory_sheet_set_from_xml(directory, xml, &local_error); if(local_error != NULL) { g_propagate_error(error, local_error); return FALSE; } if(sheet_set == NULL || sheet_set->n_sheets == 0) { g_set_error_literal( error, inf_request_error_quark(), INF_REQUEST_ERROR_NO_SUCH_ATTRIBUTE, _("The set-acl request does not have any ACL provided") ); return FALSE; } /* Make sure the CAN_CREATE_ACCOUNT permission cannot be activated when * we cannot support it. */ if(node == priv->root) { if(infd_directory_report_support_in_sheets(directory, sheet_set) == FALSE) { g_set_error_literal( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_OPERATION_UNSUPPORTED, _("This server does not support the requested permissions") ); inf_acl_sheet_set_free(sheet_set); return FALSE; } } if(!infd_directory_make_seq(directory, connection, xml, &seq, error)) { inf_acl_sheet_set_free(sheet_set); return FALSE; } request = INFD_REQUEST( g_object_new( INFD_TYPE_REQUEST, "type", "set-acl", "node-id", node->id, "requestor", connection, NULL ) ); iter.node_id = node->id; iter.node = node; inf_browser_begin_request(INF_BROWSER(directory), &iter, INF_REQUEST(request) ); node->acl = inf_acl_sheet_set_merge_sheets(node->acl, sheet_set); if(node == priv->root) { priv->orig_root_acl = inf_acl_sheet_set_merge_sheets( priv->orig_root_acl, sheet_set ); } /* Apply the effect of the new ACL */ default_id = inf_acl_account_id_from_string("default"); default_sheet = inf_acl_sheet_set_find_const_sheet(sheet_set, default_id); g_hash_table_iter_init(&conn_iter, priv->connections); while(g_hash_table_iter_next(&conn_iter, &key, &value)) { conn = (InfXmlConnection*)key; info = (InfdDirectoryConnectionInfo*)value; if(default_sheet == NULL) { account_sheet = inf_acl_sheet_set_find_const_sheet( sheet_set, info->account_id ); } if(default_sheet != NULL || account_sheet != NULL) infd_directory_enforce_acl(directory, conn, node, NULL); } /* Announce to all connections but this one, since for this connection we * need to set the seq (done below) */ infd_directory_announce_acl_sheets( directory, node, request, sheet_set, connection ); infd_directory_write_acl(directory, node); reply_xml = xmlNewNode(NULL, (const xmlChar*)"set-acl"); inf_xml_util_set_attribute_uint(reply_xml, "id", node->id); if(seq != NULL) inf_xml_util_set_attribute(reply_xml, "seq", seq); infd_directory_acl_sheets_to_xml_for_connection( directory, node->acl_connections, sheet_set, connection, reply_xml ); inf_communication_group_send_message( INF_COMMUNICATION_GROUP(priv->group), connection, reply_xml ); inf_request_finish( INF_REQUEST(request), inf_request_result_make_set_acl(INF_BROWSER(directory), &iter) ); g_object_unref(request); inf_acl_sheet_set_free(sheet_set); g_free(seq); return TRUE; } static gboolean infd_directory_handle_subscribe_ack(InfdDirectory* directory, InfXmlConnection* connection, const xmlNodePtr xml, GError** error) { InfdDirectoryPrivate* priv; InfdDirectorySubreq* subreq; InfdDirectoryNode* node; InfXmlConnection* conn; InfAclMask perms; xmlNodePtr reply_xml; GSList* item; InfdDirectorySubreq* subsubreq; InfdDirectorySyncIn* sync_in; InfdSessionProxy* proxy; InfSession* session; InfdDirectoryConnectionInfo* info; GError* local_error; InfBrowserIter parent_iter; InfBrowserIter iter; priv = INFD_DIRECTORY_PRIVATE(directory); subreq = infd_directory_get_subreq_from_xml( directory, connection, xml, error ); if(subreq == NULL) return FALSE; /* Unlink, so that the subreq itself does not cause the is_name_available * assertions below to fail. */ infd_directory_unlink_subreq(directory, subreq); info = g_hash_table_lookup(priv->connections, connection); g_assert(info != NULL); switch(subreq->type) { case INFD_DIRECTORY_SUBREQ_CHAT: /* Note that it doesn't matter whether the chat was disabled+enabled * between subreq generation and handling - the group * is always called InfChat so the client joins the correct group in * all cases. */ /* TODO: check for CAN_SUBSCRIBE_CHAT at this point... */ if(priv->chat_session != NULL) { infd_session_proxy_subscribe_to( priv->chat_session, connection, info->seq_id, TRUE ); } else { /* The chat does not exist anymore - just create a temporary chat, * subscribe the client and then close the chat right aftewards, to * notify the client about the chat not existing anymore. */ /* TODO: Make a helper function creating the chat proxy but not * setting the member var / doing the property notify */ g_object_freeze_notify(G_OBJECT(directory)); infd_directory_enable_chat(directory, TRUE); infd_session_proxy_subscribe_to( priv->chat_session, connection, info->seq_id, TRUE ); infd_directory_enable_chat(directory, FALSE); g_object_thaw_notify(G_OBJECT(directory)); } break; case INFD_DIRECTORY_SUBREQ_SESSION: node = g_hash_table_lookup( priv->nodes, GUINT_TO_POINTER(subreq->node_id) ); /* Remove the request from other subreqs, if any, because we are going * to finish it now. */ for(item = priv->subscription_requests; item != NULL; item = item->next) { subsubreq = (InfdDirectorySubreq*)item->data; if(subsubreq->type == INFD_DIRECTORY_SUBREQ_SESSION && subsubreq->node_id == subreq->node_id) { g_assert(subsubreq->shared.session.request == subreq->shared.session.request); if(subsubreq->shared.session.request != NULL) { g_object_unref(subsubreq->shared.session.request); subsubreq->shared.session.request = NULL; } } } /* The node this client wants to subscribe might have been removed in the * meanwhile. Also, make sure that the permissions are still granted. */ local_error = NULL; conn = connection; inf_acl_mask_set1(&perms, INF_ACL_CAN_SUBSCRIBE_SESSION); if(node != NULL && node->type != INFD_DIRECTORY_NODE_UNKNOWN && infd_directory_check_auth(directory, node, conn, &perms, &local_error)) { g_assert(node->type == INFD_DIRECTORY_NODE_NOTE); g_assert(node->shared.note.session == NULL || node->shared.note.session == subreq->shared.session.session); g_assert( ((node->shared.note.session == NULL || node->shared.note.weakref == TRUE) && subreq->shared.session.request != NULL) || ((node->shared.note.session != NULL && node->shared.note.weakref == FALSE) && subreq->shared.session.request == NULL) ); if(node->shared.note.session == NULL || node->shared.note.weakref == TRUE) { infd_directory_node_link_session( directory, node, subreq->shared.session.request, subreq->shared.session.session ); iter.node_id = node->id; iter.node = node; inf_request_finish( INF_REQUEST(subreq->shared.session.request), inf_request_result_make_subscribe_session( INF_BROWSER(directory), &iter, INF_SESSION_PROXY(subreq->shared.session.session) ) ); } } else { if(subreq->shared.session.request != NULL) { /* TODO: Better error message needed: It could also be that the * permissions were changed or the note plugin was unloaded. */ if(local_error == NULL) { g_set_error_literal( &local_error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_NO_SUCH_NODE, _("The node to be subscribed to has been removed") ); } inf_request_fail( INF_REQUEST(subreq->shared.session.request), local_error ); } if(local_error != NULL) g_error_free(local_error); } infd_session_proxy_subscribe_to( subreq->shared.session.session, connection, info->seq_id, TRUE ); break; case INFD_DIRECTORY_SUBREQ_ADD_NODE: g_assert(subreq->shared.add_node.request != NULL); node = subreq->shared.add_node.parent; /* The parent node might have been removed meanwhile, also check that the * permissions are still granted. */ local_error = NULL; conn = connection; infd_directory_get_add_node_permissions( directory, &perms, FALSE, TRUE, FALSE, subreq->shared.add_node.sheet_set ); if(node != NULL && subreq->shared.add_node.plugin != NULL && infd_directory_check_auth(directory, node, conn, &perms, &local_error)) { g_assert( infd_directory_node_is_name_available( directory, subreq->shared.add_node.parent, subreq->shared.add_node.name, NULL ) == TRUE ); g_assert( g_slist_find( subreq->shared.add_node.parent->shared.subdir.connections, subreq->connection ) != NULL ); proxy = subreq->shared.add_node.proxy; g_object_ref(proxy); node = infd_directory_node_new_note( directory, subreq->shared.add_node.parent, subreq->node_id, g_strdup(subreq->shared.add_node.name), subreq->shared.add_node.sheet_set, TRUE, subreq->shared.add_node.plugin ); /* register to all but conn. conn already added the node after * having sent subscribe-ack. */ infd_directory_node_register( directory, node, subreq->shared.add_node.request, connection, NULL ); infd_directory_node_link_session( directory, node, subreq->shared.add_node.request, proxy ); g_assert(subreq->shared.add_node.request != NULL); parent_iter.node_id = subreq->shared.add_node.parent->id; parent_iter.node = subreq->shared.add_node.parent; iter.node_id = node->id; iter.node = node; inf_request_finish( INF_REQUEST(subreq->shared.add_node.request), inf_request_result_make_add_node( INF_BROWSER(directory), &parent_iter, &iter ) ); } else { /* The add-node request can't be performed properly because the parent * node has been removed. Still create a session proxy and subscribe to * connection before unrefing it again, so that the remote host gets * notified that this session is no longer active. */ proxy = subreq->shared.add_node.proxy; g_object_ref(proxy); if(local_error == NULL) { /* TODO: Better error message needed: It could also be that the * permissions were changed or the note plugin was unloaded. */ g_set_error_literal( &local_error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_NO_SUCH_NODE, _("The parent node of the node to be added has been removed") ); } if(node != NULL) { /* If the parent node still exists, then the client has created the * node, and we refused it because the permissions are no longer * granted. Even though we close the session, the client does not know * that the node was not even created. For the client, the ACL * update comes too late, so it cannot know that the request failed. * Therefore, send a remove-node message for the client to get rid * of the node again. */ reply_xml = xmlNewNode(NULL, (const xmlChar*)"remove-node"); inf_xml_util_set_attribute_uint(reply_xml, "id", subreq->node_id); inf_communication_group_send_message( INF_COMMUNICATION_GROUP(priv->group), connection, reply_xml ); } inf_request_fail( INF_REQUEST(subreq->shared.add_node.request), local_error ); g_error_free(local_error); } /* Don't sync session to client if the client added this node, since the * node is empty anyway. */ infd_session_proxy_subscribe_to(proxy, connection, info->seq_id, FALSE); g_object_unref(proxy); break; case INFD_DIRECTORY_SUBREQ_SYNC_IN: case INFD_DIRECTORY_SUBREQ_SYNC_IN_SUBSCRIBE: g_assert(subreq->shared.sync_in.request != NULL); node = subreq->shared.sync_in.parent; /* Group and method are OK for the client, so start synchronization */ g_object_get( G_OBJECT(subreq->shared.sync_in.proxy), "session", &session, NULL ); inf_session_synchronize_from(session); g_object_unref(session); /* The parent node might have been removed meanwhile, also check that the * permissions are still granted. */ local_error = NULL; conn = connection; infd_directory_get_add_node_permissions( directory, &perms, FALSE, TRUE, FALSE, subreq->shared.sync_in.sheet_set ); if(node != NULL && subreq->shared.sync_in.plugin != NULL && infd_directory_check_auth(directory, node, conn, &perms, &local_error)) { g_assert( infd_directory_node_is_name_available( directory, subreq->shared.sync_in.parent, subreq->shared.sync_in.name, NULL ) == TRUE ); g_assert( g_slist_find( subreq->shared.sync_in.parent->shared.subdir.connections, subreq->connection ) != NULL ); proxy = subreq->shared.sync_in.proxy; g_object_ref(proxy); sync_in = infd_directory_add_sync_in( directory, subreq->shared.sync_in.parent, subreq->shared.sync_in.request, subreq->node_id, subreq->shared.sync_in.name, subreq->shared.sync_in.sheet_set, subreq->shared.sync_in.plugin, proxy ); } else { /* The sync-in can't be performed properly because the parent node of * the node to sync-in has been removed. Still create the corresponding * session and close it immediately (cancelling the synchronization, to * tell the client). */ proxy = subreq->shared.sync_in.proxy; g_object_ref(proxy); /* TODO: Better error message needed: It could also be that the * permissions were changed or the note plugin was unloaded. */ if(local_error == NULL) { g_set_error_literal( &local_error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_NO_SUCH_NODE, _("The parent node of the node to be added has been removed") ); } /* If the parent node still exists, then the client has created the * node, and we refused it because the permissions are no longer * granted. We don't need to do anything extra, though, since we * cancel the synchronization, and that will let the client know not * to create the node. */ inf_request_fail( INF_REQUEST(subreq->shared.sync_in.request), local_error ); g_error_free(local_error); } if(subreq->type == INFD_DIRECTORY_SUBREQ_SYNC_IN) { /* No subscription, so add connection to synchronization group * explicitely. */ inf_communication_hosted_group_add_member( subreq->shared.sync_in.synchronization_group, connection ); } else { /* subscribe_to adds connection to subscription group which is the * same as the synchronization group. */ infd_session_proxy_subscribe_to(proxy, connection, info->seq_id, FALSE); } g_object_unref(proxy); break; default: g_assert_not_reached(); break; } infd_directory_free_subreq(subreq); return TRUE; } static gboolean infd_directory_handle_subscribe_nack(InfdDirectory* directory, InfXmlConnection* connection, const xmlNodePtr xml, GError** error) { InfdDirectoryPrivate* priv; InfdDirectorySubreq* subreq; InfdDirectorySubreq* subsubreq; GSList* item; InfdRequest* other_request; gchar* path; gboolean result; GError* local_error; priv = INFD_DIRECTORY_PRIVATE(directory); subreq = infd_directory_get_subreq_from_xml( directory, connection, xml, error ); if(subreq == NULL) return FALSE; result = TRUE; if(priv->storage != NULL && (subreq->type == INFD_DIRECTORY_SUBREQ_SESSION || subreq->type == INFD_DIRECTORY_SUBREQ_ADD_NODE || subreq->type == INFD_DIRECTORY_SUBREQ_SYNC_IN || subreq->type == INFD_DIRECTORY_SUBREQ_SYNC_IN_SUBSCRIBE)) { local_error = NULL; g_set_error_literal( &local_error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_SUBSCRIPTION_REJECTED, _("Client did not acknowledge initial subscription") ); switch(subreq->type) { case INFD_DIRECTORY_SUBREQ_CHAT: break; case INFD_DIRECTORY_SUBREQ_SESSION: /* Only fail the request if there are no other requests with the same * node around. */ other_request = NULL; /* Cannot use infd_directory_find_subreq_by_node_id() because that * way we cannot ignore the subreq currently being processed. */ for(item = priv->subscription_requests; item != NULL; item = item->next) { subsubreq = (InfdDirectorySubreq*)item->data; if(subsubreq == subreq) continue; if(subsubreq->type == INFD_DIRECTORY_SUBREQ_SESSION && subsubreq->node_id == subreq->node_id) { g_assert(subsubreq->shared.session.request == subreq->shared.session.request); other_request = subsubreq->shared.session.request; break; } } if(other_request == NULL) { inf_request_fail( INF_REQUEST(subreq->shared.session.request), local_error ); } /* No need to remove the node from storage since it existed * already before */ result = TRUE; break; case INFD_DIRECTORY_SUBREQ_ADD_NODE: inf_request_fail( INF_REQUEST(subreq->shared.add_node.request), local_error ); infd_directory_node_make_path( subreq->shared.add_node.parent, subreq->shared.add_node.name, &path, NULL ); result = infd_storage_remove_node( priv->storage, subreq->shared.add_node.plugin->note_type, path, error ); g_free(path); break; case INFD_DIRECTORY_SUBREQ_SYNC_IN: case INFD_DIRECTORY_SUBREQ_SYNC_IN_SUBSCRIBE: inf_request_fail( INF_REQUEST(subreq->shared.sync_in.request), local_error ); infd_directory_node_make_path( subreq->shared.sync_in.parent, subreq->shared.sync_in.name, &path, NULL ); result = infd_storage_remove_node( priv->storage, subreq->shared.sync_in.plugin->note_type, path, error ); g_free(path); break; default: g_assert_not_reached(); break; } g_error_free(local_error); } infd_directory_remove_subreq(directory, subreq); return result; } /* * Signal handlers. */ static void infd_directory_connection_notify_status_cb(GObject* object, GParamSpec* pspec, gpointer user_data) { InfdDirectory* directory; InfdDirectoryPrivate* priv; InfXmlConnection* connection; InfXmlConnectionStatus status; InfdDirectoryConnectionInfo* info; directory = INFD_DIRECTORY(user_data), priv = INFD_DIRECTORY_PRIVATE(directory); connection = INF_XML_CONNECTION(object); g_object_get(object, "status", &status, NULL); if(status == INF_XML_CONNECTION_OPEN) { info = (InfdDirectoryConnectionInfo*)g_hash_table_lookup( priv->connections, connection ); g_assert(info != NULL); g_assert(info->account_id == 0); info->account_id = infd_directory_login_by_certificate( directory, connection ); infd_directory_send_welcome_message(directory, connection); } } static void infd_directory_member_removed_cb(InfCommunicationGroup* group, InfXmlConnection* connection, gpointer user_data) { InfdDirectory* directory; InfdDirectoryPrivate* priv; GSList* item; InfdDirectorySyncIn* sync_in; InfXmlConnection* sync_in_connection; InfdDirectorySubreq* request; InfdDirectoryConnectionInfo* info; directory = INFD_DIRECTORY(user_data); priv = INFD_DIRECTORY_PRIVATE(directory); /* TODO: Update last seen time, and write user list to storage */ /* Remove sync-ins from this connection */ item = priv->sync_ins; while(item != NULL) { sync_in = (InfdDirectorySyncIn*)item->data; item = item->next; g_object_get( G_OBJECT(sync_in->request), "requestor", &sync_in_connection, NULL ); if(sync_in_connection == connection) infd_directory_remove_sync_in(directory, sync_in); g_object_unref(sync_in_connection); } /* Remove all subscription requests for this connection */ item = priv->subscription_requests; while(item != NULL) { request = (InfdDirectorySubreq*)item->data; item = item->next; if(request->connection == connection) infd_directory_remove_subreq(directory, request); } if(priv->root != NULL) { if(priv->root->shared.subdir.explored == TRUE) { infd_directory_node_remove_connection(priv->root, connection); } else { /* If the root directory was not explored it could still happen that * the connection queried its ACL. */ priv->root->acl_connections = g_slist_remove( priv->root->acl_connections, connection ); } } info = g_hash_table_lookup(priv->connections, connection); g_slice_free(InfdDirectoryConnectionInfo, info); inf_signal_handlers_disconnect_by_func(G_OBJECT(connection), G_CALLBACK(infd_directory_connection_notify_status_cb), directory); g_hash_table_remove(priv->connections, connection); g_signal_emit( G_OBJECT(directory), directory_signals[CONNECTION_REMOVED], 0, connection ); g_object_unref(connection); } static void infd_directory_account_storage_account_added_cb(InfdAccountStorage* storage, const InfAclAccount* acc, gpointer user_data) { /* An account has been externally added to the storage: Announce */ infd_directory_announce_acl_account(INFD_DIRECTORY(user_data), acc, NULL); } static void infd_directory_account_storage_account_removed_cb(InfdAccountStorage* storage, const InfAclAccount* acc, gpointer user_data) { /* An account has been externally removed from the storage: Cleanup ACL * sheets and announce. */ infd_directory_cleanup_acl_account( INFD_DIRECTORY(user_data), acc, TRUE, NULL, NULL, NULL ); } /* * Property modification. */ static void infd_directory_set_storage(InfdDirectory* directory, InfdStorage* storage) { InfdDirectoryPrivate* priv; InfdDirectoryNode* child; GError* error; priv = INFD_DIRECTORY_PRIVATE(directory); g_assert(priv->root != NULL); /* If we are setting a new storage, then remove all documents. If we are * going to no storage, then keep current set of documents. */ if(storage != NULL) { /* TODO: Update last seen times of all connected users, * and write user list to storage. */ if(priv->root->shared.subdir.explored == TRUE) { /* Clear directory tree. This will cause all sessions to be saved in * storage. Note that sessions are not closed, but further * modifications to the sessions will not be stored in storage. */ while((child = priv->root->shared.subdir.child) != NULL) { /* TODO: Do make requests here */ infd_directory_node_unlink_child_sessions( directory, child, NULL, TRUE ); infd_directory_node_unregister(directory, child, NULL, NULL); infd_directory_node_free(directory, child); } } } if(priv->storage != NULL) g_object_unref(priv->storage); priv->storage = storage; if(storage != NULL) { /* Read user list from new storage, and new ACL for the root node. This * overwrites the current ACL for the root node. If no new storage is set, * then we keep the previous ACL for the root node. */ infd_directory_read_root_acl(directory); /* root folder was explored before storage change, so keep it * explored. */ if(priv->root->shared.subdir.explored == TRUE) { /* Need to set explored flag to FALSE to meet preconditions of * infd_directory_node_explore(). */ priv->root->shared.subdir.explored = FALSE; /* Do not make a request here, since we don't formally re-explore the * root node -- once a node is explored, it always stays explored. */ error = NULL; infd_directory_node_explore(directory, priv->root, NULL, &error); if(error != NULL) { g_warning( _("Failed to explore the root directory of the new storage: %s"), error->message ); g_error_free(error); } } g_object_ref(storage); } } /* This function goes through the client list and changes the account of * every client according to the current account storage. This is useful to * re-obtain consistency when the account storage has been changed. */ static void infd_directory_relogin_clients(InfdDirectory* directory) { InfdDirectoryPrivate* priv; GArray* lookup_ids; GPtrArray* lookup_conns; GHashTableIter hash_iter; gpointer key; gpointer value; InfdDirectoryConnectionInfo* conn_info; InfAclAccountId new_account; InfdDirectoryTransientAccount* transient; InfAclAccount* accounts; GError* error; guint i; InfAclAccountId default_id; const InfdDirectoryTransientAccount* default_account; priv = INFD_DIRECTORY_PRIVATE(directory); lookup_ids = g_array_new(FALSE, FALSE, sizeof(InfAclAccountId)); lookup_conns = g_ptr_array_new(); g_hash_table_iter_init(&hash_iter, priv->connections); while(g_hash_table_iter_next(&hash_iter, &key, &value)) { conn_info = (InfdDirectoryConnectionInfo*)value; new_account = infd_directory_login_by_certificate( directory, INF_XML_CONNECTION(key) ); if(new_account != conn_info->account_id) { transient = infd_directory_lookup_transient_account( directory, new_account ); /* If the account change it cannot be transient, since transient * accounts don't change when changing the account storage backend */ if(transient != NULL) { infd_directory_change_acl_account( directory, INF_XML_CONNECTION(key), &transient->account ); } else { g_array_append_val(lookup_ids, new_account); g_ptr_array_add(lookup_conns, key); } } } accounts = NULL; if(priv->account_storage != NULL && lookup_ids->len > 0) { error = NULL; accounts = infd_account_storage_lookup_accounts( priv->account_storage, (InfAclAccountId*)lookup_ids->data, lookup_ids->len, &error ); if(error != NULL) { g_warning( _("Failed to lookup account IDs on account storage change: %s. " "Demoting clients to default account."), error->message ); g_error_free(error); } } for(i = 0; i < lookup_ids->len; ++i) { conn_info = g_hash_table_lookup( priv->connections, g_ptr_array_index(lookup_conns, i) ); g_assert(conn_info != NULL); if(accounts == NULL || accounts[i].id == 0) { default_id = inf_acl_account_id_from_string("default"); default_account = infd_directory_lookup_transient_account( directory, default_id ); g_assert(default_account != NULL); infd_directory_change_acl_account( directory, INF_XML_CONNECTION(g_ptr_array_index(lookup_conns, i)), &default_account->account ); } else { infd_directory_change_acl_account( directory, INF_XML_CONNECTION(g_ptr_array_index(lookup_conns, i)), &accounts[i] ); } } if(accounts != NULL) inf_acl_account_array_free(accounts, lookup_ids->len); g_ptr_array_free(lookup_conns, TRUE); g_array_free(lookup_ids, TRUE); } static void infd_directory_get_account_list_from_storage(InfdAccountStorage* storage, InfAclAccount** accounts, guint* n_accounts, gboolean* has_accounts) { gboolean supports_list; GError* error; if(storage != NULL) { supports_list = infd_account_storage_supports( storage, INFD_ACCOUNT_STORAGE_SUPPORT_LIST_ACCOUNTS ); if(supports_list) { error = NULL; *accounts = infd_account_storage_list_accounts( storage, n_accounts, &error ); if(error != NULL) { g_warning( _("Failed to obtain account list from account storage: %s"), error->message ); g_error_free(error); *n_accounts = 0; *has_accounts = FALSE; } else { *has_accounts = TRUE; } } else { *accounts = NULL; *n_accounts = 0; *has_accounts = FALSE; } } else { *accounts = NULL; *n_accounts = 0; *has_accounts = TRUE; } } GHashTable* infd_directory_make_account_storage_change_announcements( InfdDirectory* directory, InfdAccountStorage* prev_account_storage) { InfdDirectoryPrivate* priv; InfAclAccount* prev_accounts; InfAclAccountId* prev_ids; guint n_prev_accounts; gboolean has_prev_accounts; InfAclAccount* new_accounts; InfAclAccountId* new_ids; guint n_new_accounts; gboolean has_new_accounts; guint i, j; GHashTable* verify_table; gboolean has_account; gpointer value; GError* error; priv = INFD_DIRECTORY_PRIVATE(directory); error = NULL; /* Third, query the account lists of the * old and new storages, if available and if notifications are * supported. */ infd_directory_get_account_list_from_storage( prev_account_storage, &prev_accounts, &n_prev_accounts, &has_prev_accounts ); infd_directory_get_account_list_from_storage( priv->account_storage, &new_accounts, &n_new_accounts, &has_new_accounts ); /* Start building a verify table by adding all accounts of the * new storage into it. If the list of new accounts is not available, * but the list of old accounts is, then lookup all old accounts in * the new table. */ verify_table = g_hash_table_new(NULL, NULL); if(has_new_accounts) { for(i = 0; i < n_new_accounts; ++i) { g_hash_table_insert( verify_table, INF_ACL_ACCOUNT_ID_TO_POINTER(new_accounts[i].id), GBOOLEAN_TO_POINTER(TRUE) ); } } else if(has_prev_accounts && n_prev_accounts > 0) { g_assert(priv->account_storage != NULL); prev_ids = g_malloc(n_prev_accounts * sizeof(InfAclAccountId)); for(i = 0; i < n_prev_accounts; ++i) prev_ids[i] = prev_accounts[i].id; new_accounts = infd_account_storage_lookup_accounts( priv->account_storage, prev_ids, n_prev_accounts, &error ); for(i = 0; i < n_prev_accounts; ++i) { if(error != NULL || new_accounts[i].id != 0) { /* This account exists in the new storage, or we couldn't * query it, and then we assume it exists, to be safe. */ g_hash_table_insert( verify_table, INF_ACL_ACCOUNT_ID_TO_POINTER(prev_ids[i]), GBOOLEAN_TO_POINTER(TRUE) ); } else { /* This account does not exist in the new storage */ g_hash_table_insert( verify_table, INF_ACL_ACCOUNT_ID_TO_POINTER(prev_ids[i]), GBOOLEAN_TO_POINTER(FALSE) ); } } g_free(prev_ids); if(error != NULL) { g_warning( _("Failed to look up accounts in new account storage: %s"), error->message ); g_error_free(error); error = NULL; } else { inf_acl_account_array_free(new_accounts, n_prev_accounts); new_accounts = NULL; } } /* If the old account list is available, emit acl-account-removed * signals for all old accounts that are not available in the new account * list. Also, if the new account list is available, add all old * accounts into the verify table that do not exist in the new list. */ for(i = 0; i < n_prev_accounts; ++i) { has_account = g_hash_table_lookup_extended( verify_table, INF_ACL_ACCOUNT_ID_TO_POINTER(prev_accounts[i].id), NULL, &value ); if(has_account == FALSE || GPOINTER_TO_BOOLEAN(value) == FALSE) { if(has_account == FALSE) { g_assert(has_new_accounts); g_hash_table_insert( verify_table, INF_ACL_ACCOUNT_ID_TO_POINTER(prev_accounts[i].id), GBOOLEAN_TO_POINTER(FALSE) ); } infd_directory_cleanup_acl_account( directory, &prev_accounts[i], FALSE, NULL, NULL, NULL ); } } /* If new accounts are available, announce those accounts that are * not present in the old account list. */ if(has_new_accounts && n_new_accounts > 0) { /* If the list of old accounts is not available, then look up the new * users in the old table. */ if(!has_prev_accounts && prev_account_storage != NULL) { new_ids = g_malloc(n_new_accounts * sizeof(InfAclAccountId)); for(i = 0; i < n_new_accounts; ++i) new_ids[i] = new_accounts[i].id; prev_accounts = infd_account_storage_lookup_accounts( prev_account_storage, new_ids, n_new_accounts, &error ); for(i = 0; i < n_new_accounts; ++i) { if(error != NULL || prev_accounts[i].id == 0) { infd_directory_announce_acl_account( directory, &new_accounts[i], NULL ); } } if(error != NULL) { g_warning( _("Failed to look up accounts in new account storage: %s"), error->message ); g_error_free(error); error = NULL; } else { inf_acl_account_array_free(prev_accounts, n_new_accounts); prev_accounts = NULL; } } else { /* We have both new and old accounts. Note that the accounts are not * necessarily in order now, so we need to X-check */ for(i = 0; i < n_new_accounts; ++i) { for(j = 0; j < n_prev_accounts; ++j) if(prev_accounts[j].id == new_accounts[i].id) break; if(j == n_prev_accounts) { infd_directory_announce_acl_account( directory, &new_accounts[i], NULL ); } } } } /* All notifications have been performed now. We can now get rid of * the user lists. The next step is ACL verifications: Verify that the ACL * sheets do not contain any invalid user. Invalid accounts in ACL sheets * are only allowed if we don't have an account storage. */ if(prev_accounts != NULL) inf_acl_account_array_free(prev_accounts, n_prev_accounts); if(new_accounts != NULL) inf_acl_account_array_free(new_accounts, n_new_accounts); return verify_table; } static void infd_directory_set_account_storage(InfdDirectory* directory, InfdAccountStorage* account_storage) { InfdDirectoryPrivate* priv; InfdAccountStorage* prev_account_storage; GHashTable* verify_table; priv = INFD_DIRECTORY_PRIVATE(directory); if(account_storage == priv->account_storage) return; /* Disconnect signal handlers of old storage */ if(priv->account_storage != NULL) { inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->account_storage), G_CALLBACK(infd_directory_account_storage_account_added_cb), directory ); inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->account_storage), G_CALLBACK(infd_directory_account_storage_account_removed_cb), directory ); } prev_account_storage = priv->account_storage; priv->account_storage = account_storage; /* Fix all client accounts */ infd_directory_relogin_clients(directory); /* Make announcements, and build a verify table while doing so */ verify_table = infd_directory_make_account_storage_change_announcements( directory, prev_account_storage ); /* Re-verify all ACLs, using the verify table from before as a starting * point, to avoid unnecessary lookups. */ if(priv->account_storage != NULL) infd_directory_verify_all_acls(directory, verify_table, TRUE); g_hash_table_destroy(verify_table); /* Connect new storage, and release previous one */ if(priv->account_storage != NULL) { g_object_ref(priv->account_storage); g_signal_connect( G_OBJECT(priv->account_storage), "account-added", G_CALLBACK(infd_directory_account_storage_account_added_cb), directory ); g_signal_connect( G_OBJECT(priv->account_storage), "account-removed", G_CALLBACK(infd_directory_account_storage_account_removed_cb), directory ); } if(prev_account_storage != NULL) g_object_unref(prev_account_storage); /* The root ACL might have changed due to added or removed support of * account creation or deletion. */ infd_directory_update_root_acl(directory); g_object_notify(G_OBJECT(directory), "account-storage"); } static void infd_directory_set_communication_manager(InfdDirectory* directory, InfCommunicationManager* manager) { InfdDirectoryPrivate* priv; priv = INFD_DIRECTORY_PRIVATE(directory); /* construct/only */ g_assert(priv->communication_manager == NULL); priv->communication_manager = manager; g_object_ref(manager); } /* * GObject overrides. */ static void infd_directory_init(InfdDirectory* directory) { InfdDirectoryPrivate* priv; priv = INFD_DIRECTORY_PRIVATE(directory); priv->io = NULL; priv->storage = NULL; priv->account_storage = NULL; priv->communication_manager = NULL; priv->group = NULL; priv->private_key = NULL; priv->certificate = NULL; priv->plugins = g_hash_table_new(g_str_hash, g_str_equal); priv->connections = g_hash_table_new(NULL, NULL); priv->transient_accounts = g_malloc(sizeof(InfdDirectoryTransientAccount)); priv->transient_accounts[0].account.id = inf_acl_account_id_from_string("default"); priv->transient_accounts[0].account.name = NULL; priv->transient_accounts[0].dn = NULL; priv->n_transient_accounts = 1; priv->node_counter = 1; priv->nodes = g_hash_table_new(NULL, NULL); /* The root node has no name. At this point we also create the root node * with no ACL. The ACL is read from storage in the constructor, or if no * ACL exists in storage, a default ACL is used. */ priv->root = infd_directory_node_new_subdirectory( directory, NULL, 0, NULL, NULL, FALSE ); priv->orig_root_acl = NULL; priv->sync_ins = NULL; priv->subscription_requests = NULL; priv->chat_session = NULL; } static void infd_directory_constructed(GObject* object) { InfdDirectory* directory; InfdDirectoryPrivate* priv; InfAclSheet sheet; InfAclSheetSet sheet_set; /* We only use central method for directory handling */ static const gchar* const methods[] = { "centrol", NULL }; G_OBJECT_CLASS(infd_directory_parent_class)->constructed(object); directory = INFD_DIRECTORY(object); priv = INFD_DIRECTORY_PRIVATE(directory); /* TODO: Use default communication manager in case none is set */ g_assert(priv->communication_manager != NULL); priv->group = inf_communication_manager_open_group( priv->communication_manager, "InfDirectory", methods ); g_signal_connect( G_OBJECT(priv->group), "member-removed", G_CALLBACK(infd_directory_member_removed_cb), directory ); inf_communication_group_set_target( INF_COMMUNICATION_GROUP(priv->group), INF_COMMUNICATION_OBJECT(directory) ); /* If we don't have a background storage then the root node has been * explored (there is simply no content yet, it has to be added via * infd_directory_add_note). */ if(priv->storage == NULL) { priv->root->shared.subdir.explored = TRUE; /* Apply default permissions for the root node */ sheet.account = inf_acl_account_id_from_string("default"); sheet.perms = INF_ACL_MASK_DEFAULT; sheet.mask = INF_ACL_MASK_ALL; g_assert(priv->root->acl == NULL); sheet_set.own_sheets = NULL; sheet_set.sheets = &sheet; sheet_set.n_sheets = 1; priv->root->acl = inf_acl_sheet_set_merge_sheets(priv->root->acl, &sheet_set); } /* Note that if storage is non-NULL the root ACL has already been loaded * when the storage property was set. */ g_assert(g_hash_table_size(priv->connections) == 0); } static void infd_directory_dispose(GObject* object) { InfdDirectory* directory; InfdDirectoryPrivate* priv; GHashTableIter iter; gpointer key; directory = INFD_DIRECTORY(object); priv = INFD_DIRECTORY_PRIVATE(directory); /* First, remove all connections */ for(g_hash_table_iter_init(&iter, priv->connections); g_hash_table_iter_next(&iter, &key, NULL); g_hash_table_iter_init(&iter, priv->connections)) { inf_communication_hosted_group_remove_member( priv->group, INF_XML_CONNECTION(key) ); } g_assert(g_hash_table_size(priv->connections) == 0); g_assert(priv->subscription_requests == NULL); g_assert(priv->sync_ins == NULL); /* We have dropped all references to connections now, so these do not try * to tell anyone that the directory tree has gone or whatever. */ inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->group), G_CALLBACK(infd_directory_member_removed_cb), directory ); /* Disable chat if any */ if(priv->chat_session != NULL) infd_directory_enable_chat(directory, FALSE); /* This frees the complete directory tree and saves sessions into the * storage. */ infd_directory_node_unlink_child_sessions( directory, priv->root, NULL, TRUE ); infd_directory_set_storage(directory, NULL); infd_directory_set_account_storage(directory, NULL); g_assert(priv->root != NULL); infd_directory_node_free(directory, priv->root); priv->root = NULL; /* Can be NULL, for example when no storage is set */ if(priv->orig_root_acl != NULL) { inf_acl_sheet_set_free(priv->orig_root_acl); priv->orig_root_acl = NULL; } g_hash_table_destroy(priv->nodes); priv->nodes = NULL; g_object_unref(priv->group); g_object_unref(priv->communication_manager); g_hash_table_destroy(priv->connections); priv->connections = NULL; g_hash_table_destroy(priv->plugins); priv->plugins = NULL; if(priv->certificate != NULL) { inf_certificate_chain_unref(priv->certificate); priv->certificate = NULL; } if(priv->io != NULL) { g_object_unref(G_OBJECT(priv->io)); priv->io = NULL; } G_OBJECT_CLASS(infd_directory_parent_class)->dispose(object); } static void infd_directory_finalize(GObject* object) { InfdDirectory* directory; InfdDirectoryPrivate* priv; guint i; directory = INFD_DIRECTORY(object); priv = INFD_DIRECTORY_PRIVATE(directory); for(i = 0; i < priv->n_transient_accounts; ++i) { g_free(priv->transient_accounts[i].account.name); g_free(priv->transient_accounts[i].dn); } g_free(priv->transient_accounts); G_OBJECT_CLASS(infd_directory_parent_class)->finalize(object); } static void infd_directory_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfdDirectory* directory; InfdDirectoryPrivate* priv; directory = INFD_DIRECTORY(object); priv = INFD_DIRECTORY_PRIVATE(directory); switch(prop_id) { case PROP_IO: g_assert(priv->io == NULL); /* construct only */ priv->io = INF_IO(g_value_dup_object(value)); break; case PROP_STORAGE: infd_directory_set_storage( directory, INFD_STORAGE(g_value_get_object(value)) ); break; case PROP_ACCOUNT_STORAGE: infd_directory_set_account_storage( directory, INFD_ACCOUNT_STORAGE(g_value_get_object(value)) ); break; case PROP_COMMUNICATION_MANAGER: infd_directory_set_communication_manager( directory, INF_COMMUNICATION_MANAGER(g_value_get_object(value)) ); break; case PROP_PRIVATE_KEY: priv->private_key = (gnutls_x509_privkey_t)g_value_get_pointer(value); break; case PROP_CERTIFICATE: priv->certificate = (InfCertificateChain*)g_value_dup_boxed(value); break; case PROP_CHAT_SESSION: case PROP_STATUS: /* read only */ default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void infd_directory_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfdDirectory* directory; InfdDirectoryPrivate* priv; directory = INFD_DIRECTORY(object); priv = INFD_DIRECTORY_PRIVATE(directory); switch(prop_id) { case PROP_IO: g_value_set_object(value, G_OBJECT(priv->io)); break; case PROP_STORAGE: g_value_set_object(value, G_OBJECT(priv->storage)); break; case PROP_ACCOUNT_STORAGE: g_value_set_object(value, G_OBJECT(priv->account_storage)); break; case PROP_COMMUNICATION_MANAGER: g_value_set_object(value, G_OBJECT(priv->communication_manager)); break; case PROP_PRIVATE_KEY: g_value_set_pointer(value, priv->private_key); break; case PROP_CERTIFICATE: g_value_set_boxed(value, priv->certificate); break; case PROP_CHAT_SESSION: g_value_set_object(value, G_OBJECT(priv->chat_session)); break; case PROP_STATUS: g_value_set_enum(value, INF_BROWSER_OPEN); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } /* * InfCommunicationObject implementation. */ static InfCommunicationScope infd_directory_communication_object_received(InfCommunicationObject* object, InfXmlConnection* connection, const xmlNodePtr node) { InfdDirectory* directory; InfdDirectoryPrivate* priv; GError* local_error; xmlNodePtr reply_xml; gchar* seq; directory = INFD_DIRECTORY(object); priv = INFD_DIRECTORY_PRIVATE(directory); local_error = NULL; if(strcmp((const char*)node->name, "explore-node") == 0) { infd_directory_handle_explore_node( directory, connection, node, &local_error ); } else if(strcmp((const char*)node->name, "add-node") == 0) { infd_directory_handle_add_node( directory, connection, node, &local_error ); } else if(strcmp((const char*)node->name, "remove-node") == 0) { infd_directory_handle_remove_node( directory, connection, node, &local_error ); } else if(strcmp((const char*)node->name, "subscribe-session") == 0) { infd_directory_handle_subscribe_session( directory, connection, node, &local_error ); } else if(strcmp((const char*)node->name, "save-session") == 0) { infd_directory_handle_save_session( directory, connection, node, &local_error ); } else if(strcmp((const char*)node->name, "subscribe-chat") == 0) { infd_directory_handle_subscribe_chat( directory, connection, node, &local_error ); } else if(strcmp((const char*)node->name, "create-acl-account") == 0) { infd_directory_handle_create_acl_account( directory, connection, node, &local_error ); } else if(strcmp((const char*)node->name, "remove-acl-account") == 0) { infd_directory_handle_remove_acl_account( directory, connection, node, &local_error ); } else if(strcmp((const char*)node->name, "query-acl-account-list") == 0) { infd_directory_handle_query_acl_account_list( directory, connection, node, &local_error ); } else if(strcmp((const char*)node->name, "lookup-acl-accounts") == 0) { infd_directory_handle_lookup_acl_accounts( directory, connection, node, &local_error ); } else if(strcmp((const char*)node->name, "query-acl") == 0) { infd_directory_handle_query_acl( directory, connection, node, &local_error ); } else if(strcmp((const char*)node->name, "set-acl") == 0) { infd_directory_handle_set_acl( directory, connection, node, &local_error ); } else if(strcmp((const char*)node->name, "subscribe-ack") == 0) { /* Don't reply to subscribe-ack. */ infd_directory_handle_subscribe_ack( directory, connection, node, &local_error ); } else if(strcmp((const char*)node->name, "subscribe-nack") == 0) { /* Don't reply to subscribe-nack. */ infd_directory_handle_subscribe_nack( directory, connection, node, &local_error ); } else { g_set_error( &local_error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_UNEXPECTED_MESSAGE, "Received unexpected network message \"%s\"", (const gchar*)node->name ); } if(local_error != NULL) { /* TODO: If error is not from the InfDirectoryError error domain, the * client cannot reconstruct the error because he possibly does not know * the error domain (it might even come from a storage plugin). */ if(!infd_directory_make_seq(directory, connection, node, &seq, NULL)) seq = NULL; /* An error happened, so tell the client that the request failed and * what has gone wrong. */ reply_xml = inf_xml_util_new_node_from_error(local_error, NULL, "request-failed"); if(seq != NULL) inf_xml_util_set_attribute(reply_xml, "seq", seq); g_free(seq); inf_communication_group_send_message( INF_COMMUNICATION_GROUP(priv->group), connection, reply_xml ); g_error_free(local_error); } /* Never forward directory messages */ return INF_COMMUNICATION_SCOPE_PTP; } /* * InfBrowser implementation */ static void infd_directory_browser_subscribe_session(InfBrowser* browser, const InfBrowserIter* iter, InfSessionProxy* proxy, InfRequest* request) { InfdDirectoryNode* node; /* If iter is NULL then we are linking the global chat session, which is * already taken care of directly by infd_directory_enable_chat(), and * does not need any further handling here in the default handler. */ if(iter != NULL) { node = (InfdDirectoryNode*)iter->node; g_assert(INFD_IS_SESSION_PROXY(proxy)); g_assert(node->type == INFD_DIRECTORY_NODE_NOTE); g_assert(node->shared.note.session == NULL || (node->shared.note.session == INFD_SESSION_PROXY(proxy) && node->shared.note.weakref == TRUE)); g_object_ref(proxy); /* Re-link a previous session which was kept around by somebody else */ if(node->shared.note.session != NULL) { g_object_weak_unref( G_OBJECT(node->shared.note.session), infd_directory_session_weak_ref_cb, node ); } else { node->shared.note.session = INFD_SESSION_PROXY(proxy); } node->shared.note.weakref = FALSE; g_object_set_qdata( G_OBJECT(proxy), infd_directory_node_id_quark, GUINT_TO_POINTER(node->id) ); g_signal_connect( G_OBJECT(proxy), "notify::idle", G_CALLBACK(infd_directory_session_idle_notify_cb), INFD_DIRECTORY(browser) ); g_signal_connect( G_OBJECT(proxy), "reject-user-join", G_CALLBACK(infd_directory_session_reject_user_join_cb), INFD_DIRECTORY(browser) ); /* TODO: Drop the session if it gets closed; don't even weak-ref * it in that case */ if(infd_session_proxy_is_idle(node->shared.note.session)) { infd_directory_start_session_save_timeout(INFD_DIRECTORY(browser), node); } } } static void infd_directory_browser_unsubscribe_session(InfBrowser* browser, const InfBrowserIter* iter, InfSessionProxy* proxy, InfRequest* request) { InfdDirectory* directory; InfdDirectoryPrivate* priv; InfdDirectoryNode* node; directory = INFD_DIRECTORY(browser); priv = INFD_DIRECTORY_PRIVATE(directory); /* If iter is NULL then we are linking the global chat session, which is * already taken care of directly by infd_directory_enable_chat(), and * does not need any further handling here in the default handler. */ if(iter != NULL) { node = (InfdDirectoryNode*)iter->node; g_assert(INFD_IS_SESSION_PROXY(proxy)); g_assert(node->type == INFD_DIRECTORY_NODE_NOTE); g_assert(node->shared.note.session == INFD_SESSION_PROXY(proxy)); g_assert(node->shared.note.weakref == FALSE); /* Remove save timeout. We are just keeping a weak reference to the session * in order to be able to re-use it when it is requested again and if * someone else is going to keep it around anyway, but in all other regards * we behave like we have dropped the session fully from memory. */ if(node->shared.note.save_timeout != NULL) { inf_io_remove_timeout(priv->io, node->shared.note.save_timeout); node->shared.note.save_timeout = NULL; } g_object_weak_ref( G_OBJECT(node->shared.note.session), infd_directory_session_weak_ref_cb, node ); node->shared.note.weakref = TRUE; g_object_unref(node->shared.note.session); } } static gboolean infd_directory_browser_get_root(InfBrowser* browser, InfBrowserIter* iter) { InfdDirectory* directory; InfdDirectoryPrivate* priv; directory = INFD_DIRECTORY(browser); priv = INFD_DIRECTORY_PRIVATE(directory); iter->node_id = priv->root->id; iter->node = priv->root; return TRUE; } static gboolean infd_directory_browser_get_next(InfBrowser* browser, InfBrowserIter* iter) { InfdDirectory* directory; InfdDirectoryPrivate* priv; InfdDirectoryNode* node; directory = INFD_DIRECTORY(browser); priv = INFD_DIRECTORY_PRIVATE(directory); infd_directory_return_val_if_iter_fail(directory, iter, FALSE); node = (InfdDirectoryNode*)iter->node; node = node->next; if(node == NULL) return FALSE; iter->node_id = node->id; iter->node = node; return TRUE; } static gboolean infd_directory_browser_get_prev(InfBrowser* browser, InfBrowserIter* iter) { InfdDirectory* directory; InfdDirectoryPrivate* priv; InfdDirectoryNode* node; directory = INFD_DIRECTORY(browser); priv = INFD_DIRECTORY_PRIVATE(directory); infd_directory_return_val_if_iter_fail(directory, iter, FALSE); node = (InfdDirectoryNode*)iter->node; node = node->prev; if(node == NULL) return FALSE; iter->node_id = node->id; iter->node = node; return TRUE; } static gboolean infd_directory_browser_get_parent(InfBrowser* browser, InfBrowserIter* iter) { InfdDirectory* directory; InfdDirectoryPrivate* priv; InfdDirectoryNode* node; directory = INFD_DIRECTORY(browser); priv = INFD_DIRECTORY_PRIVATE(directory); infd_directory_return_val_if_iter_fail(directory, iter, FALSE); node = (InfdDirectoryNode*)iter->node; node = node->parent; if(node == NULL) return FALSE; iter->node_id = node->id; iter->node = node; return TRUE; } static gboolean infd_directory_browser_get_child(InfBrowser* browser, InfBrowserIter* iter) { InfdDirectory* directory; InfdDirectoryPrivate* priv; InfdDirectoryNode* node; directory = INFD_DIRECTORY(browser); priv = INFD_DIRECTORY_PRIVATE(directory); infd_directory_return_val_if_iter_fail(directory, iter, FALSE); node = (InfdDirectoryNode*)iter->node; g_return_val_if_fail(node->type == INFD_DIRECTORY_NODE_SUBDIRECTORY, FALSE); g_return_val_if_fail(node->shared.subdir.explored == TRUE, FALSE); node = node->shared.subdir.child; if(node == NULL) return FALSE; iter->node_id = node->id; iter->node = node; return TRUE; } static InfRequest* infd_directory_browser_explore(InfBrowser* browser, const InfBrowserIter* iter, InfRequestFunc func, gpointer user_data) { InfdDirectory* directory; InfdDirectoryPrivate* priv; InfdDirectoryNode* node; InfdProgressRequest* request; directory = INFD_DIRECTORY(browser); priv = INFD_DIRECTORY_PRIVATE(directory); infd_directory_return_val_if_iter_fail(directory, iter, NULL); node = (InfdDirectoryNode*)iter->node; g_return_val_if_fail(node->type == INFD_DIRECTORY_NODE_SUBDIRECTORY, NULL); g_return_val_if_fail(node->shared.subdir.explored == FALSE, NULL); request = g_object_new( INFD_TYPE_PROGRESS_REQUEST, "type", "explore-node", "node-id", node->id, "requestor", NULL, NULL ); if(func != NULL) { g_signal_connect_after( G_OBJECT(request), "finished", G_CALLBACK(func), user_data ); } inf_browser_begin_request(browser, iter, INF_REQUEST(request)); infd_directory_node_explore( directory, node, request, NULL ); g_object_unref(request); return NULL; } static gboolean infd_directory_browser_get_explored(InfBrowser* browser, const InfBrowserIter* iter) { InfdDirectory* directory; InfdDirectoryPrivate* priv; InfdDirectoryNode* node; directory = INFD_DIRECTORY(browser); priv = INFD_DIRECTORY_PRIVATE(directory); infd_directory_return_val_if_iter_fail(directory, iter, FALSE); node = (InfdDirectoryNode*)iter->node; g_return_val_if_fail(node->type == INFD_DIRECTORY_NODE_SUBDIRECTORY, FALSE); return node->shared.subdir.explored; } static gboolean infd_directory_browser_is_subdirectory(InfBrowser* browser, const InfBrowserIter* iter) { InfdDirectory* directory; InfdDirectoryPrivate* priv; InfdDirectoryNode* node; directory = INFD_DIRECTORY(browser); priv = INFD_DIRECTORY_PRIVATE(directory); infd_directory_return_val_if_iter_fail(directory, iter, FALSE); node = (InfdDirectoryNode*)iter->node; if(node->type != INFD_DIRECTORY_NODE_SUBDIRECTORY) return FALSE; return TRUE; } static InfRequest* infd_directory_browser_add_note(InfBrowser* browser, const InfBrowserIter* iter, const char* name, const char* type, const InfAclSheetSet* sheet_set, InfSession* session, gboolean initial_subscribe, InfRequestFunc func, gpointer user_data) { InfdDirectory* directory; InfdDirectoryPrivate* priv; InfdDirectoryNode* node; const InfdNotePlugin* plugin; InfdRequest* request; directory = INFD_DIRECTORY(browser); priv = INFD_DIRECTORY_PRIVATE(directory); infd_directory_return_val_if_iter_fail(directory, iter, NULL); node = (InfdDirectoryNode*)iter->node; g_return_val_if_fail(node->type == INFD_DIRECTORY_NODE_SUBDIRECTORY, NULL); g_return_val_if_fail(node->shared.subdir.explored == TRUE, NULL); plugin = infd_directory_lookup_plugin(directory, type); g_return_val_if_fail(plugin != NULL, NULL); request = g_object_new( INFD_TYPE_REQUEST, "type", "add-node", "node-id", node->id, "requestor", NULL, NULL ); if(func != NULL) { g_signal_connect_after( G_OBJECT(request), "finished", G_CALLBACK(func), user_data ); } inf_browser_begin_request(browser, iter, INF_REQUEST(request)); infd_directory_node_add_note( directory, node, request, name, sheet_set, plugin, session, NULL, FALSE, NULL, NULL ); g_object_unref(request); return NULL; } static InfRequest* infd_directory_browser_add_subdirectory(InfBrowser* browser, const InfBrowserIter* iter, const char* name, const InfAclSheetSet* sheet_set, InfRequestFunc func, gpointer user_data) { InfdDirectory* directory; InfdDirectoryPrivate* priv; InfdDirectoryNode* node; InfdRequest* request; directory = INFD_DIRECTORY(browser); priv = INFD_DIRECTORY_PRIVATE(directory); infd_directory_return_val_if_iter_fail(directory, iter, NULL); node = (InfdDirectoryNode*)iter->node; g_return_val_if_fail(node->type == INFD_DIRECTORY_NODE_SUBDIRECTORY, NULL); g_return_val_if_fail(node->shared.subdir.explored == TRUE, NULL); request = g_object_new( INFD_TYPE_REQUEST, "type", "add-node", "node-id", node->id, "requestor", NULL, NULL ); if(func != NULL) { g_signal_connect_after( G_OBJECT(request), "finished", G_CALLBACK(func), user_data ); } inf_browser_begin_request(browser, iter, INF_REQUEST(request)); infd_directory_node_add_subdirectory( directory, node, request, name, sheet_set, NULL, NULL, NULL ); g_object_unref(request); return NULL; } static InfRequest* infd_directory_browser_remove_node(InfBrowser* browser, const InfBrowserIter* iter, InfRequestFunc func, gpointer user_data) { InfdDirectory* directory; InfdDirectoryPrivate* priv; InfdDirectoryNode* node; InfdRequest* request; directory = INFD_DIRECTORY(browser); priv = INFD_DIRECTORY_PRIVATE(directory); infd_directory_return_val_if_iter_fail(directory, iter, NULL); node = (InfdDirectoryNode*)iter->node; request = g_object_new( INFD_TYPE_REQUEST, "type", "remove-node", "node-id", node->id, "requestor", NULL, NULL ); if(func != NULL) { g_signal_connect_after( G_OBJECT(request), "finished", G_CALLBACK(func), user_data ); } inf_browser_begin_request(browser, iter, INF_REQUEST(request)); infd_directory_node_remove(directory, node, request, NULL, NULL); g_object_unref(request); return NULL; } static const gchar* infd_directory_browser_get_node_name(InfBrowser* browser, const InfBrowserIter* iter) { InfdDirectory* directory; InfdDirectoryPrivate* priv; InfdDirectoryNode* node; directory = INFD_DIRECTORY(browser); priv = INFD_DIRECTORY_PRIVATE(directory); infd_directory_return_val_if_iter_fail(directory, iter, NULL); node = (InfdDirectoryNode*)iter->node; return node->name; } static const gchar* infd_directory_browser_get_node_type(InfBrowser* browser, const InfBrowserIter* iter) { InfdDirectory* directory; InfdDirectoryPrivate* priv; InfdDirectoryNode* node; directory = INFD_DIRECTORY(browser); priv = INFD_DIRECTORY_PRIVATE(directory); infd_directory_return_val_if_iter_fail(directory, iter, NULL); node = (InfdDirectoryNode*)iter->node; g_return_val_if_fail(node->type != INFD_DIRECTORY_NODE_SUBDIRECTORY, NULL); switch(node->type) { case INFD_DIRECTORY_NODE_SUBDIRECTORY: g_assert_not_reached(); return NULL; case INFD_DIRECTORY_NODE_NOTE: return node->shared.note.plugin->note_type; case INFD_DIRECTORY_NODE_UNKNOWN: return g_quark_to_string(node->shared.unknown.type); default: g_assert_not_reached(); return NULL; } } static InfRequest* infd_directory_browser_subscribe(InfBrowser* browser, const InfBrowserIter* iter, InfRequestFunc func, gpointer user_data) { InfdDirectory* directory; InfdDirectoryPrivate* priv; InfdDirectoryNode* node; InfdDirectorySubreq* subreq; InfdRequest* request; InfdSessionProxy* proxy; GSList* item; GError* error; directory = INFD_DIRECTORY(browser); priv = INFD_DIRECTORY_PRIVATE(directory); infd_directory_return_val_if_iter_fail(directory, iter, NULL); node = (InfdDirectoryNode*)iter->node; g_return_val_if_fail(node->type == INFD_DIRECTORY_NODE_NOTE, NULL); g_return_val_if_fail( node->shared.note.session == NULL || node->shared.note.weakref == TRUE, NULL ); /* See whether there is a subreq for this node. If yes, take the request * from there instead of creating a new one. Note that this usually does * not happen, since clients will ask for pending requests first, and if * a pending request exists, they will wait for it to finish. However, in * this case we support subscribing to a session while a subreq is still * pending, so that the session can be created immediately on the server * side if needed, without waiting for the client acknowledging or denying * the subscription. * * TODO: This is a bit of a flaw in the API. To fix this, we could allow * calling this function (and the other request functions) while a request * is already in progress, and document it such that in this case the * existing request will be used and the passed function added to it. * On the server side this would not require many changes, since there * are no requests other than subscribe-session that do not finish * immediately (at the moment). * * Only the client side functions would need to be changed such that they * return existing requests. This would also simplify using the API, because * no explicit checks for whether they are already pending requests would * be necessary. */ subreq = infd_directory_find_subreq_by_node_id( directory, INFD_DIRECTORY_SUBREQ_SESSION, node->id ); if(subreq != NULL) { request = subreq->shared.session.request; g_object_ref(request); } else { request = g_object_new( INFD_TYPE_REQUEST, "type", "subscribe-session", "node-id", node->id, "requestor", NULL, NULL ); } if(func != NULL) { g_signal_connect_after( G_OBJECT(request), "finished", G_CALLBACK(func), user_data ); } /* Emit begin-request if we created a new request */ if(subreq == NULL) { inf_browser_begin_request(browser, iter, INF_REQUEST(request)); } /* Take the session proxy from pending subscription requests, if any. Also, * remove the request reference from them, since we will finish the * request. */ proxy = NULL; for(item = priv->subscription_requests; item != NULL; item = item->next) { subreq = (InfdDirectorySubreq*)item->data; if(subreq->type == INFD_DIRECTORY_SUBREQ_SESSION) { if(subreq->node_id == node->id) { /* Note there can be more than one subreq */ g_assert(subreq->shared.session.request == request); g_object_unref(subreq->shared.session.request); subreq->shared.session.request = NULL; /* Get the session proxy from the subreq, to avoid making it * again. */ g_assert(proxy == NULL || proxy == subreq->shared.session.session); if(proxy == NULL) { proxy = subreq->shared.session.session; g_object_ref(proxy); } } } } /* If there was no subreq, create the session here */ error = NULL; if(proxy == NULL) { proxy = infd_directory_node_make_session(directory, node, &error); } if(proxy != NULL) { g_assert(error == NULL); infd_directory_node_link_session(directory, node, request, proxy); g_object_unref(proxy); inf_request_finish( INF_REQUEST(request), inf_request_result_make_subscribe_session( INF_BROWSER(directory), iter, INF_SESSION_PROXY(proxy) ) ); } else { g_assert(error != NULL); inf_request_fail(INF_REQUEST(request), error); g_error_free(error); } g_object_unref(request); return NULL; } static InfSessionProxy* infd_directory_browser_get_session(InfBrowser* browser, const InfBrowserIter* iter) { InfdDirectory* directory; InfdDirectoryPrivate* priv; InfdDirectoryNode* node; directory = INFD_DIRECTORY(browser); priv = INFD_DIRECTORY_PRIVATE(directory); infd_directory_return_val_if_iter_fail(directory, iter, NULL); node = (InfdDirectoryNode*)iter->node; g_return_val_if_fail(node->type != INFD_DIRECTORY_NODE_SUBDIRECTORY, NULL); if(node->type == INFD_DIRECTORY_NODE_UNKNOWN) return NULL; g_assert(node->type == INFD_DIRECTORY_NODE_NOTE); if(node->shared.note.session == NULL || node->shared.note.weakref == TRUE) return NULL; return INF_SESSION_PROXY(node->shared.note.session); } static GSList* infd_directory_browser_list_pending_requests(InfBrowser* browser, const InfBrowserIter* iter, const gchar* request_type) { InfdDirectory* directory; InfdDirectoryPrivate* priv; InfdDirectoryNode* node; InfdDirectorySubreq* subreq; InfRequest* request; gchar* type; gboolean right_type; GSList* list; GSList* item; directory = INFD_DIRECTORY(browser); priv = INFD_DIRECTORY_PRIVATE(directory); node = NULL; if(iter != NULL) { infd_directory_return_val_if_iter_fail(directory, iter, NULL); node = (InfdDirectoryNode*)iter->node; } list = NULL; for(item = priv->subscription_requests; item != NULL; item = item->next) { request = NULL; subreq = (InfdDirectorySubreq*)item->data; switch(subreq->type) { case INFD_DIRECTORY_SUBREQ_CHAT: break; case INFD_DIRECTORY_SUBREQ_SESSION: if(iter != NULL && subreq->node_id == node->id) request = INF_REQUEST(subreq->shared.session.request); break; case INFD_DIRECTORY_SUBREQ_ADD_NODE: if(iter != NULL && subreq->shared.add_node.parent == node) request = INF_REQUEST(subreq->shared.add_node.request); break; case INFD_DIRECTORY_SUBREQ_SYNC_IN: case INFD_DIRECTORY_SUBREQ_SYNC_IN_SUBSCRIBE: if(iter != NULL && subreq->shared.sync_in.parent == node) request = INF_REQUEST(subreq->shared.sync_in.request); break; default: g_assert_not_reached(); break; } if(request != NULL) { right_type = TRUE; if(request_type != NULL) { g_object_get(G_OBJECT(request), "type", &type, NULL); if(strcmp(type, request_type) != 0) right_type = FALSE; g_free(type); } if(right_type == TRUE) { if(g_slist_find(list, request) == NULL) list = g_slist_prepend(list, request); } } } return list; } static gboolean infd_directory_browser_iter_from_request(InfBrowser* browser, InfRequest* request, InfBrowserIter* iter) { InfdDirectory* directory; InfdDirectoryPrivate* priv; InfdDirectoryNode* node; guint node_id; directory = INFD_DIRECTORY(browser); priv = INFD_DIRECTORY_PRIVATE(directory); g_object_get(G_OBJECT(request), "node-id", &node_id, NULL); if(node_id == G_MAXUINT) return FALSE; node = g_hash_table_lookup(priv->nodes, GUINT_TO_POINTER(node_id)); if(node == NULL) return FALSE; iter->node_id = node_id; iter->node = node; return TRUE; } static const InfAclAccount* infd_directory_browser_get_acl_default_account(InfBrowser* browser) { InfdDirectory* directory; InfdDirectoryPrivate* priv; InfAclAccountId default_id; const InfdDirectoryTransientAccount* account; directory = INFD_DIRECTORY(browser); priv = INFD_DIRECTORY_PRIVATE(directory); default_id = inf_acl_account_id_from_string("default"); account = infd_directory_lookup_transient_account(directory, default_id); g_assert(account != NULL); return &account->account; } static const InfAclAccount* infd_directory_browser_get_acl_local_account(InfBrowser* browser) { /* There is no local account. This means direct access to the directory and * no ACL applies for local operations. */ return NULL; } static InfRequest* infd_directory_browser_query_acl_account_list(InfBrowser* browser, InfRequestFunc func, gpointer user_data) { InfdDirectory* directory; InfdDirectoryPrivate* priv; InfRequest* request; InfAclAccount* accounts; guint n_accounts; guint i; GError* error; directory = INFD_DIRECTORY(browser); priv = INFD_DIRECTORY_PRIVATE(directory); request = g_object_new( INFD_TYPE_PROGRESS_REQUEST, "type", "query-acl-account-list", "requestor", NULL, NULL ); if(func != NULL) { g_signal_connect_after( G_OBJECT(request), "finished", G_CALLBACK(func), user_data ); } inf_browser_begin_request(browser, NULL, INF_REQUEST(request)); if(priv->account_storage != NULL) { error = NULL; accounts = infd_account_storage_list_accounts( priv->account_storage, &n_accounts, &error ); if(error != NULL) { inf_request_fail(INF_REQUEST(request), error); g_object_unref(request); return NULL; } } else { accounts = NULL; n_accounts = 0; } infd_progress_request_initiated( INFD_PROGRESS_REQUEST(request), n_accounts + priv->n_transient_accounts ); accounts = g_realloc( accounts, sizeof(InfAclAccount) * (n_accounts + priv->n_transient_accounts) ); for(i = 0; i < priv->n_transient_accounts; ++i) accounts[n_accounts + i] = priv->transient_accounts[i].account; for(i = 0; i < n_accounts + priv->n_transient_accounts; ++i) infd_progress_request_progress(INFD_PROGRESS_REQUEST(request)); inf_request_finish( request, inf_request_result_make_query_acl_account_list( INF_BROWSER(browser), accounts, n_accounts + priv->n_transient_accounts, TRUE /* notifications */ ) ); g_object_unref(request); for(i = 0; i < n_accounts; ++i) g_free(accounts[i].name); g_free(accounts); return NULL; } static InfRequest* infd_directory_browser_lookup_acl_accounts(InfBrowser* browser, const InfAclAccountId* ids, guint n_ids, InfRequestFunc func, gpointer user_data) { InfdDirectory* directory; InfdDirectoryPrivate* priv; InfRequest* request; GArray* nontransient_ids; GPtrArray* transient_accounts; InfAclAccount* accounts; InfdDirectoryTransientAccount* transient; GError* error; guint i; directory = INFD_DIRECTORY(browser); priv = INFD_DIRECTORY_PRIVATE(directory); request = g_object_new( INFD_TYPE_REQUEST, "type", "lookup-acl-accounts", "requestor", NULL, NULL ); if(func != NULL) { g_signal_connect_after( G_OBJECT(request), "finished", G_CALLBACK(func), user_data ); } inf_browser_begin_request(browser, NULL, INF_REQUEST(request)); /* Lookup the transient IDs and build an array of non-transient IDs * that we are going to feed to the storage backend. */ nontransient_ids = g_array_sized_new( FALSE, FALSE, sizeof(InfAclAccountId), n_ids ); transient_accounts = g_ptr_array_new(); for(i = 0; i < n_ids; ++i) { transient = infd_directory_lookup_transient_account(directory, ids[i]); if(transient != NULL) g_ptr_array_add(transient_accounts, transient); else g_array_append_val(nontransient_ids, ids[i]); } if(priv->account_storage != NULL) { error = NULL; accounts = infd_account_storage_lookup_accounts( priv->account_storage, (InfAclAccountId*)nontransient_ids->data, nontransient_ids->len, &error ); if(error != NULL) { g_ptr_array_free(transient_accounts, TRUE); g_array_free(nontransient_ids, TRUE); inf_request_fail(INF_REQUEST(request), error); g_error_free(error); g_object_unref(request); return NULL; } for(i = 0; i < nontransient_ids->len; ++i) { if(accounts[i].id == 0) { accounts[i].id = g_array_index(nontransient_ids, InfAclAccountId, i); accounts[i].name = NULL; } } /* Add more space behind the array to add the transient accounts */ if(transient_accounts->len > 0) accounts = g_realloc(accounts, sizeof(InfAclAccount) * n_ids); } else { accounts = g_malloc(n_ids * sizeof(InfAclAccount)); for(i = 0; i < nontransient_ids->len; ++i) { accounts[i].id = g_array_index(nontransient_ids, InfAclAccountId, i); accounts[i].name = NULL; } } for(i = 0; i < transient_accounts->len; ++i) { transient = transient_accounts->pdata[i]; accounts[nontransient_ids->len + i] = transient->account; } inf_request_finish( request, inf_request_result_make_lookup_acl_accounts( INF_BROWSER(browser), accounts, n_ids ) ); g_ptr_array_free(transient_accounts, TRUE); g_array_free(nontransient_ids, TRUE); g_object_unref(request); for(i = 0; i < nontransient_ids->len; ++i) g_free(accounts[i].name); g_free(accounts); return NULL; } static InfRequest* infd_directory_browser_lookup_acl_account_by_name(InfBrowser* browser, const gchar* name, InfRequestFunc func, gpointer user_data) { InfdDirectory* directory; InfdDirectoryPrivate* priv; InfRequest* request; InfAclAccount* accounts; guint n_accounts; guint n_total; guint i; GError* error; directory = INFD_DIRECTORY(browser); priv = INFD_DIRECTORY_PRIVATE(directory); request = g_object_new( INFD_TYPE_REQUEST, "type", "lookup-acl-accounts", "requestor", NULL, NULL ); if(func != NULL) { g_signal_connect_after( G_OBJECT(request), "finished", G_CALLBACK(func), user_data ); } inf_browser_begin_request(browser, NULL, INF_REQUEST(request)); if(priv->account_storage != NULL) { accounts = infd_account_storage_lookup_accounts_by_name( priv->account_storage, name, &n_accounts, &error ); if(error != NULL) { inf_request_fail(INF_REQUEST(request), error); g_object_unref(request); g_error_free(error); return NULL; } } else { accounts = NULL; n_accounts = 0; } /* Add transient accounts */ n_total = n_accounts; for(i = 0; i < priv->n_transient_accounts; ++i) { if(priv->transient_accounts[i].account.name != NULL) { if(strcmp(priv->transient_accounts[i].account.name, name) == 0) { accounts = g_realloc(accounts, (n_total + 1) * sizeof(InfAclAccount)); accounts[n_total] = priv->transient_accounts[i].account; ++n_total; } } } if(n_total == 0) { accounts = g_realloc(accounts, sizeof(InfAclAccount)); accounts[0].id = 0; accounts[0].name = (gchar*)name; } inf_request_finish( request, inf_request_result_make_lookup_acl_accounts( INF_BROWSER(browser), accounts, n_total ) ); g_object_unref(request); /* Don't free transient account names */ for(i = 0; i < n_accounts; ++i) g_free(accounts[i].name); g_free(accounts); return NULL; } static InfRequest* infd_directory_browser_create_acl_account(InfBrowser* browser, gnutls_x509_crq_t crq, InfRequestFunc func, gpointer user_data) { GError* error; InfRequest* request; gnutls_x509_crt_t cert; gnutls_x509_crt_t* certs; InfCertificateChain* chain; InfAclAccount account; InfAclAccountId account_id; gchar* account_name; gboolean ret; request = g_object_new( INFD_TYPE_REQUEST, "type", "create-acl-account", "requestor", NULL, NULL ); if(func != NULL) { g_signal_connect_after( G_OBJECT(request), "finished", G_CALLBACK(func), user_data ); } inf_browser_begin_request(browser, NULL, INF_REQUEST(request)); error = NULL; cert = infd_directory_create_certificate_from_crq( INFD_DIRECTORY(browser), crq, 365 * DAYS, &error ); if(error != NULL) { inf_request_fail(request, error); g_object_unref(request); g_error_free(error); return NULL; } account_name = infd_directory_account_name_from_certificate(cert, &error); if(error != NULL) { gnutls_x509_crt_deinit(cert); inf_request_fail(request, error); g_object_unref(request); g_error_free(error); return NULL; } account_id = infd_directory_create_acl_account_with_certificate( INFD_DIRECTORY(browser), account_name, cert, NULL, &error ); if(error != NULL) { g_free(account_name); gnutls_x509_crt_deinit(cert); inf_request_fail(request, error); g_object_unref(request); g_error_free(error); return NULL; } certs = g_malloc(sizeof(gnutls_x509_crt_t)); *certs = cert; chain = inf_certificate_chain_new(certs, 1); account.id = account_id; account.name = account_name; inf_request_finish( request, inf_request_result_make_create_acl_account( INF_BROWSER(browser), &account, chain ) ); g_free(account_name); inf_certificate_chain_unref(chain); g_object_unref(request); return NULL; } static InfRequest* infd_directory_browser_remove_acl_account(InfBrowser* browser, InfAclAccountId account, InfRequestFunc func, gpointer user_data) { InfdDirectory* directory; InfdDirectoryPrivate* priv; InfdRequest* request; GError* error; directory = INFD_DIRECTORY(browser); priv = INFD_DIRECTORY_PRIVATE(directory); request = g_object_new( INFD_TYPE_REQUEST, "type", "remove-acl-account", "requestor", NULL, NULL ); if(func != NULL) { g_signal_connect_after( G_OBJECT(request), "finished", G_CALLBACK(func), user_data ); } inf_browser_begin_request(browser, NULL, INF_REQUEST(request)); error = NULL; /* Note this finishes the request if successful, but it does not fail * it on error. * TODO: This is not very nice, we should make this function such that it * does not take a request, and so that it returns all data that is needed * to finish the request, i.e. the InfAclAccount. Adapt other places... */ infd_directory_remove_acl_account( directory, account, NULL, NULL, request, &error ); if(error != NULL) { inf_request_fail(INF_REQUEST(request), error); g_error_free(error); g_object_unref(request); return NULL; } g_object_unref(request); return NULL; } static InfRequest* infd_directory_browser_query_acl(InfBrowser* browser, const InfBrowserIter* iter, InfRequestFunc func, gpointer user_data) { /* We always have the full ACL since we read it directly with the * exploration of a node. Therefore, there is nothing to query and the * full ACL is available with inf_browser_get_acl(). */ g_return_val_if_reached(NULL); return NULL; } static gboolean infd_directory_browser_has_acl(InfBrowser* browser, const InfBrowserIter* iter, InfAclAccountId account) { /* The full ACL is always available */ return TRUE; } static const InfAclSheetSet* infd_directory_browser_get_acl(InfBrowser* browser, const InfBrowserIter* iter) { InfdDirectory* directory; InfdDirectoryPrivate* priv; InfdDirectoryNode* node; directory = INFD_DIRECTORY(browser); priv = INFD_DIRECTORY_PRIVATE(directory); infd_directory_return_val_if_iter_fail(directory, iter, NULL); node = (InfdDirectoryNode*)iter->node; return node->acl; } static InfRequest* infd_directory_browser_set_acl(InfBrowser* browser, const InfBrowserIter* iter, const InfAclSheetSet* sheet_set, InfRequestFunc func, gpointer user_data) { InfdDirectory* directory; InfdDirectoryPrivate* priv; InfdDirectoryNode* node; InfdRequest* request; InfAclSheetSet* copy_set; GError* error; directory = INFD_DIRECTORY(browser); priv = INFD_DIRECTORY_PRIVATE(directory); infd_directory_return_val_if_iter_fail(directory, iter, NULL); node = (InfdDirectoryNode*)iter->node; request = g_object_new( INFD_TYPE_REQUEST, "type", "set-acl", "node-id", node->id, "requestor", NULL, NULL ); if(func != NULL) { g_signal_connect_after( G_OBJECT(request), "finished", G_CALLBACK(func), user_data ); } inf_browser_begin_request(browser, iter, INF_REQUEST(request)); error = NULL; if(infd_directory_verify_sheet_set(directory, sheet_set, &error) != TRUE) { inf_request_fail(INF_REQUEST(request), error); g_object_unref(request); g_error_free(error); return NULL; } /* Make sure the CAN_CREATE_ACCOUNT permission cannot be activated when * we cannot support it. */ if(node == priv->root) { copy_set = inf_acl_sheet_set_copy(sheet_set); inf_acl_sheet_set_sink(copy_set); if(infd_directory_report_support_in_sheets(directory, copy_set) == FALSE) { g_set_error_literal( &error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_OPERATION_UNSUPPORTED, _("This server does not support the requested permissions") ); inf_request_fail(INF_REQUEST(request), error); g_object_unref(request); g_error_free(error); inf_acl_sheet_set_free(copy_set); return NULL; } inf_acl_sheet_set_free(copy_set); } node->acl = inf_acl_sheet_set_merge_sheets(node->acl, sheet_set); if(node == priv->root) { priv->orig_root_acl = inf_acl_sheet_set_merge_sheets( priv->orig_root_acl, sheet_set ); } infd_directory_announce_acl_sheets( directory, node, request, sheet_set, NULL ); infd_directory_write_acl(directory, node); inf_request_finish( INF_REQUEST(request), inf_request_result_make_set_acl(INF_BROWSER(directory), iter) ); g_object_unref(request); return NULL; } /* * GType registration. */ static void infd_directory_class_init(InfdDirectoryClass* directory_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(directory_class); object_class->constructed = infd_directory_constructed; object_class->dispose = infd_directory_dispose; object_class->finalize = infd_directory_finalize; object_class->set_property = infd_directory_set_property; object_class->get_property = infd_directory_get_property; directory_class->connection_added = NULL; directory_class->connection_removed = NULL; infd_directory_node_id_quark = g_quark_from_static_string("INFD_DIRECTORY_NODE_ID"); g_object_class_install_property( object_class, PROP_IO, g_param_spec_object( "io", "IO", "IO object to watch sockets and schedule timeouts", INF_TYPE_IO, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_STORAGE, g_param_spec_object( "storage", "Storage backend", "The storage backend to use", INFD_TYPE_STORAGE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT ) ); g_object_class_install_property( object_class, PROP_ACCOUNT_STORAGE, g_param_spec_object( "account-storage", "Account Storage backend", "The account storage backend, to read available user accounts from", INFD_TYPE_ACCOUNT_STORAGE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT ) ); g_object_class_install_property( object_class, PROP_COMMUNICATION_MANAGER, g_param_spec_object( "communication-manager", "Communication manager", "The communication manager for the directory", INF_COMMUNICATION_TYPE_MANAGER, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_PRIVATE_KEY, g_param_spec_pointer( "private-key", "Private Key", "The private key of the server with which belongs to its certificate", G_PARAM_READWRITE ) ); g_object_class_install_property( object_class, PROP_CERTIFICATE, g_param_spec_boxed( "certificate", "Certificate", "The certificate chain of the server", INF_TYPE_CERTIFICATE_CHAIN, G_PARAM_READWRITE ) ); g_object_class_install_property( object_class, PROP_CHAT_SESSION, g_param_spec_object( "chat-session", "Chat session", "The server's chat session", INFD_TYPE_SESSION_PROXY, G_PARAM_READABLE ) ); /** * InfdDirectory::connection-added: * @directory: The #InfdDirectory emitting the signal. * @connection: The #InfXmlConnection that was added. * * This signal is emitted when a connection that is served by the * #InfdDirectory was added. The only way this can happen is by a call to * infd_directory_add_connection(). This can be done automatically by an * #InfdServerPool instance, however. **/ directory_signals[CONNECTION_ADDED] = g_signal_new( "connection-added", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfdDirectoryClass, connection_added), NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, INF_TYPE_XML_CONNECTION ); /** * InfdDirectory::connection-removed: * @directory: The #InfdDirectory emitting the signal. * @connection: The #InfXmlConnection that was removed. * * This signal is emitted when a connection stopes being served by * @directory. Usually this happens only when the connection is closed. **/ directory_signals[CONNECTION_REMOVED] = g_signal_new( "connection-removed", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfdDirectoryClass, connection_removed), NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, INF_TYPE_XML_CONNECTION ); g_object_class_override_property(object_class, PROP_STATUS, "status"); } static void infd_directory_communication_object_iface_init( InfCommunicationObjectInterface* iface) { iface->received = infd_directory_communication_object_received; } static void infd_directory_browser_iface_init(InfBrowserInterface* iface) { iface->error = NULL; iface->node_added = NULL; iface->node_removed = NULL; iface->subscribe_session = infd_directory_browser_subscribe_session; iface->unsubscribe_session = infd_directory_browser_unsubscribe_session; iface->begin_request = NULL; iface->acl_account_added = NULL; iface->acl_account_removed = NULL; iface->acl_local_account_changed = NULL; iface->acl_changed = NULL; iface->get_root = infd_directory_browser_get_root; iface->get_next = infd_directory_browser_get_next; iface->get_prev = infd_directory_browser_get_prev; iface->get_parent = infd_directory_browser_get_parent; iface->get_child = infd_directory_browser_get_child; iface->explore = infd_directory_browser_explore; iface->get_explored = infd_directory_browser_get_explored; iface->is_subdirectory = infd_directory_browser_is_subdirectory; iface->add_note = infd_directory_browser_add_note; iface->add_subdirectory = infd_directory_browser_add_subdirectory; iface->remove_node = infd_directory_browser_remove_node; iface->get_node_name = infd_directory_browser_get_node_name; iface->get_node_type = infd_directory_browser_get_node_type; iface->subscribe = infd_directory_browser_subscribe; iface->get_session = infd_directory_browser_get_session; iface->list_pending_requests = infd_directory_browser_list_pending_requests; iface->iter_from_request = infd_directory_browser_iter_from_request; iface->get_acl_default_account = infd_directory_browser_get_acl_default_account; iface->get_acl_local_account = infd_directory_browser_get_acl_local_account; iface->query_acl_account_list = infd_directory_browser_query_acl_account_list; iface->lookup_acl_accounts = infd_directory_browser_lookup_acl_accounts; iface->lookup_acl_account_by_name = infd_directory_browser_lookup_acl_account_by_name; iface->create_acl_account = infd_directory_browser_create_acl_account; iface->remove_acl_account = infd_directory_browser_remove_acl_account; iface->query_acl = infd_directory_browser_query_acl; iface->has_acl = infd_directory_browser_has_acl; iface->get_acl = infd_directory_browser_get_acl; iface->set_acl = infd_directory_browser_set_acl; } /* * Public API. */ /** * infd_directory_new: (constructor) * @io: IO object to watch connections and schedule timeouts. * @storage: Storage backend that is used to read/write notes from * permanent memory into #InfBuffer objects, or %NULL. * @comm_manager: A #InfCommunicationManager to register added * connections to and which forwards incoming data to the directory * or running sessions. * * Creates a new #InfdDirectory. If @storage is %NULL then the directory * keeps all content in memory. This can make sense for ad-hoc sessions where * no central document storage is required. * * Returns: (transfer full): A new #InfdDirectory. **/ InfdDirectory* infd_directory_new(InfIo* io, InfdStorage* storage, InfCommunicationManager* comm_manager) { GObject* object; g_return_val_if_fail(INF_IS_IO(io), NULL); g_return_val_if_fail(storage == NULL || INFD_IS_STORAGE(storage), NULL); g_return_val_if_fail(INF_COMMUNICATION_IS_MANAGER(comm_manager), NULL); object = g_object_new( INFD_TYPE_DIRECTORY, "io", io, "storage", storage, "communication-manager", comm_manager, NULL ); return INFD_DIRECTORY(object); } /** * infd_directory_get_io: * @directory: A #InfdDirectory. * * Returns the IO object in use by the directory. * * Returns: (transfer none): A #InfIo. **/ InfIo* infd_directory_get_io(InfdDirectory* directory) { g_return_val_if_fail(INFD_IS_DIRECTORY(directory), NULL); return INFD_DIRECTORY_PRIVATE(directory)->io; } /** * infd_directory_get_storage: * @directory: A #InfdDirectory: * * Returns the storage backend in use by the directory. * * Returns: (transfer none) (allow-none): An #InfdStorage. **/ InfdStorage* infd_directory_get_storage(InfdDirectory* directory) { g_return_val_if_fail(INFD_IS_DIRECTORY(directory), NULL); return INFD_DIRECTORY_PRIVATE(directory)->storage; } /** * infd_directory_get_communication_manager: * @directory: A #InfdDirectory. * * Returns the connection manager of the directory. * * Returns: (transfer none): An #InfCommunicationManager. **/ InfCommunicationManager* infd_directory_get_communication_manager(InfdDirectory* directory) { g_return_val_if_fail(INFD_IS_DIRECTORY(directory), NULL); return INFD_DIRECTORY_PRIVATE(directory)->communication_manager; } /** * infd_directory_set_certificate: * @directory: A #InfdDirectory. * @key: The private key of the directory. * @cert: (transfer none): The certificate chain of the directory. * * Sets the private key and certificate chain of the directory. The directory * does not use these for certificate authentication with added connections. * Connections should already be authenticated, for example with the means of * #InfXmppConnection. * * At the moment, the directory certificate is used to sign incoming * certificate requests. Selected clients can request a certificate signed * with the server's certificates, see inf_browser_create_acl_account(). * If the server certificate is set with this function, the request is handled * properly. If no certificate is set with this function, such a request is * rejected. */ void infd_directory_set_certificate(InfdDirectory* directory, gnutls_x509_privkey_t key, InfCertificateChain* cert) { InfdDirectoryPrivate* priv; guint i; InfAclAccountId account; const InfAclSheet* orig_sheet; const InfAclSheet* sheet; InfAclSheetSet* merge_sheets; InfAclSheet* merge_sheet; InfAclMask neg_mask; g_return_if_fail(INFD_IS_DIRECTORY(directory)); priv = INFD_DIRECTORY_PRIVATE(directory); /* TODO: assert that the key belongs to the certificate */ if(priv->certificate != NULL) inf_certificate_chain_unref(priv->certificate); priv->private_key = key; priv->certificate = cert; if(cert != NULL) inf_certificate_chain_ref(cert); g_object_notify(G_OBJECT(directory), "private-key"); g_object_notify(G_OBJECT(directory), "certificate"); infd_directory_update_root_acl(directory); } /** * infd_directory_add_plugin: * @directory: A #InfdDirectory. * @plugin: A #InfdNotePlugin. * * Adds @plugin to @directory. This allows the directory to create sessions * of the plugin's type. Only one plugin of each type can be added to the * directory. The plugin's storage_type must match the storage of @directory. * If the directory's storage is %NULL, then the plugin's storage type does * not matter, and the plugin's @session_read and @session_write functions * will not be used (and can therefore be %NULL). * * Returns: Whether the plugin was added successfully. **/ gboolean infd_directory_add_plugin(InfdDirectory* directory, const InfdNotePlugin* plugin) { InfdDirectoryPrivate* priv; GQuark note_type; GHashTableIter iter; gpointer value; InfdDirectoryNode* node; g_return_val_if_fail(INFD_IS_DIRECTORY(directory), FALSE); g_return_val_if_fail(plugin != NULL, FALSE); priv = INFD_DIRECTORY_PRIVATE(directory); g_return_val_if_fail( priv->storage == NULL || strcmp( plugin->storage_type, g_type_name(G_TYPE_FROM_INSTANCE(priv->storage)) ) == 0, FALSE ); if(g_hash_table_lookup(priv->plugins, plugin->note_type) != NULL) return FALSE; g_hash_table_insert( priv->plugins, /* cast const away without warning */ /* take addr -> char const * const * * cast -> void const * * cast -> void * const * * deref -> void * const */ *(const gpointer*)(gconstpointer)&plugin->note_type, *(gpointer*)(gpointer)&plugin ); /* Turn unknown nodes into known nodes */ note_type = g_quark_from_string(plugin->note_type); g_hash_table_iter_init(&iter, priv->nodes); while(g_hash_table_iter_next(&iter, NULL, &value)) { node = (InfdDirectoryNode*)value; if(node->type == INFD_DIRECTORY_NODE_UNKNOWN && node->shared.unknown.type == note_type) { node->type = INFD_DIRECTORY_NODE_NOTE; node->shared.note.session = NULL; node->shared.note.plugin = plugin; node->shared.note.save_timeout = NULL; node->shared.note.weakref = FALSE; } } return TRUE; } /** * infd_directory_remove_plugin: * @directory: A #InfdDirectory. * @plugin: The plugin to remove. * * Removes a note plugin from the directory. If there are any sessions running * using this plugin, they are unsubscribed from the directory. */ void infd_directory_remove_plugin(InfdDirectory* directory, const InfdNotePlugin* plugin) { InfdDirectoryPrivate* priv; GQuark note_type; GHashTableIter iter; gpointer value; InfdDirectoryNode* node; InfdSessionProxy* proxy; GSList* item; GSList* next; InfdDirectorySyncIn* sync_in; InfdDirectorySubreq* subreq; g_return_if_fail(INFD_IS_DIRECTORY(directory)); g_return_if_fail(plugin != NULL); priv = INFD_DIRECTORY_PRIVATE(directory); g_return_if_fail( g_hash_table_lookup(priv->plugins, plugin->note_type) == plugin ); /* Turn unknown nodes into known nodes */ note_type = g_quark_from_string(plugin->note_type); g_hash_table_iter_init(&iter, priv->nodes); while(g_hash_table_iter_next(&iter, NULL, &value)) { node = (InfdDirectoryNode*)value; if(node->type == INFD_DIRECTORY_NODE_NOTE && node->shared.note.plugin == plugin) { /* First, remove the note's session, if any */ if(node->shared.note.session != NULL && node->shared.note.weakref == FALSE) { infd_directory_node_unlink_session(directory, node, NULL); } if(node->shared.note.session != NULL) { infd_directory_release_session( directory, node, node->shared.note.session ); } g_assert(node->shared.note.session == NULL); g_assert(node->shared.note.plugin == plugin); g_assert(node->shared.note.save_timeout == NULL); g_assert(node->shared.note.weakref == FALSE); /* Then, change the type to unknown */ node->type = INFD_DIRECTORY_NODE_UNKNOWN; node->shared.unknown.type = g_quark_from_string(plugin->note_type); } } /* Remove all sync-ins with this plugin */ for(item = priv->sync_ins; item != NULL; item = next) { next = item->next; sync_in = (InfdDirectorySyncIn*)item->data; if(sync_in->plugin == plugin) infd_directory_remove_sync_in(directory, sync_in); } /* Remove plugin from all subscription requests, the requests will * subsequently fail in handle_subscribe_ack(). */ for(item = priv->subscription_requests; item != NULL; item = next) { next = item->next; subreq = (InfdDirectorySubreq*)item->data; switch(subreq->type) { case INFD_DIRECTORY_SUBREQ_CHAT: break; case INFD_DIRECTORY_SUBREQ_SESSION: break; case INFD_DIRECTORY_SUBREQ_ADD_NODE: if(subreq->shared.add_node.plugin == plugin) subreq->shared.add_node.plugin = NULL; break; case INFD_DIRECTORY_SUBREQ_SYNC_IN: case INFD_DIRECTORY_SUBREQ_SYNC_IN_SUBSCRIBE: if(subreq->shared.sync_in.plugin == plugin) subreq->shared.sync_in.plugin = NULL; break; default: g_assert_not_reached(); break; } } /* Finally, remove the plugin from the list of loaded plugins */ g_hash_table_remove(priv->plugins, plugin->note_type); } /** * infd_directory_lookup_plugin: * @directory: A #InfdDirectory. * @note_type: A note type for which to lookup the plugin. * * Returns the #InfdNotePlugin that handles the given note type, or %NULL * in case no corresponding plugin was added. * * Returns: (transfer none) (allow-none): A #InfdNotePlugin, or %NULL. **/ const InfdNotePlugin* infd_directory_lookup_plugin(InfdDirectory* directory, const gchar* note_type) { InfdDirectoryPrivate* priv; g_return_val_if_fail(INFD_IS_DIRECTORY(directory), NULL); g_return_val_if_fail(note_type != NULL, NULL); priv = INFD_DIRECTORY_PRIVATE(directory); return (const InfdNotePlugin*)g_hash_table_lookup(priv->plugins, note_type); } /** * infd_directory_add_connection: * @directory: A #InfdDirectory. * @connection: A #InfXmlConnection. * * Adds @connection to the connections of @directory. The directory will then * receive requests from @connection. If the directory's method manager does * not contain a "central" method for connection's network, then the * connection will not be added and the function returns %FALSE. * * The connection is removed again automatically if it is closed. * * Returns: Whether the connection was added to the directory. **/ gboolean infd_directory_add_connection(InfdDirectory* directory, InfXmlConnection* connection) { InfdDirectoryPrivate* priv; InfdDirectoryConnectionInfo* info; InfXmlConnectionStatus status; GHashTableIter iter; gpointer value; guint seq_id; g_return_val_if_fail(INFD_IS_DIRECTORY(directory), FALSE); g_return_val_if_fail(INF_IS_XML_CONNECTION(connection), FALSE); priv = INFD_DIRECTORY_PRIVATE(directory); g_return_val_if_fail(priv->communication_manager != NULL, FALSE); g_return_val_if_fail( g_hash_table_lookup(priv->connections, connection) == NULL, FALSE ); inf_communication_hosted_group_add_member(priv->group, connection); /* Find a free seq id */ seq_id = 1; g_hash_table_iter_init(&iter, priv->connections); while(g_hash_table_iter_next(&iter, NULL, &value)) { info = (InfdDirectoryConnectionInfo*)value; if(info->seq_id >= seq_id) seq_id = info->seq_id + 1; g_assert(seq_id > info->seq_id); /* check for overflow */ } info = g_slice_new(InfdDirectoryConnectionInfo); info->seq_id = seq_id; info->account_id = 0; g_hash_table_insert(priv->connections, connection, info); g_object_ref(connection); g_signal_connect( G_OBJECT(connection), "notify::status", G_CALLBACK(infd_directory_connection_notify_status_cb), directory ); g_object_get(G_OBJECT(connection), "status", &status, NULL); if(status == INF_XML_CONNECTION_OPEN) { info->account_id = infd_directory_login_by_certificate(directory, connection); infd_directory_send_welcome_message(directory, connection); } g_signal_emit( G_OBJECT(directory), directory_signals[CONNECTION_ADDED], 0, connection ); return TRUE; } /** * infd_directory_get_support_mask: * @directory: A #InfdDirectory. * @mask: (out): A pointer to a #InfAclMask that will be filled. * * This function writes all operations supported by @directory to @mask. If * an operation is unsupported by the server, the corresponding field in the * mask will not be set. */ void infd_directory_get_support_mask(InfdDirectory* directory, InfAclMask* mask) { InfAclSheet sheet; InfAclSheetSet set; g_return_if_fail(INFD_IS_DIRECTORY(directory)); g_return_if_fail(mask != NULL); sheet.account = 0; sheet.perms = INF_ACL_MASK_ALL; sheet.mask = INF_ACL_MASK_ALL; set.own_sheets = &sheet; set.sheets = &sheet; set.n_sheets = 1; infd_directory_report_support_in_sheets(directory, &set); *mask = sheet.perms; } /** * infd_directory_get_acl_account_for_connection: * @directory: A #InfdDirectory. * @connection: A @connection added to @directory. * * This function returns the #InfAclAccountId that the given connection is * logged into. The @connection must have been added to the directory before * with infd_directory_add_connection(). If no special login was performed, * the default account is returned. * * Returns: (transfer full): A #InfAclAccountId. */ InfAclAccountId infd_directory_get_acl_account_for_connection(InfdDirectory* directory, InfXmlConnection* connection) { InfdDirectoryPrivate* priv; InfdDirectoryConnectionInfo* info; g_return_val_if_fail(INFD_IS_DIRECTORY(directory), 0); g_return_val_if_fail(INF_IS_XML_CONNECTION(connection), 0); priv = INFD_DIRECTORY_PRIVATE(directory); info = (InfdDirectoryConnectionInfo*)g_hash_table_lookup( priv->connections, connection ); g_return_val_if_fail(info != NULL, 0); return info->account_id; } /** * infd_directory_set_acl_account_for_connection: * @directory: A #InfdDirectory. * @connection: A @connection added to @directory. * @account_id: A #InfAclAccountId representing a valid account in @directory. * @error: Location to store error information, if any, or %NULL. * * This function changes the account that the given connection is * logged into. The @connection must have been added to the directory before * with infd_directory_add_connection(). In order to remove a login, * @account_id should be set to the default account. * * The function might fail if there is no account that corresponds to * @account, or if the account storage reports an error when looking up the * account. * * Returns: %TRUE on success or %FALSE on error. */ gboolean infd_directory_set_acl_account_for_connection(InfdDirectory* directory, InfXmlConnection* connection, InfAclAccountId account_id, GError** error) { InfdDirectoryPrivate* priv; InfAclAccount* account; GError* local_error; g_return_val_if_fail(INFD_IS_DIRECTORY(directory), FALSE); g_return_val_if_fail(INF_IS_XML_CONNECTION(connection), FALSE); g_return_val_if_fail(account != 0, FALSE); priv = INFD_DIRECTORY_PRIVATE(directory); local_error = NULL; account = infd_directory_lookup_account( directory, account_id, NULL, &local_error ); if(local_error != NULL) { g_propagate_error(error, local_error); return FALSE; } if(account == NULL) { g_set_error( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_NO_SUCH_ACCOUNT, _("There is no such account with ID \"%s\""), inf_acl_account_id_to_string(account_id) ); return FALSE; } infd_directory_change_acl_account(directory, connection, account); inf_acl_account_free(account); return TRUE; } /** * infd_directory_foreach_connection: * @directory: A #InfdDirectory. * @func: (scope call): The function to call for each connection in * @directory. * @user_data: Additional data to pass to the callback function. * * Calls @func for each connection in @directory that has previously been * added to the directory. It is allowed to add and remove connections while * this function is being called. */ void infd_directory_foreach_connection(InfdDirectory* directory, InfdDirectoryForeachConnectionFunc func, gpointer userdata) { InfdDirectoryPrivate* priv; GList* keys; GList* item; g_return_if_fail(INFD_IS_DIRECTORY(directory)); g_return_if_fail(func != NULL); priv = INFD_DIRECTORY_PRIVATE(directory); keys = g_hash_table_get_keys(priv->connections); for(item = keys; item != NULL; item = item->next) { /* Make sure the entry still exists: */ if(g_hash_table_lookup(priv->connections, item->data) != NULL) func(INF_XML_CONNECTION(item->data), userdata); } g_list_free(keys); } /** * infd_directory_iter_save_session: * @directory: A #InfdDirectory. * @iter: A #InfBrowserIter pointing to a note in @directory. * @error: Location to store error information. * * Attempts to store the session the node @iter points to represents into the * background storage. * * Returns: %TRUE if the operation succeeded, %FALSE otherwise. */ gboolean infd_directory_iter_save_session(InfdDirectory* directory, const InfBrowserIter* iter, GError** error) { InfdDirectoryPrivate* priv; InfdDirectoryNode* node; gchar* path; InfSession* session; gboolean result; g_return_val_if_fail(INFD_IS_DIRECTORY(directory), FALSE); infd_directory_return_val_if_iter_fail(directory, iter, FALSE); priv = INFD_DIRECTORY_PRIVATE(directory); node = (InfdDirectoryNode*)iter->node; g_return_val_if_fail(node->type == INFD_DIRECTORY_NODE_NOTE, FALSE); if(priv->storage == NULL) { g_set_error_literal( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_NO_STORAGE, _("No background storage available") ); return FALSE; } infd_directory_node_get_path(node, &path, NULL); g_object_get( G_OBJECT(node->shared.note.session), "session", &session, NULL ); result = node->shared.note.plugin->session_write( priv->storage, session, path, node->shared.note.plugin->user_data, error ); /* TODO: Unset modified flag of buffer if result == TRUE */ g_object_unref(session); g_free(path); return result; } /** * infd_directory_enable_chat: * @directory: A #InfdDirectory. * @enable: Whether to enable or disable the chat. * * If @enable is %TRUE, this enables the chat on the server. This allows * clients subscribing to the chat via infc_browser_subscribe_chat(). If * @enable is %FALSE the chat is disabled which means closing an existing * chat session if any and no longer allowing subscription to the chat. * The chat is initially disabled. */ void infd_directory_enable_chat(InfdDirectory* directory, gboolean enable) { InfdDirectoryPrivate* priv; InfCommunicationHostedGroup* group; InfChatBuffer* chat_buffer; InfChatSession* chat_session; InfSession* session; /* TODO: For the moment, there only exist central methods anyway. In the * long term, this should probably be a property, though. */ static const gchar* const methods[] = { "central", NULL }; g_return_if_fail(INFD_IS_DIRECTORY(directory)); priv = INFD_DIRECTORY_PRIVATE(directory); if(enable) { if(priv->chat_session == NULL) { group = inf_communication_manager_open_group( priv->communication_manager, "InfChat", methods ); chat_buffer = inf_chat_buffer_new(256); chat_session = inf_chat_session_new( priv->communication_manager, chat_buffer, INF_SESSION_RUNNING, NULL, NULL ); g_object_unref(chat_buffer); priv->chat_session = INFD_SESSION_PROXY( g_object_new( INFD_TYPE_SESSION_PROXY, "io", priv->io, "session", chat_session, "subscription-group", group, NULL ) ); inf_communication_group_set_target( INF_COMMUNICATION_GROUP(group), INF_COMMUNICATION_OBJECT(priv->chat_session) ); g_object_unref(chat_session); g_object_unref(group); g_object_notify(G_OBJECT(directory), "chat-session"); inf_browser_subscribe_session( INF_BROWSER(directory), NULL, INF_SESSION_PROXY(priv->chat_session), NULL ); } } else { if(priv->chat_session != NULL) { inf_browser_unsubscribe_session( INF_BROWSER(directory), NULL, INF_SESSION_PROXY(priv->chat_session), NULL ); g_object_get(G_OBJECT(priv->chat_session), "session", &session, NULL); inf_session_close(session); g_object_unref(session); g_object_unref(priv->chat_session); priv->chat_session = NULL; g_object_notify(G_OBJECT(directory), "chat-session"); } } } /** * infd_directory_get_chat_session: * @directory: A #InfdDirectory. * * Returns a #InfdSessionProxy for the chat session, if any. If the chat is * enabled (see infd_directory_enable_chat()) this returns a #InfdSessionProxy * that can be used to join local users to the chat, or to get chat contents * (by getting the #InfChatBuffer from the proxy's #InfChatSession). If the * chat is disabled the function returns %NULL. * * Returns: (transfer none) (allow-none): A #InfdSessionProxy, or %NULL if * the chat is disabled. */ InfdSessionProxy* infd_directory_get_chat_session(InfdDirectory* directory) { g_return_val_if_fail(INFD_IS_DIRECTORY(directory), NULL); return INFD_DIRECTORY_PRIVATE(directory)->chat_session; } /** * infd_directory_create_acl_account: * @directory: A #InfdDirectory. * @account_name: The name of the new account. * @transient: Whether the account should be transient or not. * @certificates: (array length=n_certificates) (allow-none): An array of * certificates to be associated to the account, or %NULL. * @n_certificates: The number of certificates. * @error: Location to store error information, if any, or %NULL. * * Creates a new account on the directory with the given @account_name. If * the @certificates array is not empty and a clients connects with one of * the certificates, the client will automatically be logged into the account. * * If the @transient parameter is %TRUE then the account is made transient, * i.e. it will not be stored to permanent storage. When the server is * re-started, the account will no longer exist. If the parameter is %FALSE, * then the account is persistent. * * This function is similar to inf_browser_create_acl_account(), but it * allows more options. * * Returns: (transfer full): The account ID of the created account, or 0 * in case of error. */ InfAclAccountId infd_directory_create_acl_account(InfdDirectory* directory, const gchar* account_name, gboolean transient, gnutls_x509_crt_t* certificates, guint n_certificates, GError** error) { InfAclAccountId account_id; g_return_val_if_fail(INFD_IS_DIRECTORY(directory), 0); g_return_val_if_fail(account_name != NULL, 0); g_return_val_if_fail(certificates != NULL || n_certificates == 0, 0); account_id = infd_directory_create_acl_account_with_certificates( directory, account_name, transient, certificates, n_certificates, NULL, error ); return account_id; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/server/PaxHeaders.26529/infd-account-storage.h0000644000000000000000000000013213034342512023613 xustar0030 mtime=1483851082.041718492 30 atime=1483851082.041718492 30 ctime=1488261588.996139074 libinfinity-0.7.1/libinfinity/server/infd-account-storage.h0000644000175000017500000002465013034342512024354 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INFD_ACCOUNT_STORAGE_H__ #define __INFD_ACCOUNT_STORAGE_H__ #include #include #include G_BEGIN_DECLS #define INFD_TYPE_ACCOUNT_STORAGE (infd_account_storage_get_type()) #define INFD_ACCOUNT_STORAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INFD_TYPE_ACCOUNT_STORAGE, InfdAccountStorage)) #define INFD_IS_ACCOUNT_STORAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INFD_TYPE_ACCOUNT_STORAGE)) #define INFD_ACCOUNT_STORAGE_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), INFD_TYPE_ACCOUNT_STORAGE, InfdAccountStorageInterface)) /** * InfdAccountStorage: * * #InfdAccountStorage is an opaque data type. You should only access it * via the public API functions. */ typedef struct _InfdAccountStorage InfdAccountStorage; typedef struct _InfdAccountStorageInterface InfdAccountStorageInterface; /** * InfdAccountStorageSupport: * @INFD_ACCOUNT_STORAGE_SUPPORT_NOTIFICATION: Whether the * #InfdAccountStorage::account-added and #InfdAccountStorage::account-removed * signals are emitted when accounts are added or removed externally. * @INFD_ACCOUNT_STORAGE_SUPPORT_LIST_ACCOUNTS: Whether obtaining a full list * of available accounts is supported. * @INFD_ACCOUNT_STORAGE_SUPPORT_ADD_ACCOUNT: Whether adding a new account to * the storage is supported. * @INFD_ACCOUNT_STORAGE_SUPPORT_REMOVE_ACCOUNT: Whether removing an existing * account from the storage is supported. * @INFD_ACCOUNT_STORAGE_SUPPORT_CERTIFICATE_LOGIN: Whether the account * storage supports authenticating users via client certificates. * @INFD_ACCOUNT_STORAGE_SUPPORT_PASSWORD_LOGIN: Whether the account storage * supports authenticating users via username and password. * @INFD_ACCOUNT_STORAGE_SUPPORT_CERTIFICATE_CHANGE: Whether the account * storage supports changing the certificate associated to a user. * @INFD_ACCOUNT_STORAGE_SUPPORT_PASSWORD_CHANGE: Whether the account storage * supports changing a user's password. * * This enumeration specifies operations that might or might not be supported * by a particular #InfdAccountStorage implementation. Looking up an account * by ID or name must always be supported. */ typedef enum _InfdAccountStorageSupport { INFD_ACCOUNT_STORAGE_SUPPORT_NOTIFICATION = 1 << 0, INFD_ACCOUNT_STORAGE_SUPPORT_LIST_ACCOUNTS = 1 << 1, INFD_ACCOUNT_STORAGE_SUPPORT_ADD_ACCOUNT = 1 << 2, INFD_ACCOUNT_STORAGE_SUPPORT_REMOVE_ACCOUNT = 1 << 3, INFD_ACCOUNT_STORAGE_SUPPORT_CERTIFICATE_LOGIN = 1 << 4, INFD_ACCOUNT_STORAGE_SUPPORT_PASSWORD_LOGIN = 1 << 5, INFD_ACCOUNT_STORAGE_SUPPORT_CERTIFICATE_CHANGE = 1 << 6, INFD_ACCOUNT_STORAGE_SUPPORT_PASSWORD_CHANGE = 1 << 7 } InfdAccountStorageSupport; /** * InfdAccountStorageInterface: * @get_support: Virtual function to get the list of supported operations * on the backend. * @list_accounts: Virtual function to obtain a list of all available accounts. * Can be %NULL if not supported by the backend. * @lookup_accounts: Virtual function to look up account by their identifier. * @lookup_accounts_by_name: Virtual function to reverse-lookup an account * identifier when given the account name. * @add_account: Virtual function to add a new account. Can be %NULL if not * supported by the backend. * @remove_account: Virtual function to remove an existing account. Can be * %NULL if not supported by the backend. * @login_by_certificate: Virtual function to look up the account associated * with a given certificate. Can be %NULL if not supported by the backend. * @login_by_password: Virtual function to check a username and password, and * return the associated account. Can be %NULL if not supported by the * backend. * @set_certificate: Set the certificate to be associated to a given account, * or %NULL if not supported. * @set_password: Set the password for a given account, or %NULL if not * supported. * @account_added: Default signal handler for the * #InfdAccountStorage::account-added signal. * @account_removed: Default signal handler for the * #InfdAccountStorage::account-removed signal. * * The virtual methods and default signal handlers of #InfdAccountStorage. * Implementing these allows an infinote server to set a specific source of * user accounts. */ struct _InfdAccountStorageInterface { /*< private >*/ GTypeInterface parent; /*< public >*/ InfdAccountStorageSupport (*get_support)(InfdAccountStorage* storage); InfAclAccount* (*lookup_accounts)(InfdAccountStorage* storage, const InfAclAccountId* accounts, guint n_accounts, GError** error); InfAclAccount* (*lookup_accounts_by_name)(InfdAccountStorage* storage, const gchar* name, guint* n_accounts, GError** error); InfAclAccount* (*list_accounts)(InfdAccountStorage* storage, guint* n_accounts, GError** error); InfAclAccountId (*add_account)(InfdAccountStorage* storage, const gchar* name, gnutls_x509_crt_t* certs, guint n_certs, const gchar* password, GError** error); gboolean (*remove_account)(InfdAccountStorage* storage, InfAclAccountId account, GError** error); InfAclAccountId (*login_by_certificate)(InfdAccountStorage* storage, gnutls_x509_crt_t cert, GError** error); InfAclAccountId (*login_by_password)(InfdAccountStorage* storage, const gchar* username, const gchar* password, GError** error); gboolean (*set_certificate)(InfdAccountStorage* storage, InfAclAccountId account, gnutls_x509_crt_t* certs, guint n_certs, GError** error); gboolean (*set_password)(InfdAccountStorage* storage, InfAclAccountId account, const gchar* password, GError** error); /* Signals */ void (*account_added)(InfdAccountStorage* storage, const InfAclAccount* account); void (*account_removed)(InfdAccountStorage* storage, const InfAclAccount* account); }; GType infd_account_storage_support_get_type(void) G_GNUC_CONST; GType infd_account_storage_get_type(void) G_GNUC_CONST; InfdAccountStorageSupport infd_account_storage_get_support(InfdAccountStorage* storage); gboolean infd_account_storage_supports(InfdAccountStorage* storage, InfdAccountStorageSupport support); InfAclAccount* infd_account_storage_lookup_accounts(InfdAccountStorage* storage, const InfAclAccountId* accounts, guint n_accounts, GError** error); InfAclAccount* infd_account_storage_lookup_accounts_by_name(InfdAccountStorage* storage, const gchar* name, guint* n_accounts, GError** error); InfAclAccount* infd_account_storage_list_accounts(InfdAccountStorage* storage, guint* n_accounts, GError** error); InfAclAccountId infd_account_storage_add_account(InfdAccountStorage* storage, const gchar* name, gnutls_x509_crt_t* certs, guint n_certs, const gchar* password, GError** error); gboolean infd_account_storage_remove_account(InfdAccountStorage* storage, InfAclAccountId account, GError** error); InfAclAccountId infd_account_storage_login_by_certificate(InfdAccountStorage* storage, gnutls_x509_crt_t cert, GError** error); InfAclAccountId infd_account_storage_login_by_password(InfdAccountStorage* storage, const gchar* username, const gchar* password, GError** error); gboolean infd_account_storage_set_certificate(InfdAccountStorage* storage, InfAclAccountId account, gnutls_x509_crt_t* certs, guint n_certs, GError** error); gboolean infd_account_storage_set_password(InfdAccountStorage* storage, InfAclAccountId account, const gchar* password, GError** error); void infd_account_storage_account_added(InfdAccountStorage* storage, const InfAclAccount* account); void infd_account_storage_account_removed(InfdAccountStorage* storage, const InfAclAccount* account); G_END_DECLS #endif /* __INFD_ACCOUNT_STORAGE_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/server/PaxHeaders.26529/infd-directory.h0000644000000000000000000000013213034342512022521 xustar0030 mtime=1483851082.041718492 30 atime=1483851082.041718492 30 ctime=1488261589.000139066 libinfinity-0.7.1/libinfinity/server/infd-directory.h0000644000175000017500000001363313034342512023261 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INFD_DIRECTORY_H__ #define __INFD_DIRECTORY_H__ #include #include #include #include #include #include #include #include G_BEGIN_DECLS #define INFD_TYPE_DIRECTORY (infd_directory_get_type()) #define INFD_DIRECTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INFD_TYPE_DIRECTORY, InfdDirectory)) #define INFD_DIRECTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INFD_TYPE_DIRECTORY, InfdDirectoryClass)) #define INFD_IS_DIRECTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INFD_TYPE_DIRECTORY)) #define INFD_IS_DIRECTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INFD_TYPE_DIRECTORY)) #define INFD_DIRECTORY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INFD_TYPE_DIRECTORY, InfdDirectoryClass)) typedef struct _InfdDirectory InfdDirectory; typedef struct _InfdDirectoryClass InfdDirectoryClass; /** * InfdDirectoryClass: * @connection_added: Default signal handler for the * #InfdDirectory::connection-added signal. * @connection_removed: Default signal handler for the * #InfdDirectory::connection-removed signal. * * Default signal handlers for #InfdDirectory. */ struct _InfdDirectoryClass { /*< private >*/ GObjectClass parent_class; /*< public >*/ void (*connection_added)(InfdDirectory* directory, InfXmlConnection* connection); void (*connection_removed)(InfdDirectory* directory, InfXmlConnection* connection); }; /** * InfdDirectory: * * #InfdDirectory is an opaque data type. You should only access it via the * public API functions. */ struct _InfdDirectory { /*< private >*/ GObject parent; }; /** * InfdDirectoryForeachConnectionFunc: * @conn: The connection corresponding to the current iteration. * @user_data: Additional data passed to the call to * infd_directory_foreach_connection(). * * This is the signature of the callback function passed to * infd_directory_foreach_connection(). */ typedef void(*InfdDirectoryForeachConnectionFunc)(InfXmlConnection* conn, gpointer user_data); GType infd_directory_get_type(void) G_GNUC_CONST; InfdDirectory* infd_directory_new(InfIo* io, InfdStorage* storage, InfCommunicationManager* comm_manager); InfIo* infd_directory_get_io(InfdDirectory* directory); InfdStorage* infd_directory_get_storage(InfdDirectory* directory); InfCommunicationManager* infd_directory_get_communication_manager(InfdDirectory* directory); void infd_directory_set_certificate(InfdDirectory* directory, gnutls_x509_privkey_t key, InfCertificateChain* cert); gboolean infd_directory_add_plugin(InfdDirectory* directory, const InfdNotePlugin* plugin); void infd_directory_remove_plugin(InfdDirectory* directory, const InfdNotePlugin* plugin); const InfdNotePlugin* infd_directory_lookup_plugin(InfdDirectory* directory, const gchar* note_type); /* TODO: Add possibility to add ACL account here, either by InfAclAccount or account ID */ gboolean infd_directory_add_connection(InfdDirectory* directory, InfXmlConnection* connection); void infd_directory_get_support_mask(InfdDirectory* directory, InfAclMask* mask); InfAclAccountId infd_directory_get_acl_account_for_connection(InfdDirectory* directory, InfXmlConnection* connection); gboolean infd_directory_set_acl_account_for_connection(InfdDirectory* directory, InfXmlConnection* connection, InfAclAccountId account_id, GError** error); void infd_directory_foreach_connection(InfdDirectory* directory, InfdDirectoryForeachConnectionFunc func, gpointer user_data); gboolean infd_directory_iter_save_session(InfdDirectory* directory, const InfBrowserIter* iter, GError** error); void infd_directory_enable_chat(InfdDirectory* directory, gboolean enable); InfdSessionProxy* infd_directory_get_chat_session(InfdDirectory* directory); InfAclAccountId infd_directory_create_acl_account(InfdDirectory* directory, const gchar* account_name, gboolean transient, gnutls_x509_crt_t* certificates, guint n_certificates, GError** error); G_END_DECLS #endif /* __INFD_DIRECTORY_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/server/PaxHeaders.26529/infd-xml-server.h0000644000000000000000000000013213034342512022621 xustar0030 mtime=1483851082.045718513 30 atime=1483851082.045718513 30 ctime=1488261589.012139039 libinfinity-0.7.1/libinfinity/server/infd-xml-server.h0000644000175000017500000000454713034342512023365 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INFD_XML_SERVER_H__ #define __INFD_XML_SERVER_H__ #include #include G_BEGIN_DECLS #define INFD_TYPE_XML_SERVER (infd_xml_server_get_type()) #define INFD_XML_SERVER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INFD_TYPE_XML_SERVER, InfdXmlServer)) #define INFD_IS_XML_SERVER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INFD_TYPE_XML_SERVER)) #define INFD_XML_SERVER_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), INFD_TYPE_XML_SERVER, InfdXmlServerInterface)) #define INFD_TYPE_XML_SERVER_STATUS (infd_xml_server_status_get_type()) typedef struct _InfdXmlServer InfdXmlServer; typedef struct _InfdXmlServerInterface InfdXmlServerInterface; typedef enum _InfdXmlServerStatus { INFD_XML_SERVER_CLOSED, INFD_XML_SERVER_CLOSING, INFD_XML_SERVER_OPEN, INFD_XML_SERVER_OPENING } InfdXmlServerStatus; struct _InfdXmlServerInterface { GTypeInterface parent; /* Virtual Table */ void (*close)(InfdXmlServer* server); /* Signals */ void (*new_connection)(InfdXmlServer* server, InfXmlConnection* connection); }; GType infd_xml_server_status_get_type(void) G_GNUC_CONST; GType infd_xml_server_get_type(void) G_GNUC_CONST; void infd_xml_server_close(InfdXmlServer* server); void infd_xml_server_new_connection(InfdXmlServer* server, InfXmlConnection* connection); G_END_DECLS #endif /* __INFD_XML_SERVER_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/server/PaxHeaders.26529/infd-tcp-server.h0000644000000000000000000000013213034342512022607 xustar0030 mtime=1483851082.045718513 30 atime=1483851082.045718513 30 ctime=1488261589.012139039 libinfinity-0.7.1/libinfinity/server/infd-tcp-server.h0000644000175000017500000000552213034342512023345 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INFD_TCP_SERVER_H__ #define __INFD_TCP_SERVER_H__ #include #include G_BEGIN_DECLS #define INFD_TYPE_TCP_SERVER (infd_tcp_server_get_type()) #define INFD_TCP_SERVER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INFD_TYPE_TCP_SERVER, InfdTcpServer)) #define INFD_TCP_SERVER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INFD_TYPE_TCP_SERVER, InfdTcpServerClass)) #define INFD_IS_TCP_SERVER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INFD_TYPE_TCP_SERVER)) #define INFD_IS_TCP_SERVER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INFD_TYPE_TCP_SERVER)) #define INFD_TCP_SERVER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INFD_TYPE_TCP_SERVER, InfdTcpServerClass)) #define INFD_TYPE_TCP_SERVER_STATUS (infd_tcp_server_status_get_type()) typedef struct _InfdTcpServer InfdTcpServer; typedef struct _InfdTcpServerClass InfdTcpServerClass; typedef enum _InfdTcpServerStatus { INFD_TCP_SERVER_CLOSED, INFD_TCP_SERVER_BOUND, INFD_TCP_SERVER_OPEN } InfdTcpServerStatus; struct _InfdTcpServerClass { GObjectClass parent_class; /* Signals */ void (*new_connection)(InfdTcpServer* server, InfTcpConnection* connection); void (*error)(InfdTcpServer* server, GError* error); }; struct _InfdTcpServer { GObject parent; }; GType infd_tcp_server_status_get_type(void) G_GNUC_CONST; GType infd_tcp_server_get_type(void) G_GNUC_CONST; gboolean infd_tcp_server_bind(InfdTcpServer* server, GError** error); gboolean infd_tcp_server_open(InfdTcpServer* server, GError** error); void infd_tcp_server_close(InfdTcpServer* server); void infd_tcp_server_set_keepalive(InfdTcpServer* server, const InfKeepalive* keepalive); const InfKeepalive* infd_tcp_server_get_keepalive(InfdTcpServer* server); G_END_DECLS #endif /* __INFD_TCP_SERVER_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/server/PaxHeaders.26529/infd-filesystem-storage.c0000644000000000000000000000013213034342512024336 xustar0030 mtime=1483851082.041718492 30 atime=1483851082.041718492 30 ctime=1488261589.120138803 libinfinity-0.7.1/libinfinity/server/infd-filesystem-storage.c0000644000175000017500000007344313034342512025103 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include "config.h" #include #include #include #include #include #include #include #include #include #include #ifndef G_OS_WIN32 # include # include # include # include # include #endif typedef struct _InfdFilesystemStoragePrivate InfdFilesystemStoragePrivate; struct _InfdFilesystemStoragePrivate { gchar* root_directory; }; enum { PROP_0, PROP_ROOT_DIRECTORY }; #define INFD_FILESYSTEM_STORAGE_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INFD_TYPE_FILESYSTEM_STORAGE, InfdFilesystemStoragePrivate)) static GQuark infd_filesystem_storage_error_quark; static void infd_filesystem_storage_storage_iface_init(InfdStorageInterface* iface); G_DEFINE_TYPE_WITH_CODE(InfdFilesystemStorage, infd_filesystem_storage, G_TYPE_OBJECT, G_ADD_PRIVATE(InfdFilesystemStorage) G_IMPLEMENT_INTERFACE(INFD_TYPE_STORAGE, infd_filesystem_storage_storage_iface_init)) /* Checks whether path is valid, and sets error if not */ static gboolean infd_filesystem_storage_verify_path(const gchar* path, GError** error) { gchar** components; gchar** component; if(path[0] != '/') { g_set_error_literal( error, infd_filesystem_storage_error_quark, INFD_FILESYSTEM_STORAGE_ERROR_INVALID_PATH, _("The path does not start with \"/\"") ); } components = g_strsplit(path + 1, "/", 0); for(component = components; *component != NULL; ++ component) { if(**component == '\0' || strcmp(*component, ".") == 0 || strcmp(*component, "..") == 0) { g_set_error_literal( error, infd_filesystem_storage_error_quark, INFD_FILESYSTEM_STORAGE_ERROR_INVALID_PATH, _("The path contains invalid components") ); g_strfreev(components); return FALSE; } } g_strfreev(components); return TRUE; } static void infd_filesystem_storage_set_root_directory(InfdFilesystemStorage* storage, const gchar* root_directory) { InfdFilesystemStoragePrivate* priv; gchar* converted; GError* error; priv = INFD_FILESYSTEM_STORAGE_PRIVATE(storage); error = NULL; converted = g_filename_from_utf8(root_directory, -1, NULL, NULL, &error); /* TODO: We should somehow report at least this error further upwards, and * let the user decide what to do. */ if(converted == NULL) { g_warning( _("Failed to convert root directory to filename encoding: %s"), error->message ); g_error_free(error); } else { if (!g_path_is_absolute(converted)) { gchar* cwd = g_get_current_dir(); gchar* full_path = g_build_filename(cwd, converted, NULL); g_free(cwd); g_free(converted); converted = full_path; } if(!inf_file_util_create_directory(converted, 0755, &error)) { g_warning( _("Failed to create root directory: %s\n" "Subsequent storage operations will most likely fail\n"), error->message ); g_error_free(error); } g_free(priv->root_directory); priv->root_directory = converted; } } static void infd_filesystem_storage_system_error(int code, GError** error) { g_set_error_literal( error, G_FILE_ERROR, g_file_error_from_errno(code), g_strerror(code) ); } static int infd_filesystem_storage_read_xml_stream_read_func(void* context, char* buffer, int len) { int res; res = fread(buffer, 1, len, (FILE*)context); if(ferror((FILE*)context)) return -1; return res; } static int infd_filesystem_storage_read_xml_stream_close_func(void* context) { return fclose((FILE*)context); } /* The following functions don't check the given path, and should only be used * when it has been checked before with infd_filesystem_storage_verify_path(). * The public functions do check the path before calling any of these. */ static FILE* infd_filesystem_storage_open_impl(InfdFilesystemStorage* storage, const gchar* path, const gchar* mode, GError** error) { FILE* res; int save_errno; #ifndef G_OS_WIN32 int fd; int open_mode; #endif #ifdef G_OS_WIN32 res = g_fopen(path, mode); #else if(strcmp(mode, "r") == 0) open_mode = O_RDONLY; else if(strcmp(mode, "w") == 0) open_mode = O_CREAT | O_WRONLY | O_TRUNC; else g_assert_not_reached(); fd = open(path, O_NOFOLLOW | open_mode, 0644); if(fd == -1) res = NULL; else res = fdopen(fd, mode); #endif save_errno = errno; if(res == NULL) { infd_filesystem_storage_system_error(save_errno, error); return NULL; } return res; } xmlDocPtr infd_filesystem_storage_read_xml_file_impl(InfdFilesystemStorage* storage, const gchar* path, const gchar* toplevel_tag, GError** error) { FILE* file; gchar* uri; xmlDocPtr doc; xmlNodePtr root; xmlErrorPtr xmlerror; file = infd_filesystem_storage_open_impl(storage, path, "r", error); if(file == NULL) return NULL; uri = g_filename_to_uri(path, NULL, error); if(uri == NULL) { fclose(file); return NULL; } doc = xmlReadIO( infd_filesystem_storage_read_xml_stream_read_func, infd_filesystem_storage_read_xml_stream_close_func, file, uri, "UTF-8", XML_PARSE_NOWARNING | XML_PARSE_NOERROR ); g_free(uri); if(doc == NULL) { xmlerror = xmlGetLastError(); g_set_error( error, g_quark_from_static_string("LIBXML2_PARSER_ERROR"), xmlerror->code, _("Error parsing XML in file \"%s\": [%d]: %s"), xmlerror->file, xmlerror->line, xmlerror->message ); } else if(toplevel_tag != NULL) { root = xmlDocGetRootElement(doc); if(root == NULL || strcmp((const char*)root->name, toplevel_tag) != 0) { g_set_error( error, infd_filesystem_storage_error_quark, INFD_FILESYSTEM_STORAGE_ERROR_INVALID_FORMAT, _("Error processing file \"%s\": Toplevel tag is not \"%s\""), doc->name, toplevel_tag ); xmlFreeDoc(doc); doc = NULL; } } return doc; } gboolean infd_filesystem_storage_write_xml_file_impl(InfdFilesystemStorage* storage, const gchar* path, xmlDocPtr doc, GError** error) { InfdFilesystemStoragePrivate* priv; FILE* file; int save_errno; xmlErrorPtr xmlerror; priv = INFD_FILESYSTEM_STORAGE_PRIVATE(storage); file = infd_filesystem_storage_open_impl(storage, path, "w", error); if(file == NULL) return FALSE; if(xmlDocFormatDump(file, doc, 1) == -1) { xmlerror = xmlGetLastError(); fclose(file); /* TODO: unlink? */ g_set_error_literal( error, g_quark_from_static_string("LIBXML2_OUTPUT_ERROR"), xmlerror->code, xmlerror->message ); return FALSE; } if(fclose(file) != 0) { save_errno = errno; infd_filesystem_storage_system_error(save_errno, error); return FALSE; } return TRUE; } static gchar* infd_filesystem_storage_get_acl_path(InfdFilesystemStorage* storage, const gchar* path, GError** error) { gchar* full_path; if(strcmp(path, "/") != 0) { full_path = infd_filesystem_storage_get_path(storage, "xml.acl", path, error); } else { full_path = infd_filesystem_storage_get_path(storage, "xml", "/global-acl", error); } return full_path; } static void infd_filesystem_storage_init(InfdFilesystemStorage* storage) { InfdFilesystemStoragePrivate* priv; priv = INFD_FILESYSTEM_STORAGE_PRIVATE(storage); priv->root_directory = NULL; } static void infd_filesystem_storage_finalize(GObject* object) { InfdFilesystemStorage* storage; InfdFilesystemStoragePrivate* priv; storage = INFD_FILESYSTEM_STORAGE(object); priv = INFD_FILESYSTEM_STORAGE_PRIVATE(storage); g_free(priv->root_directory); G_OBJECT_CLASS(infd_filesystem_storage_parent_class)->finalize(object); } static void infd_filesystem_storage_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfdFilesystemStorage* storage; InfdFilesystemStoragePrivate* priv; storage = INFD_FILESYSTEM_STORAGE(object); priv = INFD_FILESYSTEM_STORAGE_PRIVATE(storage); switch(prop_id) { case PROP_ROOT_DIRECTORY: infd_filesystem_storage_set_root_directory( storage, g_value_get_string(value) ); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void infd_filesystem_storage_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfdFilesystemStorage* storage; InfdFilesystemStoragePrivate* priv; storage = INFD_FILESYSTEM_STORAGE(object); priv = INFD_FILESYSTEM_STORAGE_PRIVATE(storage); switch(prop_id) { case PROP_ROOT_DIRECTORY: g_value_set_string(value, priv->root_directory); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static gboolean infd_filesystem_storage_storage_read_subdirectory_list_func(const gchar* name, const gchar* path, InfFileType type, gpointer data, GError** error) { GSList** list; gchar* converted_name; gsize name_len; gchar* separator; list = (GSList**)data; converted_name = g_filename_to_utf8(name, -1, NULL, &name_len, error); if(converted_name == NULL) return FALSE; if(type == INF_FILE_TYPE_DIR) { *list = g_slist_prepend( *list, infd_storage_node_new_subdirectory(converted_name) ); } else if(type == INF_FILE_TYPE_REG) { /* The note type identifier is behind the last '.'. Only note * types starting with "Inf" are recognized, other files are * auxiliary files in the directory. */ separator = g_strrstr_len(converted_name, name_len, "."); if(separator != NULL && strncmp(separator + 1, "Inf", 3) == 0) { *separator = '\0'; *list = g_slist_prepend( *list, infd_storage_node_new_note(converted_name, separator + 1) ); } } g_free(converted_name); return TRUE; } static GSList* infd_filesystem_storage_storage_read_subdirectory(InfdStorage* storage, const gchar* path, GError** error) { InfdFilesystemStorage* fs_storage; InfdFilesystemStoragePrivate* priv; GSList* list; gchar* converted_name; gchar* full_name; gboolean result; fs_storage = INFD_FILESYSTEM_STORAGE(storage); priv = INFD_FILESYSTEM_STORAGE_PRIVATE(fs_storage); if(infd_filesystem_storage_verify_path(path, error) == FALSE) return NULL; converted_name = g_filename_from_utf8(path, -1, NULL, NULL, error); if(converted_name == NULL) return NULL; full_name = g_build_filename(priv->root_directory, converted_name, NULL); g_free(converted_name); list = NULL; result = inf_file_util_list_directory( full_name, infd_filesystem_storage_storage_read_subdirectory_list_func, &list, error ); g_free(full_name); if(result == FALSE) { infd_storage_node_list_free(list); return NULL; } return list; } static gboolean infd_filesystem_storage_storage_create_subdirectory(InfdStorage* storage, const gchar* path, GError** error) { InfdFilesystemStorage* fs_storage; InfdFilesystemStoragePrivate* priv; gchar* converted_name; gchar* full_name; gboolean result; fs_storage = INFD_FILESYSTEM_STORAGE(storage); priv = INFD_FILESYSTEM_STORAGE_PRIVATE(fs_storage); if(infd_filesystem_storage_verify_path(path, error) == FALSE) return FALSE; converted_name = g_filename_from_utf8(path, -1, NULL, NULL, error); if(converted_name == NULL) return FALSE; full_name = g_build_filename(priv->root_directory, converted_name, NULL); g_free(converted_name); result = inf_file_util_create_single_directory(full_name, 0755, error); g_free(full_name); return result; } static gboolean infd_filesystem_storage_storage_remove_node(InfdStorage* storage, const gchar* identifier, const gchar* path, GError** error) { InfdFilesystemStorage* fs_storage; InfdFilesystemStoragePrivate* priv; gchar* converted_name; gchar* disk_name; gchar* full_name; gboolean result; int save_errno; fs_storage = INFD_FILESYSTEM_STORAGE(storage); priv = INFD_FILESYSTEM_STORAGE_PRIVATE(fs_storage); if(infd_filesystem_storage_verify_path(path, error) == FALSE) return FALSE; converted_name = g_filename_from_utf8(path, -1, NULL, NULL, error); if(converted_name == NULL) return FALSE; if(identifier != NULL) { disk_name = g_strconcat(converted_name, ".", identifier, NULL); } else { disk_name = converted_name; } full_name = g_build_filename(priv->root_directory, disk_name, NULL); if(disk_name != converted_name) g_free(disk_name); result = inf_file_util_delete(full_name, error); g_free(full_name); if(result == TRUE) { disk_name = g_strconcat(converted_name, ".xml.acl", NULL); full_name = g_build_filename(priv->root_directory, disk_name, NULL); g_free(disk_name); if(g_unlink(full_name) == -1) { save_errno = errno; if(save_errno != ENOENT) { infd_filesystem_storage_system_error(save_errno, error); result = FALSE; } } g_free(full_name); } g_free(converted_name); return result; } static GSList* infd_filesystem_storage_storage_read_acl(InfdStorage* storage, const gchar* path, GError** error) { InfdFilesystemStorage* fs_storage; InfdFilesystemStoragePrivate* priv; gchar* full_path; GError* local_error; xmlDocPtr doc; xmlNodePtr root; xmlNodePtr child; GSList* list; InfdStorageAcl* acl; xmlChar* account_id; fs_storage = INFD_FILESYSTEM_STORAGE(storage); priv = INFD_FILESYSTEM_STORAGE_PRIVATE(storage); full_path = infd_filesystem_storage_get_acl_path(fs_storage, path, error); if(full_path == NULL) return NULL; local_error = NULL; doc = infd_filesystem_storage_read_xml_file_impl( fs_storage, full_path, "inf-acl", &local_error ); g_free(full_path); if(local_error != NULL) { if(local_error->domain == G_FILE_ERROR && local_error->code == G_FILE_ERROR_NOENT) { /* The ACL file does not exist. This is not an error, but just means * the ACL is empty. */ g_error_free(local_error); return NULL; } g_propagate_error(error, local_error); return NULL; } root = xmlDocGetRootElement(doc); list = NULL; for(child = root->children; child != NULL; child = child->next) { if(child->type != XML_ELEMENT_NODE) continue; if(strcmp((const char*)child->name, "sheet") == 0) { account_id = inf_xml_util_get_attribute_required(child, "account", error); if(account_id == NULL) { infd_storage_acl_list_free(list); xmlFreeDoc(doc); return NULL; } acl = g_slice_new(InfdStorageAcl); acl->account_id = g_strdup((const gchar*)account_id); xmlFree(account_id); if(!inf_acl_sheet_perms_from_xml(child, &acl->mask, &acl->perms, error)) { g_free(acl->account_id); g_slice_free(InfdStorageAcl, acl); infd_storage_acl_list_free(list); xmlFreeDoc(doc); return NULL; } if(!inf_acl_mask_empty(&acl->mask)) { list = g_slist_prepend(list, acl); } else { g_free(acl->account_id); g_slice_free(InfdStorageAcl, acl); } } } xmlFreeDoc(doc); return list; } static gboolean infd_filesystem_storage_storage_write_acl(InfdStorage* storage, const gchar* path, const InfAclSheetSet* sheet_set, GError** error) { InfdFilesystemStorage* fs_storage; InfdFilesystemStoragePrivate* priv; gchar* full_path; xmlNodePtr root; xmlNodePtr child; guint i; xmlDocPtr doc; gboolean result; int save_errno; fs_storage = INFD_FILESYSTEM_STORAGE(storage); priv = INFD_FILESYSTEM_STORAGE_PRIVATE(storage); full_path = infd_filesystem_storage_get_acl_path(fs_storage, path, error); if(full_path == NULL) return FALSE; root = NULL; if(sheet_set != NULL) { root = xmlNewNode(NULL, (const xmlChar*)"inf-acl"); for(i = 0; i < sheet_set->n_sheets; ++i) { if(!inf_acl_mask_empty(&sheet_set->sheets[i].mask)) { child = xmlNewChild(root, NULL, (const xmlChar*)"sheet", NULL); inf_xml_util_set_attribute( child, "account", inf_acl_account_id_to_string(sheet_set->sheets[i].account) ); inf_acl_sheet_perms_to_xml( &sheet_set->sheets[i].mask, &sheet_set->sheets[i].perms, child ); } } if(root->children == NULL) { xmlFreeNode(root); root = NULL; } } if(root == NULL) { if(g_unlink(full_path) == -1) { save_errno = errno; if(save_errno != ENOENT) { g_free(full_path); infd_filesystem_storage_system_error(save_errno, error); return FALSE; } } } else { doc = xmlNewDoc((const xmlChar*)"1.0"); xmlDocSetRootElement(doc, root); result = infd_filesystem_storage_write_xml_file_impl( INFD_FILESYSTEM_STORAGE(storage), full_path, doc, error ); xmlFreeDoc(doc); if(result == FALSE) { g_free(full_path); return FALSE; } } g_free(full_path); return TRUE; } static void infd_filesystem_storage_class_init( InfdFilesystemStorageClass* filesystem_storage_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(filesystem_storage_class); object_class->finalize = infd_filesystem_storage_finalize; object_class->set_property = infd_filesystem_storage_set_property; object_class->get_property = infd_filesystem_storage_get_property; infd_filesystem_storage_error_quark = g_quark_from_static_string( "INFD_FILESYSTEM_STORAGE_ERROR" ); g_object_class_install_property( object_class, PROP_ROOT_DIRECTORY, g_param_spec_string( "root-directory", "Root directory", "The directory in which the storage stores its content", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); } static void infd_filesystem_storage_storage_iface_init(InfdStorageInterface* iface) { iface->read_subdirectory = infd_filesystem_storage_storage_read_subdirectory; iface->create_subdirectory = infd_filesystem_storage_storage_create_subdirectory; iface->remove_node = infd_filesystem_storage_storage_remove_node; iface->read_acl = infd_filesystem_storage_storage_read_acl; iface->write_acl = infd_filesystem_storage_storage_write_acl; } /** * infd_filesystem_storage_new: (constructor) * @root_directory: A directory name in UTF-8. * * Creates a new #InfdFilesystemStorage that stores its nodes in the * given directory on the file system. The directory is created if it does * not exist. * * Returns: (transfer full): A new #InfdFilesystemStorage. **/ InfdFilesystemStorage* infd_filesystem_storage_new(const gchar* root_directory) { GObject* object; object = g_object_new( INFD_TYPE_FILESYSTEM_STORAGE, "root-directory", root_directory, NULL ); return INFD_FILESYSTEM_STORAGE(object); } /** * infd_filesystem_storage_get_path: * @storage: A #InfdFilesystemStorage. * @identifier: The type of node to open. * @path: The path to open, in UTF-8. * @error: Location to store error information, if any, or %NULL. * * Returns the full file name to the given path within the storage's root * directory. The function might fail if @path contains invalid characters. * If the function fails, %NULL is returned and @error is set. * * Only if @identifier starts with "Inf", the file will show up in * the directory listing of infd_storage_read_subdirectory(). Other * identifiers can be used to store custom data in the filesystem, linked to * this #InfdFilesystemStorage object. * * Returns: (type filename) (allow-none) (transfer full): An absolute * filename path to be freed with g_free(), or %NULL. */ gchar* infd_filesystem_storage_get_path(InfdFilesystemStorage* storage, const gchar* identifier, const gchar* path, GError** error) { InfdFilesystemStoragePrivate* priv; gchar* converted_name; gchar* disk_name; gchar* full_name; priv = INFD_FILESYSTEM_STORAGE_PRIVATE(storage); if(infd_filesystem_storage_verify_path(path, error) == FALSE) return NULL; converted_name = g_filename_from_utf8(path, -1, NULL, NULL, error); if(converted_name == NULL) return NULL; disk_name = g_strconcat(converted_name, ".", identifier, NULL); g_free(converted_name); full_name = g_build_filename(priv->root_directory, disk_name, NULL); g_free(disk_name); return full_name; } /** * infd_filesystem_storage_open: * @storage: A #InfdFilesystemStorage. * @identifier: The type of node to open. * @path: The path to open, in UTF-8. * @mode: Either "r" for reading or "w" for writing. * @full_path: (out) (type filename) (transfer full): Return location * of the full filename, or %NULL. * @error: Location to store error information, if any. * * Opens a file in the given path within the storage's root directory. If * the file exists already, and @mode is set to "w", the file is overwritten. * * If @full_path is not %NULL, then it will be set to a newly allocated * string which contains the full name of the opened file, in the Glib file * name encoding. Note that @full_path will also be set if the function fails. * * Only if @identifier starts with "Inf", the file will show up in * the directory listing of infd_storage_read_subdirectory(). Other * identifiers can be used to store custom data in the filesystem, linked to * this #InfdFilesystemStorage object. * * Returns: (transfer full): A stream for the open file. Close with * infd_filesystem_storage_stream_close(). **/ FILE* infd_filesystem_storage_open(InfdFilesystemStorage* storage, const gchar* identifier, const gchar* path, const gchar* mode, gchar** full_path, GError** error) { gchar* full_name; FILE* res; g_return_val_if_fail(INFD_IS_FILESYSTEM_STORAGE(storage), NULL); g_return_val_if_fail(identifier != NULL, NULL); g_return_val_if_fail(path != NULL, NULL); g_return_val_if_fail(mode != NULL, NULL); g_return_val_if_fail(error == NULL || *error == NULL, NULL); full_name = infd_filesystem_storage_get_path( storage, identifier, path, error ); if(full_name == NULL) return NULL; res = infd_filesystem_storage_open_impl( storage, full_name, mode, error ); if(full_path != NULL) *full_path = full_name; else g_free(full_name); return res; } /** * infd_filesystem_storage_read_xml_file: * @storage: A #InfdFilesystemStorage. * @identifier: The type of node to open. * @path: The path to open, in UTF-8. * @toplevel_tag: The expected toplevel XML tag name, or %NULL. * @error: Location to store error information, if any. * * Opens a file in the given path, and parses its XML content. See * infd_filesystem_storage_open() for how @identifier and @path should be * interpreted. * * If @toplevel_tag is non-%NULL, then this function generates an error if * the XML document read has a toplevel tag with a different name. * * Returns: (transfer full) (allow-none): A new XML document, or %NULL on * error. Free with xmlDocFree(). **/ xmlDocPtr infd_filesystem_storage_read_xml_file(InfdFilesystemStorage* storage, const gchar* identifier, const gchar* path, const gchar* toplevel_tag, GError** error) { gchar* full_name; xmlDocPtr res; g_return_val_if_fail(INFD_IS_FILESYSTEM_STORAGE(storage), NULL); g_return_val_if_fail(identifier != NULL, NULL); g_return_val_if_fail(path != NULL, NULL); g_return_val_if_fail(error == NULL || *error == NULL, NULL); full_name = infd_filesystem_storage_get_path( storage, identifier, path, error ); if(full_name == NULL) return NULL; res = infd_filesystem_storage_read_xml_file_impl( storage, full_name, toplevel_tag, error ); g_free(full_name); return res; } /** * infd_filesystem_storage_write_xml_file: * @storage: A #InfdFilesystemStorage. * @identifier: The type of node to write. * @path: The path to write to, in UTF-8. * @doc: The XML document to write. * @error: Location to store error information, if any. * * Writes the XML doument in @doc into a file in the filesystem indicated * by @identifier and @path. See infd_filesystem_storage_open() for how * @identifier and @path should be interpreted. * * Returns: %TRUE on success or %FALSE on error. **/ gboolean infd_filesystem_storage_write_xml_file(InfdFilesystemStorage* storage, const gchar* identifier, const gchar* path, xmlDocPtr doc, GError** error) { gchar* full_name; gboolean result; g_return_val_if_fail(INFD_IS_FILESYSTEM_STORAGE(storage), FALSE); g_return_val_if_fail(identifier != NULL, FALSE); g_return_val_if_fail(path != NULL, FALSE); g_return_val_if_fail(doc != NULL, FALSE); g_return_val_if_fail(error == NULL || *error == NULL, FALSE); full_name = infd_filesystem_storage_get_path( storage, identifier, path, error ); if(full_name == NULL) return FALSE; result = infd_filesystem_storage_write_xml_file_impl( storage, full_name, doc, error ); g_free(full_name); return result; } /** * infd_filesystem_storage_stream_close: * @file: A #FILE opened with infd_filesystem_storage_open(). * * This is a thin wrapper around fclose(). Use this function instead of * fclose() if you have opened the file with infd_filesystem_storage_open(), * to make sure that the same C runtime is closing the file that has opened * it. * * Returns: The return value of fclose(). */ int infd_filesystem_storage_stream_close(FILE* file) { return fclose(file); } /** * infd_filesystem_storage_stream_read: * @file: A #FILE opened with infd_filesystem_storage_open(). * @buffer: (type guint8*) (array length=len) (out): A buffer * into which to read data. * @len: Maximum number of bytes to read. * * This is a thin wrapper around fread(). Use this function instead of * fread() if you have opened the file with infd_filesystem_storage_open(), * to make sure that the same C runtime is closing the file that has opened * it. * * Returns: The return value of fread(). */ gsize infd_filesystem_storage_stream_read(FILE* file, gpointer buffer, gsize len) { return fread(buffer, 1, len, file); } /** * infd_filesystem_storage_stream_write: * @file: A #FILE opened with infd_filesystem_storage_open(). * @buffer: The data to write. * @len: Maximum number of bytes to write. * * This is a thin wrapper around fwrite(). Use this function instead of * fwrite() if you have opened the file with infd_filesystem_storage_open(), * to make sure that the same C runtime is closing the file that has opened * it. * * Returns: The return value of fwrite(). */ gsize infd_filesystem_storage_stream_write(FILE* file, gconstpointer buffer, gsize len) { return fwrite(buffer, 1, len, file); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/server/PaxHeaders.26529/infd-request.h0000644000000000000000000000013213034342512022205 xustar0030 mtime=1483851082.041718492 30 atime=1483851082.041718492 30 ctime=1488261589.008139048 libinfinity-0.7.1/libinfinity/server/infd-request.h0000644000175000017500000000412013034342512022734 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INFD_REQUEST_H__ #define __INFD_REQUEST_H__ #include G_BEGIN_DECLS #define INFD_TYPE_REQUEST (infd_request_get_type()) #define INFD_REQUEST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INFD_TYPE_REQUEST, InfdRequest)) #define INFD_REQUEST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INFD_TYPE_REQUEST, InfdRequestClass)) #define INFD_IS_REQUEST(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INFD_TYPE_REQUEST)) #define INFD_IS_REQUEST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INFD_TYPE_REQUEST)) #define INFD_REQUEST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INFD_TYPE_REQUEST, InfdRequestClass)) /** * InfdRequest: * * #InfdRequest is an opaque data type. You should only access it * via the public API functions. */ typedef struct _InfdRequest InfdRequest; typedef struct _InfdRequestClass InfdRequestClass; /** * InfdRequestClass: * * This structure does not contain any public fields. */ struct _InfdRequestClass { /*< private >*/ GObjectClass parent_class; /*< public >*/ }; struct _InfdRequest { GObject parent; }; GType infd_request_get_type(void) G_GNUC_CONST; G_END_DECLS #endif /* __INFD_REQUEST_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/server/PaxHeaders.26529/infd-session-proxy.c0000644000000000000000000000013213034342512023352 xustar0030 mtime=1483851082.045718513 30 atime=1483851082.045718513 30 ctime=1488261589.128138785 libinfinity-0.7.1/libinfinity/server/infd-session-proxy.c0000644000175000017500000014053713034342512024116 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:infd-session-proxy * @title: InfdSessionProxy * @short_description: Server-side session management * @include: libinfinity/server/infd-session-proxy.h * @see_also: #InfSession * @stability: Unstable * * #InfdSessionProxy is a manager for #InfSession that is specific for the * server side. The #InfdSessionProxy manages exactly one #InfSession. It is * usually created by #InfdDirectory when the content of a node is requested. * * #InfdSessionProxy allows to perform server-specific operations for the * session it manages, such as joining a local user, or removing a connection * from the list of subscribed connections. In addition it handles requests * made by its counterpart, #InfcSessionProxy, for the client side, such as * remote user joins. * * #InfdSessionProxy implements the #InfSessionProxy interface, which can be * used to access the underlying #InfSession or to join a local user. */ #include #include #include #include #include #include #include #include #include #include typedef struct _InfdSessionProxySubscription InfdSessionProxySubscription; struct _InfdSessionProxySubscription { InfXmlConnection* connection; guint seq_id; GSList* users; /* Available users joined via this connection */ }; typedef struct _InfdSessionProxyPrivate InfdSessionProxyPrivate; struct _InfdSessionProxyPrivate { InfIo* io; InfSession* session; InfCommunicationHostedGroup* subscription_group; GSList* subscriptions; guint user_id_counter; /* Local users that do not belong to a particular connection */ GSList* local_users; /* Whether there are any subscriptions / synchronizations */ gboolean idle; }; enum { PROP_0, /* construct/only */ PROP_IO, PROP_SESSION, PROP_SUBSCRIPTION_GROUP, /* read/only */ PROP_IDLE }; enum { ADD_SUBSCRIPTION, REMOVE_SUBSCRIPTION, REJECT_USER_JOIN, LAST_SIGNAL }; #define INFD_SESSION_PROXY_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INFD_TYPE_SESSION_PROXY, InfdSessionProxyPrivate)) static guint session_proxy_signals[LAST_SIGNAL]; static void infd_session_proxy_communication_object_iface_init(InfCommunicationObjectInterface* iface); static void infd_session_proxy_session_proxy_iface_init(InfSessionProxyInterface* iface); G_DEFINE_TYPE_WITH_CODE(InfdSessionProxy, infd_session_proxy, G_TYPE_OBJECT, G_ADD_PRIVATE(InfdSessionProxy) G_IMPLEMENT_INTERFACE(INF_COMMUNICATION_TYPE_OBJECT, infd_session_proxy_communication_object_iface_init) G_IMPLEMENT_INTERFACE(INF_TYPE_SESSION_PROXY, infd_session_proxy_session_proxy_iface_init)) /* * SessionProxy subscriptions. */ static InfdSessionProxySubscription* infd_session_proxy_subscription_new(InfXmlConnection* connection, guint seq_id) { InfdSessionProxySubscription* subscription; subscription = g_slice_new(InfdSessionProxySubscription); subscription->connection = connection; subscription->seq_id = seq_id; subscription->users = NULL; g_object_ref(G_OBJECT(connection)); return subscription; } static void infd_session_proxy_subscription_free(InfdSessionProxySubscription* subscr) { g_object_unref(G_OBJECT(subscr->connection)); g_slist_free(subscr->users); g_slice_free(InfdSessionProxySubscription, subscr); } static GSList* infd_session_proxy_find_subscription_item(InfdSessionProxy* proxy, InfXmlConnection* connection) { InfdSessionProxyPrivate* priv; GSList* item; priv = INFD_SESSION_PROXY_PRIVATE(proxy); for(item = priv->subscriptions; item != NULL; item = g_slist_next(item)) if( ((InfdSessionProxySubscription*)item->data)->connection == connection) return item; return NULL; } static InfdSessionProxySubscription* infd_session_proxy_find_subscription(InfdSessionProxy* proxy, InfXmlConnection* connection) { GSList* item; item = infd_session_proxy_find_subscription_item(proxy, connection); if(item == NULL) return NULL; return (InfdSessionProxySubscription*)item->data; } static gboolean infd_session_proxy_check_idle(InfdSessionProxy* proxy) { InfdSessionProxyPrivate* priv; priv = INFD_SESSION_PROXY_PRIVATE(proxy); if(priv->subscriptions == NULL && priv->local_users == NULL && !inf_session_has_synchronizations(priv->session)) { return TRUE; } return FALSE; } static void infd_session_proxy_user_notify_status_cb(InfUser* user, const GParamSpec* pspec, gpointer user_data) { InfdSessionProxy* proxy; InfdSessionProxyPrivate* priv; InfdSessionProxySubscription* subscr; if(inf_user_get_status(user) == INF_USER_UNAVAILABLE) { proxy = INFD_SESSION_PROXY(user_data); priv = INFD_SESSION_PROXY_PRIVATE(proxy); if(inf_user_get_connection(user)) { subscr = infd_session_proxy_find_subscription( proxy, inf_user_get_connection(user) ); g_assert(subscr != NULL); subscr->users = g_slist_remove(subscr->users, user); g_object_set(G_OBJECT(user), "connection", NULL, NULL); } else { priv->local_users = g_slist_remove(priv->local_users, user); if(priv->idle == FALSE && infd_session_proxy_check_idle(proxy) == TRUE) { priv->idle = TRUE; g_object_notify(G_OBJECT(proxy), "idle"); } } inf_signal_handlers_disconnect_by_func( G_OBJECT(user), G_CALLBACK(infd_session_proxy_user_notify_status_cb), proxy ); } } /* * Utility functions. */ static gboolean infd_session_proxy_make_seq(InfdSessionProxy* proxy, InfXmlConnection* connection, xmlNodePtr xml, gchar** seq, GError** error) { InfdSessionProxyPrivate* priv; InfdSessionProxySubscription* subscription; GError* local_error; guint seq_num; priv = INFD_SESSION_PROXY_PRIVATE(proxy); local_error = NULL; if(!inf_xml_util_get_attribute_uint(xml, "seq", &seq_num, &local_error)) { if(local_error) { g_propagate_error(error, local_error); return FALSE; } *seq = NULL; return TRUE; } subscription = infd_session_proxy_find_subscription(proxy, connection); g_assert(subscription != NULL); *seq = g_strdup_printf("%u/%u", subscription->seq_id, seq_num); return TRUE; } /* Performs a user join on the given proxy. If connection is not null, the * user join is made from that connection, otherwise a local user join is * performed. seq is the seq of the user join request and used in * the reply, or NULL if there was no seq. */ static InfUser* infd_session_proxy_perform_user_join(InfdSessionProxy* proxy, InfXmlConnection* connection, const gchar* seq, GArray* user_props, GError** error) { InfSessionClass* session_class; InfdSessionProxyPrivate* priv; InfdSessionProxySubscription* subscription; InfUser* user; const GParameter* name_param; GParameter* param; gboolean result; xmlNodePtr xml; guint i; priv = INFD_SESSION_PROXY_PRIVATE(proxy); session_class = INF_SESSION_GET_CLASS(priv->session); g_assert(session_class->validate_user_props != NULL); g_assert(session_class->user_new != NULL); name_param = inf_session_lookup_user_property( (const GParameter*)user_props->data, user_props->len, "name" ); if(name_param == NULL) { g_set_error_literal( error, inf_request_error_quark(), INF_REQUEST_ERROR_NO_SUCH_ATTRIBUTE, _("Request does not contain required attribute \"name\"") ); return NULL; } /* TODO: Isn't this already done in validate_user_props? */ user = inf_user_table_lookup_user_by_name( inf_session_get_user_table(priv->session), g_value_get_string(&name_param->value) ); if(user != NULL && inf_user_get_status(user) != INF_USER_UNAVAILABLE) { g_set_error( error, inf_user_error_quark(), INF_USER_ERROR_NAME_IN_USE, _("Name \"%s\" already in use"), g_value_get_string(&name_param->value) ); return NULL; } /* User join requests must not have the id value set because the server * chooses an ID, or reuses an existing one in the case of a rejoin. */ param = inf_session_get_user_property(user_props, "id"); if(G_IS_VALUE(¶m->value)) { g_set_error_literal( error, inf_request_error_quark(), INF_REQUEST_ERROR_INVALID_ATTRIBUTE, inf_user_strerror(INF_USER_ERROR_ID_PROVIDED) ); return NULL; } /* The user ID counter is increased in the add-user default signal * handler. */ g_value_init(¶m->value, G_TYPE_UINT); /* Reuse user ID on rejoin. */ if(user != NULL) g_value_set_uint(¶m->value, inf_user_get_id(user)); else g_value_set_uint(¶m->value, priv->user_id_counter); /* Check user status. It must not be unavailable on join/rejoin */ param = inf_session_get_user_property(user_props, "status"); if(G_IS_VALUE(¶m->value)) { if(g_value_get_enum(¶m->value) == INF_USER_UNAVAILABLE) { g_set_error_literal( error, inf_request_error_quark(), INF_REQUEST_ERROR_INVALID_ATTRIBUTE, _("\"status\" attribute is \"unavailable\" in user join request") ); return NULL; } } else { g_value_init(¶m->value, INF_TYPE_USER_STATUS); g_value_set_enum(¶m->value, INF_USER_ACTIVE); } /* flags should not be set by get_xml_user_props, nor given * to infd_session_proxy_add_user. */ param = inf_session_get_user_property(user_props, "flags"); g_assert(!G_IS_VALUE(¶m->value)); g_value_init(¶m->value, INF_TYPE_USER_FLAGS); if(connection == NULL) g_value_set_flags(¶m->value, INF_USER_LOCAL); else g_value_set_flags(¶m->value, 0); /* same with connection */ param = inf_session_get_user_property(user_props, "connection"); g_assert(!G_IS_VALUE(¶m->value)); g_value_init(¶m->value, INF_TYPE_XML_CONNECTION); g_value_set_object(¶m->value, G_OBJECT(connection)); /* Validate properties, but exclude the rejoining user from the check. * Otherwise, we would get conflicts because the name and the ID * of the request and the rejoining user are the same. */ result = session_class->validate_user_props( priv->session, (const GParameter*)user_props->data, user_props->len, user, error ); if(result == FALSE) return NULL; g_signal_emit( proxy, session_proxy_signals[REJECT_USER_JOIN], 0, connection, user_props, user, &result ); if(result == TRUE) { g_set_error_literal( error, inf_request_error_quark(), INF_REQUEST_ERROR_NOT_AUTHORIZED, _("Permission denied") ); return NULL; } if(user == NULL) { user = inf_session_add_user( priv->session, (const GParameter*)user_props->data, user_props->len ); g_assert(user != NULL); xml = xmlNewNode(NULL, (const xmlChar*)"user-join"); } else { g_object_freeze_notify(G_OBJECT(user)); /* Set properties on already existing user object. */ for(i = 0; i < user_props->len; ++ i) { param = &g_array_index(user_props, GParameter, i); /* Don't set name and ID because they did not change, and we are not * even allowed to set ID because it is construct only. */ if(strcmp(param->name, "name") != 0 && strcmp(param->name, "id") != 0) g_object_set_property(G_OBJECT(user), param->name, ¶m->value); } g_object_thaw_notify(G_OBJECT(user)); xml = xmlNewNode(NULL, (const xmlChar*)"user-rejoin"); } inf_session_user_to_xml(priv->session, user, xml); if(seq != NULL) inf_xml_util_set_attribute(xml, "seq", seq); /* TODO: Send with "connection" to subscriptions that are in the same * network, and that are non-local. */ g_signal_connect( G_OBJECT(user), "notify::status", G_CALLBACK(infd_session_proxy_user_notify_status_cb), proxy ); inf_session_send_to_subscriptions(priv->session, xml); if(connection != NULL) { subscription = infd_session_proxy_find_subscription(proxy, connection); g_assert(subscription != NULL); subscription->users = g_slist_prepend(subscription->users, user); } else { priv->local_users = g_slist_prepend(priv->local_users, user); if(priv->idle == TRUE) { priv->idle = FALSE; g_object_notify(G_OBJECT(proxy), "idle"); } } return user; } /* * Signal handlers. */ static void infd_session_proxy_member_removed_cb(InfCommunicationGroup* group, InfXmlConnection* connection, gpointer user_data) { InfdSessionProxy* proxy; InfdSessionProxyPrivate* priv; InfdSessionProxySubscription* subscription; xmlNodePtr xml; GSList* item; InfUser* user; proxy = INFD_SESSION_PROXY(user_data); priv = INFD_SESSION_PROXY_PRIVATE(proxy); subscription = infd_session_proxy_find_subscription(proxy, connection); g_assert(subscription != NULL); /* TODO: Only send user-status-change to users that don't have a direct * connection to the closed connection. */ for(item = subscription->users; item != NULL; item = g_slist_next(item)) { user = INF_USER(item->data); /* Send user-status-change to remaining subscriptions. */ /* Note: We cannot simply use inf_session_set_user_status because it * would also try to send the status change to the subscription we are * removing, and because it only works for local users. */ xml = xmlNewNode(NULL, (const xmlChar*)"user-status-change"); inf_xml_util_set_attribute_uint(xml, "id", inf_user_get_id(user)); inf_xml_util_set_attribute( xml, "status", inf_user_status_to_string(INF_USER_UNAVAILABLE) ); /* The actual status change is performed in the default signal handler * of the remove-subscription signal. */ inf_session_send_to_subscriptions(priv->session, xml); } g_signal_emit( proxy, session_proxy_signals[REMOVE_SUBSCRIPTION], 0, connection ); } static void infd_session_proxy_add_user_cb(InfUserTable* user_table, InfUser* user, gpointer user_data) { InfdSessionProxy* proxy; InfdSessionProxyPrivate* priv; InfXmlConnection* sync_conn; InfdSessionProxySubscription* subscription; proxy = INFD_SESSION_PROXY(user_data); priv = INFD_SESSION_PROXY_PRIVATE(proxy); /* Make sure that we generate a non-existing user ID for the next user. */ if(priv->user_id_counter <= inf_user_get_id(user)) priv->user_id_counter = inf_user_get_id(user) + 1; if(inf_session_get_status(priv->session) == INF_SESSION_SYNCHRONIZING) { if(inf_user_get_status(user) != INF_USER_UNAVAILABLE) { g_object_get( G_OBJECT(priv->session), "sync-connection", &sync_conn, NULL ); g_assert(sync_conn != NULL); subscription = infd_session_proxy_find_subscription(proxy, sync_conn); /* During synchronization, available users are always considered to * belong to the synchronizing connection. Everything else is just not * supported and causes session closure. */ if(sync_conn != inf_user_get_connection(user) || subscription == NULL) { /* This actually cancels the synchronization: */ inf_session_close(priv->session); } else { subscription->users = g_slist_prepend(subscription->users, user); g_signal_connect( G_OBJECT(user), "notify::status", G_CALLBACK(infd_session_proxy_user_notify_status_cb), proxy ); } g_object_unref(sync_conn); } } } static void infd_session_proxy_synchronization_begin_cb(InfSession* session, InfCommunicationGroup* group, InfXmlConnection* connection, gpointer user_data) { InfdSessionProxy* proxy; InfdSessionProxyPrivate* priv; proxy = INFD_SESSION_PROXY(user_data); priv = INFD_SESSION_PROXY_PRIVATE(proxy); if(priv->idle) { priv->idle = FALSE; g_object_notify(G_OBJECT(proxy), "idle"); } } static void infd_session_proxy_synchronization_complete_cb(InfSession* session, InfXmlConnection* conn, gpointer user_data) { InfdSessionProxy* proxy; InfdSessionProxyPrivate* priv; proxy = INFD_SESSION_PROXY(user_data); priv = INFD_SESSION_PROXY_PRIVATE(proxy); /* Set idle if no more synchronizations are running */ if(!priv->idle && priv->subscriptions == NULL && priv->local_users == NULL && !inf_session_has_synchronizations(session)) { priv->idle = TRUE; g_object_notify(G_OBJECT(proxy), "idle"); } } static void infd_session_proxy_synchronization_failed_cb_before(InfSession* session, InfXmlConnection* conn, const GError* error, gpointer user_data) { InfdSessionProxy* proxy; InfdSessionProxyPrivate* priv; InfSessionStatus status; InfdSessionProxySubscription* subscription; proxy = INFD_SESSION_PROXY(user_data); priv = INFD_SESSION_PROXY_PRIVATE(proxy); g_object_get(session, "status", &status, NULL); /* We do not need handle the status == INF_SESSION_PROXY_SYNCHRONIZING case * since there cannot be any subscriptions while we are synchronizing. */ if(status == INF_SESSION_RUNNING) { /* Remove from subscription group if the connection was subscribed */ subscription = infd_session_proxy_find_subscription(proxy, conn); if(subscription != NULL) { inf_communication_hosted_group_remove_member( priv->subscription_group, conn ); } } } static void infd_session_proxy_synchronization_failed_cb_after(InfSession* session, InfXmlConnection* conn, const GError* error, gpointer user_data) { InfdSessionProxy* proxy; InfdSessionProxyPrivate* priv; proxy = INFD_SESSION_PROXY(user_data); priv = INFD_SESSION_PROXY_PRIVATE(proxy); /* Set idle if no more synchronizations are running */ if(!priv->idle && priv->subscriptions == NULL && !inf_session_has_synchronizations(session)) { priv->idle = TRUE; g_object_notify(G_OBJECT(proxy), "idle"); } } static void infd_session_proxy_session_close_cb(InfSession* session, gpointer user_data) { InfdSessionProxy* proxy; InfdSessionProxyPrivate* priv; InfdSessionProxySubscription* subscription; proxy = INFD_SESSION_PROXY(user_data); priv = INFD_SESSION_PROXY_PRIVATE(proxy); inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->subscription_group), G_CALLBACK(infd_session_proxy_member_removed_cb), proxy ); while(priv->subscriptions != NULL) { subscription = (InfdSessionProxySubscription*)priv->subscriptions->data; /* Note that this does not call our signal handler because we already * disconnected it. This way, we make sure not to send user status updates * which would be pointless since we are closing the group anyway. */ infd_session_proxy_unsubscribe(proxy, subscription->connection); /* However, this means we need to emit the unsubscribe signal ourselves */ g_signal_emit( proxy, session_proxy_signals[REMOVE_SUBSCRIPTION], 0, subscription->connection ); } /* Set local users to unavailable */ while(priv->local_users != NULL) { g_object_set( G_OBJECT(priv->local_users->data), "status", INF_USER_UNAVAILABLE, NULL ); } g_object_unref(priv->subscription_group); priv->subscription_group = NULL; } /* * GObject overrides. */ static void infd_session_proxy_init(InfdSessionProxy* session_proxy) { InfdSessionProxyPrivate* priv; priv = INFD_SESSION_PROXY_PRIVATE(session_proxy); priv->io = NULL; priv->subscriptions = NULL; priv->subscription_group = NULL; priv->user_id_counter = 1; priv->local_users = NULL; priv->idle = TRUE; } static void infd_session_proxy_constructed(GObject* object) { InfdSessionProxy* session_proxy; InfdSessionProxyPrivate* priv; session_proxy = INFD_SESSION_PROXY(object); priv = INFD_SESSION_PROXY_PRIVATE(session_proxy); G_OBJECT_CLASS(infd_session_proxy_parent_class)->constructed(object); g_assert(priv->subscription_group != NULL); g_assert(priv->session != NULL); /* Set unidle when session is currently being synchronized */ if(inf_session_get_status(priv->session) == INF_SESSION_SYNCHRONIZING || priv->local_users != NULL) { priv->idle = FALSE; } /* TODO: We could perhaps optimize by only setting the subscription * group when there are subscribed connections. */ inf_session_set_subscription_group( priv->session, INF_COMMUNICATION_GROUP(priv->subscription_group) ); } static void infd_session_proxy_dispose(GObject* object) { InfdSessionProxy* proxy; InfdSessionProxyPrivate* priv; InfCommunicationManager* manager; proxy = INFD_SESSION_PROXY(object); priv = INFD_SESSION_PROXY_PRIVATE(proxy); manager = inf_session_get_communication_manager(priv->session); g_object_ref(manager); g_slist_free(priv->local_users); priv->local_users = NULL; /* We need to close the session explicitely before we unref so that * the signal handler for the close signal is called. */ /* Note this emits the close signal, removing all subscriptions and * the subscription group */ if(inf_session_get_status(priv->session) != INF_SESSION_CLOSED) inf_session_close(priv->session); inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->session), G_CALLBACK(infd_session_proxy_session_close_cb), proxy ); inf_signal_handlers_disconnect_by_func( G_OBJECT(inf_session_get_user_table(priv->session)), G_CALLBACK(infd_session_proxy_add_user_cb), proxy ); inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->session), G_CALLBACK(infd_session_proxy_synchronization_begin_cb), proxy ); inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->session), G_CALLBACK(infd_session_proxy_synchronization_complete_cb), proxy ); inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->session), G_CALLBACK(infd_session_proxy_synchronization_failed_cb_before), proxy ); inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->session), G_CALLBACK(infd_session_proxy_synchronization_failed_cb_after), proxy ); g_object_unref(priv->session); priv->session = NULL; g_assert(priv->subscription_group == NULL); g_assert(priv->subscriptions == NULL); g_object_unref(priv->io); priv->io = NULL; g_object_unref(manager); G_OBJECT_CLASS(infd_session_proxy_parent_class)->dispose(object); } static void infd_session_proxy_session_init_user_func(InfUser* user, gpointer user_data) { InfdSessionProxy* proxy; InfdSessionProxyPrivate* priv; proxy = INFD_SESSION_PROXY(user_data); priv = INFD_SESSION_PROXY_PRIVATE(proxy); if(priv->user_id_counter <= inf_user_get_id(user)) priv->user_id_counter = inf_user_get_id(user) + 1; } static void infd_session_proxy_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfdSessionProxy* proxy; InfdSessionProxyPrivate* priv; proxy = INFD_SESSION_PROXY(object); priv = INFD_SESSION_PROXY_PRIVATE(proxy); switch(prop_id) { case PROP_IO: g_assert(priv->io == NULL); /* construct only */ priv->io = INF_IO(g_value_dup_object(value)); break; case PROP_SESSION: g_assert(priv->session == NULL); /* construct only */ priv->session = INF_SESSION(g_value_dup_object(value)); /* Adjust user id counter so the next joining user gets a free ID */ /* TODO: Add local users to priv->local_users, assert that there are no * available non-local users. */ inf_user_table_foreach_user( inf_session_get_user_table(priv->session), infd_session_proxy_session_init_user_func, proxy ); /* This in not connect_after to fix bug #499. This makes more sense * anyway, because otherwise the signal handler does not have any * synchronization info anymore. */ g_signal_connect( G_OBJECT(priv->session), "close", G_CALLBACK(infd_session_proxy_session_close_cb), proxy ); g_signal_connect( G_OBJECT(inf_session_get_user_table(priv->session)), "add-user", G_CALLBACK(infd_session_proxy_add_user_cb), proxy ); g_signal_connect_after( G_OBJECT(priv->session), "synchronization-begin", G_CALLBACK(infd_session_proxy_synchronization_begin_cb), proxy ); g_signal_connect_after( G_OBJECT(priv->session), "synchronization-complete", G_CALLBACK(infd_session_proxy_synchronization_complete_cb), proxy ); g_signal_connect( G_OBJECT(priv->session), "synchronization-failed", G_CALLBACK(infd_session_proxy_synchronization_failed_cb_before), proxy ); g_signal_connect_after( G_OBJECT(priv->session), "synchronization-failed", G_CALLBACK(infd_session_proxy_synchronization_failed_cb_after), proxy ); break; case PROP_SUBSCRIPTION_GROUP: g_assert(priv->subscription_group == NULL); /* construct only */ priv->subscription_group = INF_COMMUNICATION_HOSTED_GROUP(g_value_dup_object(value)); g_signal_connect( G_OBJECT(priv->subscription_group), "member-removed", G_CALLBACK(infd_session_proxy_member_removed_cb), proxy ); break; case PROP_IDLE: /* read/only */ default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void infd_session_proxy_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfdSessionProxy* proxy; InfdSessionProxyPrivate* priv; proxy = INFD_SESSION_PROXY(object); priv = INFD_SESSION_PROXY_PRIVATE(proxy); switch(prop_id) { case PROP_IO: g_value_set_object(value, priv->io); break; case PROP_SESSION: g_value_set_object(value, priv->session); break; case PROP_SUBSCRIPTION_GROUP: g_value_set_object(value, priv->subscription_group); break; case PROP_IDLE: g_value_set_boolean(value, priv->idle); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } /* * Default signal handlers */ static void infd_session_proxy_add_subscription(InfdSessionProxy* proxy, InfXmlConnection* connection, guint seq_id) { InfdSessionProxyPrivate* priv; InfdSessionProxySubscription* subscription; priv = INFD_SESSION_PROXY_PRIVATE(proxy); g_assert(infd_session_proxy_find_subscription(proxy, connection) == NULL); subscription = infd_session_proxy_subscription_new(connection, seq_id); priv->subscriptions = g_slist_prepend(priv->subscriptions, subscription); if(priv->idle == TRUE) { priv->idle = FALSE; g_object_notify(G_OBJECT(proxy), "idle"); } } static void infd_session_proxy_remove_subscription(InfdSessionProxy* proxy, InfXmlConnection* connection) { InfdSessionProxyPrivate* priv; InfdSessionProxySubscription* subscr; priv = INFD_SESSION_PROXY_PRIVATE(proxy); subscr = infd_session_proxy_find_subscription(proxy, connection); g_assert(subscr != NULL); /* TODO: Cancel synchronization if the synchronization to this subscription * did not yet finish. */ while(subscr->users) { /* The signal handler of the user's notify::status signal removes the user * from the subscription. */ g_object_set( G_OBJECT(subscr->users->data), "status", INF_USER_UNAVAILABLE, NULL ); } priv->subscriptions = g_slist_remove(priv->subscriptions, subscr); infd_session_proxy_subscription_free(subscr); if(priv->idle == FALSE && infd_session_proxy_check_idle(proxy) == TRUE) { priv->idle = TRUE; g_object_notify(G_OBJECT(proxy), "idle"); } } static gboolean infd_session_proxy_reject_user_join(InfdSessionProxy* proxy, InfXmlConnection* connection, const GArray* user_properties, InfUser* user_rejoin) { /* Allow user join by default */ return FALSE; } /* * Message handling. */ static gboolean infd_session_proxy_handle_user_join(InfdSessionProxy* proxy, InfXmlConnection* connection, xmlNodePtr xml, GError** error) { InfdSessionProxyPrivate* priv; InfSessionClass* session_class; GArray* array; InfUser* user; gchar* seq; guint i; priv = INFD_SESSION_PROXY_PRIVATE(proxy); session_class = INF_SESSION_GET_CLASS(priv->session); if(!infd_session_proxy_make_seq(proxy, connection, xml, &seq, error)) return FALSE; array = session_class->get_xml_user_props( priv->session, connection, xml ); user = infd_session_proxy_perform_user_join( proxy, connection, seq, array, error ); for(i = 0; i < array->len; ++ i) g_value_unset(&g_array_index(array, GParameter, i).value); g_array_free(array, TRUE); g_free(seq); if(user == NULL) return FALSE; return TRUE; } static gboolean infd_session_proxy_handle_session_unsubscribe(InfdSessionProxy* proxy, InfXmlConnection* connection, const xmlNodePtr xml, GError** error) { InfdSessionProxyPrivate* priv; priv = INFD_SESSION_PROXY_PRIVATE(proxy); g_assert(infd_session_proxy_find_subscription(proxy, connection) != NULL); inf_communication_hosted_group_remove_member( priv->subscription_group, connection ); return TRUE; } /* * InfCommunicationObject implementation */ static void infd_session_proxy_communication_object_sent(InfCommunicationObject* object, InfXmlConnection* connection, xmlNodePtr node) { InfdSessionProxy* proxy; InfdSessionProxyPrivate* priv; proxy = INFD_SESSION_PROXY(object); priv = INFD_SESSION_PROXY_PRIVATE(proxy); /* TODO: Don't forward for messages the proxy issued */ g_assert(priv->session != NULL); inf_communication_object_sent( INF_COMMUNICATION_OBJECT(priv->session), connection, node ); } static void infd_session_proxy_communication_object_enqueued(InfCommunicationObject* obj, InfXmlConnection* connection, xmlNodePtr node) { InfdSessionProxy* proxy; InfdSessionProxyPrivate* priv; proxy = INFD_SESSION_PROXY(obj); priv = INFD_SESSION_PROXY_PRIVATE(proxy); /* TODO: Don't forward for messages the proxy issued */ g_assert(priv->session != NULL); inf_communication_object_enqueued( INF_COMMUNICATION_OBJECT(priv->session), connection, node ); } static InfCommunicationScope infd_session_proxy_communication_object_received(InfCommunicationObject* obj, InfXmlConnection* connection, xmlNodePtr node) { InfdSessionProxy* proxy; InfdSessionProxyPrivate* priv; InfSessionSyncStatus status; GError* local_error; xmlNodePtr reply_xml; gchar* seq; proxy = INFD_SESSION_PROXY(obj); priv = INFD_SESSION_PROXY_PRIVATE(proxy); /* TODO: Don't forward for messages the proxy issued */ g_assert(priv->session != NULL); status = inf_session_get_synchronization_status(priv->session, connection); local_error = NULL; if(status != INF_SESSION_SYNC_NONE) { return inf_communication_object_received( INF_COMMUNICATION_OBJECT(priv->session), connection, node ); } else { if(strcmp((const char*)node->name, "user-join") == 0) { infd_session_proxy_handle_user_join( proxy, connection, node, &local_error ); } else if(strcmp((const char*)node->name, "session-unsubscribe") == 0) { /* TODO: Handle this in InfSession, if possible */ infd_session_proxy_handle_session_unsubscribe( proxy, connection, node, &local_error ); } else { return inf_communication_object_received( INF_COMMUNICATION_OBJECT(priv->session), connection, node ); } } if(local_error != NULL) { if(!infd_session_proxy_make_seq(proxy, connection, node, &seq, NULL)) seq = NULL; /* Only send request-failed when it was a proxy-related request */ reply_xml = inf_xml_util_new_node_from_error(local_error, NULL, "request-failed"); if(seq != NULL) inf_xml_util_set_attribute(reply_xml, "seq", seq); g_free(seq); inf_communication_group_send_message( INF_COMMUNICATION_GROUP(priv->subscription_group), connection, reply_xml ); g_error_free(local_error); } /* Don't forward proxy-related messages */ return INF_COMMUNICATION_SCOPE_PTP; } /* * InfSessionProxy implementation */ static InfRequest* infd_session_proxy_session_proxy_join_user(InfSessionProxy* proxy, guint n_params, const GParameter* params, InfRequestFunc func, gpointer user_data) { InfdRequest* request; GArray* array; guint i; GParameter param; GError* error; InfUser* user; g_return_val_if_fail(INFD_IS_SESSION_PROXY(proxy), NULL); request = g_object_new( INFD_TYPE_REQUEST, "type", "user-join", NULL ); if(func != NULL) { g_signal_connect_after( G_OBJECT(request), "finished", G_CALLBACK(func), user_data ); } array = g_array_sized_new( FALSE, FALSE, sizeof(GParameter), n_params ); g_array_append_vals(array, params, n_params); error = NULL; user = infd_session_proxy_perform_user_join( INFD_SESSION_PROXY(proxy), NULL, NULL, array, &error ); /* Remove only those parameters that were added by the * infd_session_proxy_perform_user_join function */ for(i = n_params; i < array->len; ++i) g_value_unset(&g_array_index(array, GParameter, i).value); g_array_free(array, TRUE); if(error != NULL) { inf_request_fail(INF_REQUEST(request), error); } else { inf_request_finish( INF_REQUEST(request), inf_request_result_make_join_user(proxy, user) ); } if(error) g_error_free(error); g_object_unref(request); return NULL; } /* * GType registration. */ static void infd_session_proxy_class_init(InfdSessionProxyClass* proxy_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(proxy_class); object_class->constructed = infd_session_proxy_constructed; object_class->dispose = infd_session_proxy_dispose; object_class->set_property = infd_session_proxy_set_property; object_class->get_property = infd_session_proxy_get_property; proxy_class->add_subscription = infd_session_proxy_add_subscription; proxy_class->remove_subscription = infd_session_proxy_remove_subscription; proxy_class->reject_user_join = infd_session_proxy_reject_user_join; g_object_class_install_property( object_class, PROP_IO, g_param_spec_object( "io", "Io", "The InfIo object for scheduling events", INF_TYPE_IO, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_SUBSCRIPTION_GROUP, g_param_spec_object( "subscription-group", "Subscription group", "The communication manager group of subscribed connections", INF_COMMUNICATION_TYPE_HOSTED_GROUP, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_IDLE, g_param_spec_boolean( "idle", "Idle", "The session is considered idle when are no subscriptions and no " "synchronizations", TRUE, G_PARAM_READABLE ) ); g_object_class_override_property(object_class, PROP_SESSION, "session"); /** * InfdSessionProxy::add-subscription: * @proxy: The #InfdSessionProxy emitting the signal. * @connection: The subscribed #InfXmlConnection. * @seq_id: The sequence identifier for @connection as passed to * infd_session_proxy_subscribe_to(). * * Emitted every time a connection is subscribed to the session. **/ session_proxy_signals[ADD_SUBSCRIPTION] = g_signal_new( "add-subscription", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfdSessionProxyClass, add_subscription), NULL, NULL, NULL, G_TYPE_NONE, 2, INF_TYPE_XML_CONNECTION, G_TYPE_UINT ); /** * InfdSessionProxy::remove-subscription: * @proxy: The #InfdSessionProxy emitting the signal. * @connection: The unsubscribed #InfXmlConnection. * * Emitted every time a connection is unsubscribed to the session, or a * subscription is removed because the session is closed. **/ session_proxy_signals[REMOVE_SUBSCRIPTION] = g_signal_new( "remove-subscription", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfdSessionProxyClass, remove_subscription), NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, INF_TYPE_XML_CONNECTION ); /** * InfdSessionProxy::reject-user-join: * @proxy: The #InfdSessionProxy emitting the signal. * @connection: A subscribed #InfXmlConnection requesting the user join. * @user_properties: An array with the properties for the new user. * @rejoin_user: The existing unavailable user that is being rejoined, or * %NULL. * * This signal is emitted before every remote user join. The signal handler * can return %TRUE in which case the #InfdSessionProxy does not allow the * user join with %INF_REQUEST_ERROR_NOT_AUTHORIZED error. If there is more * than one signal handler, then if one of them returns %TRUE the user * join is rejected. * * The @user_properties parameter is a #GArray of #GParameter values. It * contains the construct properties for the #InfUser object that would be * created if the user join is not rejected. It must not be modified, but * it can be used to make the decision whether to reject the user join or * not dependent on the parameters, such as allowing the user join only if * the user has a predefined name. The function * inf_session_lookup_user_property() can be used to look up a named * parameter in the array. */ session_proxy_signals[REJECT_USER_JOIN] = g_signal_new( "reject-user-join", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfdSessionProxyClass, reject_user_join), g_signal_accumulator_true_handled, NULL, NULL, G_TYPE_BOOLEAN, 3, INF_TYPE_XML_CONNECTION, G_TYPE_ARRAY, INF_TYPE_USER ); } static void infd_session_proxy_communication_object_iface_init( InfCommunicationObjectInterface* iface) { iface->sent = infd_session_proxy_communication_object_sent; iface->enqueued = infd_session_proxy_communication_object_enqueued; iface->received = infd_session_proxy_communication_object_received; } static void infd_session_proxy_session_proxy_iface_init(InfSessionProxyInterface* iface) { iface->join_user = infd_session_proxy_session_proxy_join_user; } /* * Public API. */ /** * infd_session_proxy_subscribe_to: * @proxy: A #InfdSessionProxy. * @connection: A #InfXmlConnection that is not yet subscribed. * @seq_id: The sequence identifier for @connection. * @synchronize: If %TRUE, then synchronize the session to @connection first. * * Subscribes @connection to @proxy's session. The first thing that will be * done is a synchronization (see inf_session_synchronize_to()). Then, all * changes to the session are propagated to @connection. * * @seq_id should be a unique number for @connection, and the same number must * be passed on the client side to the #InfcSessionProxy object. Normally * #InfdDirectory and #InfcBrowser take care of choosing an appropriate * sequence identifier. * * Normally, you want to set @synchronize to %TRUE in which case the whole * session state will be synchronized to @connection (within the subscription * group). However, if for whatever reason the remote site already has a * copy of the session, then you may set @synchronize to %FALSE to skip * synchronization. This happens for example for newly created documents, or * when the remote site synchronized the local site and wants to be * initially subscribed. * * If @proxy's session is not in %INF_SESSION_RUNNING status, but in * %INF_SESSION_SYNCHRONIZING, then @connection must be the connection that * synchronizes the session and @synchronize needs to be set to %FALSE. This * causes the synchronizing connection to initially be subscribed. This * needs to be called directly after having created the session proxy (i.e. * without returning to the main loop before) so that the synchronization * connection is added to the subscription group for synchronization. * * Otherwise a subscription can only be initiated if @proxy's session is in * state %INF_SESSION_RUNNING. **/ void infd_session_proxy_subscribe_to(InfdSessionProxy* proxy, InfXmlConnection* connection, guint seq_id, gboolean synchronize) { InfdSessionProxyPrivate* priv; g_return_if_fail(INFD_IS_SESSION_PROXY(proxy)); g_return_if_fail(INF_IS_XML_CONNECTION(connection)); g_return_if_fail( infd_session_proxy_find_subscription(proxy, connection) == NULL ); priv = INFD_SESSION_PROXY_PRIVATE(proxy); g_return_if_fail(priv->session != NULL); /* TODO: Also check connection against sync-conn in synchronizing case: */ g_return_if_fail( inf_session_get_status(priv->session) == INF_SESSION_RUNNING || (synchronize == FALSE) ); /* Note we can't do this in the default signal handler since it doesn't * know the parent group. TODO: We can, meanwhile. */ inf_communication_hosted_group_add_member( priv->subscription_group, connection ); g_signal_emit( G_OBJECT(proxy), session_proxy_signals[ADD_SUBSCRIPTION], 0, connection, seq_id ); /* Make sure the default handler ran. Stopping the signal emission before * would leave us in an inconsistent state. */ g_assert(infd_session_proxy_find_subscription(proxy, connection) != NULL); if(synchronize) { /* Directly synchronize within the subscription group so that we do not * need a group change after synchronization, and the connection already * receives requests from other group members to process after * synchronization. */ inf_session_synchronize_to( priv->session, INF_COMMUNICATION_GROUP(priv->subscription_group), connection ); } } /** * infd_session_proxy_unsubscribe: * @proxy: A #InfdSessionProxy. * @connection: The #InfXmlConnection to unsubscribe. * * Unsubscribes a subscribed connection from @proxy's session. This will * prevent all users joined via @connection to continue modifying the * session's buffer, and it will cancel ongoing synchronization to * @connection, if not yet finished. */ void infd_session_proxy_unsubscribe(InfdSessionProxy* proxy, InfXmlConnection* connection) { InfdSessionProxyPrivate* priv; InfdSessionProxySubscription* subscription; InfSessionSyncStatus status; xmlNodePtr xml; g_return_if_fail(INFD_IS_SESSION_PROXY(proxy)); g_return_if_fail(INF_IS_XML_CONNECTION(connection)); priv = INFD_SESSION_PROXY_PRIVATE(proxy); /* TODO: Can we support the SYNCHRONIZING case? In that case the session * will probably end up closed... */ g_assert(inf_session_get_status(priv->session) == INF_SESSION_RUNNING); subscription = infd_session_proxy_find_subscription(proxy, connection); g_return_if_fail(subscription != NULL); status = inf_session_get_synchronization_status( priv->session, subscription->connection ); /* If synchronization is still in progress, the default handler of * InfSession will cancel the synchronization in which case we do * not need to send an extra session-close message. */ /* We send session_close when we are in AWAITING_ACK status. In * AWAITING_ACK status we cannot cancel the synchronization anymore * because everything has already been sent out. Therefore the client * will eventuelly get in RUNNING state when it receives this message, * and process it correctly. */ if(status != INF_SESSION_SYNC_IN_PROGRESS) { xml = xmlNewNode(NULL, (const xmlChar*)"session-close"); inf_communication_group_send_message( INF_COMMUNICATION_GROUP(priv->subscription_group), subscription->connection, xml ); } else { /* In case we are synchronizing the client */ inf_session_cancel_synchronization( priv->session, subscription->connection ); } inf_communication_hosted_group_remove_member( priv->subscription_group, subscription->connection ); } /** * infd_session_proxy_has_subscriptions: * @proxy: A #InfdSessionProxy. * * Returns whether there are subscribed connections to the session. * * Returns: Whether there are subscribed connections. **/ gboolean infd_session_proxy_has_subscriptions(InfdSessionProxy* proxy) { InfdSessionProxyPrivate* priv; g_return_val_if_fail(INFD_IS_SESSION_PROXY(proxy), FALSE); priv = INFD_SESSION_PROXY_PRIVATE(proxy); if(priv->subscriptions == NULL) return FALSE; return TRUE; } /** * infd_session_proxy_is_subscribed: * @proxy: A #InfdSessionProxy. * @connection: The connection to check for being subscribed. * * Returns %TRUE when @connection is subscribed to the session and %FALSE * otherwise. * * Returns: Whether @connection is subscribed. **/ gboolean infd_session_proxy_is_subscribed(InfdSessionProxy* proxy, InfXmlConnection* connection) { g_return_val_if_fail(INFD_IS_SESSION_PROXY(proxy), FALSE); g_return_val_if_fail(INF_IS_XML_CONNECTION(connection), FALSE); if(infd_session_proxy_find_subscription(proxy, connection) == NULL) return FALSE; return TRUE; } /** * infd_session_proxy_is_idle: * @proxy: A #InfdSessionProxy. * * Returns whether the session is idle. The session is considered idle when * there are no subscriptions and no synchronizations (in either direction). * * Returns: Whether the session is idle. **/ gboolean infd_session_proxy_is_idle(InfdSessionProxy* proxy) { g_return_val_if_fail(INFD_IS_SESSION_PROXY(proxy), FALSE); return INFD_SESSION_PROXY_PRIVATE(proxy)->idle; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/server/PaxHeaders.26529/infd-progress-request.h0000644000000000000000000000013213034342512024047 xustar0030 mtime=1483851082.041718492 30 atime=1483851082.041718492 30 ctime=1488261589.008139048 libinfinity-0.7.1/libinfinity/server/infd-progress-request.h0000644000175000017500000000505313034342512024604 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INFD_PROGRESS_REQUEST_H__ #define __INFD_PROGRESS_REQUEST_H__ #include #include G_BEGIN_DECLS #define INFD_TYPE_PROGRESS_REQUEST (infd_progress_request_get_type()) #define INFD_PROGRESS_REQUEST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INFD_TYPE_PROGRESS_REQUEST, InfdProgressRequest)) #define INFD_PROGRESS_REQUEST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INFD_TYPE_PROGRESS_REQUEST, InfdProgressRequestClass)) #define INFD_IS_PROGRESS_REQUEST(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INFD_TYPE_PROGRESS_REQUEST)) #define INFD_IS_PROGRESS_REQUEST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INFD_TYPE_PROGRESS_REQUEST)) #define INFD_PROGRESS_REQUEST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INFD_TYPE_PROGRESS_REQUEST, InfdProgressRequestClass)) typedef struct _InfdProgressRequest InfdProgressRequest; typedef struct _InfdProgressRequestClass InfdProgressRequestClass; /** * InfdProgressRequestClass: * * This structure does not contain any public fields. */ struct _InfdProgressRequestClass { /*< private >*/ InfdRequestClass parent_class; }; /** * InfdProgressRequest: * * #InfdProgressRequest is an opaque data type. You should only access it via * the public API functions. */ struct _InfdProgressRequest { /*< private >*/ InfdRequest parent; }; GType infd_progress_request_get_type(void) G_GNUC_CONST; void infd_progress_request_initiated(InfdProgressRequest* request, guint total); void infd_progress_request_progress(InfdProgressRequest* request); G_END_DECLS #endif /* __INFD_PROGRESS_REQUEST_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/server/PaxHeaders.26529/infd-server-pool.c0000644000000000000000000000013213034342512022765 xustar0030 mtime=1483851082.045718513 30 atime=1483851082.041718492 30 ctime=1488261589.124138795 libinfinity-0.7.1/libinfinity/server/infd-server-pool.c0000644000175000017500000003611413034342512023524 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include typedef enum _InfdServerPoolPublisherType { INFD_SERVER_POOL_PUBLISHER_LOCAL } InfdServerPoolPublisherType; typedef struct _InfdServerPoolPublisher InfdServerPoolPublisher; struct _InfdServerPoolPublisher { InfdServerPoolPublisherType type; union { struct { InfLocalPublisher* publisher; InfLocalPublisherItem* item; } local; } shared; }; typedef struct _InfdServerPoolEntry InfdServerPoolEntry; struct _InfdServerPoolEntry { InfdXmlServer* server; GSList* publishers; }; typedef struct _InfdServerPoolPrivate InfdServerPoolPrivate; struct _InfdServerPoolPrivate { InfdDirectory* directory; GHashTable* servers; /* server -> entry */ }; enum { PROP_0, PROP_DIRECTORY }; #define INFD_SERVER_POOL_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INFD_TYPE_SERVER_POOL, InfdServerPoolPrivate)) G_DEFINE_TYPE_WITH_CODE(InfdServerPool, infd_server_pool, G_TYPE_OBJECT, G_ADD_PRIVATE(InfdServerPool)) static const gchar* infd_server_pool_get_local_service_name(void) { /* TODO: It would be nice to have the host name as service name for * dedicated servers and user name otherwise. This should maybe be a * property. */ const gchar* name; name = g_get_real_name(); if(name == NULL || g_ascii_strcasecmp(name, "unknown") == 0) name = g_get_user_name(); return name; } static void infd_server_pool_entry_publish_with(InfdServerPoolEntry* entry, InfdServerPoolPublisher* publisher) { InfdTcpServer* tcp; guint port; switch(publisher->type) { case INFD_SERVER_POOL_PUBLISHER_LOCAL: g_assert(INFD_IS_XMPP_SERVER(entry->server)); if(publisher->shared.local.item == NULL) { g_object_get(G_OBJECT(entry->server), "tcp-server", &tcp, NULL); g_object_get(G_OBJECT(tcp), "local-port", &port, NULL); g_object_unref(G_OBJECT(tcp)); publisher->shared.local.item = inf_local_publisher_publish( publisher->shared.local.publisher, "_infinote._tcp", infd_server_pool_get_local_service_name(), port ); } break; default: g_assert_not_reached(); break; } } static void infd_server_pool_entry_unpublish_with(InfdServerPoolEntry* entry, InfdServerPoolPublisher* publisher) { switch(publisher->type) { case INFD_SERVER_POOL_PUBLISHER_LOCAL: if(publisher->shared.local.item != NULL) { inf_local_publisher_unpublish( publisher->shared.local.publisher, publisher->shared.local.item ); publisher->shared.local.item = NULL; } break; default: g_assert_not_reached(); break; } } static void infd_server_pool_entry_publish(InfdServerPoolEntry* entry) { GSList* item; for(item = entry->publishers; item != NULL; item = g_slist_next(item)) { infd_server_pool_entry_publish_with( entry, (InfdServerPoolPublisher*)item->data ); } } static void infd_server_pool_entry_unpublish(InfdServerPoolEntry* entry) { GSList* item; for(item = entry->publishers; item != NULL; item = g_slist_next(item)) { infd_server_pool_entry_unpublish_with( entry, (InfdServerPoolPublisher*)item->data ); } } static void infd_server_pool_notify_status_cb(InfdXmlServer* server, GParamSpec* pspec, gpointer user_data) { InfdServerPool* server_pool; InfdServerPoolPrivate* priv; InfdServerPoolEntry* entry; InfdXmlServerStatus status; server_pool = INFD_SERVER_POOL(user_data); priv = INFD_SERVER_POOL_PRIVATE(server_pool); entry = (InfdServerPoolEntry*)g_hash_table_lookup(priv->servers, server); g_assert(entry != NULL); g_object_get(G_OBJECT(server), "status", &status, NULL); if(status == INFD_XML_SERVER_OPEN) infd_server_pool_entry_publish(entry); else infd_server_pool_entry_unpublish(entry); } static void infd_server_pool_new_connection_cb(InfdXmlServer* server, InfXmlConnection* connection, gpointer user_data) { InfdServerPool* server_pool; InfdServerPoolPrivate* priv; server_pool = INFD_SERVER_POOL(user_data); priv = INFD_SERVER_POOL_PRIVATE(server_pool); /* If the addition fails, then the directory does not ref the connection and * it will be unrefed (and therefore be closed) right after this function * terminates. */ if(priv->directory != NULL) infd_directory_add_connection(priv->directory, connection); } static void infd_server_pool_entry_free(InfdServerPool* server_pool, InfdServerPoolEntry* entry) { GSList* item; InfdServerPoolPublisher* publisher; inf_signal_handlers_disconnect_by_func( G_OBJECT(entry->server), G_CALLBACK(infd_server_pool_notify_status_cb), server_pool ); inf_signal_handlers_disconnect_by_func( G_OBJECT(entry->server), G_CALLBACK(infd_server_pool_new_connection_cb), server_pool ); for(item = entry->publishers; item != NULL; item = g_slist_next(item)) { publisher = (InfdServerPoolPublisher*)item->data; switch(publisher->type) { case INFD_SERVER_POOL_PUBLISHER_LOCAL: infd_server_pool_entry_unpublish_with(entry, publisher); g_object_unref(G_OBJECT(publisher->shared.local.publisher)); break; default: g_assert_not_reached(); break; } g_slice_free(InfdServerPoolPublisher, publisher); } g_slist_free(entry->publishers); g_slice_free(InfdServerPoolEntry, entry); } static void infd_server_pool_init(InfdServerPool* server_pool) { InfdServerPoolPrivate* priv; priv = INFD_SERVER_POOL_PRIVATE(server_pool); priv->directory = NULL; /* We don't set a value destroy func but rather make sure we free the * InfdServerPoolEntrys ourselves before removing them from the hashtable. * This is because the GDestroyNotify doesn't allow a user_data parameter * and therefore doesn't know the InfdServerPool from which the entry is * removed, but it is required to correctly disconnect the signals from * the InfXmlServer. */ priv->servers = g_hash_table_new(NULL, NULL); } static void infd_server_pool_dispose_foreach_func(gpointer key, gpointer value, gpointer user_data) { infd_server_pool_entry_free( INFD_SERVER_POOL(user_data), (InfdServerPoolEntry*)value ); } static void infd_server_pool_dispose(GObject* object) { InfdServerPool* server_pool; InfdServerPoolPrivate* priv; server_pool = INFD_SERVER_POOL(object); priv = INFD_SERVER_POOL_PRIVATE(server_pool); g_hash_table_foreach( priv->servers, infd_server_pool_dispose_foreach_func, server_pool ); g_hash_table_remove_all(priv->servers); if(priv->directory != NULL) { g_object_unref(G_OBJECT(priv->directory)); priv->directory = NULL; } G_OBJECT_CLASS(infd_server_pool_parent_class)->dispose(object); } static void infd_server_pool_finalize(GObject* object) { InfdServerPool* server_pool; InfdServerPoolPrivate* priv; server_pool = INFD_SERVER_POOL(object); priv = INFD_SERVER_POOL_PRIVATE(server_pool); /* Should have been cleared in dispose */ g_assert(g_hash_table_size(priv->servers) == 0); g_hash_table_destroy(priv->servers); G_OBJECT_CLASS(infd_server_pool_parent_class)->finalize(object); } static void infd_server_pool_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfdServerPool* server_pool; InfdServerPoolPrivate* priv; server_pool = INFD_SERVER_POOL(object); priv = INFD_SERVER_POOL_PRIVATE(server_pool); switch(prop_id) { case PROP_DIRECTORY: g_assert(priv->directory == NULL); /* construct only */ priv->directory = INFD_DIRECTORY(g_value_dup_object(value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void infd_server_pool_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfdServerPool* server_pool; InfdServerPoolPrivate* priv; server_pool = INFD_SERVER_POOL(object); priv = INFD_SERVER_POOL_PRIVATE(server_pool); switch(prop_id) { case PROP_DIRECTORY: g_value_set_object(value, G_OBJECT(priv->directory)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void infd_server_pool_class_init(InfdServerPoolClass* server_pool_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(server_pool_class); object_class->dispose = infd_server_pool_dispose; object_class->finalize = infd_server_pool_finalize; object_class->set_property = infd_server_pool_set_property; object_class->get_property = infd_server_pool_get_property; g_object_class_install_property( object_class, PROP_DIRECTORY, g_param_spec_object( "directory", "Directory", "The directory to which to register incoming connections to", INFD_TYPE_DIRECTORY, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); } /** * infd_server_pool_new: (constructor) * @directory: A #InfdDirectory to which to add incoming connections. * * Creates a new #InfdServerPool. * * Returns: (transfer full): A new #InfdServerPool. */ InfdServerPool* infd_server_pool_new(InfdDirectory* directory) { GObject* object; g_return_val_if_fail(INFD_IS_DIRECTORY(directory), NULL); object = g_object_new( INFD_TYPE_SERVER_POOL, "directory", directory, NULL ); return INFD_SERVER_POOL(object); } /** * infd_server_pool_add_server: * @server_pool: A #InfdServerPool. * @server: A #InfdXmlServer. * * Adds @server to @server_pool. The server pool accepts incoming connections * and gives them to its directory which processes incoming requests. */ void infd_server_pool_add_server(InfdServerPool* server_pool, InfdXmlServer* server) { InfdServerPoolPrivate* priv; InfdServerPoolEntry* entry; g_return_if_fail(INFD_IS_SERVER_POOL(server_pool)); g_return_if_fail(INFD_IS_XML_SERVER(server)); priv = INFD_SERVER_POOL_PRIVATE(server_pool); g_return_if_fail(g_hash_table_lookup(priv->servers, server) == NULL); g_signal_connect_after( G_OBJECT(server), "notify::status", G_CALLBACK(infd_server_pool_notify_status_cb), server_pool ); g_signal_connect_after( G_OBJECT(server), "new-connection", G_CALLBACK(infd_server_pool_new_connection_cb), server_pool ); entry = g_slice_new(InfdServerPoolEntry); entry->server = server; entry->publishers = NULL; g_hash_table_insert(priv->servers, server, entry); g_object_ref(G_OBJECT(server)); } /** * infd_server_pool_add_local_publisher: * @server_pool: A #InfdServerPool. * @server: A #InfdXmppServer added to @server_pool. * @publisher: A #InfLocalPublisher. * * Publishes a service offered by @server on the local network via * @publisher. This can safely be called when @server is not yet open. The * service will be published as soon as the server opens. */ /* TODO: Make a InfdLocalServer interface to query the port? */ void infd_server_pool_add_local_publisher(InfdServerPool* server_pool, InfdXmppServer* server, InfLocalPublisher* publisher) { InfdServerPoolPrivate* priv; InfdServerPoolEntry* entry; InfdServerPoolPublisher* server_pool_publisher; InfdXmlServerStatus status; g_return_if_fail(INFD_IS_SERVER_POOL(server_pool)); g_return_if_fail(INFD_IS_XMPP_SERVER(server)); g_return_if_fail(INF_IS_LOCAL_PUBLISHER(publisher)); priv = INFD_SERVER_POOL_PRIVATE(server_pool); entry = (InfdServerPoolEntry*)g_hash_table_lookup(priv->servers, server); g_return_if_fail(entry != NULL); /* TODO: Bail if we are already publishing via this publisher */ /* TODO: Only announce on the address family server is listening on. * Otherwise we might announce the service on ipv6 without anyone * listening there. */ server_pool_publisher = g_slice_new(InfdServerPoolPublisher); server_pool_publisher->type = INFD_SERVER_POOL_PUBLISHER_LOCAL; server_pool_publisher->shared.local.publisher = publisher; server_pool_publisher->shared.local.item = NULL; g_object_ref(G_OBJECT(publisher)); entry->publishers = g_slist_prepend( entry->publishers, server_pool_publisher ); /* Initial publish when server is open */ g_object_get(G_OBJECT(server), "status", &status, NULL); if(status == INFD_XML_SERVER_OPEN) infd_server_pool_entry_publish_with(entry, server_pool_publisher); } /** * infd_server_pool_remove_server: * @server_pool: A #InfdServerPool. * @server: A #InfdXmlServer which was previously added to @server_pool. * * Removed @server from @servor_pool. If @server was published via * some publishers then it will be unpublished automatically. */ void infd_server_pool_remove_server(InfdServerPool* server_pool, InfdXmlServer* server) { InfdServerPoolPrivate* priv; InfdServerPoolEntry* entry; g_return_if_fail(INFD_IS_SERVER_POOL(server_pool)); g_return_if_fail(INFD_IS_XML_SERVER(server)); priv = INFD_SERVER_POOL_PRIVATE(server_pool); entry = (InfdServerPoolEntry*)g_hash_table_lookup(priv->servers, server); g_return_if_fail(entry != NULL); infd_server_pool_entry_free(server_pool, entry); g_hash_table_remove(priv->servers, server); } /** * infd_server_pool_foreach_server: * @server_pool: A #InfdServerPool. * @func: (scope call): The function to be called for each server. * @user_data: Additional data to pass to @func. * * Calls @func for each server in pool registered with * infd_server_pool_add_server(). */ void infd_server_pool_foreach_server(InfdServerPool* server_pool, InfdServerPoolForeachServerFunc func, gpointer user_data) { InfdServerPoolPrivate* priv; GHashTableIter iter; gpointer value; priv = INFD_SERVER_POOL_PRIVATE(server_pool); g_hash_table_iter_init(&iter, priv->servers); while(g_hash_table_iter_next(&iter, NULL, &value)) func( ((InfdServerPoolEntry*)value)->server, user_data); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/PaxHeaders.26529/Makefile.am0000644000000000000000000000013213034544714020164 xustar0030 mtime=1483917772.686920573 30 atime=1483917772.682920565 30 ctime=1488261588.904139275 libinfinity-0.7.1/libinfinity/Makefile.am0000644000175000017500000002177513034544714020732 0ustar00arminarmin00000000000000# TODO: Find a way to have the version number set automatically. lib_LTLIBRARIES = libinfinity-0.7.la libinfinity_0_7_la_CPPFLAGS = \ -I$(top_srcdir) \ $(infinity_CFLAGS) \ $(avahi_CFLAGS) libinfinity_0_7_la_LDFLAGS = \ -no-undefined \ -version-info $(LIBINFINITY_LIBTOOL_VERSION) libinfinity_0_7_la_LIBADD = \ $(infinity_LIBS) \ $(glib_LIBS) \ $(avahi_LIBS) libinfinity_0_7_ladir = \ $(includedir)/libinfinity-$(LIBINFINITY_API_VERSION)/libinfinity adopteddir = $(libinfinity_0_7_ladir)/adopted adopted_HEADERS = \ adopted/inf-adopted-algorithm.h \ adopted/inf-adopted-no-operation.h \ adopted/inf-adopted-operation.h \ adopted/inf-adopted-request.h \ adopted/inf-adopted-request-log.h \ adopted/inf-adopted-session.h \ adopted/inf-adopted-session-record.h \ adopted/inf-adopted-session-replay.h \ adopted/inf-adopted-split-operation.h \ adopted/inf-adopted-state-vector.h \ adopted/inf-adopted-undo-grouping.h \ adopted/inf-adopted-user.h commondir = $(libinfinity_0_7_ladir)/common common_HEADERS = \ common/inf-acl.h \ common/inf-async-operation.h \ common/inf-browser.h \ common/inf-browser-iter.h \ common/inf-buffer.h \ common/inf-certificate-chain.h \ common/inf-certificate-credentials.h \ common/inf-certificate-verify.h \ common/inf-cert-util.h \ common/inf-chat-buffer.h \ common/inf-chat-session.h \ common/inf-discovery.h \ common/inf-discovery-avahi.h \ common/inf-error.h \ common/inf-file-util.h \ common/inf-init.h \ common/inf-io.h \ common/inf-ip-address.h \ common/inf-keepalive.h \ common/inf-local-publisher.h \ common/inf-name-resolver.h \ common/inf-native-socket.h \ common/inf-protocol.h \ common/inf-request.h \ common/inf-request-result.h \ common/inf-sasl-context.h \ common/inf-session.h \ common/inf-session-proxy.h \ common/inf-simulated-connection.h \ common/inf-standalone-io.h \ common/inf-tcp-connection.h \ common/inf-user.h \ common/inf-user-table.h \ common/inf-xml-connection.h \ common/inf-xml-util.h \ common/inf-xmpp-connection.h \ common/inf-xmpp-manager.h communicationdir = $(libinfinity_0_7_ladir)/communication communication_HEADERS = \ communication/inf-communication-central-factory.h \ communication/inf-communication-central-method.h \ communication/inf-communication-factory.h \ communication/inf-communication-group.h \ communication/inf-communication-hosted-group.h \ communication/inf-communication-joined-group.h \ communication/inf-communication-manager.h \ communication/inf-communication-method.h \ communication/inf-communication-object.h \ communication/inf-communication-registry.h clientdir = $(libinfinity_0_7_ladir)/client client_HEADERS = \ client/infc-browser.h \ client/infc-note-plugin.h \ client/infc-progress-request.h \ client/infc-request.h \ client/infc-request-manager.h \ client/infc-session-proxy.h serverdir = $(libinfinity_0_7_ladir)/server server_HEADERS = \ server/infd-account-storage.h \ server/infd-chat-filesystem-format.h \ server/infd-directory.h \ server/infd-filesystem-account-storage.h \ server/infd-filesystem-storage.h \ server/infd-note-plugin.h \ server/infd-progress-request.h \ server/infd-request.h \ server/infd-server-pool.h \ server/infd-session-proxy.h \ server/infd-storage.h \ server/infd-tcp-server.h \ server/infd-xml-server.h \ server/infd-xmpp-server.h libinfinity_0_7_la_HEADERS = \ inf-config.h noinst_HEADERS = \ common/inf-tcp-connection-private.h \ communication/inf-communication-group-private.h \ inf-define-enum.h \ inf-dll.h \ inf-i18n.h \ inf-signals.h commonSOURCES = \ adopted/inf-adopted-algorithm.c \ adopted/inf-adopted-no-operation.c \ adopted/inf-adopted-operation.c \ adopted/inf-adopted-request.c \ adopted/inf-adopted-request-log.c \ adopted/inf-adopted-session.c \ adopted/inf-adopted-session-record.c \ adopted/inf-adopted-session-replay.c \ adopted/inf-adopted-split-operation.c \ adopted/inf-adopted-state-vector.c \ adopted/inf-adopted-undo-grouping.c \ adopted/inf-adopted-user.c \ common/inf-acl.c \ common/inf-async-operation.c \ common/inf-browser.c \ common/inf-browser-iter.c \ common/inf-buffer.c \ common/inf-certificate-chain.c \ common/inf-certificate-credentials.c \ common/inf-certificate-verify.c \ common/inf-cert-util.c \ common/inf-chat-buffer.c \ common/inf-chat-session.c \ common/inf-discovery-avahi.c \ common/inf-discovery.c \ common/inf-error.c \ common/inf-file-util.c \ common/inf-init.c \ common/inf-io.c \ common/inf-ip-address.c \ common/inf-keepalive.c \ common/inf-local-publisher.c \ common/inf-name-resolver.c \ common/inf-native-socket.c \ common/inf-protocol.c \ common/inf-request.c \ common/inf-request-result.c \ common/inf-sasl-context.c \ common/inf-session.c \ common/inf-session-proxy.c \ common/inf-simulated-connection.c \ common/inf-standalone-io.c \ common/inf-tcp-connection.c \ common/inf-user.c \ common/inf-user-table.c \ common/inf-xml-connection.c \ common/inf-xml-util.c \ common/inf-xmpp-connection.c \ common/inf-xmpp-manager.c \ communication/inf-communication-central-factory.c \ communication/inf-communication-central-method.c \ communication/inf-communication-factory.c \ communication/inf-communication-group.c \ communication/inf-communication-hosted-group.c \ communication/inf-communication-joined-group.c \ communication/inf-communication-manager.c \ communication/inf-communication-method.c \ communication/inf-communication-object.c \ communication/inf-communication-registry.c clientSOURCES = \ client/infc-browser.c \ client/infc-progress-request.c \ client/infc-request.c \ client/infc-request-manager.c \ client/infc-session-proxy.c serverSOURCES = \ server/infd-account-storage.c \ server/infd-chat-filesystem-format.c \ server/infd-directory.c \ server/infd-filesystem-account-storage.c \ server/infd-filesystem-storage.c \ server/infd-progress-request.c \ server/infd-request.c \ server/infd-server-pool.c \ server/infd-session-proxy.c \ server/infd-storage.c \ server/infd-tcp-server.c \ server/infd-xml-server.c \ server/infd-xmpp-server.c libinfinity_0_7_la_SOURCES = \ ${commonSOURCES} \ ${clientSOURCES} \ ${serverSOURCES} \ inf-dll.c \ inf-i18n.c \ inf-signals.c if HAVE_INTROSPECTION -include $(INTROSPECTION_MAKEFILE) INTROSPECTION_GIRS = Infinity-0.7.gir Infinityc-0.7.gir Infinityd-0.7.gir INTROSPECTION_SCANNER_ENV = CC="${CC}" INTROSPECTION_COMPILER_ARGS = \ --includedir=${top_srcdir}/libinfinity Infinity-0.7.gir: libinfinity-0.7.la Infinityc-0.7.gir: libinfinity-0.7.la Infinity-0.7.typelib Infinityd-0.7.gir: libinfinity-0.7.la Infinity-0.7.typelib Infinity_0_7_gir_SCANNERFLAGS = \ -I${top_srcdir} \ -n Infinity \ --add-include-path=${top_srcdir}/libinfinity \ --identifier-prefix=Inf Infinity_0_7_gir_NAMESPACE = Infinity Infinity_0_7_gir_VERSION = 0.7 Infinity_0_7_gir_CFLAGS = $(infinity_CFLAGS) Infinity_0_7_gir_LIBS = libinfinity-0.7.la Infinity_0_7_gir_FILES = \ $(commonSOURCES) \ $(adopted_HEADERS) \ $(common_HEADERS) \ $(communication_HEADERS) # We ship simple "stub" .gir files for gnutls and gsasl, since we expose some # of these objects and expect the user of the library to use their API. Infinity_0_7_gir_INCLUDES = GObject-2.0 libxml2-2.0 InfGnutls-3.0 InfGsasl-1.0 Infinity_0_7_gir_PACKAGES = gobject-2.0 Infinity_0_7_gir_EXPORT_PACKAGES = libinfinity-0.7 # TODO: I would prefer to have all symbols in one gir, however that does not # work at the moment since the prefix for client or server specific functions # have a different prefix. We should just rename those classes, so that all # prefixes inside libinfinity are the same. Infinityc_0_7_gir_SCANNERFLAGS = \ -I${top_srcdir} \ --add-include-path=${top_srcdir}/libinfinity \ --add-include-path=${top_builddir}/libinfinity \ -n Infinityc \ --identifier-prefix=Infc Infinityc_0_7_gir_NAMESPACE = Infinityc Infinityc_0_7_gir_VERSION = 0.7 Infinityc_0_7_gir_CFLAGS = $(infinity_CFLAGS) Infinityc_0_7_gir_LIBS = libinfinity-0.7.la Infinityc_0_7_gir_FILES = \ $(clientSOURCES) \ $(client_HEADERS) Infinityc_0_7_gir_INCLUDES = Infinity-0.7 Infinityc_0_7_gir_PACKAGES = gobject-2.0 Infinityc_0_7_gir_EXPORT_PACKAGES = libinfinity-0.7 Infinityd_0_7_gir_SCANNERFLAGS = \ -I${top_srcdir} \ --add-include-path=${top_srcdir}/libinfinity \ --add-include-path=${top_builddir}/libinfinity \ -n Infinityd \ --identifier-prefix=Infd Infinityd_0_7_gir_NAMESPACE = Infinityd Infinityd_0_7_gir_VERSION = 0.7 Infinityd_0_7_gir_CFLAGS = $(infinity_CFLAGS) Infinityd_0_7_gir_LIBS = libinfinity-0.7.la Infinityd_0_7_gir_FILES = \ $(serverSOURCES) \ $(server_HEADERS) Infinityd_0_7_gir_INCLUDES = Infinity-0.7 Infinityd_0_7_gir_PACKAGES = gobject-2.0 Infinityd_0_7_gir_EXPORT_PACKAGES = libinfinity-0.7 girdir = $(datadir)/gir-1.0 gir_DATA = InfGnutls-3.0.gir InfGsasl-1.0.gir Infinity-0.7.gir Infinityc-0.7.gir Infinityd-0.7.gir typelibdir = $(libdir)/girepository-1.0 typelib_DATA = InfGnutls-3.0.typelib InfGsasl-1.0.typelib Infinity-0.7.typelib Infinityc-0.7.typelib Infinityd-0.7.typelib CLEANFILES = \ $(INTROSPECTION_GIRS) \ $(typelib_DATA) EXTRA_DIST = \ InfGnutls-3.0.gir \ InfGsasl-1.0.gir endif libinfinity-0.7.1/libinfinity/PaxHeaders.26529/inf-define-enum.h0000644000000000000000000000013213034342512021237 xustar0030 mtime=1483851082.041718492 30 atime=1483851082.041718492 30 ctime=1488261588.992139083 libinfinity-0.7.1/libinfinity/inf-define-enum.h0000644000175000017500000000360113034342512021771 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_DEFINE_ENUM_H__ #define __INF_DEFINE_ENUM_H__ #include #define INF_DEFINE_ENUM_TYPE(TypeName, type_name, values) \ GType \ type_name##_get_type(void) \ { \ static volatile gsize inf_define_type_id__volatile = 0; \ if(g_once_init_enter(&inf_define_type_id__volatile)) \ { \ GType inf_define_type_id = g_enum_register_static( \ #TypeName, \ values \ ); \ g_once_init_leave(&inf_define_type_id__volatile, inf_define_type_id); \ } \ \ return inf_define_type_id__volatile; \ } #define INF_DEFINE_FLAGS_TYPE(TypeName, type_name, values) \ GType \ type_name##_get_type(void) \ { \ static volatile gsize inf_define_type_id__volatile = 0; \ if(g_once_init_enter(&inf_define_type_id__volatile)) \ { \ GType inf_define_type_id = g_flags_register_static( \ #TypeName, \ values \ ); \ g_once_init_leave(&inf_define_type_id__volatile, inf_define_type_id); \ } \ \ return inf_define_type_id__volatile; \ } #endif /* __INF_DEFINE_ENUM_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/PaxHeaders.26529/inf-signals.h0000644000000000000000000000013213034342512020503 xustar0030 mtime=1483851082.041718492 30 atime=1483851082.041718492 30 ctime=1488261588.996139074 libinfinity-0.7.1/libinfinity/inf-signals.h0000644000175000017500000000277213034342512021245 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_SIGNALS_H__ #define __INF_SIGNALS_H__ #include G_BEGIN_DECLS guint inf_signal_handlers_disconnect_by_func(gpointer instance, GCallback func, gpointer data); guint inf_signal_handlers_block_by_func(gpointer instance, GCallback func, gpointer data); guint inf_signal_handlers_unblock_by_func(gpointer instance, GCallback func, gpointer data); G_END_DECLS #endif /* __INF_SIGNALS_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/PaxHeaders.26529/InfGsasl-1.0.gir0000644000000000000000000000013213034342512020625 xustar0030 mtime=1483851082.021718383 30 atime=1483851082.021718383 30 ctime=1488261589.140138759 libinfinity-0.7.1/libinfinity/InfGsasl-1.0.gir0000644000175000017500000000122713034342512021361 0ustar00arminarmin00000000000000 libinfinity-0.7.1/libinfinity/PaxHeaders.26529/client0000644000000000000000000000013213055210725017324 xustar0030 mtime=1488261589.112138821 30 atime=1488261588.904139275 30 ctime=1488261589.112138821 libinfinity-0.7.1/libinfinity/client/0000755000175000017500000000000013055210725020133 5ustar00arminarmin00000000000000libinfinity-0.7.1/libinfinity/client/PaxHeaders.26529/infc-request.h0000644000000000000000000000013213034342512022154 xustar0030 mtime=1483851082.029718427 30 atime=1483851082.029718427 30 ctime=1488261588.928139222 libinfinity-0.7.1/libinfinity/client/infc-request.h0000644000175000017500000000412013034342512022703 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INFC_REQUEST_H__ #define __INFC_REQUEST_H__ #include G_BEGIN_DECLS #define INFC_TYPE_REQUEST (infc_request_get_type()) #define INFC_REQUEST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INFC_TYPE_REQUEST, InfcRequest)) #define INFC_REQUEST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INFC_TYPE_REQUEST, InfcRequestClass)) #define INFC_IS_REQUEST(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INFC_TYPE_REQUEST)) #define INFC_IS_REQUEST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INFC_TYPE_REQUEST)) #define INFC_REQUEST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INFC_TYPE_REQUEST, InfcRequestClass)) /** * InfcRequest: * * #InfcRequest is an opaque data type. You should only access it * via the public API functions. */ typedef struct _InfcRequest InfcRequest; typedef struct _InfcRequestClass InfcRequestClass; /** * InfcRequestClass: * * This structure does not contain any public fields. */ struct _InfcRequestClass { /*< private >*/ GObjectClass parent_class; /*< public >*/ }; struct _InfcRequest { GObject parent; }; GType infc_request_get_type(void) G_GNUC_CONST; G_END_DECLS #endif /* __INFC_REQUEST_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/client/PaxHeaders.26529/infc-note-plugin.h0000644000000000000000000000013213034342512022725 xustar0030 mtime=1483851082.025718404 30 atime=1483851082.025718404 30 ctime=1488261588.924139232 libinfinity-0.7.1/libinfinity/client/infc-note-plugin.h0000644000175000017500000000332113034342512023456 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INFC_NOTE_PLUGIN_H__ #define __INFC_NOTE_PLUGIN_H__ #include #include #include G_BEGIN_DECLS typedef InfSession*(*InfcNotePluginSessionNew)(InfIo*, InfCommunicationManager*, InfSessionStatus, InfCommunicationGroup*, InfXmlConnection*, const char*, gpointer); typedef struct _InfcNotePlugin InfcNotePlugin; struct _InfcNotePlugin { gpointer user_data; const gchar* note_type; InfcNotePluginSessionNew session_new; }; G_END_DECLS #endif /* __INFC_NOTE_PLUGIN_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/client/PaxHeaders.26529/infc-request-manager.c0000644000000000000000000000013213034342512023557 xustar0030 mtime=1483851082.029718427 30 atime=1483851082.029718427 30 ctime=1488261589.112138821 libinfinity-0.7.1/libinfinity/client/infc-request-manager.c0000644000175000017500000006103413034342512024315 0ustar00arminarmin00000000000000/* infcinote - Collaborative notetaking application * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:infc-request-manager * @short_description: Keeps track of pending asynchronous requests * @see_also: #InfRequest, #InfcRequest, #InfcBrowser, #InfcSessionProxy * @include: libinfinity/client/infc-request-manager.h * @stability: Unstable * * This class keeps track of requests sent by #InfcBrowser and * #InfcSessionProxy (typically via the #InfBrowser and #InfSessionProxy * APIs). It is used internally by #InfcBrowser and #InfcSessionProxy, and * usually end-users of the libinfinity API do not need to use this class * directly. * * Requests can be added with the infc_request_manager_add_request() and * infc_request_manager_add_request_valist() methods and retrieved back via * their unique seq number with infc_request_manager_get_request_by_seq(). In * addition to this basic API, there are various convenience functions * available as well. **/ #include #include #include #include #include #include #include #include typedef struct _InfcRequestManagerForeachData InfcRequestManagerForeachData; struct _InfcRequestManagerForeachData { InfcRequestManagerForeachFunc func; gpointer user_data; const gchar* name; }; typedef struct _InfcRequestManagerPrivate InfcRequestManagerPrivate; struct _InfcRequestManagerPrivate { GHashTable* requests; guint seq_id; guint seq_counter; }; enum { PROP_0, PROP_SEQUENCE_ID }; enum { REQUEST_ADD, REQUEST_REMOVE, LAST_SIGNAL }; #define INFC_REQUEST_MANAGER_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INFC_TYPE_REQUEST_MANAGER, InfcRequestManagerPrivate)) static guint request_manager_signals[LAST_SIGNAL]; G_DEFINE_TYPE_WITH_CODE(InfcRequestManager, infc_request_manager, G_TYPE_OBJECT, G_ADD_PRIVATE(InfcRequestManager)) static void infc_request_manager_foreach_request_func(gpointer key, gpointer value, gpointer user_data) { InfcRequest* request; InfcRequestManagerForeachData* foreach_data; gchar* type; request = INFC_REQUEST(value); foreach_data = (InfcRequestManagerForeachData*)user_data; g_object_get(G_OBJECT(request), "type", &type, NULL); if(foreach_data->name == NULL || strcmp(foreach_data->name, type) == 0) { foreach_data->func(request, foreach_data->user_data); } g_free(type); } /* TODO: inf_protocol_version_parse() uses a very similar routine. We should * avoid the code duplication. */ static gboolean infc_request_manager_parse_seq(const gchar* seq, guint* seq_id, guint* seq_num, GError** error) { gchar* endptr; unsigned long sid; unsigned long snum; errno = 0; sid = strtoul(seq, &endptr, 10); if(errno == ERANGE || sid > (unsigned long)G_MAXUINT) { g_set_error_literal( error, inf_request_error_quark(), INF_REQUEST_ERROR_INVALID_SEQ, _("Sequence identifier causes overflow") ); return FALSE; } if(*endptr != '/') { g_set_error_literal( error, inf_request_error_quark(), INF_REQUEST_ERROR_INVALID_SEQ, _("Sequence components are not separated by '/'") ); return FALSE; } errno = 0; snum = strtoul(endptr + 1, &endptr, 10); if(errno == ERANGE || snum > (unsigned long)G_MAXUINT) { g_set_error_literal( error, inf_request_error_quark(), INF_REQUEST_ERROR_INVALID_SEQ, _("Sequence number causes overflow") ); return FALSE; } if(*endptr != '\0') { g_set_error_literal( error, inf_request_error_quark(), INF_REQUEST_ERROR_INVALID_SEQ, _("Trailing characters after sequence number") ); return FALSE; } if(seq_id) *seq_id = sid; if(seq_num) *seq_num = snum; return TRUE; } static void infc_request_manager_init(InfcRequestManager* manager) { InfcRequestManagerPrivate* priv; priv = INFC_REQUEST_MANAGER_PRIVATE(manager); priv->requests = g_hash_table_new_full( NULL, NULL, NULL, (GDestroyNotify)g_object_unref ); priv->seq_id = 0; priv->seq_counter = 0; } static void infc_request_manager_dispose(GObject* object) { InfcRequestManager* request_manager; InfcRequestManagerPrivate* priv; request_manager = INFC_REQUEST_MANAGER(object); priv = INFC_REQUEST_MANAGER_PRIVATE(request_manager); g_hash_table_destroy(priv->requests); priv->requests = NULL; G_OBJECT_CLASS(infc_request_manager_parent_class)->dispose(object); } static void infc_request_manager_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfcRequestManager* request_manager; InfcRequestManagerPrivate* priv; request_manager = INFC_REQUEST_MANAGER(object); priv = INFC_REQUEST_MANAGER_PRIVATE(request_manager); switch(prop_id) { case PROP_SEQUENCE_ID: priv->seq_id = g_value_get_uint(value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void infc_request_manager_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfcRequestManager* request_manager; InfcRequestManagerPrivate* priv; request_manager = INFC_REQUEST_MANAGER(object); priv = INFC_REQUEST_MANAGER_PRIVATE(request_manager); switch(prop_id) { case PROP_SEQUENCE_ID: g_value_set_uint(value, priv->seq_id); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void infc_request_manager_request_add(InfcRequestManager* manager, InfcRequest* request) { InfcRequestManagerPrivate* priv; guint seq; gpointer seq_ptr; priv = INFC_REQUEST_MANAGER_PRIVATE(manager); g_object_get(G_OBJECT(request), "seq", &seq, NULL); seq_ptr = GUINT_TO_POINTER(seq); g_assert(g_hash_table_lookup(priv->requests, seq_ptr) == NULL); g_hash_table_insert(priv->requests, seq_ptr, request); g_object_ref(G_OBJECT(request)); } static void infc_request_manager_request_remove(InfcRequestManager* manager, InfcRequest* request) { InfcRequestManagerPrivate* priv; guint seq; gpointer seq_ptr; priv = INFC_REQUEST_MANAGER_PRIVATE(manager); g_object_get(G_OBJECT(request), "seq", &seq, NULL); seq_ptr = GUINT_TO_POINTER(seq); g_assert(g_hash_table_lookup(priv->requests, seq_ptr) != NULL); g_hash_table_remove(priv->requests, seq_ptr); } static void infc_request_manager_class_init( InfcRequestManagerClass* request_manager_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(request_manager_class); object_class->dispose = infc_request_manager_dispose; object_class->set_property = infc_request_manager_set_property; object_class->get_property = infc_request_manager_get_property; request_manager_class->request_add = infc_request_manager_request_add; request_manager_class->request_remove = infc_request_manager_request_remove; g_object_class_install_property( object_class, PROP_SEQUENCE_ID, g_param_spec_uint( "sequence-id", "Sequence ID", "The local sequence identifier", 0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); /** * InfcRequestManager::request-add: * @manager: The #InfcRequestManager emitting the signal. * @request: The #InfcRequest that was added. * * This signal is emitted whenever a request was added to the request * manager. */ request_manager_signals[REQUEST_ADD] = g_signal_new( "request-add", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfcRequestManagerClass, request_add), NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, INFC_TYPE_REQUEST ); /** * InfcRequestManager::request-remove: * @manager: The #InfcRequestManager emitting the signal. * @request: The #InfcRequest that was removed. * * This signal is emitted whenever a request was removed from the request * manager. Typically this happens when the request has finished (either * successfully or unsuccessfully). It can also happen when the client is * disconnected from the server while a request was still pending. */ request_manager_signals[REQUEST_REMOVE] = g_signal_new( "request-remove", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfcRequestManagerClass, request_remove), NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, INFC_TYPE_REQUEST ); } /** * infc_request_manager_new: (constructor) * @seq_id: The local sequence ID. * * Creates a new #InfcRequestManager. * * Returns: (transfer full): A newly allocated #InfcRequestManager. **/ InfcRequestManager* infc_request_manager_new(guint seq_id) { GObject* object; object = g_object_new(INFC_TYPE_REQUEST_MANAGER, "sequence-id", seq_id, NULL); return INFC_REQUEST_MANAGER(object); } /** * infc_request_manager_add_request: * @manager: A #InfcRequestManager. * @request_type: The type of request to add, such as #InfcProgressRequest. * @request_name: The name of the request, such as "explore-node" or * "subscribe-session". * @callback: (scope async): A #GCallback that will be called when the request * has completed, or %NULL. * @user_data: Additional data passed to the callback. * @first_property_name: The first property name apart from name and seq to * set for the new request. * @...: The value of the first property, followed optionally by more * name/value pairs, followed by %NULL. * * Adds a request to the request manager. A new signal handler for the * request's "finished" signal will be installed and made to invoke the given * callback. * * Returns: (transfer none): The generated #InfcRequest (actually of type * @request_type). **/ InfcRequest* infc_request_manager_add_request(InfcRequestManager* manager, GType request_type, const gchar* request_name, GCallback callback, gpointer user_data, const gchar* first_property_name, ...) { InfcRequest* request; va_list arglist; va_start(arglist, first_property_name); request = infc_request_manager_add_request_valist( manager, request_type, request_name, callback, user_data, first_property_name, arglist ); va_end(arglist); return request; } /** * infc_request_manager_add_request_valist: * @manager: A #InfcRequestManager. * @request_type: The type of request to add, such as #InfcProgressRequest. * @request_name: The name of the request, such as "explore-node" or * "subscribe-session" * @callback: (scope async): A #GCallback that will be called when the request * has completed, or %NULL. * @user_data: Additional data passed to the callback. * @first_property_name: The first property name apart from name and seq to * set for the new request. * @arglist: The value of the first property, followed optionally by more * name/value pairs, followed by %NULL. * * Adds a request to the request manager. A new signal handler for the * request's "finished" signal will be installed and made to invoke the given * callback. * * Returns: (transfer none): The generated #InfcRequest (actually of type * @request_type). */ InfcRequest* infc_request_manager_add_request_valist(InfcRequestManager* manager, GType request_type, const gchar* request_name, GCallback callback, gpointer user_data, const gchar* first_property_name, va_list arglist) { InfcRequestManagerPrivate* priv; GObjectClass* request_class; InfcRequest* request; GParameter* params; const gchar* prop_name; gsize param_size; gsize param_alloc; guint seq; gchar* error; GParamSpec* pspec; guint i; g_return_val_if_fail(INFC_IS_REQUEST_MANAGER(manager), NULL); g_return_val_if_fail(request_name != NULL, NULL); request_class = g_type_class_ref(request_type); g_return_val_if_fail(request_class != NULL, NULL); priv = INFC_REQUEST_MANAGER_PRIVATE(manager); seq = priv->seq_counter; g_assert( g_hash_table_lookup(priv->requests, GUINT_TO_POINTER(seq)) == NULL ); param_size = 0; param_alloc = 16; params = g_malloc0(param_alloc * sizeof(GParameter)); params[param_size].name = "type"; g_value_init(¶ms[param_size].value, G_TYPE_STRING); g_value_set_static_string(¶ms[param_size].value, request_name); ++ param_size; params[param_size].name = "seq"; g_value_init(¶ms[param_size].value, G_TYPE_UINT); g_value_set_uint(¶ms[param_size].value, seq); ++ param_size; prop_name = first_property_name; error = NULL; while(prop_name != NULL) { pspec = g_object_class_find_property(request_class, prop_name); if(pspec == NULL) { g_warning( "%s: object class `%s' has no attribute named `%s'", G_STRFUNC, g_type_name(request_type), prop_name ); break; } if(param_size >= param_alloc) { param_alloc += 16; params = g_realloc(params, param_alloc * sizeof(GParameter)); } params[param_size].name = prop_name; g_value_init(¶ms[param_size].value, G_PARAM_SPEC_VALUE_TYPE(pspec)); G_VALUE_COLLECT(¶ms[param_size].value, arglist, 0, &error); if(error != NULL) { g_warning("%s: %s", G_STRFUNC, error); g_value_unset(¶ms[param_size].value); g_free(error); break; } ++ param_size; prop_name = va_arg(arglist, const gchar*); } if(prop_name == NULL) { request = INFC_REQUEST(g_object_newv(request_type, param_size, params)); g_hash_table_insert(priv->requests, GUINT_TO_POINTER(seq), request); ++ priv->seq_counter; } else { /* An error occured. We do not use GError here tough, because this is a * most likely a bug in someone's code (if not, it is one in * libinfinity's code). */ request = NULL; } for(i = 0; i < param_size; ++ i) g_value_unset(¶ms[i].value); g_free(params); g_type_class_unref(request_class); if(callback != NULL) { g_signal_connect_after( G_OBJECT(request), "finished", callback, user_data ); } return request; } /** * infc_request_manager_remove_request: * @manager: A #InfcRequestManager. * @request: A #InfcRequest that has previously been added to @manager. * * Removes a request from the request manager. **/ void infc_request_manager_remove_request(InfcRequestManager* manager, InfcRequest* request) { g_return_if_fail(INFC_IS_REQUEST_MANAGER(manager)); g_return_if_fail(INFC_IS_REQUEST(request)); g_object_ref(G_OBJECT(request)); g_signal_emit( G_OBJECT(manager), request_manager_signals[REQUEST_REMOVE], 0, request ); g_object_unref(G_OBJECT(request)); } /** * infc_request_manager_finish_request: * @manager: A #InfcRequestManager. * @request: A #InfcRequest that has previously been added to @manager. * @result: (transfer full): The request result. * * Marks @request as finished using inf_request_finish() and then removes the * request from the manager. The function takes ownership of @result. **/ void infc_request_manager_finish_request(InfcRequestManager* manager, InfcRequest* request, InfRequestResult* result) { g_return_if_fail(INFC_IS_REQUEST_MANAGER(manager)); g_return_if_fail(INFC_IS_REQUEST(request)); g_return_if_fail(result != NULL); g_object_ref(request); infc_request_manager_remove_request(manager, request); inf_request_finish(INF_REQUEST(request), result); g_object_unref(request); } /** * infc_request_manager_fail_request: * @manager: A #InfcRequestManager. * @request: A #InfcRequest that has previously been added to @manager. * @error: Error information why the request failed. * * Marks @request as failed using inf_request_fail() and then removes the * request from the manager. **/ void infc_request_manager_fail_request(InfcRequestManager* manager, InfcRequest* request, const GError* error) { g_return_if_fail(INFC_IS_REQUEST_MANAGER(manager)); g_return_if_fail(INFC_IS_REQUEST(request)); g_return_if_fail(error != NULL); g_object_ref(request); infc_request_manager_remove_request(manager, request); inf_request_fail(INF_REQUEST(request), error); g_object_unref(request); } /** * infc_request_manager_clear: * @manager: A #InfcRequestManager. * * Removes all the requests in @manager. **/ void infc_request_manager_clear(InfcRequestManager* manager) { g_return_if_fail(INFC_IS_REQUEST_MANAGER(manager)); g_hash_table_remove_all(INFC_REQUEST_MANAGER_PRIVATE(manager)->requests); } /** * infc_request_manager_get_request_by_seq: * @manager: A #InfcRequestManager. * @seq: The sequence number to which the request should be retrieved. * * Returns a previously-added request that has the given seq. * * Returns: (transfer none) (allow-none): The request with the given seq, * or %NULL if there is no such request. **/ InfcRequest* infc_request_manager_get_request_by_seq(InfcRequestManager* manager, guint seq) { InfcRequestManagerPrivate* priv; g_return_val_if_fail(INFC_IS_REQUEST_MANAGER(manager), NULL); priv = INFC_REQUEST_MANAGER_PRIVATE(manager); return INFC_REQUEST( g_hash_table_lookup(priv->requests, GUINT_TO_POINTER(seq)) ); } /** * infc_request_manager_get_request_by_xml: * @manager: A #InfcRequestManager. * @name: Name of the expected request. May be %NULL to allow all requests. * @xml: XML node that is supposed to contain a "seq" attribute. * @error: Location to store error information. * * Looks whether there is a "seq" attribute in @xml. If not, the function * returns %NULL (without setting @error). Otherwise, it returns the request * with the given seq and name, if the sequence ID matches. If the "seq" * attribute is set but the actual request is not present (or has another * name), the function returns %NULL and @error is set. * * Returns: (transfer none) (allow-none): The resulting request, or %NULL * if the "seq" attribute was not present or an error occured. **/ InfcRequest* infc_request_manager_get_request_by_xml(InfcRequestManager* manager, const gchar* name, xmlNodePtr xml, GError** error) { InfcRequestManagerPrivate* priv; InfcRequest* request; xmlChar* seq_attr; gboolean has_seq; guint seq_id; guint seq; gchar* request_type; g_return_val_if_fail(INFC_IS_REQUEST_MANAGER(manager), NULL); g_return_val_if_fail(xml != NULL, NULL); priv = INFC_REQUEST_MANAGER_PRIVATE(manager); request = NULL; seq_attr = inf_xml_util_get_attribute(xml, "seq"); if(!seq_attr) return NULL; has_seq = infc_request_manager_parse_seq( (const gchar*)seq_attr, &seq_id, &seq, error ); xmlFree(seq_attr); if(!has_seq) return NULL; /* Not our seq ID */ if(seq_id != priv->seq_id) return NULL; request = infc_request_manager_get_request_by_seq(manager, seq); if(request == NULL) { g_set_error( error, inf_request_error_quark(), INF_REQUEST_ERROR_INVALID_SEQ, _("No such sequence number %u"), seq ); } else { g_object_get(G_OBJECT(request), "type", &request_type, NULL); if(name != NULL && strcmp(name, request_type) != 0) { g_set_error( error, inf_request_error_quark(), INF_REQUEST_ERROR_INVALID_SEQ, _("The request contains a sequence number refering to a request of " "type '%s', but a request of type '%s' was expected"), request_type, name ); request = NULL; } g_free(request_type); } return request; } /** * infc_request_manager_get_request_by_xml_required: * @manager: A #InfcRequestManager. * @name: Name of the expected request. May be %NULL to allow all requests. * @xml: XML node that is supposed to contain a "seq" attribute. * @error: Location to store error information. * * Looks whether there is a "seq" attribute in @xml. If so, it returns the * request with the given seq and name, if the sequence ID matches. If the * "seq" attribute is not set or the actual request is not present (or has * another name), the function returns %NULL and @error is set. * * Returns: (transfer none): The resulting request, or %NULL if an error * occured. **/ InfcRequest* infc_request_manager_get_request_by_xml_required(InfcRequestManager* manager, const gchar* name, xmlNodePtr xml, GError** error) { InfcRequest* request; GError* own_error; own_error = NULL; request = infc_request_manager_get_request_by_xml( manager, name, xml, &own_error ); if(request == NULL) { if(own_error == NULL) { g_set_error_literal( error, inf_request_error_quark(), INF_REQUEST_ERROR_INVALID_SEQ, _("The request does not contain a sequence number, but one " "is required") ); } else { g_propagate_error(error, own_error); } } return request; } /** * infc_request_manager_foreach_request: * @manager: A #InfcRequestManager. * @func: (scope call): The function to be called. * @user_data: Arbitrary data to be passed to @func. * * Calls the given function for each request that has been added to the * request manager. **/ void infc_request_manager_foreach_request(InfcRequestManager* manager, InfcRequestManagerForeachFunc func, gpointer user_data) { InfcRequestManagerPrivate* priv; InfcRequestManagerForeachData data; g_return_if_fail(INFC_IS_REQUEST_MANAGER(manager)); g_return_if_fail(func != NULL); priv = INFC_REQUEST_MANAGER_PRIVATE(manager); data.func = func; data.user_data = user_data; data.name = NULL; g_hash_table_foreach( priv->requests, infc_request_manager_foreach_request_func, &data ); } /** * infc_request_manager_foreach_named_request: * @manager: A #InfcRequestManager. * @name: The name of the request to look for. * @func: (scope call): The function to be called. * @user_data: Arbitrary data to be passed to @func. * * Calls the given function for each request that has been added to the * request manager that has the name @name. **/ void infc_request_manager_foreach_named_request(InfcRequestManager* manager, const gchar* name, InfcRequestManagerForeachFunc func, gpointer user_data) { InfcRequestManagerPrivate* priv; InfcRequestManagerForeachData data; g_return_if_fail(INFC_IS_REQUEST_MANAGER(manager)); g_return_if_fail(func != NULL); priv = INFC_REQUEST_MANAGER_PRIVATE(manager); data.func = func; data.user_data = user_data; data.name = name; g_hash_table_foreach( priv->requests, infc_request_manager_foreach_request_func, &data ); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/client/PaxHeaders.26529/infc-request.c0000644000000000000000000000013213034342512022147 xustar0030 mtime=1483851082.029718427 30 atime=1483851082.029718427 30 ctime=1488261589.112138821 libinfinity-0.7.1/libinfinity/client/infc-request.c0000644000175000017500000001310113034342512022675 0ustar00arminarmin00000000000000/* infcinote - Collaborative notetaking application * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:infc-request * @title: InfcRequest * @short_description: Asynchronous request * @include: libinfinity/client/infc-request.h * @see_also: #InfcBrowser * @stability: Unstable * * #InfcRequest represents an asynchronous operation on the client side, * waiting for a reply from the server. */ #include #include typedef struct _InfcRequestPrivate InfcRequestPrivate; struct _InfcRequestPrivate { gchar* type; guint seq; guint node_id; gboolean finished; }; enum { PROP_0, PROP_TYPE, PROP_SEQ, PROP_PROGRESS, PROP_NODE_ID }; #define INFC_REQUEST_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INFC_TYPE_REQUEST, InfcRequestPrivate)) static void infc_request_request_iface_init(InfRequestInterface* iface); G_DEFINE_TYPE_WITH_CODE(InfcRequest, infc_request, G_TYPE_OBJECT, G_ADD_PRIVATE(InfcRequest) G_IMPLEMENT_INTERFACE(INF_TYPE_REQUEST, infc_request_request_iface_init)) static void infc_request_init(InfcRequest* request) { InfcRequestPrivate* priv; priv = INFC_REQUEST_PRIVATE(request); priv->type = NULL; priv->seq = G_MAXUINT; priv->node_id = G_MAXUINT; priv->finished = FALSE; } static void infc_request_finalize(GObject* object) { InfcRequest* request; InfcRequestPrivate* priv; request = INFC_REQUEST(object); priv = INFC_REQUEST_PRIVATE(request); g_free(priv->type); G_OBJECT_CLASS(infc_request_parent_class)->finalize(object); } static void infc_request_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfcRequest* request; InfcRequestPrivate* priv; request = INFC_REQUEST(object); priv = INFC_REQUEST_PRIVATE(request); switch(prop_id) { case PROP_TYPE: g_assert(priv->type == NULL); /* construct only */ priv->type = g_value_dup_string(value); break; case PROP_SEQ: g_assert(priv->seq == G_MAXUINT); /* construct only */ priv->seq = g_value_get_uint(value); break; case PROP_NODE_ID: g_assert(priv->node_id == G_MAXUINT); /* construct only */ priv->node_id = g_value_get_uint(value); break; case PROP_PROGRESS: /* read only */ default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void infc_request_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfcRequest* request; InfcRequestPrivate* priv; request = INFC_REQUEST(object); priv = INFC_REQUEST_PRIVATE(request); switch(prop_id) { case PROP_TYPE: g_value_set_string(value, priv->type); break; case PROP_SEQ: g_value_set_uint(value, priv->seq); break; case PROP_NODE_ID: g_value_set_uint(value, priv->node_id); break; case PROP_PROGRESS: if(priv->finished) g_value_set_double(value, 1.0); else g_value_set_double(value, 0.0); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static gboolean infc_request_is_local(InfRequest* request) { InfcRequestPrivate* priv; priv = INFC_REQUEST_PRIVATE(request); if(priv->seq == G_MAXUINT) return FALSE; return TRUE; } static void infc_request_finished(InfRequest* request, const InfRequestResult* result, const GError* error) { InfcRequestPrivate* priv; priv = INFC_REQUEST_PRIVATE(request); priv->finished = TRUE; g_object_notify(G_OBJECT(request), "progress"); } static void infc_request_class_init(InfcRequestClass* request_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(request_class); object_class->finalize = infc_request_finalize; object_class->set_property = infc_request_set_property; object_class->get_property = infc_request_get_property; g_object_class_install_property( object_class, PROP_SEQ, g_param_spec_uint( "seq", "Seq", "The sequence number of the request", 0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_NODE_ID, g_param_spec_uint( "node-id", "Node ID", "The ID of the node affected by this request", 0, G_MAXUINT, G_MAXUINT, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_override_property(object_class, PROP_TYPE, "type"); g_object_class_override_property(object_class, PROP_PROGRESS, "progress"); } static void infc_request_request_iface_init(InfRequestInterface* iface) { iface->finished = infc_request_finished; iface->is_local = infc_request_is_local; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/client/PaxHeaders.26529/infc-progress-request.h0000644000000000000000000000013213034342512024016 xustar0030 mtime=1483851082.029718427 30 atime=1483851082.025718404 30 ctime=1488261588.924139232 libinfinity-0.7.1/libinfinity/client/infc-progress-request.h0000644000175000017500000000517013034342512024553 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INFC_PROGRESS_REQUEST_H__ #define __INFC_PROGRESS_REQUEST_H__ #include #include G_BEGIN_DECLS #define INFC_TYPE_PROGRESS_REQUEST (infc_progress_request_get_type()) #define INFC_PROGRESS_REQUEST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INFC_TYPE_PROGRESS_REQUEST, InfcProgressRequest)) #define INFC_PROGRESS_REQUEST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INFC_TYPE_PROGRESS_REQUEST, InfcProgressRequestClass)) #define INFC_IS_PROGRESS_REQUEST(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INFC_TYPE_PROGRESS_REQUEST)) #define INFC_IS_PROGRESS_REQUEST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INFC_TYPE_PROGRESS_REQUEST)) #define INFC_PROGRESS_REQUEST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INFC_TYPE_PROGRESS_REQUEST, InfcProgressRequestClass)) typedef struct _InfcProgressRequest InfcProgressRequest; typedef struct _InfcProgressRequestClass InfcProgressRequestClass; /** * InfcProgressRequestClass: * * This structure does not contain any public fields. */ struct _InfcProgressRequestClass { /*< private >*/ InfcRequestClass parent_class; }; /** * InfcProgressRequest: * * #InfcProgressRequest is an opaque data type. You should only access it via * the public API functions. */ struct _InfcProgressRequest { /*< private >*/ InfcRequest parent; }; GType infc_progress_request_get_type(void) G_GNUC_CONST; void infc_progress_request_initiated(InfcProgressRequest* request, guint total); gboolean infc_progress_request_get_initiated(InfcProgressRequest* request); void infc_progress_request_progress(InfcProgressRequest* request); G_END_DECLS #endif /* __INFC_PROGRESS_REQUEST_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/client/PaxHeaders.26529/infc-progress-request.c0000644000000000000000000000013213034342512024011 xustar0030 mtime=1483851082.025718404 30 atime=1483851082.025718404 30 ctime=1488261589.108138829 libinfinity-0.7.1/libinfinity/client/infc-progress-request.c0000644000175000017500000001503013034342512024542 0ustar00arminarmin00000000000000/* infcinote - Collaborative notetaking application * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:infc-progress-request * @title: InfcProgressRequest * @short_description: Asynchronous request with dynamic progress. * @include: libinfinity/client/infc-progress-request.h * @see_also: #InfcRequest, #InfcBrowser * @stability: Unstable * * This class represents a request which consists of multiple steps and * for which progress on the overall operation is reported. */ #include typedef struct _InfcProgressRequestPrivate InfcProgressRequestPrivate; struct _InfcProgressRequestPrivate { guint current; guint total; gboolean initiated; }; enum { PROP_0, PROP_CURRENT, PROP_TOTAL, PROP_PROGRESS }; #define INFC_PROGRESS_REQUEST_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INFC_TYPE_PROGRESS_REQUEST, InfcProgressRequestPrivate)) G_DEFINE_TYPE_WITH_CODE(InfcProgressRequest, infc_progress_request, INFC_TYPE_REQUEST, G_ADD_PRIVATE(InfcProgressRequest)) static void infc_progress_request_init(InfcProgressRequest* request) { InfcProgressRequestPrivate* priv; priv = INFC_PROGRESS_REQUEST_PRIVATE(request); priv->current = 0; priv->total = 0; priv->initiated = FALSE; } static void infc_progress_request_finalize(GObject* object) { InfcProgressRequest* request; InfcProgressRequestPrivate* priv; request = INFC_PROGRESS_REQUEST(object); priv = INFC_PROGRESS_REQUEST_PRIVATE(request); G_OBJECT_CLASS(infc_progress_request_parent_class)->finalize(object); } static void infc_progress_request_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfcProgressRequest* request; InfcProgressRequestPrivate* priv; request = INFC_PROGRESS_REQUEST(object); priv = INFC_PROGRESS_REQUEST_PRIVATE(request); switch(prop_id) { case PROP_TOTAL: case PROP_CURRENT: case PROP_PROGRESS: /* readonly */ default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void infc_progress_request_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfcProgressRequest* progress_request; InfcProgressRequestPrivate* priv; gboolean finished; progress_request = INFC_PROGRESS_REQUEST(object); priv = INFC_PROGRESS_REQUEST_PRIVATE(progress_request); switch(prop_id) { case PROP_TOTAL: g_value_set_uint(value, priv->total); break; case PROP_CURRENT: g_value_set_uint(value, priv->current); break; case PROP_PROGRESS: if(priv->initiated == FALSE) g_value_set_double(value, 0.0); else if(priv->total == 0) g_value_set_double(value, 1.0); else g_value_set_double(value, (double)priv->current / (double)priv->total); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void infc_progress_request_class_init(InfcProgressRequestClass* request_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(request_class); object_class->finalize = infc_progress_request_finalize; object_class->set_property = infc_progress_request_set_property; object_class->get_property = infc_progress_request_get_property; g_object_class_install_property( object_class, PROP_CURRENT, g_param_spec_uint( "current", "Current", "The current number of finished operations", 0, G_MAXUINT, 0, G_PARAM_READABLE ) ); g_object_class_install_property( object_class, PROP_TOTAL, g_param_spec_uint( "total", "Total", "The total number of operations", 0, G_MAXUINT, 0, G_PARAM_READABLE ) ); g_object_class_override_property(object_class, PROP_PROGRESS, "progress"); } /** * infc_progress_request_initiated: * @request: An #InfcProgressRequest. * @total: The total number of items. * * Initiates the request. A progress request is considered initiated as soon * as the total number of items is known. **/ void infc_progress_request_initiated(InfcProgressRequest* request, guint total) { InfcProgressRequestPrivate* priv; g_return_if_fail(INFC_IS_PROGRESS_REQUEST(request)); priv = INFC_PROGRESS_REQUEST_PRIVATE(request); g_return_if_fail(priv->initiated == FALSE); priv->total = total; priv->initiated = TRUE; g_object_notify(G_OBJECT(request), "total"); if(priv->total == 0) g_object_notify(G_OBJECT(request), "progress"); } /** * infc_progress_request_get_initiated: * @request: A #InfcProgressRequest. * * Returns whether the request was initiated, i.e. the total number of items * is known. * * Returns: Whether the request was initiated. **/ gboolean infc_progress_request_get_initiated(InfcProgressRequest* request) { g_return_val_if_fail(INFC_IS_PROGRESS_REQUEST(request), FALSE); return INFC_PROGRESS_REQUEST_PRIVATE(request)->initiated; } /** * infc_progress_request_progress: * @request: A #InfcProgressRequest. * * Indicates that one more operation has been performed and changes the * #InfcProgressRequest:current property accordingly. The request must be * initiated before this function can be called. **/ void infc_progress_request_progress(InfcProgressRequest* request) { InfcProgressRequestPrivate* priv; g_return_if_fail(INFC_IS_PROGRESS_REQUEST(request)); priv = INFC_PROGRESS_REQUEST_PRIVATE(request); g_return_if_fail(priv->initiated == TRUE); g_return_if_fail(priv->current < priv->total); ++priv->current; g_object_notify(G_OBJECT(request), "current"); g_object_notify(G_OBJECT(request), "progress"); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/client/PaxHeaders.26529/infc-session-proxy.c0000644000000000000000000000013213034342512023321 xustar0030 mtime=1483851082.029718427 30 atime=1483851082.029718427 30 ctime=1488261589.116138812 libinfinity-0.7.1/libinfinity/client/infc-session-proxy.c0000644000175000017500000010645113034342512024062 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:infc-session-proxy * @title: InfcSessionProxy * @short_description: Client-side session management * @include: libinfinity/client/infc-session-proxy.h * @see_also: #InfSession * @stability: Unstable * * #InfcSessionProxy is a manager for #InfSession that is specific for the * client side. The #InfcSessionProxy manages exactly one #InfSession. It is * usually created by #InfcBrowser when a subscription to a node is made. * * #InfcSessionProxy allows to perform client-specific operations for the * session it manages, such as joining a user. In addition it handles requests * made by its counterpart, #InfdSessionProxy, for the server side, such as * remote user joins and forced session closure. * * #InfcSessionProxy implements the #InfSessionProxy interface, which can be * used to access the underlying #InfSession or to join a user. */ #include #include #include #include #include #include #include #include #include #include #include typedef struct _InfcSessionProxyPrivate InfcSessionProxyPrivate; struct _InfcSessionProxyPrivate { InfSession* session; InfCommunicationJoinedGroup* subscription_group; InfXmlConnection* connection; InfcRequestManager* request_manager; }; enum { PROP_0, PROP_SESSION, PROP_SUBSCRIPTION_GROUP, PROP_SEQUENCE_ID, PROP_CONNECTION }; #define INFC_SESSION_PROXY_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INFC_TYPE_SESSION_PROXY, InfcSessionProxyPrivate)) static void infc_session_proxy_communication_object_iface_init(InfCommunicationObjectInterface* iface); static void infc_session_proxy_session_proxy_iface_init(InfSessionProxyInterface* iface); G_DEFINE_TYPE_WITH_CODE(InfcSessionProxy, infc_session_proxy, G_TYPE_OBJECT, G_ADD_PRIVATE(InfcSessionProxy) G_IMPLEMENT_INTERFACE(INF_COMMUNICATION_TYPE_OBJECT, infc_session_proxy_communication_object_iface_init) G_IMPLEMENT_INTERFACE(INF_TYPE_SESSION_PROXY, infc_session_proxy_session_proxy_iface_init)) static void infc_session_proxy_release_connection(InfcSessionProxy* proxy); static void infc_session_proxy_unsubscribe_connection(InfcSessionProxy* proxy) { InfcSessionProxyPrivate* priv; InfSessionSyncStatus sync_status; InfXmlConnectionStatus conn_status; xmlNodePtr xml; priv = INFC_SESSION_PROXY_PRIVATE(proxy); g_assert(priv->connection != NULL); g_assert(priv->session != NULL); sync_status = inf_session_get_synchronization_status( priv->session, priv->connection ); g_object_get(G_OBJECT(priv->connection), "status", &conn_status, NULL); /* If synchronization is still in progress, the close default signal * handler in InfSession the base class will cancel the synchronization in * which case we do not need to send an extra session-unsubscribe * message. */ /* However, in case we are in AWAITING_ACK status we send session * unsubscribe because we cannot cancel the synchronization anymore but * the server will go into RUNNING state before receiving this message. */ /* Note that, also, the connection might not be open anymore at this point * if a handler for the connection's notify::status signal finalized or * closed the session explicitely before our handler was called. Therefore * we also check the connection status here. */ if(conn_status == INF_XML_CONNECTION_OPEN && sync_status != INF_SESSION_SYNC_IN_PROGRESS) { xml = xmlNewNode(NULL, (const xmlChar*)"session-unsubscribe"); inf_communication_group_send_message( INF_COMMUNICATION_GROUP(priv->subscription_group), priv->connection, xml ); } /* If an error occurs while sending the "session-unsubscribe" message, the * connection is released already as a result of the connection status * notify handler, so we need another check here. */ if(priv->connection != NULL) infc_session_proxy_release_connection(proxy); } /* * Signal handlers */ static void infc_session_proxy_connection_notify_status_cb(InfXmlConnection* connection, GParamSpec* pspec, gpointer user_data) { InfcSessionProxy* proxy; InfXmlConnectionStatus status; proxy = INFC_SESSION_PROXY(user_data); g_object_get(G_OBJECT(connection), "status", &status, NULL); if(status == INF_XML_CONNECTION_CLOSED || status == INF_XML_CONNECTION_CLOSING) { /* Reset connection in case of closure */ infc_session_proxy_release_connection(proxy); } } static void infc_session_proxy_session_synchronization_complete_cb(InfSession* session, InfXmlConnection* conn, gpointer user_data) { InfcSessionProxy* proxy; InfcSessionProxyPrivate* priv; InfSessionStatus status; proxy = INFC_SESSION_PROXY(user_data); priv = INFC_SESSION_PROXY_PRIVATE(proxy); g_object_get(G_OBJECT(session), "status", &status, NULL); /* There are actually 4 different situations here, depending on status * and priv->connection: * * 1) status == SYNCHRONIZING and priv->connection == NULL * This means that someone synchronized its session to us, but we are not * subscribed to that session. * * 2) status == SYNCHRONIZING and priv->connection != NULL * This means that someone synchronized us and we are subscribed to that * session. * * 3) status == RUNNING and priv->connection == NULL * This means that we synchronized our session to someone else but are * not subscribed to any session. * * 4) status == RUNNING and priv->connection != NULL * This means that we synchronized our session to someone else and are * subscribed to a session (possibly on another host as the one we * synchronized to!). */ if(status == INF_SESSION_SYNCHRONIZING) { if(priv->connection != NULL) { /* The connection that synchronized the session to us should be the * one we subscribed to. */ g_assert(priv->connection == conn); } } } static void infc_session_proxy_session_synchronization_failed_cb(InfSession* session, InfXmlConnection* conn, const GError* error, gpointer user_data) { InfcSessionProxy* proxy; InfcSessionProxyPrivate* priv; InfSessionStatus status; proxy = INFC_SESSION_PROXY(user_data); priv = INFC_SESSION_PROXY_PRIVATE(proxy); g_object_get(G_OBJECT(session), "status", &status, NULL); switch(status) { case INF_SESSION_SYNCHRONIZING: /* When the synchronization failed in synchronizing state, the session * will close itself anyway which is where we do the cleanup in this * case. */ break; case INF_SESSION_RUNNING: /* We do not need to send an explicit session-unsubscribe, because the * failed synchronization should already let the host know that * subscription makes no sense anymore. */ /* If the synchronization failed because the connection was closed, then * the connection might not exist anymore at this point since the * notify::status handler ran before this handler. */ if(priv->connection != NULL) infc_session_proxy_release_connection(proxy); break; case INF_SESSION_CLOSED: default: g_assert_not_reached(); break; } } static void infc_session_proxy_session_close_cb(InfSession* session, gpointer user_data) { InfcSessionProxy* proxy; InfcSessionProxyPrivate* priv; proxy = INFC_SESSION_PROXY(user_data); priv = INFC_SESSION_PROXY_PRIVATE(proxy); if(priv->connection != NULL) infc_session_proxy_unsubscribe_connection(proxy); /* Don't release session so others can still access */ #if 0 inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->session), G_CALLBACK(infc_session_proxy_session_close_cb), proxy ); inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->session), G_CALLBACK(infc_session_proxy_session_synchronization_complete_cb), proxy ); inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->session), G_CALLBACK(infc_session_proxy_session_synchronization_failed_cb), proxy ); g_object_unref(G_OBJECT(priv->session)); priv->session = NULL; #endif } /* * Helper functions */ static void infc_session_proxy_release_connection_foreach_user_func(InfUser* user, gpointer user_data) { g_object_set(G_OBJECT(user), "status", INF_USER_UNAVAILABLE, NULL); } static void infc_session_proxy_release_connection(InfcSessionProxy* proxy) { InfcSessionProxyPrivate* priv; priv = INFC_SESSION_PROXY_PRIVATE(proxy); g_assert(priv->connection != NULL); g_assert(priv->subscription_group != NULL); g_assert(priv->request_manager != NULL); /* TODO: Emit failed signal with some "cancelled" error? */ infc_request_manager_clear(priv->request_manager); g_object_unref(priv->request_manager); priv->request_manager = NULL; /* Set status of all users to unavailable */ /* TODO: Keep local users available if session is still open. Then make * sure when the session is closed everybody is set to unavailable. */ inf_user_table_foreach_user( inf_session_get_user_table(priv->session), infc_session_proxy_release_connection_foreach_user_func, NULL ); inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->connection), G_CALLBACK(infc_session_proxy_connection_notify_status_cb), proxy ); g_object_unref(priv->subscription_group); priv->subscription_group = NULL; g_object_unref(G_OBJECT(priv->connection)); priv->connection = NULL; /* Keep the proxy alive while re-setting the session's subscription group, * to be able to announce our status changes afterwards. */ g_object_ref(proxy); inf_session_set_subscription_group(priv->session, NULL); g_object_notify(G_OBJECT(proxy), "connection"); g_object_notify(G_OBJECT(proxy), "subscription-group"); g_object_unref(proxy); } /* TODO: This function should be moved to InfcRequest */ static xmlNodePtr infc_session_proxy_request_to_xml(InfcRequest* request) { xmlNodePtr xml; gchar* type; guint seq; gchar seq_buffer[16]; g_object_get(G_OBJECT(request), "type", &type, "seq", &seq, NULL); sprintf(seq_buffer, "%u", seq); xml = xmlNewNode(NULL, (const xmlChar*)type); xmlNewProp(xml, (const xmlChar*)"seq", (const xmlChar*)seq_buffer); g_free(type); return xml; } /* * GObject overrides. */ static void infc_session_proxy_init(InfcSessionProxy* proxy) { InfcSessionProxyPrivate* priv; priv = INFC_SESSION_PROXY_PRIVATE(proxy); priv->session = NULL; priv->subscription_group = NULL; priv->connection = NULL; priv->request_manager = NULL; } static void infc_session_proxy_dispose(GObject* object) { InfcSessionProxy* proxy; InfcSessionProxyPrivate* priv; proxy = INFC_SESSION_PROXY(object); priv = INFC_SESSION_PROXY_PRIVATE(proxy); if(priv->connection) infc_session_proxy_unsubscribe_connection(proxy); /* Release session */ if(priv->session != NULL) { inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->session), G_CALLBACK(infc_session_proxy_session_close_cb), proxy ); inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->session), G_CALLBACK(infc_session_proxy_session_synchronization_complete_cb), proxy ); inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->session), G_CALLBACK(infc_session_proxy_session_synchronization_failed_cb), proxy ); g_object_unref(G_OBJECT(priv->session)); priv->session = NULL; } g_assert(priv->request_manager == NULL); G_OBJECT_CLASS(infc_session_proxy_parent_class)->dispose(object); } static void infc_session_proxy_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfcSessionProxy* proxy; InfcSessionProxyPrivate* priv; proxy = INFC_SESSION_PROXY(object); priv = INFC_SESSION_PROXY_PRIVATE(proxy); switch(prop_id) { case PROP_SESSION: g_assert(priv->session == NULL); /* construct only */ priv->session = INF_SESSION(g_value_dup_object(value)); g_signal_connect( G_OBJECT(priv->session), "close", G_CALLBACK(infc_session_proxy_session_close_cb), proxy ); g_signal_connect( G_OBJECT(priv->session), "synchronization-complete", G_CALLBACK(infc_session_proxy_session_synchronization_complete_cb), proxy ); g_signal_connect( G_OBJECT(priv->session), "synchronization-failed", G_CALLBACK(infc_session_proxy_session_synchronization_failed_cb), proxy ); break; case PROP_SUBSCRIPTION_GROUP: case PROP_CONNECTION: /* these are read-only because they can only be changed both at once, * refer to infc_session_proxy_set_connection(). */ default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void infc_session_proxy_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfcSessionProxy* session; InfcSessionProxyPrivate* priv; session = INFC_SESSION_PROXY(object); priv = INFC_SESSION_PROXY_PRIVATE(session); switch(prop_id) { case PROP_SESSION: g_value_set_object(value, G_OBJECT(priv->session)); break; case PROP_SUBSCRIPTION_GROUP: g_value_set_boxed(value, priv->subscription_group); break; case PROP_CONNECTION: g_value_set_object(value, G_OBJECT(priv->connection)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static GError* infc_session_proxy_translate_error_impl(InfcSessionProxy* proxy, GQuark domain, guint code) { GError* error; const gchar* error_msg; if(domain == inf_request_error_quark()) error_msg = inf_request_strerror(code); else if(domain == inf_user_error_quark()) error_msg = inf_user_strerror(code); else error_msg = NULL; error = NULL; if(error_msg != NULL) { g_set_error_literal(&error, domain, code, error_msg); } else { /* TODO: Check whether a human-readable error string was sent (that * we cannot translate then, of course). */ g_set_error( &error, inf_request_error_quark(), INF_REQUEST_ERROR_UNKNOWN_DOMAIN, _("Error comes from unknown error domain \"%s\" (code %u)"), g_quark_to_string(domain), (guint)code ); } return error; } /* * Message handling. */ static gboolean infc_session_proxy_handle_user_join(InfcSessionProxy* proxy, InfXmlConnection* connection, xmlNodePtr xml, GError** error) { InfcSessionProxyPrivate* priv; InfSessionClass* session_class; InfcRequest* request; GArray* array; InfUser* user; GParameter* param; gboolean result; guint i; priv = INFC_SESSION_PROXY_PRIVATE(proxy); session_class = INF_SESSION_GET_CLASS(priv->session); request = infc_request_manager_get_request_by_xml( priv->request_manager, "user-join", xml, NULL ); array = session_class->get_xml_user_props(priv->session, connection, xml); /* Set local flag if the join was requested by us. */ param = inf_session_get_user_property(array, "flags"); g_assert(!G_IS_VALUE(¶m->value)); /* must not have been set already */ g_value_init(¶m->value, INF_TYPE_USER_FLAGS); if(request != NULL) g_value_set_flags(¶m->value, INF_USER_LOCAL); else g_value_set_flags(¶m->value, 0); /* Set connection. If none was given, use publisher connection */ param = inf_session_get_user_property(array, "connection"); if(!G_IS_VALUE(¶m->value)) { g_value_init(¶m->value, INF_TYPE_XML_CONNECTION); g_value_set_object(¶m->value, G_OBJECT(connection)); } result = session_class->validate_user_props( priv->session, (const GParameter*)array->data, array->len, NULL, error ); if(result == TRUE) { user = inf_session_add_user( priv->session, (const GParameter*)array->data, array->len ); g_assert(user != NULL); } for(i = 0; i < array->len; ++ i) g_value_unset(&g_array_index(array, GParameter, i).value); g_array_free(array, TRUE); if(user != NULL) { if(request != NULL) { infc_request_manager_finish_request( priv->request_manager, request, inf_request_result_make_join_user(INF_SESSION_PROXY(proxy), user) ); } return TRUE; } else { return FALSE; } } static gboolean infc_session_proxy_handle_user_rejoin(InfcSessionProxy* proxy, InfXmlConnection* connection, xmlNodePtr xml, GError** error) { InfcSessionProxyPrivate* priv; InfSessionClass* session_class; InfcRequest* request; GArray* array; InfUser* user; const GParameter* idparam; GParameter* param; guint id; gboolean result; guint i; priv = INFC_SESSION_PROXY_PRIVATE(proxy); session_class = INF_SESSION_GET_CLASS(priv->session); request = infc_request_manager_get_request_by_xml( priv->request_manager, "user-join", xml, NULL ); array = session_class->get_xml_user_props(priv->session, connection, xml); /* Find rejoining user first */ idparam = inf_session_lookup_user_property( (const GParameter*)array->data, array->len, "id" ); if(idparam == NULL) { g_set_error_literal( error, inf_request_error_quark(), INF_REQUEST_ERROR_NO_SUCH_ATTRIBUTE, _("Request does not contain required attribute \"id\"") ); goto error; } id = g_value_get_uint(&idparam->value); user = inf_user_table_lookup_user_by_id( inf_session_get_user_table(priv->session), id ); if(user == NULL) { g_set_error( error, inf_user_error_quark(), INF_USER_ERROR_NO_SUCH_USER, _("No such user with ID %u"), id ); goto error; } /* Set local flag if the join was requested by us */ param = inf_session_get_user_property(array, "flags"); g_assert(!G_IS_VALUE(¶m->value)); /* must not have been set already */ g_value_init(¶m->value, INF_TYPE_USER_FLAGS); if(request != NULL) g_value_set_flags(¶m->value, INF_USER_LOCAL); else g_value_set_flags(¶m->value, 0); /* Set connection. If none was given, use publisher connection */ param = inf_session_get_user_property(array, "connection"); if(!G_IS_VALUE(¶m->value)) { g_value_init(¶m->value, INF_TYPE_XML_CONNECTION); g_value_set_object(¶m->value, G_OBJECT(connection)); } result = session_class->validate_user_props( priv->session, (const GParameter*)array->data, array->len, user, error ); if(result == FALSE) goto error; /* Set properties on the found user object, performing the rejoin */ g_object_freeze_notify(G_OBJECT(user)); for(i = 0; i < array->len; ++ i) { param = &g_array_index(array, GParameter, i); /* Don't set ID because the ID is the same anyway (we did the user lookup * by it). The "id" property is construct only anyway. */ if(strcmp(param->name, "id") != 0) g_object_set_property(G_OBJECT(user), param->name, ¶m->value); } /* TODO: Set user status to available, if the server did not send the * status property? Require the status property being set on a rejoin? * Make sure it is not unavailable? */ g_object_thaw_notify(G_OBJECT(user)); for(i = 0; i < array->len; ++ i) g_value_unset(&g_array_index(array, GParameter, i).value); g_array_free(array, TRUE); if(request != NULL) { infc_request_manager_finish_request( priv->request_manager, request, inf_request_result_make_join_user(INF_SESSION_PROXY(proxy), user) ); } return TRUE; error: for(i = 0; i < array->len; ++ i) g_value_unset(&g_array_index(array, GParameter, i).value); g_array_free(array, TRUE); return FALSE; } static gboolean infc_session_proxy_handle_request_failed(InfcSessionProxy* proxy, InfXmlConnection* connection, xmlNodePtr xml, GError** error) { InfcSessionProxyPrivate* priv; InfcSessionProxyClass* proxy_class; xmlChar* domain; gboolean has_code; guint code; GError* req_error; InfcRequest* request; priv = INFC_SESSION_PROXY_PRIVATE(proxy); proxy_class = INFC_SESSION_PROXY_GET_CLASS(proxy); has_code = inf_xml_util_get_attribute_uint_required( xml, "code", &code, error ); if(has_code == FALSE) return FALSE; domain = inf_xml_util_get_attribute_required(xml, "domain", error); if(domain == NULL) return FALSE; req_error = NULL; request = infc_request_manager_get_request_by_xml_required( priv->request_manager, NULL, xml, error ); if(request == NULL) return FALSE; g_assert(proxy_class->translate_error != NULL); /* TODO: Add a GError* paramater to translate_error so that an error * can be reported if the error could not be translated. */ req_error = proxy_class->translate_error( proxy, g_quark_from_string((const gchar*)domain), code ); infc_request_manager_fail_request( priv->request_manager, request, req_error ); g_error_free(req_error); xmlFree(domain); return TRUE; } static gboolean infc_session_proxy_handle_session_close(InfcSessionProxy* proxy, InfXmlConnection* connection, xmlNodePtr xml, GError** error) { InfcSessionProxyPrivate* priv; priv = INFC_SESSION_PROXY_PRIVATE(proxy); g_assert(priv->connection != NULL); infc_session_proxy_release_connection(proxy); /* Do not call inf_session_close so the session can be reused by * reconnecting/synchronizing to another host. */ return TRUE; } /* * InfNetObject implementation */ static void infc_session_proxy_communication_object_sent(InfCommunicationObject* object, InfXmlConnection* connection, xmlNodePtr node) { InfcSessionProxy* proxy; InfcSessionProxyPrivate* priv; proxy = INFC_SESSION_PROXY(object); priv = INFC_SESSION_PROXY_PRIVATE(proxy); /* TODO: Don't forward for messages the proxy issued */ g_assert(priv->session != NULL); inf_communication_object_sent( INF_COMMUNICATION_OBJECT(priv->session), connection, node ); } static void infc_session_proxy_communication_object_enqueued(InfCommunicationObject* obj, InfXmlConnection* connection, xmlNodePtr node) { InfcSessionProxy* proxy; InfcSessionProxyPrivate* priv; proxy = INFC_SESSION_PROXY(obj); priv = INFC_SESSION_PROXY_PRIVATE(proxy); /* TODO: Don't forward for messages the proxy issued */ g_assert(priv->session != NULL); inf_communication_object_enqueued( INF_COMMUNICATION_OBJECT(priv->session), connection, node ); } static InfCommunicationScope infc_session_proxy_communication_object_received(InfCommunicationObject* obj, InfXmlConnection* connection, xmlNodePtr node) { InfcSessionProxy* proxy; InfcSessionProxyPrivate* priv; InfcSessionProxyClass* proxy_class; InfSessionSyncStatus status; GError* local_error; InfcRequest* request; GError* seq_error; proxy = INFC_SESSION_PROXY(obj); priv = INFC_SESSION_PROXY_PRIVATE(proxy); proxy_class = INFC_SESSION_PROXY_GET_CLASS(proxy); status = inf_session_get_synchronization_status(priv->session, connection); local_error = NULL; g_assert(status != INF_SESSION_SYNC_NONE || priv->connection == connection); g_assert(inf_session_get_status(priv->session) != INF_SESSION_CLOSED); if(status != INF_SESSION_SYNC_NONE) { /* Direct delegate during synchronization */ return inf_communication_object_received( INF_COMMUNICATION_OBJECT(priv->session), connection, node ); } else { if(strcmp((const char*)node->name, "user-join") == 0) { infc_session_proxy_handle_user_join( proxy, connection, node, &local_error ); } else if(strcmp((const char*)node->name, "user-rejoin") == 0) { infc_session_proxy_handle_user_rejoin( proxy, connection, node, &local_error ); } else if(strcmp((const char*)node->name, "request-failed") == 0) { infc_session_proxy_handle_request_failed( proxy, connection, node, &local_error ); } else if(strcmp((const char*)node->name, "session-close") == 0) { infc_session_proxy_handle_session_close( proxy, connection, node, &local_error ); } else { /* forward to session */ return inf_communication_object_received( INF_COMMUNICATION_OBJECT(priv->session), connection, node ); } } if(local_error != NULL) { /* If the request had a (valid) seq set, we cancel the corresponding * request because the reply could not be processed. */ request = infc_request_manager_get_request_by_xml( priv->request_manager, NULL, node, NULL ); if(request != NULL) { /* If the request had a seq set, we cancel the corresponding request * because the reply could not be processed. */ seq_error = NULL; g_set_error( &seq_error, inf_request_error_quark(), INF_REQUEST_ERROR_REPLY_UNPROCESSED, _("Server reply could not be processed: %s"), local_error->message ); infc_request_manager_fail_request( priv->request_manager, request, seq_error ); g_error_free(seq_error); } /* TODO: Do we want to emit session's error signal? */ g_error_free(local_error); } /* Don't forward any of the handled messages */ return INF_COMMUNICATION_SCOPE_PTP; } /* * InfSessionProxy implementation */ InfRequest* infc_session_proxy_session_proxy_join_user(InfSessionProxy* proxy, guint n_params, const GParameter* params, InfRequestFunc func, gpointer user_data) { InfcSessionProxyPrivate* priv; InfSessionClass* session_class; InfSessionStatus status; InfcRequest* request; xmlNodePtr xml; g_return_val_if_fail(INFC_IS_SESSION_PROXY(proxy), NULL); g_return_val_if_fail(n_params == 0 || params != NULL, NULL); priv = INFC_SESSION_PROXY_PRIVATE(proxy); g_return_val_if_fail(priv->session != NULL, NULL); session_class = INF_SESSION_GET_CLASS(priv->session); /* Make sure we are subscribed */ g_object_get(G_OBJECT(priv->session), "status", &status, NULL); g_return_val_if_fail(status == INF_SESSION_RUNNING, NULL); g_return_val_if_fail(priv->connection != NULL, NULL); g_return_val_if_fail(priv->request_manager != NULL, NULL); request = infc_request_manager_add_request( priv->request_manager, INFC_TYPE_REQUEST, "user-join", G_CALLBACK(func), user_data, NULL ); xml = infc_session_proxy_request_to_xml(INFC_REQUEST(request)); g_assert(session_class->set_xml_user_props != NULL); session_class->set_xml_user_props(priv->session, params, n_params, xml); inf_communication_group_send_message( INF_COMMUNICATION_GROUP(priv->subscription_group), priv->connection, xml ); return INF_REQUEST(request); } /* * GType registration. */ static void infc_session_proxy_class_init(InfcSessionProxyClass* proxy_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(proxy_class); object_class->dispose = infc_session_proxy_dispose; object_class->set_property = infc_session_proxy_set_property; object_class->get_property = infc_session_proxy_get_property; proxy_class->translate_error = infc_session_proxy_translate_error_impl; g_object_class_install_property( object_class, PROP_SUBSCRIPTION_GROUP, g_param_spec_object( "subscription-group", "Subscription group", "The communication group of subscribed connections", INF_COMMUNICATION_TYPE_JOINED_GROUP, G_PARAM_READABLE ) ); g_object_class_install_property( object_class, PROP_CONNECTION, g_param_spec_object( "connection", "Subscription connection", "The connection with which the session communicates with the server", INF_TYPE_XML_CONNECTION, G_PARAM_READABLE ) ); g_object_class_override_property(object_class, PROP_SESSION, "session"); } static void infc_session_proxy_communication_object_iface_init( InfCommunicationObjectInterface* iface) { iface->sent = infc_session_proxy_communication_object_sent; iface->enqueued = infc_session_proxy_communication_object_enqueued; iface->received = infc_session_proxy_communication_object_received; } static void infc_session_proxy_session_proxy_iface_init(InfSessionProxyInterface* iface) { iface->join_user = infc_session_proxy_session_proxy_join_user; } /* * Public API. */ /** * infc_session_proxy_set_connection: * @proxy: A #InfcSessionProxy. * @group: A #InfCommunicationJoinedGroup of subscribed connections. Ignored * if @connection is %NULL. * @connection: A #InfXmlConnection. * @seq_id: A sequence identifier for @connection. Ignored if @connection * is %NULL. * * Sets the subscription connection for the given session. The subscription * connection is the connection through which session requests are transmitted * during subscription. * * The subscription connection might be set even if the session is in * SYNCHRONIZING state in which case the session is immediately subscribed * after synchronization. Note that no attempt is made to tell the other end * about the subscription. * * @seq_id should be a sequence identifier obtained from the server side. It * must be the same number that is used on the corresponding #InfdSessionProxy * on the remote side, see infd_session_proxy_subscribe_to(). Normally * #InfdDirectory or #InfcBrowser, respectively, take care of passing the * correct sequence identifier. * * When the subscription connection is being closed or replaced (by a * subsequent call to this function), all pending requests are dropped and * all users are set to be unavailable, but the session will not be closed, * so it may be reused by setting another subscription connection. However, * the session might not be synchronized again, but it is fully okay to close * the session by hand (using inf_session_close) and create a new session * that is synchronized. **/ void infc_session_proxy_set_connection(InfcSessionProxy* proxy, InfCommunicationJoinedGroup* group, InfXmlConnection* connection, guint seq_id) { InfcSessionProxyPrivate* priv; xmlNodePtr xml; g_return_if_fail(INFC_IS_SESSION_PROXY(proxy)); g_return_if_fail(connection == NULL || INF_IS_XML_CONNECTION(connection)); g_return_if_fail( (group == NULL && connection == NULL) || (INF_COMMUNICATION_IS_JOINED_GROUP(group) && connection != NULL) ); priv = INFC_SESSION_PROXY_PRIVATE(proxy); g_return_if_fail(priv->session != NULL); g_object_freeze_notify(G_OBJECT(proxy)); g_object_freeze_notify(G_OBJECT(priv->session)); if(priv->connection != NULL) { /* Unsubscribe from running session. Always send the unsubscribe request * because synchronizations are not cancelled through this call. */ xml = xmlNewNode(NULL, (const xmlChar*)"session-unsubscribe"); inf_communication_group_send_message( INF_COMMUNICATION_GROUP(priv->subscription_group), priv->connection, xml ); /* Note that this would cause a notify on the connection property, but * notifications have been freezed until the end of this function call. * Same with the subscription-group property of priv->session. */ infc_session_proxy_release_connection(proxy); } priv->connection = connection; if(connection != NULL) { priv->connection = connection; g_object_ref(G_OBJECT(connection)); g_signal_connect( G_OBJECT(connection), "notify::status", G_CALLBACK(infc_session_proxy_connection_notify_status_cb), proxy ); /* Set new group */ priv->subscription_group = group; g_object_ref(priv->subscription_group); g_assert(priv->request_manager == NULL); priv->request_manager = infc_request_manager_new(seq_id); } inf_session_set_subscription_group( priv->session, INF_COMMUNICATION_GROUP(priv->subscription_group) ); g_object_notify(G_OBJECT(proxy), "connection"); g_object_notify(G_OBJECT(proxy), "subscription-group"); g_object_thaw_notify(G_OBJECT(priv->session)); g_object_thaw_notify(G_OBJECT(proxy)); } /** * infc_session_proxy_get_connection: * @proxy: A #InfcSessionProxy. * * Returns the connection that is used to transmit requests to the publisher * of the session, or %NULL if the session is not subscribed. * * Returns: (transfer none): A #InfXmlConnection, or %NULL. **/ InfXmlConnection* infc_session_proxy_get_connection(InfcSessionProxy* proxy) { g_return_val_if_fail(INFC_IS_SESSION_PROXY(proxy), NULL); return INFC_SESSION_PROXY_PRIVATE(proxy)->connection; } /** * infc_session_proxy_get_subscription_group: * @proxy: A #InfcSessionProxy. * * Returns the group with all subscribed connections to the session, or %NULL * if the session is not subscribed. * * Returns: (transfer none): A #InfCommunicationJoinedGroup, or %NULL. **/ InfCommunicationJoinedGroup* infc_session_proxy_get_subscription_group(InfcSessionProxy* proxy) { g_return_val_if_fail(INFC_IS_SESSION_PROXY(proxy), NULL); return INFC_SESSION_PROXY_PRIVATE(proxy)->subscription_group; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/client/PaxHeaders.26529/infc-browser.h0000644000000000000000000000013213034342512022147 xustar0030 mtime=1483851082.025718404 30 atime=1483851082.025718404 30 ctime=1488261588.924139232 libinfinity-0.7.1/libinfinity/client/infc-browser.h0000644000175000017500000000744313034342512022711 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INFC_BROWSER_H__ #define __INFC_BROWSER_H__ #include #include #include #include #include #include #include G_BEGIN_DECLS #define INFC_TYPE_BROWSER (infc_browser_get_type()) #define INFC_BROWSER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INFC_TYPE_BROWSER, InfcBrowser)) #define INFC_BROWSER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INFC_TYPE_BROWSER, InfcBrowserClass)) #define INFC_IS_BROWSER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INFC_TYPE_BROWSER)) #define INFC_IS_BROWSER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INFC_TYPE_BROWSER)) #define INFC_BROWSER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INFC_TYPE_BROWSER, InfcBrowserClass)) typedef struct _InfcBrowser InfcBrowser; typedef struct _InfcBrowserClass InfcBrowserClass; /** * InfcBrowserClass: * * This structure does not contain any public fields. */ struct _InfcBrowserClass { /*< private >*/ GObjectClass parent_class; }; /** * InfcBrowser: * * #InfcBrowser is an opaque data type. You should only access it via the * public API functions. */ struct _InfcBrowser { /*< private >*/ GObject parent; }; GType infc_browser_get_type(void) G_GNUC_CONST; InfcBrowser* infc_browser_new(InfIo* io, InfCommunicationManager* comm_manager, InfXmlConnection* connection); InfCommunicationManager* infc_browser_get_communication_manager(InfcBrowser* browser); InfXmlConnection* infc_browser_get_connection(InfcBrowser* browser); gboolean infc_browser_add_plugin(InfcBrowser* browser, const InfcNotePlugin* plugin); const InfcNotePlugin* infc_browser_lookup_plugin(InfcBrowser* browser, const gchar* note_type); InfRequest* infc_browser_iter_save_session(InfcBrowser* browser, const InfBrowserIter* iter, InfRequestFunc func, gpointer user_data); InfcSessionProxy* infc_browser_iter_get_sync_in(InfcBrowser* browser, const InfBrowserIter* iter); GSList* infc_browser_iter_get_sync_in_requests(InfcBrowser* browser, const InfBrowserIter* iter); gboolean infc_browser_iter_is_valid(InfcBrowser* browser, const InfBrowserIter* iter); InfRequest* infc_browser_subscribe_chat(InfcBrowser* browser, InfRequestFunc func, gpointer user_data); InfRequest* infc_browser_get_subscribe_chat_request(InfcBrowser* browser); InfcSessionProxy* infc_browser_get_chat_session(InfcBrowser* browser); G_END_DECLS #endif /* __INFC_BROWSER_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/client/PaxHeaders.26529/infc-request-manager.h0000644000000000000000000000013213034342512023564 xustar0030 mtime=1483851082.029718427 30 atime=1483851082.029718427 30 ctime=1488261588.928139222 libinfinity-0.7.1/libinfinity/client/infc-request-manager.h0000644000175000017500000001357113034342512024325 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INFC_REQUEST_MANAGER_H__ #define __INFC_REQUEST_MANAGER_H__ #include #include #include #include G_BEGIN_DECLS #define INFC_TYPE_REQUEST_MANAGER (infc_request_manager_get_type()) #define INFC_REQUEST_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INFC_TYPE_REQUEST_MANAGER, InfcRequestManager)) #define INFC_REQUEST_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INFC_TYPE_REQUEST_MANAGER, InfcRequestManagerClass)) #define INFC_IS_REQUEST_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INFC_TYPE_REQUEST_MANAGER)) #define INFC_IS_REQUEST_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INFC_TYPE_REQUEST_MANAGER)) #define INFC_REQUEST_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INFC_TYPE_REQUEST_MANAGER, InfcRequestManagerClass)) typedef struct _InfcRequestManager InfcRequestManager; typedef struct _InfcRequestManagerClass InfcRequestManagerClass; /** * InfcRequestManagerClass: * @request_add: Default signal handler for the * #InfcRequestManager::request-add signal. * @request_remove: Default signal handler for the * #InfcRequestManager::request-remove signal. * * This structure contains the default signal handlers of the * #InfcRequestManager class. */ struct _InfcRequestManagerClass { /*< private >*/ GObjectClass parent_class; /*< public >*/ void (*request_add)(InfcRequestManager* manager, InfcRequest* request); void (*request_remove)(InfcRequestManager* manager, InfcRequest* request); }; /** * InfcRequestManager: * * #InfcRequestManager is an opaque data type. You should only access it via * the public API functions. */ struct _InfcRequestManager { /*< private >*/ GObject parent; }; /** * InfcRequestManagerForeachFunc: * @request: The current request. * @user_data: Additional data passed to * infc_request_manager_foreach_request() or * infc_request_manager_foreach_named_request(). * * This signature specifies the callback type when iterating over all * requests of the request manager. */ typedef void(*InfcRequestManagerForeachFunc)(InfcRequest* request, gpointer user_data); GType infc_request_manager_get_type(void) G_GNUC_CONST; InfcRequestManager* infc_request_manager_new(guint seq_id); InfcRequest* infc_request_manager_add_request(InfcRequestManager* manager, GType request_type, const gchar* request_name, GCallback callback, gpointer user_data, const gchar* first_property_name, ...); InfcRequest* infc_request_manager_add_request_valist(InfcRequestManager* manager, GType request_type, const gchar* request_name, GCallback callback, gpointer user_data, const gchar* first_property_name, va_list arglist); void infc_request_manager_remove_request(InfcRequestManager* manager, InfcRequest* request); void infc_request_manager_finish_request(InfcRequestManager* manager, InfcRequest* request, InfRequestResult* result); void infc_request_manager_fail_request(InfcRequestManager* manager, InfcRequest* request, const GError* error); void infc_request_manager_clear(InfcRequestManager* manager); InfcRequest* infc_request_manager_get_request_by_seq(InfcRequestManager* manager, guint seq); InfcRequest* infc_request_manager_get_request_by_xml(InfcRequestManager* manager, const gchar* name, xmlNodePtr xml, GError** error); InfcRequest* infc_request_manager_get_request_by_xml_required(InfcRequestManager* manager, const gchar* name, xmlNodePtr xml, GError** error); void infc_request_manager_foreach_request(InfcRequestManager* manager, InfcRequestManagerForeachFunc func, gpointer user_data); void infc_request_manager_foreach_named_request(InfcRequestManager* manager, const gchar* name, InfcRequestManagerForeachFunc func, gpointer user_data); G_END_DECLS #endif /* __INFC_REQUEST_MANAGER_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/client/PaxHeaders.26529/infc-session-proxy.h0000644000000000000000000000013213034342512023326 xustar0030 mtime=1483851082.029718427 30 atime=1483851082.029718427 30 ctime=1488261588.928139222 libinfinity-0.7.1/libinfinity/client/infc-session-proxy.h0000644000175000017500000000632313034342512024064 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INFC_SESSION_PROXY_H__ #define __INFC_SESSION_PROXY_H__ #include #include G_BEGIN_DECLS #define INFC_TYPE_SESSION_PROXY (infc_session_proxy_get_type()) #define INFC_SESSION_PROXY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INFC_TYPE_SESSION_PROXY, InfcSessionProxy)) #define INFC_SESSION_PROXY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INFC_TYPE_SESSION_PROXY, InfcSessionProxyClass)) #define INFC_IS_SESSION_PROXY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INFC_TYPE_SESSION_PROXY)) #define INFC_IS_SESSION_PROXY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INFC_TYPE_SESSION_PROXY)) #define INFC_SESSION_PROXY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INFC_TYPE_SESSION_PROXY, InfcSessionProxyClass)) typedef struct _InfcSessionProxy InfcSessionProxy; typedef struct _InfcSessionProxyClass InfcSessionProxyClass; /** * InfcSessionProxyClass: * @translate_error: Virtual function to transform an error domain and code * into a #GError object. If the domain and code are known, this allows to * show a localized error message to the user, independent from the language * the server uses in the error message that went over the wire. * * This structure contains virtual functions of the #InfcSessionProxy class. */ struct _InfcSessionProxyClass { /*< private >*/ GObjectClass parent_class; /* Virtual Functions */ /*< public >*/ GError* (*translate_error)(InfcSessionProxy* session, GQuark domain, guint code); }; /** * InfcSessionProxy: * * #InfcSessionProxy is an opaque data type. You should only access it via the * public API functions. */ struct _InfcSessionProxy { /*< private >*/ GObject parent; }; GType infc_session_proxy_get_type(void) G_GNUC_CONST; void infc_session_proxy_set_connection(InfcSessionProxy* proxy, InfCommunicationJoinedGroup* group, InfXmlConnection* connection, guint seq_id); InfXmlConnection* infc_session_proxy_get_connection(InfcSessionProxy* proxy); InfCommunicationJoinedGroup* infc_session_proxy_get_subscription_group(InfcSessionProxy* proxy); G_END_DECLS #endif /* __INFC_SESSION_PROXY_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/client/PaxHeaders.26529/infc-browser.c0000644000000000000000000000013213034342512022142 xustar0030 mtime=1483851082.025718404 30 atime=1483851082.025718404 30 ctime=1488261589.108138829 libinfinity-0.7.1/libinfinity/client/infc-browser.c0000644000175000017500000056665413034342512022722 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:infc-browser * @short_description: Browse remote directories * @see_also: #InfdDirectory * @include: libinfinity/client/infc-browser.h * @stability: Unstable * * The #InfcBrowser is used to browse a remote directory and can be used * to subscribe to sessions. #InfcBrowser implements the #InfBrowser * interface, through which most operations are performed. **/ #include #include #include #include #include #include #include #include #include #include #include #include /* Some Windows header #defines error for no good */ #ifdef G_OS_WIN32 # ifdef ERROR # undef ERROR # endif #endif typedef enum _InfcBrowserNodeType { INFC_BROWSER_NODE_SUBDIRECTORY = 1 << 0, /* We found a plugin to handle the note type */ INFC_BROWSER_NODE_NOTE_KNOWN = 1 << 1, /* There was no plugin registered to handle the note's type */ INFC_BROWSER_NODE_NOTE_UNKNOWN = 1 << 2 } InfcBrowserNodeType; typedef struct _InfcBrowserMakeAclAccountListData InfcBrowserMakeAclAccountListData; struct _InfcBrowserMakeAclAccountListData { InfAclAccount* accounts; guint index; }; typedef struct _InfcBrowserLookupAclAccountByByNameData InfcBrowserLookupAclAccountByByNameData; struct _InfcBrowserLookupAclAccountByByNameData { const gchar* name; GArray* accounts; }; typedef struct _InfcBrowserListPendingRequestsForeachData InfcBrowserListPendingRequestsForeachData; struct _InfcBrowserListPendingRequestsForeachData { const InfBrowserIter* iter; GSList* result; }; typedef struct _InfcBrowserIterGetChatRequestForeachData InfcBrowserIterGetChatRequestForeachData; struct _InfcBrowserIterGetChatRequestForeachData { const InfBrowserIter* iter; InfcRequest* result; }; typedef struct _InfcBrowserIterGetSyncInRequestsForeachData InfcBrowserIterGetSyncInRequestsForeachData; struct _InfcBrowserIterGetSyncInRequestsForeachData { const InfBrowserIter* iter; GSList* result; }; typedef struct _InfcBrowserNode InfcBrowserNode; struct _InfcBrowserNode { InfcBrowserNode* parent; InfcBrowserNode* prev; InfcBrowserNode* next; guint id; gchar* name; InfcBrowserNodeType type; InfAclSheetSet* acl; gboolean acl_queried; /*InfcBrowserNodeStatus status;*/ union { struct { InfcSessionProxy* session; const InfcNotePlugin* plugin; } known; struct { gchar* type; } unknown; struct { /* First child node */ InfcBrowserNode* child; /* Whether we requested the node already from the server. * This is required because the child field may be NULL due to an empty * subdirectory or due to an unexplored subdirectory. */ gboolean explored; } subdir; } shared; }; typedef struct _InfcBrowserSyncIn InfcBrowserSyncIn; struct _InfcBrowserSyncIn { InfcBrowser* browser; InfcBrowserNode* node; InfXmlConnection* connection; /* The connection we are synchronizing to */ /*const InfcNotePlugin* plugin;*/ InfcSessionProxy* proxy; }; typedef enum _InfcBrowserSubreqType { INFC_BROWSER_SUBREQ_CHAT, INFC_BROWSER_SUBREQ_SESSION, INFC_BROWSER_SUBREQ_ADD_NODE, INFC_BROWSER_SUBREQ_SYNC_IN } InfcBrowserSubreqType; typedef struct _InfcBrowserSubreq InfcBrowserSubreq; struct _InfcBrowserSubreq { InfcBrowserSubreqType type; /* TODO: This should maybe go to shared, as not required for chat: */ guint node_id; union { struct { InfcRequest* request; InfCommunicationJoinedGroup* subscription_group; } chat; struct { InfcBrowserNode* node; InfcRequest* request; InfCommunicationJoinedGroup* subscription_group; } session; /* TODO: It would simplify some code if we merge the add_node * and sync_in blocks. */ struct { InfcBrowserNode* parent; const InfcNotePlugin* plugin; gchar* name; InfAclSheetSet* sheet_set; InfcRequest* request; InfCommunicationJoinedGroup* subscription_group; } add_node; struct { InfcBrowserNode* parent; const InfcNotePlugin* plugin; gchar* name; InfAclSheetSet* sheet_set; InfcRequest* request; InfCommunicationJoinedGroup* synchronization_group; InfCommunicationJoinedGroup* subscription_group; /* can be NULL */ InfSession* session; } sync_in; } shared; }; typedef enum _InfcBrowserAccountListStatus { INFC_BROWSER_ACCOUNT_LIST_NOT_QUERIED, INFC_BROWSER_ACCOUNT_LIST_NO_NOTIFICATIONS, INFC_BROWSER_ACCOUNT_LIST_NOTIFICATIONS } InfcBrowserAccountListStatus; typedef struct _InfcBrowserPrivate InfcBrowserPrivate; struct _InfcBrowserPrivate { InfIo* io; InfCommunicationManager* communication_manager; InfCommunicationJoinedGroup* group; InfXmlConnection* connection; guint seq_id; InfIoTimeout* welcome_timeout; InfcRequestManager* request_manager; GHashTable* plugins; /* Registered plugins */ InfBrowserStatus status; GHashTable* nodes; /* Mapping from id to node */ InfcBrowserNode* root; GHashTable* accounts; /* known accounts, id -> InfAclAccount* */ const InfAclAccount* local_account; InfcBrowserAccountListStatus account_list_status; GSList* sync_ins; GSList* subscription_requests; InfcSessionProxy* chat_session; }; #define INFC_BROWSER_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INFC_TYPE_BROWSER, InfcBrowserPrivate)) enum { PROP_0, PROP_IO, PROP_COMMUNICATION_MANAGER, PROP_CONNECTION, /* read only */ PROP_STATUS, PROP_CHAT_SESSION }; /* These make sure that the node iter points to is contained in browser */ #define infc_browser_return_if_iter_fail(browser, iter) \ g_return_if_fail( \ iter != NULL && \ g_hash_table_lookup( \ INFC_BROWSER_PRIVATE(INFC_BROWSER(browser))->nodes, \ GUINT_TO_POINTER((iter)->node_id) \ ) == (iter)->node \ ) #define infc_browser_return_val_if_iter_fail(browser, iter, val) \ g_return_val_if_fail( \ iter != NULL && \ g_hash_table_lookup( \ INFC_BROWSER_PRIVATE(INFC_BROWSER(browser))->nodes, \ GUINT_TO_POINTER((iter)->node_id) \ ) == (iter)->node, \ val \ ) /* These make sure that node is a subdirectory node */ #define infc_browser_return_if_subdir_fail(node) \ g_return_if_fail( \ ((InfcBrowserNode*)node)->type == INFC_BROWSER_NODE_SUBDIRECTORY \ ) #define infc_browser_return_val_if_subdir_fail(node, val) \ g_return_val_if_fail( \ ((InfcBrowserNode*)node)->type == INFC_BROWSER_NODE_SUBDIRECTORY, \ val \ ) static GQuark infc_browser_session_proxy_quark; static GQuark infc_browser_sync_in_session_quark; static GQuark infc_browser_sync_in_plugin_quark; static GQuark infc_browser_lookup_acl_accounts_ids_quark; static GQuark infc_browser_lookup_acl_accounts_n_ids_quark; static GQuark infc_browser_lookup_acl_accounts_name_quark; static GQuark infc_browser_query_acl_account_list_accounts_quark; static void infc_browser_communication_object_iface_init(InfCommunicationObjectInterface* iface); static void infc_browser_browser_iface_init(InfBrowserInterface* iface); G_DEFINE_TYPE_WITH_CODE(InfcBrowser, infc_browser, G_TYPE_OBJECT, G_ADD_PRIVATE(InfcBrowser) G_IMPLEMENT_INTERFACE(INF_COMMUNICATION_TYPE_OBJECT, infc_browser_communication_object_iface_init) G_IMPLEMENT_INTERFACE(INF_TYPE_BROWSER, infc_browser_browser_iface_init)) /* * Callbacks */ static void infc_browser_make_acl_account_list_foreach_func(gpointer key, gpointer value, gpointer user_data) { InfcBrowserMakeAclAccountListData* data; data = (InfcBrowserMakeAclAccountListData*)user_data; data->accounts[data->index++] = *(const InfAclAccount*)value; } static void infc_browser_browser_lookup_acl_account_by_name_find_func(gpointer key, gpointer value, gpointer user_data) { const InfcBrowserLookupAclAccountByByNameData* data; const InfAclAccount* acc; data = (InfcBrowserLookupAclAccountByByNameData*)user_data; acc = (const InfAclAccount*)value; if(acc->name != NULL) if(strcmp(acc->name, data->name) == 0) g_array_append_val(data->accounts, *acc); } InfAclAccount* infc_browser_make_acl_account_list(InfcBrowser* browser, guint* n_accounts) { InfcBrowserPrivate* priv; InfcBrowserMakeAclAccountListData data; guint n; priv = INFC_BROWSER_PRIVATE(browser); n = g_hash_table_size(priv->accounts); data.index = 0; data.accounts = g_malloc(sizeof(InfAclAccount) * n); g_hash_table_foreach( priv->accounts, infc_browser_make_acl_account_list_foreach_func, &data ); g_assert(data.index == n); if(n_accounts != NULL) *n_accounts = n; return data.accounts; } static void infc_browser_browser_list_pending_requests_foreach_func(InfcRequest* request, gpointer user_data) { InfcBrowserListPendingRequestsForeachData* data; guint node_id; data = (InfcBrowserListPendingRequestsForeachData*)user_data; g_object_get(G_OBJECT(request), "node-id", &node_id, NULL); if(node_id == G_MAXUINT) { if(data->iter == NULL) data->result = g_slist_prepend(data->result, request); } else { if(data->iter != NULL && node_id == data->iter->node_id) data->result = g_slist_prepend(data->result, request); } } static void infc_browser_iter_get_sync_in_requests_foreach_func(InfcRequest* request, gpointer user_data) { InfcBrowserIterGetSyncInRequestsForeachData* data; InfSession* session; guint node_id; data = (InfcBrowserIterGetSyncInRequestsForeachData*)user_data; /* This is only a sync-in request if we assigned a session to sync with */ session = g_object_get_qdata( G_OBJECT(request), infc_browser_sync_in_session_quark ); if(session != NULL) { g_object_get(G_OBJECT(request), "node-id", &node_id, NULL); if(node_id != G_MAXUINT && node_id == data->iter->node_id) data->result = g_slist_prepend(data->result, request); } } static void infc_browser_get_chat_request_foreach_func(InfcRequest* request, gpointer user_data) { InfcBrowserIterGetChatRequestForeachData* data; data = (InfcBrowserIterGetChatRequestForeachData*)user_data; /* There can only be one such request: */ g_assert(data->result == NULL); /* TODO: Stop foreach when we found the request. Requires changes in * InfcRequestManager. */ data->result = request; } /* * Path handling */ /* Returns the complete path to this node in the given GString */ static void infc_browser_node_get_path_string(InfcBrowserNode* node, GString* string) { g_return_if_fail(node != NULL); g_return_if_fail(string != NULL); if(node->parent != NULL) { /* Each node except the root node has a name */ g_assert(node->name != NULL); /* Make sure to not recurse if our parent is the root node because * this would add an additional slash */ if(node->parent->parent != NULL) infc_browser_node_get_path_string(node->parent, string); g_string_append_c(string, '/'); g_string_append(string, node->name); } else { /* This node has no parent, so it is the root node */ g_assert(node->name == NULL); g_string_append_c(string, '/'); } } static void infc_browser_node_get_path(InfcBrowserNode* node, gchar** path, gsize* len) { GString* str; g_return_if_fail(node != NULL); g_return_if_fail(path != NULL); str = g_string_sized_new(128); infc_browser_node_get_path_string(node, str); *path = str->str; if(len != NULL) *len = str->len; g_string_free(str, FALSE); } /* * Tree handling */ static void infc_browser_node_link(InfcBrowserNode* node, InfcBrowserNode* parent) { g_assert(parent != NULL); g_assert(parent->type == INFC_BROWSER_NODE_SUBDIRECTORY); node->prev = NULL; if(parent->shared.subdir.child != NULL) { parent->shared.subdir.child->prev = node; node->next = parent->shared.subdir.child; } else { node->next = NULL; } parent->shared.subdir.child = node; } static void infc_browser_node_unlink(InfcBrowserNode* node) { g_assert(node->parent != NULL); g_assert(node->parent->type == INFC_BROWSER_NODE_SUBDIRECTORY); if(node->prev != NULL) node->prev->next = node->next; else node->parent->shared.subdir.child = node->next; if(node->next != NULL) node->next->prev = node->prev; } static InfcBrowserNode* infc_browser_node_new_common(InfcBrowser* browser, InfcBrowserNode* parent, guint id, InfcBrowserNodeType type, const gchar* name, const InfAclSheetSet* sheet_set) { InfcBrowserPrivate* priv; InfcBrowserNode* node; InfBrowserIter iter; priv = INFC_BROWSER_PRIVATE(browser); node = g_slice_new(InfcBrowserNode); node->parent = parent; node->id = id; node->name = g_strdup(name); node->type = type; if(sheet_set != NULL) node->acl = inf_acl_sheet_set_copy(sheet_set); else node->acl = NULL; node->acl_queried = FALSE; if(parent != NULL) { /*node->status = INFC_BROWSER_NODE_INHERIT;*/ infc_browser_node_link(node, parent); } else { /*node->status = INFC_BROWSER_NODE_SYNC;*/ node->prev = NULL; node->next = NULL; } g_assert( g_hash_table_lookup(priv->nodes, GUINT_TO_POINTER(node->id)) == NULL ); g_hash_table_insert(priv->nodes, GUINT_TO_POINTER(node->id), node); return node; } static InfcBrowserNode* infc_browser_node_new_subdirectory(InfcBrowser* browser, InfcBrowserNode* parent, guint id, const gchar* name, const InfAclSheetSet* sheet_set) { InfcBrowserNode* node; node = infc_browser_node_new_common( browser, parent, id, INFC_BROWSER_NODE_SUBDIRECTORY, name, sheet_set ); node->shared.subdir.explored = FALSE; node->shared.subdir.child = NULL; return node; } static InfcBrowserNode* infc_browser_node_new_note(InfcBrowser* browser, InfcBrowserNode* parent, guint id, const gchar* name, const gchar* type, const InfAclSheetSet* sheet_set) { InfcBrowserPrivate* priv; InfcBrowserNode* node; InfcNotePlugin* plugin; priv = INFC_BROWSER_PRIVATE(browser); plugin = g_hash_table_lookup(priv->plugins, type); node = infc_browser_node_new_common( browser, parent, id, (plugin != NULL) ? INFC_BROWSER_NODE_NOTE_KNOWN : INFC_BROWSER_NODE_NOTE_UNKNOWN, name, sheet_set ); if(plugin != NULL) { node->shared.known.plugin = plugin; node->shared.known.session = NULL; } else { node->shared.unknown.type = g_strdup(type); } return node; } /* Required by infc_browser_session_remove_session */ static void infc_browser_session_notify_subscription_group_cb(InfSession* session, const GParamSpec* pspec, gpointer user_data); static void infc_browser_session_remove_session(InfcBrowser* browser, InfcBrowserNode* node, InfcRequest* request) { InfSession* session; InfcSessionProxy* proxy; InfBrowserIter iter; g_assert(node->type == INFC_BROWSER_NODE_NOTE_KNOWN); g_assert(node->shared.known.session != NULL); proxy = node->shared.known.session; g_object_get(G_OBJECT(proxy), "session", &session, NULL); inf_signal_handlers_disconnect_by_func( session, G_CALLBACK(infc_browser_session_notify_subscription_group_cb), browser ); g_object_set_qdata( G_OBJECT(session), infc_browser_session_proxy_quark, NULL ); node->shared.known.session = NULL; inf_browser_unsubscribe_session( INF_BROWSER(browser), &iter, INF_SESSION_PROXY(proxy), INF_REQUEST(request) ); g_object_unref(session); g_object_unref(proxy); } static void infc_browser_session_remove_child_sessions(InfcBrowser* browser, InfcBrowserNode* node, InfcRequest* request) { InfcBrowserNode* child; switch(node->type) { case INFC_BROWSER_NODE_SUBDIRECTORY: if(node->shared.subdir.explored == TRUE) { for(child = node->shared.subdir.child; child != NULL; child = child->next) { infc_browser_session_remove_child_sessions(browser, child, request); } } break; case INFC_BROWSER_NODE_NOTE_KNOWN: if(node->shared.known.session != NULL) infc_browser_session_remove_session(browser, node, request); break; case INFC_BROWSER_NODE_NOTE_UNKNOWN: /* nothing to do */ break; } } static void infc_browser_node_register(InfcBrowser* browser, InfcBrowserNode* node, InfcRequest* request) { InfBrowserIter iter; iter.node_id = node->id; iter.node = node; inf_browser_node_added(INF_BROWSER(browser), &iter, INF_REQUEST(request)); } static void infc_browser_node_unregister(InfcBrowser* browser, InfcBrowserNode* node, InfcRequest* request) { InfBrowserIter iter; iter.node_id = node->id; iter.node = node; inf_browser_node_removed(INF_BROWSER(browser), &iter, INF_REQUEST(request)); } /* Required by infc_browser_node_free */ static void infc_browser_remove_sync_in(InfcBrowser* browser, InfcBrowserSyncIn* sync_in); static void infc_browser_remove_subreq(InfcBrowser* browser, InfcBrowserSubreq* request); static void infc_browser_node_free(InfcBrowser* browser, InfcBrowserNode* node) { InfcBrowserPrivate* priv; gboolean removed; GSList* item; InfcBrowserSyncIn* sync_in; InfcBrowserSubreq* request; InfBrowserIter iter; GError* error; priv = INFC_BROWSER_PRIVATE(browser); switch(node->type) { case INFC_BROWSER_NODE_SUBDIRECTORY: /* Also do this for nodes that don't have the explored flag to TRUE, to * delete nodes in case we are still in the middle of an exploration */ while(node->shared.subdir.child != NULL) infc_browser_node_free(browser, node->shared.subdir.child); break; case INFC_BROWSER_NODE_NOTE_KNOWN: /* Is first unlinked with remove_child_sessions */ g_assert(node->shared.known.session == NULL); break; case INFC_BROWSER_NODE_NOTE_UNKNOWN: g_free(node->shared.unknown.type); break; default: g_assert_not_reached(); break; } /* Remove sync-ins that sync into this node */ for(item = priv->sync_ins; item != NULL; ) { sync_in = (InfcBrowserSyncIn*)item->data; item = item->next; if(sync_in->node == node) infc_browser_remove_sync_in(browser, sync_in); } /* Check subscription requests for this node */ for(item = priv->subscription_requests; item != NULL; ) { request = (InfcBrowserSubreq*)item->data; item = item->next; /* TODO: Can't we remove the subscription requests here already, and * assert that a request exists in * infc_browser_communication_object_sent()? Or is there something that * needs to be done in infc_browser_communication_object_sent() even if * the corresponding node has been removed? */ switch(request->type) { case INFC_BROWSER_SUBREQ_SESSION: if(request->shared.session.node == node) { request->shared.session.node = NULL; if(request->shared.session.request != NULL) { error = g_error_new_literal( inf_directory_error_quark(), INF_DIRECTORY_ERROR_NO_SUCH_NODE, _("The node to subscribe to has been removed") ); infc_request_manager_fail_request( priv->request_manager, INFC_REQUEST(request->shared.session.request), error ); g_error_free(error); g_object_unref(request->shared.session.request); request->shared.session.request = NULL; } } break; case INFC_BROWSER_SUBREQ_ADD_NODE: if(request->shared.add_node.parent == node) { request->shared.add_node.parent = NULL; if(request->shared.add_node.request != NULL) { error = g_error_new_literal( inf_directory_error_quark(), INF_DIRECTORY_ERROR_NO_SUCH_NODE, _("The subdirectory into which the new node should have been " "created has been removed") ); infc_request_manager_fail_request( priv->request_manager, INFC_REQUEST(request->shared.add_node.request), error ); g_error_free(error); g_object_unref(request->shared.add_node.request); request->shared.add_node.request = NULL; } } break; case INFC_BROWSER_SUBREQ_SYNC_IN: if(request->shared.sync_in.parent == node) { request->shared.sync_in.parent = NULL; g_assert(request->shared.sync_in.request != NULL); error = g_error_new_literal( inf_directory_error_quark(), INF_DIRECTORY_ERROR_NO_SUCH_NODE, _("The subdirectory into which the new node should have been " "created has been removed") ); infc_request_manager_fail_request( priv->request_manager, INFC_REQUEST(request->shared.sync_in.request), error ); g_error_free(error); g_object_unref(request->shared.sync_in.request); request->shared.sync_in.request = NULL; } break; default: g_assert_not_reached(); break; } } if(node->parent != NULL) infc_browser_node_unlink(node); if(node->acl != NULL) inf_acl_sheet_set_free(node->acl); removed = g_hash_table_remove(priv->nodes, GUINT_TO_POINTER(node->id)); g_assert(removed == TRUE); g_free(node->name); g_slice_free(InfcBrowserNode, node); } static void infc_browser_remove_acl_sheet_from_sheet_set(InfAclSheetSet* sheet_set, InfAclAccountId account) { InfAclSheet* sheet; if(sheet_set != NULL) { sheet = inf_acl_sheet_set_find_sheet(sheet_set, account); if(sheet != NULL) inf_acl_sheet_set_remove_sheet(sheet_set, sheet); } } static void infc_browser_remove_account_from_sheets(InfcBrowser* browser, InfcBrowserNode* node, InfAclAccountId account) { InfcBrowserNode* child; InfAclSheet* sheet; InfAclSheet announce_sheet; InfAclSheetSet sheet_set; InfBrowserIter iter; if(node->type == INFC_BROWSER_NODE_SUBDIRECTORY && node->shared.subdir.explored) { for(child = node->shared.subdir.child; child != NULL; child = child->next) { infc_browser_remove_account_from_sheets(browser, child, account); } } if(node->acl != NULL) { sheet = inf_acl_sheet_set_find_sheet(node->acl, account); if(sheet != NULL) { announce_sheet = *sheet; inf_acl_sheet_set_remove_sheet(node->acl, sheet); /* Clear the mask, to announce that all permissions * have been reset to default */ inf_acl_mask_clear(&announce_sheet.mask); sheet_set.own_sheets = NULL; sheet_set.sheets = &announce_sheet; sheet_set.n_sheets = 1; iter.node = node; iter.node_id = node->id; inf_browser_acl_changed(INF_BROWSER(browser), &iter, &sheet_set, NULL); } } } /* Enforce the ACL for the current user. If the server changes ACLs or we are * switching accounts, then we need to update our internal state to the new * permissions. new_sheet contains a ACL sheet for the current user which we * add to the node's ACL. This is used when before enforcing the new ACL the * ACL for this node was not known. */ static void infc_browser_enforce_single_acl(InfcBrowser* browser, InfcBrowserNode* node, InfcRequest* request, const InfAclSheet* new_sheet) { InfcBrowserPrivate* priv; InfBrowser* ibrowser; InfBrowserIter iter; InfAclAccountId account; InfAclMask mask; InfcRequest* req; GError* error; InfcBrowserNode* child; GSList* item; InfcBrowserSubreq* subreq; InfAclAccountId default_id; InfAclSheetSet* sheet_set; InfAclSheet* sheet; InfAclSheet* added_sheet; priv = INFC_BROWSER_PRIVATE(browser); ibrowser = INF_BROWSER(browser); iter.node = node; iter.node_id = node->id; account = priv->local_account->id; g_assert(new_sheet == NULL || new_sheet->account == account); if(node->type == INFC_BROWSER_NODE_SUBDIRECTORY) { if(node->shared.subdir.explored == TRUE) { inf_acl_mask_set1(&mask, INF_ACL_CAN_EXPLORE_NODE); if(!inf_browser_check_acl(ibrowser, &iter, account, &mask, NULL)) { req = INFC_REQUEST( inf_browser_get_pending_request( ibrowser, &iter, "explore-node" ) ); if(req != NULL) { error = NULL; g_set_error_literal( &error, inf_request_error_quark(), INF_REQUEST_ERROR_NOT_AUTHORIZED, _("Permissions to explore this node have been revoked") ); infc_request_manager_fail_request(priv->request_manager, req, error); g_error_free(error); } while(node->shared.subdir.child != NULL) { child = node->shared.subdir.child; infc_browser_node_unregister(browser, child, request); infc_browser_node_free(browser, child); } /* Cancel any subscription request that wants to create a node in this * node. It is important to this here and not in * communication_object_sent(), so that there are no inconsistencies * when the server re-explores the node for us. */ for(item = priv->subscription_requests; item != NULL; ) { subreq = (InfcBrowserSubreq*)item->data; item = item->next; switch(subreq->type) { case INFC_BROWSER_SUBREQ_CHAT: case INFC_BROWSER_SUBREQ_SESSION: break; case INFC_BROWSER_SUBREQ_ADD_NODE: if(subreq->shared.add_node.parent == node) { subreq->shared.add_node.parent = NULL; if(subreq->shared.add_node.request != NULL) { error = NULL; g_set_error_literal( &error, inf_request_error_quark(), INF_REQUEST_ERROR_NOT_AUTHORIZED, _("Permissions to explore the parent node " "have been revoked") ); infc_request_manager_fail_request( priv->request_manager, subreq->shared.add_node.request, error ); g_error_free(error); g_object_unref(subreq->shared.add_node.request); subreq->shared.add_node.request = NULL; } } break; case INFC_BROWSER_SUBREQ_SYNC_IN: if(subreq->shared.sync_in.parent == node) { subreq->shared.sync_in.parent = NULL; if(subreq->shared.sync_in.request != NULL) { error = NULL; g_set_error_literal( &error, inf_request_error_quark(), INF_REQUEST_ERROR_NOT_AUTHORIZED, _("Permissions to explore the parent node " "have been revoked") ); infc_request_manager_fail_request( priv->request_manager, subreq->shared.sync_in.request, error ); g_error_free(error); g_object_unref(subreq->shared.sync_in.request); subreq->shared.sync_in.request = NULL; } } break; default: g_assert_not_reached(); break; } } node->shared.subdir.explored = FALSE; } } } else { /* Don't handle subscriptions explicitely, they will be ended by the * server on session level (or, if the server allows them to live on, * even better). */ } /* Check if query-acl was revoked, and if yes, reset the acl_queried flag * for the node. */ if(node->acl_queried == TRUE) { inf_acl_mask_set1(&mask, INF_ACL_CAN_QUERY_ACL); if(inf_browser_check_acl(ibrowser, &iter, account, &mask, NULL) == FALSE) node->acl_queried = FALSE; } /* If query-acl was revoked, then update the sheet set by removing all * sheets other than the default one and the one for our account. */ if(node->acl_queried == FALSE) { if(node->acl != NULL) sheet_set = inf_acl_sheet_set_get_clear_sheets(node->acl); else sheet_set = inf_acl_sheet_set_new(); default_id = inf_acl_account_id_from_string("default"); sheet = inf_acl_sheet_set_find_sheet(sheet_set, default_id); if(sheet != NULL) inf_acl_sheet_set_remove_sheet(sheet_set, sheet); if(priv->local_account->id != default_id) { sheet = inf_acl_sheet_set_find_sheet(sheet_set, priv->local_account->id); if(sheet != NULL) { inf_acl_sheet_set_remove_sheet(sheet_set, sheet); g_assert(new_sheet == NULL); } else if(new_sheet != NULL) { added_sheet = inf_acl_sheet_set_add_sheet(sheet_set, new_sheet->account); *added_sheet = *new_sheet; } } if(sheet_set != NULL && sheet_set->n_sheets > 0) { node->acl = inf_acl_sheet_set_merge_sheets(node->acl, sheet_set); /* Check subscription requests for this node, and adapt the sheet set, * so that the sheet set is correct when the node is * eventually created. */ for(item = priv->subscription_requests; item != NULL; ) { subreq = (InfcBrowserSubreq*)item->data; item = item->next; switch(subreq->type) { case INFC_BROWSER_SUBREQ_CHAT: case INFC_BROWSER_SUBREQ_SESSION: break; case INFC_BROWSER_SUBREQ_ADD_NODE: if(subreq->shared.add_node.parent == node) { subreq->shared.add_node.sheet_set = inf_acl_sheet_set_merge_sheets( subreq->shared.add_node.sheet_set, sheet_set ); } break; case INFC_BROWSER_SUBREQ_SYNC_IN: if(subreq->shared.sync_in.parent == node) { subreq->shared.sync_in.sheet_set = inf_acl_sheet_set_merge_sheets( subreq->shared.sync_in.sheet_set, sheet_set ); } break; default: g_assert_not_reached(); break; } } inf_browser_acl_changed( INF_BROWSER(browser), &iter, sheet_set, INF_REQUEST(request) ); } inf_acl_sheet_set_free(sheet_set); } } static void infc_browser_enforce_acl(InfcBrowser* browser, InfcBrowserNode* node, InfcRequest* request, GHashTable* new_acls) { InfBrowser* ibrowser; InfcBrowserPrivate* priv; InfcBrowserNode* child; InfBrowserIter iter; InfAclMask mask; const InfAclSheet* sheet; InfAclAccountId account; ibrowser = INF_BROWSER(browser); priv = INFC_BROWSER_PRIVATE(browser); /* First, check whether the account_list_queried flag needs to be reset * because we lost the can-query-account-list permission. Technically we * still have the account list queried, but we do not receive notifications * anymore from the server if this permission has been revoked. */ if(node == priv->root && priv->account_list_status == INFC_BROWSER_ACCOUNT_LIST_NOTIFICATIONS) { iter.node = node; iter.node_id = node->id; inf_acl_mask_set1(&mask, INF_ACL_CAN_QUERY_ACCOUNT_LIST); account = priv->local_account->id; if(inf_browser_check_acl(ibrowser, &iter, account, &mask, NULL) == FALSE) { priv->account_list_status = INFC_BROWSER_ACCOUNT_LIST_NO_NOTIFICATIONS; } } /* Enforce ACL for this node */ sheet = NULL; if(new_acls != NULL) sheet = g_hash_table_lookup(new_acls, GUINT_TO_POINTER(node->id)); infc_browser_enforce_single_acl(browser, node, request, sheet); /* Enforce it for all children. Note that if the explore-node permission was * revoked, then the above call has already removed all child nodes. */ if(node->type == INFC_BROWSER_NODE_SUBDIRECTORY) { for(child = node->shared.subdir.child; child != NULL; child = child->next) { infc_browser_enforce_acl(browser, child, request, new_acls); } } /* Note that even if are no longer allowed to query the account list, we * can still keep around our cache of accounts, it just will not be updated * anymore from now on. */ } /* * Signal handlers */ static void infc_browser_session_notify_subscription_group_cb(InfSession* session, const GParamSpec* spec, gpointer user_data) { InfcBrowser* browser; InfcBrowserPrivate* priv; InfBrowserIter* iter; InfcBrowserNode* node; InfcSessionProxy* proxy; InfSession* proxy_session; browser = INFC_BROWSER(user_data); priv = INFC_BROWSER_PRIVATE(browser); /* When the session loses its subscription group, we detach it from the * browser. It means that we are not subscribed to the session anymore. The * session is now in a "floating" state. It can still be used, for example * to sync-in the session into another node, but it is not connected * anymore to any other host. */ if(inf_session_get_subscription_group(session) == NULL) { iter = (InfBrowserIter*)g_object_get_qdata( G_OBJECT(session), infc_browser_session_proxy_quark ); if(iter != NULL) { g_assert( g_hash_table_lookup( INFC_BROWSER_PRIVATE(browser)->nodes, GUINT_TO_POINTER(iter->node_id) ) == iter->node ); node = (InfcBrowserNode*)iter->node; g_assert(node->type == INFC_BROWSER_NODE_NOTE_KNOWN); g_assert(node->shared.known.session != NULL); g_object_get( G_OBJECT(node->shared.known.session), "session", &proxy_session, NULL ); g_assert(proxy_session == session); g_object_unref(proxy_session); infc_browser_session_remove_session(browser, node, NULL); } else { g_assert(priv->chat_session != NULL); g_object_get( G_OBJECT(priv->chat_session), "session", &proxy_session, NULL ); g_assert(proxy_session == session); inf_signal_handlers_disconnect_by_func( proxy_session, G_CALLBACK(infc_browser_session_notify_subscription_group_cb), browser ); g_object_unref(proxy_session); proxy = priv->chat_session; priv->chat_session = NULL; g_object_notify(G_OBJECT(browser), "chat-session"); inf_browser_unsubscribe_session( INF_BROWSER(browser), NULL, INF_SESSION_PROXY(proxy), NULL ); g_object_unref(proxy); } } } static void infc_browser_welcome_timeout_func(gpointer user_data) { InfcBrowser* browser; InfcBrowserPrivate* priv; GError* error; browser = INFC_BROWSER(user_data); priv = INFC_BROWSER_PRIVATE(browser); priv->welcome_timeout = NULL; error = NULL; g_set_error_literal( &error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_NO_WELCOME_MESSAGE, _("The server did not send an initial welcome message. This means that " "the server is running a lower version of the software which is " "incompatible to the client. Consider downgrading the client, or ask " "the server administrators to upgrade their software.") ); inf_browser_error(INF_BROWSER(browser), error); g_error_free(error); g_assert(priv->status != INF_BROWSER_CLOSED); priv->status = INF_BROWSER_CLOSED; g_object_notify(G_OBJECT(browser), "status"); } /* Required by infc_browser_disconnected */ static void infc_browser_member_removed_cb(InfCommunicationGroup* group, InfXmlConnection* connection, gpointer user_data); static void infc_browser_connected(InfcBrowser* browser) { InfcBrowserPrivate* priv; priv = INFC_BROWSER_PRIVATE(browser); g_assert(priv->group == NULL); /* Join directory group of server */ /* directory group always uses central method */ priv->group = inf_communication_manager_join_group( priv->communication_manager, "InfDirectory", priv->connection, "central" ); /* "central" method should always be available */ g_assert(priv->group != NULL); inf_communication_group_set_target( INF_COMMUNICATION_GROUP(priv->group), INF_COMMUNICATION_OBJECT(browser) ); g_signal_connect( priv->group, "member-removed", G_CALLBACK(infc_browser_member_removed_cb), browser ); /* Wait for welcome message */ if(priv->status != INF_BROWSER_OPENING) { priv->status = INF_BROWSER_OPENING; g_object_notify(G_OBJECT(browser), "status"); } /* TODO: We have a relatively low timeout here to easily recognize when * we try to connect to a server which does not yet send a welcome * message. We can set it somewhat higher later when there are fewer * old servers around. */ g_assert(priv->welcome_timeout == NULL); priv->welcome_timeout = inf_io_add_timeout( priv->io, 5*1000, infc_browser_welcome_timeout_func, browser, NULL ); } static void infc_browser_disconnected(InfcBrowser* browser) { InfcBrowserPrivate* priv; InfcBrowserNode* child; InfcBrowserNode* next; InfSession* session; InfBrowserIter iter; priv = INFC_BROWSER_PRIVATE(browser); /* Note that we do not remove the corresponding node that we sync in. We * lost the connection to the server anyway, so we do not care whether * that node exists on the server or not. */ while(priv->sync_ins != NULL) infc_browser_remove_sync_in(browser, priv->sync_ins->data); while(priv->subscription_requests != NULL) infc_browser_remove_subreq(browser, priv->subscription_requests->data); /* TODO: Emit failed signal with some "disconnected" error */ if(priv->request_manager) { infc_request_manager_clear(priv->request_manager); g_object_unref(priv->request_manager); priv->request_manager = NULL; } inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->group), G_CALLBACK(infc_browser_member_removed_cb), browser ); /* Reset group since the browser's connection is always the publisher. */ g_object_unref(priv->group); priv->group = NULL; #if 0 /* Remove tree */ for(child = priv->root->shared.subdir.child; child != NULL; child = next) { next = child->next; infc_browser_node_unregister(browser, child); infc_browser_node_free(browser, child); } #endif if(priv->root != NULL) { infc_browser_session_remove_child_sessions(browser, priv->root, NULL); infc_browser_node_unregister(browser, priv->root, NULL); infc_browser_node_free(browser, priv->root); priv->root = NULL; } priv->account_list_status = INFC_BROWSER_ACCOUNT_LIST_NOT_QUERIED; priv->local_account = NULL; if(priv->accounts != NULL) { g_hash_table_destroy(priv->accounts); priv->accounts = NULL; } g_object_freeze_notify(G_OBJECT(browser)); if(priv->chat_session != NULL) { g_object_get(G_OBJECT(priv->chat_session), "session", &session, NULL); inf_signal_handlers_disconnect_by_func( session, G_CALLBACK(infc_browser_session_notify_subscription_group_cb), browser ); g_object_unref(session); g_object_unref(priv->chat_session); priv->chat_session = NULL; g_object_notify(G_OBJECT(browser), "chat-session"); } if(priv->welcome_timeout != NULL) { inf_io_remove_timeout(priv->io, priv->welcome_timeout); priv->welcome_timeout = NULL; } priv->status = INF_BROWSER_CLOSED; g_object_notify(G_OBJECT(browser), "status"); g_object_thaw_notify(G_OBJECT(browser)); } static void infc_browser_member_removed_cb(InfCommunicationGroup* group, InfXmlConnection* connection, gpointer user_data) { InfcBrowser* browser; InfcBrowserPrivate* priv; browser = INFC_BROWSER(user_data); priv = INFC_BROWSER_PRIVATE(browser); g_assert(INF_COMMUNICATION_GROUP(priv->group) == group); if(connection == priv->connection) infc_browser_disconnected(browser); } static void infc_browser_connection_notify_status_cb(GObject* object, GParamSpec* pspec, gpointer user_data) { InfcBrowser* browser; InfcBrowserPrivate* priv; InfXmlConnectionStatus status; browser = INFC_BROWSER(user_data); priv = INFC_BROWSER_PRIVATE(browser); g_object_get(object, "status", &status, NULL); switch(status) { case INF_XML_CONNECTION_OPENING: if(priv->status != INF_BROWSER_OPENING) { priv->status = INF_BROWSER_OPENING; g_object_notify(G_OBJECT(browser), "status"); } break; case INF_XML_CONNECTION_OPEN: infc_browser_connected(browser); break; case INF_XML_CONNECTION_CLOSING: case INF_XML_CONNECTION_CLOSED: /* The group will emit ::member-removed in this case in which we * do some cleanup. If we got here from INF_XML_CONNECTION_OPENING then * that cleanup is not required, but remember to reset status. */ if(priv->group == NULL && priv->status != INF_BROWSER_CLOSED) { g_assert(priv->request_manager == NULL); priv->status = INF_BROWSER_CLOSED; g_object_notify(G_OBJECT(browser), "status"); } break; default: g_assert_not_reached(); break; } } static void infc_browser_connection_error_cb(InfXmlConnection* connection, const GError* error, gpointer user_data) { InfcBrowser* browser; browser = INFC_BROWSER(user_data); /* Just relay to save others some work */ inf_browser_error(INF_BROWSER(browser), error); } /* * Helper functions */ /* TODO: This function should be moved to InfcRequest */ static xmlNodePtr infc_browser_request_to_xml(InfcRequest* request) { xmlNodePtr xml; gchar* type; guint seq; gchar seq_buffer[16]; g_object_get(G_OBJECT(request), "type", &type, "seq", &seq, NULL); sprintf(seq_buffer, "%u", seq); xml = xmlNewNode(NULL, (const xmlChar*)type); xmlNewProp(xml, (const xmlChar*)"seq", (const xmlChar*)seq_buffer); g_free(type); return xml; } static GError* infc_browser_method_unsupported_error(const gchar* method_name, InfXmlConnection* connection) { GError* error; gchar* network; g_object_get(G_OBJECT(connection), "network", &network, NULL); error = g_error_new( inf_directory_error_quark(), INF_DIRECTORY_ERROR_METHOD_UNSUPPORTED, _("This session requires communication method `%s' which is not " "installed for network `%s'"), method_name, network ); g_free(network); return error; } /* * GObject overrides. */ static void infc_browser_init(InfcBrowser* browser) { InfcBrowserPrivate* priv; priv = INFC_BROWSER_PRIVATE(browser); priv->io = NULL; priv->communication_manager = NULL; priv->group = NULL; priv->connection = NULL; priv->seq_id = 0; priv->welcome_timeout = NULL; priv->request_manager = NULL; priv->plugins = g_hash_table_new(g_str_hash, g_str_equal); priv->status = INF_BROWSER_CLOSED; priv->nodes = g_hash_table_new(NULL, NULL); priv->root = NULL; priv->accounts = NULL; priv->local_account = NULL; priv->account_list_status = INFC_BROWSER_ACCOUNT_LIST_NOT_QUERIED; priv->sync_ins = NULL; priv->subscription_requests = NULL; priv->chat_session = NULL; } static void infc_browser_dispose(GObject* object) { InfcBrowser* browser; InfcBrowserPrivate* priv; InfSession* session; browser = INFC_BROWSER(object); priv = INFC_BROWSER_PRIVATE(browser); /* TODO: Use infc_browser_set_connection() as soon as it is available - * should be trivial to implement now. Remember to make the "connection" * property writable also. */ #if 0 infc_browser_set_connection(browser, NULL); #else if(priv->group != NULL) infc_browser_disconnected(browser); g_assert(priv->group == NULL); /* Should have been freed by infc_browser_disconnected */ g_assert(priv->accounts == NULL); g_assert(priv->sync_ins == NULL); g_assert(priv->subscription_requests == NULL); if(priv->connection != NULL) { inf_signal_handlers_disconnect_by_func( priv->connection, G_CALLBACK(infc_browser_connection_notify_status_cb), browser ); inf_signal_handlers_disconnect_by_func( priv->connection, G_CALLBACK(infc_browser_connection_error_cb), browser ); g_object_unref(priv->connection); priv->connection = NULL; } #endif /* Close chat session if it is open */ if(priv->chat_session != NULL) { g_object_get(G_OBJECT(priv->chat_session), "session", &session, NULL); inf_session_close(session); g_object_unref(session); } g_assert(priv->chat_session == NULL); g_object_unref(priv->communication_manager); priv->communication_manager = NULL; g_hash_table_destroy(priv->plugins); priv->plugins = NULL; g_assert(priv->request_manager == NULL); if(priv->welcome_timeout != NULL) { inf_io_remove_timeout(priv->io, priv->welcome_timeout); priv->welcome_timeout = NULL; } if(priv->io != NULL) { g_object_unref(G_OBJECT(priv->io)); priv->io = NULL; } G_OBJECT_CLASS(infc_browser_parent_class)->dispose(object); } static void infc_browser_finalize(GObject* object) { InfcBrowser* browser; InfcBrowserPrivate* priv; browser = INFC_BROWSER(object); priv = INFC_BROWSER_PRIVATE(browser); g_hash_table_destroy(priv->nodes); priv->nodes = NULL; G_OBJECT_CLASS(infc_browser_parent_class)->finalize(object); } static void infc_browser_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfcBrowser* browser; InfcBrowserPrivate* priv; InfXmlConnectionStatus status; browser = INFC_BROWSER(object); priv = INFC_BROWSER_PRIVATE(browser); switch(prop_id) { case PROP_IO: g_assert(priv->io == NULL); /* construct only */ priv->io = INF_IO(g_value_dup_object(value)); break; case PROP_COMMUNICATION_MANAGER: g_assert(priv->communication_manager == NULL); /* construct/only */ priv->communication_manager = INF_COMMUNICATION_MANAGER(g_value_dup_object(value)); break; case PROP_CONNECTION: if(priv->connection != NULL) { if(priv->group != NULL) infc_browser_disconnected(browser); inf_signal_handlers_disconnect_by_func( priv->connection, G_CALLBACK(infc_browser_connection_notify_status_cb), browser ); inf_signal_handlers_disconnect_by_func( priv->connection, G_CALLBACK(infc_browser_connection_error_cb), browser ); g_object_unref(priv->connection); } priv->connection = INF_XML_CONNECTION(g_value_get_object(value)); if(priv->connection) { g_object_ref(priv->connection); g_object_get(G_OBJECT(priv->connection), "status", &status, NULL); g_signal_connect( G_OBJECT(priv->connection), "notify::status", G_CALLBACK(infc_browser_connection_notify_status_cb), browser ); g_signal_connect( G_OBJECT(priv->connection), "error", G_CALLBACK(infc_browser_connection_error_cb), browser ); switch(status) { case INF_XML_CONNECTION_OPENING: if(priv->status != INF_BROWSER_OPENING) { priv->status = INF_BROWSER_OPENING; g_object_notify(G_OBJECT(browser), "status"); } break; case INF_XML_CONNECTION_OPEN: infc_browser_connected(browser); break; case INF_XML_CONNECTION_CLOSING: case INF_XML_CONNECTION_CLOSED: if(priv->status != INF_BROWSER_CLOSED) { priv->status = INF_BROWSER_CLOSED; g_object_notify(G_OBJECT(browser), "status"); } break; } } else { if(priv->status != INF_BROWSER_CLOSED) { priv->status = INF_BROWSER_CLOSED; g_object_notify(G_OBJECT(browser), "status"); } } break; case PROP_STATUS: case PROP_CHAT_SESSION: /* read only */ default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void infc_browser_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfcBrowser* browser; InfcBrowserPrivate* priv; browser = INFC_BROWSER(object); priv = INFC_BROWSER_PRIVATE(browser); switch(prop_id) { case PROP_IO: g_value_set_object(value, G_OBJECT(priv->io)); break; case PROP_COMMUNICATION_MANAGER: g_value_set_object(value, G_OBJECT(priv->communication_manager)); break; case PROP_CONNECTION: g_value_set_object(value, G_OBJECT(priv->connection)); break; case PROP_STATUS: g_value_set_enum(value, priv->status); break; case PROP_CHAT_SESSION: g_value_set_object(value, G_OBJECT(priv->chat_session)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } /* * Subscription requests */ static InfcBrowserSubreq* infc_browser_add_subreq_common(InfcBrowser* browser, InfcBrowserSubreqType type, guint node_id) { InfcBrowserPrivate* priv; InfcBrowserSubreq* request; priv = INFC_BROWSER_PRIVATE(browser); request = g_slice_new(InfcBrowserSubreq); request->type = type; request->node_id = node_id; priv->subscription_requests = g_slist_prepend(priv->subscription_requests, request); return request; } static InfcBrowserSubreq* infc_browser_add_subreq_chat(InfcBrowser* browser, InfcRequest* request, InfCommunicationJoinedGroup* group) { InfcBrowserSubreq* subreq; subreq = infc_browser_add_subreq_common( browser, INFC_BROWSER_SUBREQ_CHAT, 0 ); subreq->shared.chat.request = request; subreq->shared.chat.subscription_group = group; /* Request can be NULL if the server subscribed us to the chat without * us asking about it. */ if(request != NULL) g_object_ref(request); g_object_ref(group); return subreq; } static InfcBrowserSubreq* infc_browser_add_subreq_session(InfcBrowser* browser, InfcBrowserNode* node, InfcRequest* request, InfCommunicationJoinedGroup* group) { InfcBrowserSubreq* subreq; subreq = infc_browser_add_subreq_common( browser, INFC_BROWSER_SUBREQ_SESSION, node->id ); subreq->shared.session.node = node; subreq->shared.session.request = request; subreq->shared.session.subscription_group = group; /* TODO: Document in what case request can be NULL, or assert if it can't */ if(request != NULL) g_object_ref(request); g_object_ref(group); return subreq; } static InfcBrowserSubreq* infc_browser_add_subreq_add_node(InfcBrowser* browser, guint node_id, InfcBrowserNode* parent, const InfcNotePlugin* plugin, const gchar* name, const InfAclSheetSet* sheet_set, InfcRequest* request, InfCommunicationJoinedGroup* group) { InfcBrowserSubreq* subreq; subreq = infc_browser_add_subreq_common( browser, INFC_BROWSER_SUBREQ_ADD_NODE, node_id ); subreq->shared.add_node.parent = parent; subreq->shared.add_node.plugin = plugin; subreq->shared.add_node.name = g_strdup(name); if(sheet_set != NULL) subreq->shared.add_node.sheet_set = inf_acl_sheet_set_copy(sheet_set); else subreq->shared.add_node.sheet_set = NULL; subreq->shared.add_node.request = request; subreq->shared.add_node.subscription_group = group; if(request != NULL) g_object_ref(request); g_object_ref(group); return subreq; } static InfcBrowserSubreq* infc_browser_add_subreq_sync_in(InfcBrowser* browser, guint node_id, InfcBrowserNode* parent, const InfcNotePlugin* plugin, const gchar* name, const InfAclSheetSet* sheet_set, InfcRequest* request, InfSession* session, InfCommunicationJoinedGroup* sync_group, InfCommunicationJoinedGroup* sub_group) { InfcBrowserSubreq* subreq; /* Request must be available for sync-in: We can't sync-in something we * didn't request, because we don't have any data to sync. */ g_assert(request != NULL); g_assert(sync_group != NULL); g_assert(session != NULL); subreq = infc_browser_add_subreq_common( browser, INFC_BROWSER_SUBREQ_SYNC_IN, node_id ); subreq->shared.sync_in.parent = parent; subreq->shared.sync_in.plugin = plugin; subreq->shared.sync_in.name = g_strdup(name); if(sheet_set != NULL) subreq->shared.sync_in.sheet_set = inf_acl_sheet_set_copy(sheet_set); else subreq->shared.sync_in.sheet_set = NULL; subreq->shared.sync_in.request = request; subreq->shared.sync_in.session = session; subreq->shared.sync_in.synchronization_group = sync_group; subreq->shared.sync_in.subscription_group = sub_group; g_object_ref(request); g_object_ref(session); g_object_ref(sync_group); if(sub_group != NULL) g_object_ref(sub_group); return subreq; } static void infc_browser_free_subreq(InfcBrowserSubreq* request) { switch(request->type) { case INFC_BROWSER_SUBREQ_CHAT: g_object_unref(request->shared.chat.subscription_group); if(request->shared.chat.request != NULL) g_object_unref(request->shared.chat.request); break; case INFC_BROWSER_SUBREQ_SESSION: g_object_unref(request->shared.session.subscription_group); if(request->shared.session.request != NULL) g_object_unref(request->shared.session.request); break; case INFC_BROWSER_SUBREQ_ADD_NODE: g_object_unref(request->shared.add_node.subscription_group); if(request->shared.add_node.request != NULL) g_object_unref(request->shared.add_node.request); if(request->shared.add_node.sheet_set != NULL) inf_acl_sheet_set_free(request->shared.add_node.sheet_set); g_free(request->shared.add_node.name); break; case INFC_BROWSER_SUBREQ_SYNC_IN: if(request->shared.sync_in.subscription_group != NULL) g_object_unref(request->shared.sync_in.subscription_group); g_object_unref(request->shared.sync_in.synchronization_group); g_object_unref(request->shared.sync_in.session); /* Can be NULL if the corresponding node (parent) has been freed */ if(request->shared.sync_in.request != NULL) g_object_unref(request->shared.sync_in.request); if(request->shared.sync_in.sheet_set != NULL) inf_acl_sheet_set_free(request->shared.sync_in.sheet_set); g_free(request->shared.sync_in.name); break; default: g_assert_not_reached(); break; } g_slice_free(InfcBrowserSubreq, request); } static void infc_browser_unlink_subreq(InfcBrowser* browser, InfcBrowserSubreq* request) { InfcBrowserPrivate* priv; priv = INFC_BROWSER_PRIVATE(browser); priv->subscription_requests = g_slist_remove(priv->subscription_requests, request); } static void infc_browser_remove_subreq(InfcBrowser* browser, InfcBrowserSubreq* request) { infc_browser_unlink_subreq(browser, request); infc_browser_free_subreq(request); } /* Find a subscription request which will create a node with the given ID * upon completion. */ static InfcBrowserSubreq* infc_browser_find_subreq(InfcBrowser* browser, guint node_id) { InfcBrowserPrivate* priv; GSList* item; InfcBrowserSubreq* subreq; priv = INFC_BROWSER_PRIVATE(browser); for(item = priv->subscription_requests; item != NULL; item = item->next) { subreq = (InfcBrowserSubreq*)item->data; switch(subreq->type) { case INFC_BROWSER_SUBREQ_CHAT: case INFC_BROWSER_SUBREQ_SESSION: /* These do not create a note */ break; case INFC_BROWSER_SUBREQ_ADD_NODE: if(subreq->node_id == node_id) return subreq; break; case INFC_BROWSER_SUBREQ_SYNC_IN: if(subreq->node_id == node_id) return subreq; break; default: g_assert_not_reached(); break; } } return NULL; } /* * Sync-In */ static void infc_browser_sync_in_synchronization_failed_cb(InfSession* session, InfXmlConnection* connection, GError* error, gpointer user_data) { InfcBrowserSyncIn* sync_in; InfcBrowser* browser; InfcBrowserNode* node; sync_in = (InfcBrowserSyncIn*)user_data; /* Ignore if this affects the synchronization to another connection */ if(connection != sync_in->connection) return; browser = sync_in->browser; node = sync_in->node; g_object_ref(browser); /* The request for the sync-in was already considered successful, now that * the synchronization failed we remove the node again without request */ infc_browser_remove_sync_in(browser, sync_in); infc_browser_node_unregister(browser, node, NULL); infc_browser_node_free(browser, node); g_object_unref(browser); } static void infc_browser_sync_in_synchronization_complete_cb(InfSession* session, InfXmlConnection* connection, gpointer user_data) { InfcBrowserSyncIn* sync_in; sync_in = (InfcBrowserSyncIn*)user_data; /* Ignore if this affects the synchronization to another connection */ if(connection != sync_in->connection) return; infc_browser_remove_sync_in(sync_in->browser, sync_in); } static InfcBrowserSyncIn* infc_browser_add_sync_in(InfcBrowser* browser, InfcBrowserNode* node, InfXmlConnection* connection, InfcSessionProxy* proxy) { InfcBrowserPrivate* priv; InfcBrowserSyncIn* sync_in; InfSession* session; priv = INFC_BROWSER_PRIVATE(browser); sync_in = g_slice_new(InfcBrowserSyncIn); sync_in->browser = browser; sync_in->node = node; /* Actually the same as browser's connection: */ sync_in->connection = connection; sync_in->proxy = proxy; g_object_ref(proxy); g_object_get(G_OBJECT(proxy), "session", &session, NULL); g_signal_connect( session, "synchronization-failed", G_CALLBACK(infc_browser_sync_in_synchronization_failed_cb), sync_in ); g_signal_connect( session, "synchronization-complete", G_CALLBACK(infc_browser_sync_in_synchronization_complete_cb), sync_in ); g_object_unref(session); priv->sync_ins = g_slist_prepend(priv->sync_ins, sync_in); return sync_in; } static void infc_browser_remove_sync_in(InfcBrowser* browser, InfcBrowserSyncIn* sync_in) { InfcBrowserPrivate* priv; InfSession* session; priv = INFC_BROWSER_PRIVATE(browser); g_object_get(G_OBJECT(sync_in->proxy), "session", &session, NULL); inf_signal_handlers_disconnect_by_func( G_OBJECT(session), G_CALLBACK(infc_browser_sync_in_synchronization_complete_cb), sync_in ); inf_signal_handlers_disconnect_by_func( G_OBJECT(session), G_CALLBACK(infc_browser_sync_in_synchronization_failed_cb), sync_in ); g_object_unref(session); g_object_unref(sync_in->proxy); g_slice_free(InfcBrowserSyncIn, sync_in); priv->sync_ins = g_slist_remove(priv->sync_ins, sync_in); } /* * Node creation */ static InfcBrowserNode* infc_browser_node_add_subdirectory(InfcBrowser* browser, InfcBrowserNode* parent, InfcRequest* request, guint id, const gchar* name, const InfAclSheetSet* sheet_set) { InfcBrowserPrivate* priv; InfcBrowserNode* node; g_assert(parent->type == INFC_BROWSER_NODE_SUBDIRECTORY); g_assert(parent->shared.subdir.explored == TRUE); priv = INFC_BROWSER_PRIVATE(browser); node = infc_browser_node_new_subdirectory( browser, parent, id, name, sheet_set ); infc_browser_node_register(browser, node, request); return node; } static InfcBrowserNode* infc_browser_node_add_note(InfcBrowser* browser, InfcBrowserNode* parent, InfcRequest* request, guint id, const gchar* name, const gchar* type, const InfAclSheetSet* sheet_set, InfcSessionProxy* sync_in_session) { InfcBrowserPrivate* priv; InfcBrowserNode* node; g_assert(parent->type == INFC_BROWSER_NODE_SUBDIRECTORY); g_assert(parent->shared.subdir.explored == TRUE); priv = INFC_BROWSER_PRIVATE(browser); g_assert(priv->connection != NULL); node = infc_browser_node_new_note( browser, parent, id, name, type, sheet_set ); if(sync_in_session != NULL) { infc_browser_add_sync_in( browser, node, priv->connection, sync_in_session ); } infc_browser_node_register(browser, node, request); return node; } /* * Network command handling. */ static void infc_browser_subscribe_ack(InfcBrowser* browser, InfXmlConnection* connection, InfcBrowserSubreq* request) { InfcBrowserPrivate* priv; xmlNodePtr xml; priv = INFC_BROWSER_PRIVATE(browser); xml = xmlNewNode(NULL, (const xmlChar*)"subscribe-ack"); if(request->type != INFC_BROWSER_SUBREQ_CHAT) inf_xml_util_set_attribute_uint(xml, "id", request->node_id); inf_communication_group_send_message( INF_COMMUNICATION_GROUP(priv->group), connection, xml ); } static void infc_browser_subscribe_nack(InfcBrowser* browser, InfXmlConnection* connection, guint node_id) { InfcBrowserPrivate* priv; xmlNodePtr xml; priv = INFC_BROWSER_PRIVATE(browser); xml = xmlNewNode(NULL, (const xmlChar*)"subscribe-nack"); if(node_id > 0) inf_xml_util_set_attribute_uint(xml, "id", node_id); inf_communication_group_send_message( INF_COMMUNICATION_GROUP(priv->group), connection, xml ); } static InfcBrowserNode* infc_browser_get_node_from_xml(InfcBrowser* browser, xmlNodePtr xml, const gchar* attrib, GError** error) { InfcBrowserPrivate* priv; InfcBrowserNode* node; guint node_id; gboolean has_node; priv = INFC_BROWSER_PRIVATE(browser); has_node = inf_xml_util_get_attribute_uint_required( xml, attrib, &node_id, error ); if(has_node == FALSE) return NULL; node = g_hash_table_lookup(priv->nodes, GUINT_TO_POINTER(node_id)); if(node == NULL) { g_set_error( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_NO_SUCH_NODE, _("There is no such node with ID %u"), node_id ); return NULL; } else { return node; } } static InfcBrowserNode* infc_browser_get_node_from_xml_typed(InfcBrowser* browser, xmlNodePtr xml, const gchar* attrib, InfcBrowserNodeType mask, GError** error) { InfcBrowserNode* node; g_assert(mask != 0); node = infc_browser_get_node_from_xml(browser, xml, attrib, error); if(node != NULL && (node->type & mask) == 0) { if(mask & INFC_BROWSER_NODE_SUBDIRECTORY) { g_set_error_literal( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_NOT_A_SUBDIRECTORY, inf_directory_strerror(INF_DIRECTORY_ERROR_NOT_A_SUBDIRECTORY) ); } else { g_set_error_literal( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_NOT_A_NOTE, inf_directory_strerror(INF_DIRECTORY_ERROR_NOT_A_NOTE) ); } return NULL; } else { return node; } } static gboolean infc_browser_validate_progress_request(InfcBrowser* browser, InfcProgressRequest* request, GError** error) { guint current; guint total; if(infc_progress_request_get_initiated(request) == FALSE) { g_set_error_literal( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_NOT_INITIATED, inf_directory_strerror(INF_DIRECTORY_ERROR_NOT_INITIATED) ); return FALSE; } else { g_object_get( G_OBJECT(request), "current", ¤t, "total", &total, NULL ); if(current >= total) { g_set_error_literal( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_TOO_MANY_CHILDREN, inf_directory_strerror(INF_DIRECTORY_ERROR_TOO_MANY_CHILDREN) ); return FALSE; } else { return TRUE; } } } static InfcRequest* infc_browser_get_add_node_request_from_xml(InfcBrowser* browser, xmlNodePtr xml, GError** error) { InfcBrowserPrivate* priv; InfcRequest* request; gchar* type; gboolean result; priv = INFC_BROWSER_PRIVATE(browser); request = infc_request_manager_get_request_by_xml( priv->request_manager, NULL, xml, NULL ); /* If no seq was set, then this add-node request was not issued by us */ if(request != NULL) { g_object_get(G_OBJECT(request), "type", &type, NULL); /* when seq was set, then we issued that add-node. We might * either do this implicitly by exploring a folder or explicitely by * sending an add-node request. */ if(strcmp(type, "add-node") != 0 && strcmp(type, "explore-node") != 0) { g_set_error( error, inf_request_error_quark(), INF_REQUEST_ERROR_INVALID_SEQ, _("The request contains a sequence number refering to a request of " "type '%s', but a request of either 'explore-node' or 'add-node' " "was expected."), type ); g_free(type); return NULL; } /* For explore request, we do some basic sanity checking here */ if(strcmp(type, "explore-node") == 0) { g_assert(INFC_IS_PROGRESS_REQUEST(request)); result = infc_browser_validate_progress_request( browser, INFC_PROGRESS_REQUEST(request), error ); if(result == FALSE) { g_free(type); return NULL; } } g_free(type); } return request; } static void infc_browser_process_add_node_request(InfcBrowser* browser, InfcRequest* request, InfcBrowserNode* node) { InfcBrowserPrivate* priv; InfBrowserIter parent_iter; InfBrowserIter iter; priv = INFC_BROWSER_PRIVATE(browser); if(INFC_IS_PROGRESS_REQUEST(request)) { infc_progress_request_progress(INFC_PROGRESS_REQUEST(request)); } else { g_object_get(G_OBJECT(request), "node-id", &parent_iter.node_id, NULL); g_assert(parent_iter.node_id != G_MAXUINT); parent_iter.node = g_hash_table_lookup( priv->nodes, GUINT_TO_POINTER(parent_iter.node_id) ); g_assert(parent_iter.node != NULL); iter.node_id = node->id; iter.node = node; g_assert(node->parent == parent_iter.node); infc_request_manager_finish_request( priv->request_manager, request, inf_request_result_make_add_node( INF_BROWSER(browser), &parent_iter, &iter ) ); } } static InfCommunicationJoinedGroup* infc_browser_create_group_from_xml(InfcBrowser* browser, InfXmlConnection* connection, xmlNodePtr xml, GError** error) { InfcBrowserPrivate* priv; xmlChar* method_name; xmlChar* group_name; InfCommunicationJoinedGroup* group; priv = INFC_BROWSER_PRIVATE(browser); method_name = inf_xml_util_get_attribute_required(xml, "method", error); if(method_name == NULL) return FALSE; group_name = inf_xml_util_get_attribute_required(xml, "group", error); if(group_name == NULL) { xmlFree(method_name); return FALSE; } /* Server is publisher */ group = inf_communication_manager_join_group( priv->communication_manager, (const gchar*)group_name, connection, (const gchar*)method_name ); if(!group) { g_propagate_error( error, infc_browser_method_unsupported_error( (const gchar*)method_name, connection ) ); } xmlFree(group_name); xmlFree(method_name); return group; } /* If initial_sync is TRUE, then the session is initially synchronized in the * subscription group. Otherwise, an empty session is used. */ static void infc_browser_subscribe_session(InfcBrowser* browser, InfcBrowserNode* node, InfcRequest* request, InfCommunicationJoinedGroup* group, InfXmlConnection* connection, gboolean initial_sync) { InfcBrowserPrivate* priv; InfcSessionProxy* proxy; InfBrowserIter iter; GString* path; InfSession* session; priv = INFC_BROWSER_PRIVATE(browser); g_assert(node->type == INFC_BROWSER_NODE_NOTE_KNOWN); g_assert(node->shared.known.plugin != NULL); g_assert(node->shared.known.session == NULL); path = g_string_sized_new(128); infc_browser_node_get_path_string(node, path); if(initial_sync) { session = node->shared.known.plugin->session_new( priv->io, priv->communication_manager, INF_SESSION_SYNCHRONIZING, INF_COMMUNICATION_GROUP(group), connection, path->str, node->shared.known.plugin->user_data ); } else { session = node->shared.known.plugin->session_new( priv->io, priv->communication_manager, INF_SESSION_RUNNING, NULL, NULL, path->str, node->shared.known.plugin->user_data ); } g_string_free(path, TRUE); proxy = g_object_new(INFC_TYPE_SESSION_PROXY, "session", session, NULL); inf_communication_group_set_target( INF_COMMUNICATION_GROUP(group), INF_COMMUNICATION_OBJECT(proxy) ); infc_session_proxy_set_connection(proxy, group, connection, priv->seq_id); g_object_unref(session); iter.node_id = node->id; iter.node = node; inf_browser_subscribe_session( INF_BROWSER(browser), &iter, INF_SESSION_PROXY(proxy), INF_REQUEST(request) ); /* The default handler refs the proxy */ g_object_unref(proxy); } static gboolean infc_browser_handle_welcome(InfcBrowser* browser, InfXmlConnection* connection, xmlNodePtr xml, GError** error) { InfcBrowserPrivate* priv; xmlChar* version; guint server_major; guint server_minor; guint own_major; guint own_minor; gboolean result; InfAclSheetSet* sheet_set; xmlNodePtr node; InfAclAccountId default_id; InfAclAccount* default_account; GError* local_error; InfAclSheet* sheet; InfAclMask default_mask; priv = INFC_BROWSER_PRIVATE(browser); version = inf_xml_util_get_attribute_required( xml, "protocol-version", error); if(!version) return FALSE; result = inf_protocol_parse_version( (const gchar*)version, &server_major, &server_minor, error ); xmlFree(version); if(!result) return FALSE; result = inf_protocol_parse_version( inf_protocol_get_version(), &own_major, &own_minor, NULL ); g_assert(result == TRUE); if(server_major < own_major) { g_set_error_literal( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_VERSION_MISMATCH, _("The server uses an older version of the protocol which is no longer " "supported by this client. Consider using an earlier version of it, " "or ask the server administrators to upgrade their software.") ); return FALSE; } if(server_major > own_major) { g_set_error_literal( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_VERSION_MISMATCH, _("The server uses a newer version of the protocol which is not " "supported by this client. Consider upgrading your client.") ); return FALSE; } result = inf_xml_util_get_attribute_uint_required( xml, "sequence-id", &priv->seq_id, error ); if(!result) return FALSE; /* Load ACL accounts */ g_assert(priv->accounts == NULL); g_assert(priv->local_account == NULL); priv->accounts = g_hash_table_new_full( NULL, NULL, NULL, (GDestroyNotify)inf_acl_account_free ); default_id = inf_acl_account_id_from_string("default"); default_account = inf_acl_account_new(default_id, NULL); g_hash_table_insert( priv->accounts, INF_ACL_ACCOUNT_ID_TO_POINTER(default_account->id), default_account ); priv->local_account = default_account; for(node = xml->children; node != NULL; node = node->next) { if(node->type != XML_ELEMENT_NODE) continue; if(strcmp(node->name, "account") == 0) { priv->local_account = inf_acl_account_from_xml(node, error); if(priv->local_account == NULL) { g_hash_table_destroy(priv->accounts); priv->accounts = NULL; return FALSE; } g_hash_table_insert( priv->accounts, INF_ACL_ACCOUNT_ID_TO_POINTER(priv->local_account->id), (gpointer)priv->local_account ); break; } } /* Load the root ACL sheet set */ local_error = NULL; sheet_set = inf_acl_sheet_set_from_xml(xml, &local_error); if(local_error != NULL) { g_hash_table_destroy(priv->accounts); priv->accounts = NULL; priv->local_account = NULL; g_propagate_error(error, local_error); return FALSE; } /* Assume default permissions for the root node if they are not sent * explicitely by the server. */ if(sheet_set == NULL) sheet_set = inf_acl_sheet_set_new(); sheet = inf_acl_sheet_set_add_sheet(sheet_set, default_id); default_mask = sheet->mask; inf_acl_mask_neg(&default_mask, &default_mask); inf_acl_mask_and(&default_mask, &INF_ACL_MASK_DEFAULT, &default_mask); inf_acl_mask_or(&sheet->perms, &default_mask, &sheet->perms); sheet->mask = INF_ACL_MASK_ALL; g_assert(priv->root == NULL); priv->root = infc_browser_node_new_subdirectory( browser, NULL, 0, NULL, sheet_set ); inf_acl_sheet_set_free(sheet_set); g_assert(priv->request_manager == NULL); priv->request_manager = infc_request_manager_new(priv->seq_id); priv->status = INF_BROWSER_OPEN; g_object_notify(G_OBJECT(browser), "status"); inf_browser_acl_account_added(INF_BROWSER(browser), default_account, NULL); if(priv->local_account != default_account) { inf_browser_acl_account_added( INF_BROWSER(browser), priv->local_account, NULL ); } return TRUE; } static gboolean infc_browser_handle_explore_begin(InfcBrowser* browser, InfXmlConnection* connection, xmlNodePtr xml, GError** error) { InfcBrowserPrivate* priv; InfcRequest* request; guint total; guint node_id; InfcBrowserNode* node; priv = INFC_BROWSER_PRIVATE(browser); /* TODO: Allow exploration without us asking. We should then create a * request here, and correctly handle the case when there is already one. */ request = infc_request_manager_get_request_by_xml_required( priv->request_manager, "explore-node", xml, error ); if(request == NULL) return FALSE; g_assert(INFC_IS_PROGRESS_REQUEST(request)); if(!inf_xml_util_get_attribute_uint_required(xml, "total", &total, error)) return FALSE; g_object_get(G_OBJECT(request), "node-id", &node_id, NULL); g_assert(node_id != G_MAXUINT); node = g_hash_table_lookup(priv->nodes, GUINT_TO_POINTER(node_id)); if(node == NULL) { g_set_error_literal( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_NO_SUCH_NODE, _("Node to explore does no longer exist") ); return FALSE; } else if(node->type != INFC_BROWSER_NODE_SUBDIRECTORY) { g_set_error_literal( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_NOT_A_SUBDIRECTORY, _("Node to explore is not a subdirectory") ); return FALSE; } else if(node->shared.subdir.explored == TRUE) { g_set_error_literal( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_ALREADY_EXPLORED, _("Node to explore is already explored") ); return FALSE; } else { node->shared.subdir.explored = TRUE; infc_progress_request_initiated(INFC_PROGRESS_REQUEST(request), total); return TRUE; } } static gboolean infc_browser_handle_explore_end(InfcBrowser* browser, InfXmlConnection* connection, xmlNodePtr xml, GError** error) { InfcBrowserPrivate* priv; InfcRequest* request; guint current; guint total; InfBrowserIter iter; priv = INFC_BROWSER_PRIVATE(browser); /* TODO: Allow exploration without us asking */ request = infc_request_manager_get_request_by_xml_required( priv->request_manager, "explore-node", xml, error ); if(request == NULL) return FALSE; g_assert(INFC_IS_PROGRESS_REQUEST(request)); g_object_get(G_OBJECT(request), "current", ¤t, "total", &total, NULL); if(current < total) { g_set_error_literal( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_TOO_FEW_CHILDREN, _("Not all nodes were received before explore-end was received") ); return FALSE; } else { g_object_get(G_OBJECT(request), "node-id", &iter.node_id, NULL); iter.node = g_hash_table_lookup( priv->nodes, GUINT_TO_POINTER(iter.node_id) ); /* The node being explored must exist, or the request would have been * cancelled before. */ g_assert(iter.node != NULL); infc_request_manager_finish_request( priv->request_manager, request, inf_request_result_make_explore_node(INF_BROWSER(browser), &iter) ); return TRUE; } } static gboolean infc_browser_handle_add_node(InfcBrowser* browser, InfXmlConnection* connection, xmlNodePtr xml, GError** error) { InfcBrowserPrivate* priv; InfcBrowserNode* parent; InfcBrowserNode* node; guint id; xmlChar* name; xmlChar* type; InfAclSheetSet* sheet_set; InfcRequest* request; GError* local_error; xmlNodePtr child; const InfcNotePlugin* plugin; InfCommunicationJoinedGroup* group; InfcBrowserSubreq* subreq; gboolean result; priv = INFC_BROWSER_PRIVATE(browser); if(inf_xml_util_get_attribute_uint_required(xml, "id", &id, error) == FALSE) return FALSE; if(g_hash_table_lookup(priv->nodes, GUINT_TO_POINTER(id)) != NULL || infc_browser_find_subreq(browser, id) != NULL) { g_set_error( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_NODE_EXISTS, _("Node with ID \"%u\" exists already"), id ); return FALSE; } parent = infc_browser_get_node_from_xml_typed( browser, xml, "parent", INFC_BROWSER_NODE_SUBDIRECTORY, error ); if(parent == NULL) return FALSE; if(parent->shared.subdir.explored == FALSE) { g_set_error_literal( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_NOT_EXPLORED, _("The parent node has not been explored yet") ); return FALSE; } local_error = NULL; request = infc_browser_get_add_node_request_from_xml(browser, xml, &local_error); if(local_error != NULL) { g_propagate_error(error, local_error); return FALSE; } type = inf_xml_util_get_attribute_required(xml, "type", error); if(type == NULL) return FALSE; name = inf_xml_util_get_attribute_required(xml, "name", error); if(name == NULL) { xmlFree(type); return FALSE; } sheet_set = inf_acl_sheet_set_from_xml(xml, &local_error); if(local_error != NULL) { xmlFree(type); xmlFree(name); g_propagate_error(error, local_error); return FALSE; } if(strcmp((const gchar*)type, "InfSubdirectory") == 0) { node = infc_browser_node_add_subdirectory( browser, parent, request, id, (const gchar*)name, sheet_set ); if(request != NULL) { infc_browser_process_add_node_request( browser, request, node ); } result = TRUE; } else { for(child = xml->children; child != NULL; child = child->next) if(strcmp((const char*)child->name, "subscribe") == 0) break; if(child != NULL) { /* Subscribe to the newly added node */ /* Request must be a node-request at this point. messages * resulting from a node exploration cannot yield subscription. */ if(request != NULL && INFC_IS_PROGRESS_REQUEST(request)) { g_set_error_literal( error, inf_request_error_quark(), INF_REQUEST_ERROR_INVALID_SEQ, _("Explored nodes cannot be initially be subscribed to") ); result = FALSE; } else { /* Can't subscribe if we don't know the note type */ plugin = g_hash_table_lookup(priv->plugins, type); if(plugin == NULL) { g_set_error( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_TYPE_UNKNOWN, _("Note type \"%s\" not known"), (const gchar*)type ); infc_browser_subscribe_nack(browser, connection, id); result = FALSE; } else { group = infc_browser_create_group_from_xml( browser, connection, child, error ); if(group == NULL) { infc_browser_subscribe_nack(browser, connection, id); result = FALSE; } else { subreq = infc_browser_add_subreq_add_node( browser, id, parent, plugin, (const gchar*)name, sheet_set, request, group ); g_object_unref(group); infc_browser_subscribe_ack(browser, connection, subreq); result = TRUE; } } } } else { node = infc_browser_node_add_note( browser, parent, request, id, (const gchar*)name, (const gchar*)type, sheet_set, NULL ); if(request != NULL) { infc_browser_process_add_node_request( browser, request, node ); } result = TRUE; } } if(sheet_set != NULL) inf_acl_sheet_set_free(sheet_set); xmlFree(type); xmlFree(name); return result; } static gboolean infc_browser_handle_sync_in(InfcBrowser* browser, InfXmlConnection* connection, xmlNodePtr xml, GError** error) { InfcBrowserPrivate* priv; guint id; InfcBrowserNode* parent; InfcRequest* request; InfSession* session; const InfcNotePlugin* plugin; InfCommunicationJoinedGroup* sync_group; xmlChar* type; xmlChar* name; GError* local_error; InfAclSheetSet* sheet_set; xmlNodePtr child; InfcBrowserSubreq* subreq; gboolean result; priv = INFC_BROWSER_PRIVATE(browser); if(inf_xml_util_get_attribute_uint_required(xml, "id", &id, error) == FALSE) return FALSE; if(g_hash_table_lookup(priv->nodes, GUINT_TO_POINTER(id)) != NULL || infc_browser_find_subreq(browser, id) != NULL) { g_set_error( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_NODE_EXISTS, _("Node with ID \"%u\" exists already"), id ); return FALSE; } parent = infc_browser_get_node_from_xml_typed( browser, xml, "parent", INFC_BROWSER_NODE_SUBDIRECTORY, error ); if(parent == NULL) return FALSE; request = infc_request_manager_get_request_by_xml_required( priv->request_manager, "add-node", xml, error ); /* Note that such a request MUST exist. We cannot sync something in without * knowing where to get the data to sync from. */ if(!request) return FALSE; session = g_object_steal_qdata( G_OBJECT(request), infc_browser_sync_in_session_quark ); plugin = g_object_steal_qdata( G_OBJECT(request), infc_browser_sync_in_plugin_quark ); if(session == NULL) { g_set_error_literal( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_UNEXPECTED_SYNC_IN, _("Received sync-in without having requested one") ); return FALSE; } /* We always set both session and plugin quark: */ g_assert(plugin != NULL); result = FALSE; type = inf_xml_util_get_attribute_required(xml, "type", error); if(type != NULL) { if(strcmp((const char*)type, plugin->note_type) != 0) { g_set_error( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_UNEXPECTED_SYNC_IN, _("Expected note type \"%s\" for sync-in, but received \"%s\""), plugin->note_type, (const gchar*)type ); } else { name = inf_xml_util_get_attribute_required(xml, "name", error); if(name != NULL) { local_error = NULL; sheet_set = inf_acl_sheet_set_from_xml(xml, &local_error); if(local_error != NULL) { g_propagate_error(error, local_error); } else { /* Note that all the errors which could have occured up to this * point are the server's fault. If one of those occured, then the * server sent us crap and could have known better. We therefore * don't reply with subscribe-nack on these errors. */ sync_group = infc_browser_create_group_from_xml( browser, connection, xml, error ); if(sync_group == NULL) { infc_browser_subscribe_nack(browser, connection, id); } else { /* TODO: The server might specify a different * subscription group */ for(child = xml->children; child != NULL; child = child->next) if(strcmp((const char*)child->name, "subscribe") == 0) break; subreq = infc_browser_add_subreq_sync_in( browser, id, parent, plugin, (const gchar*)name, sheet_set, request, session, sync_group, child != NULL ? sync_group : NULL ); g_object_unref(sync_group); infc_browser_subscribe_ack(browser, connection, subreq); result = TRUE; } if(sheet_set != NULL) inf_acl_sheet_set_free(sheet_set); } xmlFree(name); } } xmlFree(type); } g_object_unref(session); return result; } static gboolean infc_browser_handle_remove_node(InfcBrowser* browser, InfXmlConnection* connection, xmlNodePtr xml, GError** error) { InfcBrowserPrivate* priv; InfcBrowserNode* node; InfcRequest* request; InfBrowserIter iter; priv = INFC_BROWSER_PRIVATE(browser); node = infc_browser_get_node_from_xml(browser, xml, "id", error); if(node == NULL) return FALSE; request = infc_request_manager_get_request_by_xml( priv->request_manager, "remove-node", xml, NULL ); if(request != NULL) { g_object_ref(request); iter.node_id = node->id; iter.node = node; infc_request_manager_finish_request( priv->request_manager, request, inf_request_result_make_remove_node(INF_BROWSER(browser), &iter) ); } infc_browser_session_remove_child_sessions(browser, node, request); infc_browser_node_unregister(browser, node, request); infc_browser_node_free(browser, node); if(request != NULL) g_object_unref(request); return TRUE; } static gboolean infc_browser_handle_subscribe_session(InfcBrowser* browser, InfXmlConnection* connection, xmlNodePtr xml, GError** error) { InfcBrowserPrivate* priv; InfcBrowserNode* node; InfcRequest* request; InfCommunicationJoinedGroup* group; InfcBrowserSubreq* subreq; priv = INFC_BROWSER_PRIVATE(browser); node = infc_browser_get_node_from_xml_typed( browser, xml, "id", INFC_BROWSER_NODE_NOTE_KNOWN | INFC_BROWSER_NODE_NOTE_UNKNOWN, error ); /* TODO: Send subscribe-nack with the id the server sent, even if we could * not find the node. */ if(node == NULL) return FALSE; if(node->type == INFC_BROWSER_NODE_NOTE_UNKNOWN) { g_set_error( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_TYPE_UNKNOWN, _("Note type '%s' is not supported"), node->shared.unknown.type ); infc_browser_subscribe_nack(browser, connection, node->id); return FALSE; } if(node->shared.known.session != NULL) { g_set_error_literal( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_ALREADY_SUBSCRIBED, _("Already subscribed to this session") ); /* Don't send subscribe-nack here, it is the server's job not to send us * subscribe-session if we are already subscribed. */ return FALSE; } group = infc_browser_create_group_from_xml( browser, connection, xml, error ); if(!group) { infc_browser_subscribe_nack(browser, connection, node->id); return FALSE; } request = infc_request_manager_get_request_by_xml( priv->request_manager, "subscribe-session", xml, NULL ); subreq = infc_browser_add_subreq_session(browser, node, request, group); g_object_unref(group); infc_browser_subscribe_ack(browser, connection, subreq); return TRUE; } static gboolean infc_browser_handle_subscribe_chat(InfcBrowser* browser, InfXmlConnection* connection, xmlNodePtr xml, GError** error) { InfcBrowserPrivate* priv; InfcRequest* request; InfCommunicationJoinedGroup* group; InfcBrowserSubreq* subreq; priv = INFC_BROWSER_PRIVATE(browser); if(priv->chat_session != NULL) { g_set_error_literal( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_ALREADY_SUBSCRIBED, _("Already subscribed to the chat session") ); /* Don't send subscribe-nack here, it is the server's job not to send us * subscribe-session if we are already subscribed. */ return FALSE; } group = infc_browser_create_group_from_xml( browser, connection, xml, error ); if(!group) { infc_browser_subscribe_nack(browser, connection, 0); return FALSE; } request = infc_request_manager_get_request_by_xml( priv->request_manager, "subscribe-chat", xml, NULL ); subreq = infc_browser_add_subreq_chat(browser, request, group); g_object_unref(group); infc_browser_subscribe_ack(browser, connection, subreq); return TRUE; } static gboolean infc_browser_handle_save_session_in_progress(InfcBrowser* browser, InfXmlConnection* connection, xmlNodePtr xml, GError** error) { InfcBrowserPrivate* priv; InfcBrowserNode* node; InfcRequest* request; priv = INFC_BROWSER_PRIVATE(browser); node = infc_browser_get_node_from_xml_typed( browser, xml, "id", INFC_BROWSER_NODE_NOTE_KNOWN, error ); if(node == NULL) return FALSE; request = infc_request_manager_get_request_by_xml( priv->request_manager, "save-session", xml, NULL ); if(request != NULL) { /* TODO: Make a special save request that could now emit * an in-progress signal */ } return TRUE; } static gboolean infc_browser_handle_saved_session(InfcBrowser* browser, InfXmlConnection* connection, xmlNodePtr xml, GError** error) { InfcBrowserPrivate* priv; InfcBrowserNode* node; InfcRequest* request; InfBrowserIter iter; priv = INFC_BROWSER_PRIVATE(browser); node = infc_browser_get_node_from_xml_typed( browser, xml, "id", INFC_BROWSER_NODE_NOTE_KNOWN, error ); if(node == NULL) return FALSE; request = infc_request_manager_get_request_by_xml( priv->request_manager, "save-session", xml, NULL ); if(request != NULL) { iter.node_id = node->id; iter.node = node; infc_request_manager_finish_request( priv->request_manager, request, inf_request_result_make_save_session(INF_BROWSER(browser), &iter) ); } return TRUE; } static gboolean infc_browser_handle_acl_account_list_begin(InfcBrowser* browser, InfXmlConnection* connection, xmlNodePtr xml, GError** error) { InfcBrowserPrivate* priv; InfcRequest* request; guint total; guint notifications_enabled; gboolean result; guint node_id; InfcBrowserNode* node; InfBrowserIter iter; priv = INFC_BROWSER_PRIVATE(browser); /* TODO: Allow account list query without us asking. We should then create a * request here, and correctly handle the case that there is already one. */ request = infc_request_manager_get_request_by_xml_required( priv->request_manager, "query-acl-account-list", xml, error ); if(request == NULL) return FALSE; g_assert(INFC_IS_PROGRESS_REQUEST(request)); if(!inf_xml_util_get_attribute_uint_required(xml, "total", &total, error)) return FALSE; result = inf_xml_util_get_attribute_uint_required( xml, "notifications-enabled", ¬ifications_enabled, error ); if(result == FALSE) return FALSE; g_object_set_qdata_full( G_OBJECT(request), infc_browser_query_acl_account_list_accounts_quark, g_hash_table_new(NULL, NULL), (GDestroyNotify)g_hash_table_destroy ); if(notifications_enabled) priv->account_list_status = INFC_BROWSER_ACCOUNT_LIST_NOTIFICATIONS; else priv->account_list_status = INFC_BROWSER_ACCOUNT_LIST_NO_NOTIFICATIONS; infc_progress_request_initiated(INFC_PROGRESS_REQUEST(request), total); return TRUE; } static gboolean infc_browser_handle_acl_account_list_end(InfcBrowser* browser, InfXmlConnection* connection, xmlNodePtr xml, GError** error) { InfcBrowserPrivate* priv; InfcRequest* request; guint current; guint total; InfBrowserIter iter; InfAclAccountId default_id; GHashTable* table; GHashTableIter hash_iter; gpointer value; InfAclAccount* account; GSList* to_be_removed; GSList* item; InfAclAccount* accounts; guint n_accounts; gboolean does_notifications; priv = INFC_BROWSER_PRIVATE(browser); /* TODO: Allow user list query without us asking. */ request = infc_request_manager_get_request_by_xml_required( priv->request_manager, "query-acl-account-list", xml, error ); if(request == NULL) return FALSE; g_assert(INFC_IS_PROGRESS_REQUEST(request)); g_object_get(G_OBJECT(request), "current", ¤t, "total", &total, NULL); if(current < total) { g_set_error_literal( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_TOO_FEW_CHILDREN, _("Not all users have been transmitted before " "user-list-end was received") ); return FALSE; } else { /* Remove all accounts that we have in our account list but has not been * listed by the server now. These seem to have been removed since the * last time we queried the account list. */ table = g_object_get_qdata( G_OBJECT(request), infc_browser_query_acl_account_list_accounts_quark ); to_be_removed = NULL; default_id = inf_acl_account_id_from_string("default"); g_hash_table_iter_init(&hash_iter, priv->accounts); while(g_hash_table_iter_next(&hash_iter, NULL, &value)) { /* Server does not explicitly send default and local account */ account = (InfAclAccount*)value; if(account != priv->local_account && account->id != default_id && g_hash_table_lookup(table, account) == NULL) { /* We cannot remove the item directly, since we are currently * iterating over the hash table. */ to_be_removed = g_slist_prepend(to_be_removed, account); } } for(item = to_be_removed; item != NULL; item = item->next) { account = (InfAclAccount*)item->data; g_hash_table_steal( priv->accounts, INF_ACL_ACCOUNT_ID_TO_POINTER(account->id) ); inf_browser_acl_account_removed(INF_BROWSER(browser), account, NULL); inf_acl_account_free(account); } /* Now with the updated account list, we can report back to the caller */ accounts = infc_browser_make_acl_account_list(browser, &n_accounts); switch(priv->account_list_status) { case INFC_BROWSER_ACCOUNT_LIST_NOT_QUERIED: g_assert_not_reached(); break; case INFC_BROWSER_ACCOUNT_LIST_NO_NOTIFICATIONS: does_notifications = FALSE; break; case INFC_BROWSER_ACCOUNT_LIST_NOTIFICATIONS: does_notifications = TRUE; break; default: g_assert_not_reached(); break; } infc_request_manager_finish_request( priv->request_manager, request, inf_request_result_make_query_acl_account_list( INF_BROWSER(browser), accounts, n_accounts, does_notifications ) ); g_free(accounts); return TRUE; } } static void infc_browser_handle_add_acl_account_foreach_func(InfcRequest* request, gpointer user_data) { GHashTable* table; table = g_object_get_qdata( G_OBJECT(request), infc_browser_query_acl_account_list_accounts_quark ); /* Only insert a pointer to the account object * in the permanent hash table. */ g_hash_table_insert(table, user_data, user_data); } static gboolean infc_browser_handle_add_acl_account(InfcBrowser* browser, InfXmlConnection* connection, xmlNodePtr xml, GError** error) { InfcBrowserPrivate* priv; GError* local_error; InfcRequest* request; gboolean result; InfAclAccount* account; InfAclAccount* cache_account; gchar* id; priv = INFC_BROWSER_PRIVATE(browser); local_error = NULL; request = infc_request_manager_get_request_by_xml( priv->request_manager, "query-acl-account-list", xml, &local_error ); if(local_error != NULL) { g_propagate_error(error, local_error); return FALSE; } if(request != NULL) { g_assert(INFC_IS_PROGRESS_REQUEST(request)); result = infc_browser_validate_progress_request( browser, INFC_PROGRESS_REQUEST(request), error ); if(result == FALSE) return FALSE; } account = inf_acl_account_from_xml(xml, error); if(account == NULL) return FALSE; cache_account = g_hash_table_lookup( priv->accounts, INF_ACL_ACCOUNT_ID_TO_POINTER(account->id) ); if(cache_account != NULL) { /* Update account name, if it has changed */ if(strcmp(cache_account->name, account->name) != 0) { g_free(cache_account->name); cache_account->name = g_strdup(account->name); } inf_acl_account_free(account); } else { g_hash_table_insert( priv->accounts, INF_ACL_ACCOUNT_ID_TO_POINTER(account->id), account ); inf_browser_acl_account_added( INF_BROWSER(browser), account, INF_REQUEST(request) ); cache_account = account; } if(request != NULL) infc_progress_request_progress(INFC_PROGRESS_REQUEST(request)); infc_request_manager_foreach_named_request( priv->request_manager, "query-acl-account-list", infc_browser_handle_add_acl_account_foreach_func, cache_account ); return TRUE; } static gboolean infc_browser_handle_lookup_acl_accounts(InfcBrowser* browser, InfXmlConnection* connection, xmlNodePtr xml, GError** error) { InfcBrowserPrivate* priv; GError* local_error; InfcRequest* request; xmlNodePtr child; GPtrArray* accounts; InfAclAccount* account; InfAclAccount* existing_account; InfAclAccount req_account; InfcBrowserLookupAclAccountByByNameData lookup_data; GArray* req_accounts; guint i; guint len; gchar* name; const InfAclAccountId* ids; guint n_ids; priv = INFC_BROWSER_PRIVATE(browser); local_error = NULL; request = infc_request_manager_get_request_by_xml( priv->request_manager, "lookup-acl-accounts", xml, error ); if(local_error != NULL) { g_propagate_error(error, local_error); return FALSE; } /* Read accounts from XML structure */ accounts = g_ptr_array_new(); for(child = xml->children; child != NULL; child = child->next) { if(child->type != XML_ELEMENT_NODE) continue; if(strcmp((const gchar*)child->name, "account") == 0) { account = inf_acl_account_from_xml(child, error); if(account == NULL) { for(i = 0; i < accounts->len; ++i) inf_acl_account_free(accounts->pdata[i]); g_ptr_array_free(accounts, TRUE); return FALSE; } g_ptr_array_add(accounts, account); } } /* Update local account table */ for(i = 0; i < accounts->len; ++i) { account = (InfAclAccount*)accounts->pdata[i]; existing_account = g_hash_table_lookup( priv->accounts, INF_ACL_ACCOUNT_ID_TO_POINTER(account->id) ); if(existing_account != NULL) { /* Update account name, if it has changed */ if(strcmp(existing_account->name, account->name) != 0) { g_free(existing_account->name); existing_account->name = g_strdup(account->name); } inf_acl_account_free(account); } else { /* Should not happen, as we should have served this from our cache. If * this happens, the server lied to us. */ if(priv->account_list_status == INFC_BROWSER_ACCOUNT_LIST_NOTIFICATIONS) { g_warning( _("Unknown account ID \"%s\" in server reply of " "\"%s\". Typically, this means the server claimed it notified us " "about new connections as soon as they are available, but it " "did not do so."), inf_acl_account_id_to_string(account->id), "lookup-acl-accounts" ); } g_hash_table_insert( priv->accounts, INF_ACL_ACCOUNT_ID_TO_POINTER(account->id), account ); inf_browser_acl_account_added( INF_BROWSER(browser), account, INF_REQUEST(request) ); } } g_ptr_array_free(accounts, TRUE); /* Lookup all requested IDs and names from local cache */ if(request != NULL) { ids = g_object_get_qdata( G_OBJECT(request), infc_browser_lookup_acl_accounts_ids_quark ); n_ids = GPOINTER_TO_UINT( g_object_get_qdata( G_OBJECT(request), infc_browser_lookup_acl_accounts_n_ids_quark ) ); name = g_object_get_qdata( G_OBJECT(request), infc_browser_lookup_acl_accounts_name_quark ); req_accounts = g_array_new(FALSE, FALSE, sizeof(InfAclAccount)); if(ids != NULL) { g_assert(n_ids > 0); for(i = 0; i < n_ids; ++i) { account = g_hash_table_lookup( priv->accounts, INF_ACL_ACCOUNT_ID_TO_POINTER(ids[i]) ); if(account != NULL) { g_array_append_val(req_accounts, *account); } else { /* The server has not sent us the name for this account. We suppose * this means that this account does not exist. */ req_account.id = ids[i]; req_account.name = NULL; g_array_append_val(req_accounts, req_account); } } } if(name != NULL) { len = req_accounts->len; lookup_data.name = name; lookup_data.accounts = req_accounts; g_hash_table_foreach( priv->accounts, infc_browser_browser_lookup_acl_account_by_name_find_func, &lookup_data ); if(req_accounts->len == len) { /* No account with this name available; create a new result entry * with 0 ID to indicate this to the caller. */ req_account.id = 0; req_account.name = name; g_array_append_val(req_accounts, req_account); } } /* TODO: Here, remove duplicates, or make sure from the start that there * will be no duplicates. */ infc_request_manager_finish_request( priv->request_manager, request, inf_request_result_make_lookup_acl_accounts( INF_BROWSER(browser), (InfAclAccount*)req_accounts->data, req_accounts->len ) ); g_array_free(req_accounts, TRUE); } return TRUE; } static gboolean infc_browser_handle_change_acl_account(InfcBrowser* browser, InfXmlConnection* connection, xmlNodePtr xml, GError** error) { InfcBrowserPrivate* priv; InfAclAccount* account; InfAclAccount* existing_account; GHashTable* new_acls; xmlNodePtr child; gboolean res; InfAclSheet* sheet; guint node_id; priv = INFC_BROWSER_PRIVATE(browser); account = inf_acl_account_from_xml(xml, error); if(account == NULL) return FALSE; existing_account = g_hash_table_lookup( priv->accounts, INF_ACL_ACCOUNT_ID_TO_POINTER(account->id) ); if(existing_account != NULL) { if(account->name == NULL || existing_account->name == NULL || strcmp(account->name, existing_account->name) != 0) { /* Update account name, if it has changed */ g_free(existing_account->name); existing_account->name = g_strdup(account->name); } inf_acl_account_free(account); account = existing_account; } new_acls = g_hash_table_new_full( NULL, NULL, NULL, (GDestroyNotify)inf_acl_sheet_free ); for(child = xml->children; child != NULL; child = child->next) { if(child->type != XML_ELEMENT_NODE) continue; if(strcmp((const gchar*)child->name, "acl") == 0) { res = inf_xml_util_get_attribute_uint_required( child, "node-id", &node_id, error ); if(res == FALSE) { if(account != existing_account) inf_acl_account_free(account); g_hash_table_destroy(new_acls); return FALSE; } sheet = inf_acl_sheet_new(account->id); res = inf_acl_sheet_perms_from_xml( child, &sheet->mask, &sheet->perms, error ); if(res == FALSE) { inf_acl_sheet_free(sheet); if(account != existing_account) inf_acl_account_free(account); g_hash_table_destroy(new_acls); return FALSE; } g_hash_table_insert(new_acls, GUINT_TO_POINTER(node_id), sheet); } } if(account != existing_account) { g_hash_table_insert( priv->accounts, INF_ACL_ACCOUNT_ID_TO_POINTER(account->id), account ); inf_browser_acl_account_added( INF_BROWSER(browser), account, NULL ); } priv->local_account = account; infc_browser_enforce_acl(browser, priv->root, NULL, new_acls); g_hash_table_destroy(new_acls); inf_browser_acl_local_account_changed(INF_BROWSER(browser), account, NULL); return TRUE; } static gboolean infc_browser_handle_create_acl_account(InfcBrowser* browser, InfXmlConnection* connection, xmlNodePtr xml, GError** error) { InfcBrowserPrivate* priv; InfcRequest* request; xmlNodePtr child; gnutls_datum_t cert_text; int res; gnutls_x509_crt_t cert; gnutls_x509_crt_t* certs; guint n_certs; GError* local_error; int verify_result; InfCertificateChain* new_chain; InfAclAccount* account; InfAclAccount* existing_account; priv = INFC_BROWSER_PRIVATE(browser); request = infc_request_manager_get_request_by_xml( priv->request_manager, "create-acl-account", xml, NULL ); if(request == NULL) { g_set_error_literal( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_UNEXPECTED_MESSAGE, _("No certificate request has been made") ); return FALSE; } cert_text.data = NULL; for(child = xml->children; child != NULL; child = child->next) { if(child->type != XML_ELEMENT_NODE) continue; if(strcmp((const char*)child->name, "certificate") == 0) { if(child->children != NULL && child->children->type == XML_TEXT_NODE) { cert_text.data = (char*)child->children->content; cert_text.size = strlen(cert_text.data); } } } if(cert_text.data == NULL) { g_set_error_literal( error, inf_request_error_quark(), INF_REQUEST_ERROR_NO_SUCH_ATTRIBUTE, _("No certificate provided") ); return FALSE; } n_certs = 10; certs = g_malloc(n_certs * sizeof(gnutls_x509_crt_t)); res = gnutls_x509_crt_list_import( certs, &n_certs, &cert_text, GNUTLS_X509_FMT_PEM, GNUTLS_X509_CRT_LIST_FAIL_IF_UNSORTED | GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED ); if(res < 0) { g_free(certs); inf_gnutls_set_error(error, res); return FALSE; } else if(res == 0) { g_set_error_literal( error, inf_request_error_quark(), INF_REQUEST_ERROR_NO_SUCH_ATTRIBUTE, _("No certificate provided") ); g_free(certs); return FALSE; } certs = g_realloc(certs, n_certs * sizeof(gnutls_x509_crt_t)); new_chain = inf_certificate_chain_new(certs, n_certs); #if 0 g_object_get(G_OBJECT(connection), "remote-certificate", &chain, NULL); if(chain == NULL) { g_set_error_literal( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_OPERATION_UNSUPPORTED, _("Cannot verify the certificate without server certificate") ); gnutls_x509_crt_deinit(cert); return FALSE; } root_cert = inf_certificate_chain_get_root_certificate(chain); #endif /* Verify that it is signed correctly. Note that we do not check who signed * the certificate. This is debatable, but it makes things a bit easier for * us. This allows the server to directly use its certificate to sign our * client certificate, and it does not need an extra (self-signed) CA * certificate for that. In the latter case it would be harder for us to * verify that we trust that CA. The certificate we obtained this way can * only be used for identifying ourselves with the server, since for other * purposes the server would make sure that our certificate was signed by * an actual CA. And we have to trust the server anyway, or otherwise it * could compromise all our data. */ res = gnutls_x509_crt_list_verify( certs, n_certs, &certs[n_certs - 1], 1, NULL, 0, GNUTLS_VERIFY_DO_NOT_ALLOW_X509_V1_CA_CRT | GNUTLS_VERIFY_DISABLE_CA_SIGN, &verify_result ); if(res != GNUTLS_E_SUCCESS || (verify_result & GNUTLS_CERT_INVALID) != 0) { if(res != GNUTLS_E_SUCCESS) { inf_gnutls_set_error(error, res); } else { local_error = NULL; inf_gnutls_certificate_verification_set_error( &local_error, verify_result ); g_set_error( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_INVALID_CERTIFICATE, _("Server sent an invalid certificate (%s)"), local_error->message ); g_error_free(local_error); } inf_certificate_chain_unref(new_chain); return FALSE; } account = inf_acl_account_from_xml(xml, error); if(account == NULL) { inf_certificate_chain_unref(new_chain); return FALSE; } /* Note that it is allowed that the account already exists, in which * case we have created a new certificate for that account. */ existing_account = g_hash_table_lookup( priv->accounts, INF_ACL_ACCOUNT_ID_TO_POINTER(account->id) ); if(existing_account != NULL) { inf_acl_account_free(account); account = existing_account; } else { g_hash_table_insert( priv->accounts, INF_ACL_ACCOUNT_ID_TO_POINTER(account->id), account ); inf_browser_acl_account_added( INF_BROWSER(browser), account, INF_REQUEST(request) ); } infc_request_manager_finish_request( priv->request_manager, request, inf_request_result_make_create_acl_account( INF_BROWSER(browser), account, new_chain ) ); inf_certificate_chain_unref(new_chain); return TRUE; } static gboolean infc_browser_handle_remove_acl_account(InfcBrowser* browser, InfXmlConnection* connection, xmlNodePtr xml, GError** error) { InfcBrowserPrivate* priv; InfcRequest* request; xmlChar* account_id; InfAclAccountId account; InfAclAccount* acc; InfAclAccount report_acc; InfAclAccountId default_id; GSList* item; InfcBrowserSubreq* subreq; priv = INFC_BROWSER_PRIVATE(browser); request = infc_request_manager_get_request_by_xml( priv->request_manager, "remove-acl-account", xml, NULL ); account_id = inf_xml_util_get_attribute_required(xml, "id", error); if(account_id == NULL) return FALSE; account = inf_acl_account_id_from_string((const gchar*)account_id); if(account == 0) { /* The server has notified us about the removal of an account that we * never heard about. This can happen if the server has notifications * enabled but we have never queried the account list. */ xmlFree(account_id); return TRUE; } xmlFree(account_id); default_id = inf_acl_account_id_from_string("default"); if(account == default_id) { g_set_error_literal( error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_NO_SUCH_ACCOUNT, _("The default account cannot be removed") ); return FALSE; } if(priv->local_account->id == account) { /* Own account was removed: Demote to default account */ priv->local_account = g_hash_table_lookup( priv->accounts, INF_ACL_ACCOUNT_ID_TO_POINTER(default_id) ); g_assert(priv->local_account != NULL); infc_browser_enforce_acl(browser, priv->root, NULL, NULL); inf_browser_acl_local_account_changed( INF_BROWSER(browser), priv->local_account, NULL ); } /* Remove sheet from all nodes and subreqs */ infc_browser_remove_account_from_sheets(browser, priv->root, account); for(item = priv->subscription_requests; item != NULL; item = item->next) { subreq = (InfcBrowserSubreq*)item->data; switch(subreq->type) { case INFC_BROWSER_SUBREQ_CHAT: case INFC_BROWSER_SUBREQ_SESSION: break; case INFC_BROWSER_SUBREQ_ADD_NODE: infc_browser_remove_acl_sheet_from_sheet_set( subreq->shared.add_node.sheet_set, account ); break; case INFC_BROWSER_SUBREQ_SYNC_IN: infc_browser_remove_acl_sheet_from_sheet_set( subreq->shared.sync_in.sheet_set, account ); break; } } /* remove account */ acc = g_hash_table_lookup( priv->accounts, INF_ACL_ACCOUNT_ID_TO_POINTER(account) ); if(acc != NULL) { g_hash_table_steal( priv->accounts, INF_ACL_ACCOUNT_ID_TO_POINTER(account) ); } else { report_acc.id = account; report_acc.name = NULL; /* unknown */ acc = &report_acc; } if(request != NULL) { infc_request_manager_finish_request( priv->request_manager, request, inf_request_result_make_remove_acl_account( INF_BROWSER(browser), acc ) ); } inf_browser_acl_account_removed(INF_BROWSER(browser), acc, NULL); if(acc != &report_acc) inf_acl_account_free(acc); return TRUE; } static gboolean infc_browser_handle_set_acl(InfcBrowser* browser, InfXmlConnection* connection, xmlNodePtr xml, GError** error) { InfcBrowserPrivate* priv; InfcBrowserNode* node; InfAclSheetSet* sheet_set; GError* local_error; InfcRequest* request; gchar* request_type; InfBrowserIter iter; InfAclAccountId default_id; InfAclSheet* default_sheet; InfAclMask default_mask; priv = INFC_BROWSER_PRIVATE(browser); node = infc_browser_get_node_from_xml(browser, xml, "id", error); if(node == NULL) return FALSE; local_error = NULL; sheet_set = inf_acl_sheet_set_from_xml(xml, &local_error); if(local_error != NULL) { g_propagate_error(error, local_error); return FALSE; } /* request can either by query-acl or set-acl */ request = infc_request_manager_get_request_by_xml( priv->request_manager, NULL, xml, &local_error ); if(local_error != NULL) { g_propagate_error(error, local_error); return FALSE; } /* Remember that we have queried this ACL */ if(request != NULL) { g_object_get(G_OBJECT(request), "type", &request_type, NULL); if(strcmp(request_type, "query-acl") == 0) { g_assert(node->acl_queried == FALSE); node->acl_queried = TRUE; } else if(strcmp(request_type, "set-acl") != 0) { g_set_error( error, inf_request_error_quark(), INF_REQUEST_ERROR_INVALID_SEQ, _("The request contains a sequence number refering to a request of " "type '%s', but a request of either 'query-acl' or 'set-acl' " "was expected."), request_type ); g_free(request_type); return FALSE; } } iter.node_id = node->id; iter.node = node; /* sheet_set can be NULL, for example when querying the ACL for a node and * the ACL is empty. */ if(sheet_set != NULL) { if(sheet_set->n_sheets > 0) { /* If the root node permissions are changed, make sure that none are * masked out and reset them to the default values instead. This can * happen if we are running against an older server which does not * support all permissions that we do support. */ if(node == priv->root) { default_id = inf_acl_account_id_from_string("default"); default_sheet = inf_acl_sheet_set_find_sheet(sheet_set, default_id); if(default_sheet != NULL) { default_mask = default_sheet->mask; /* Make sure that all masked-out bits * in permissions are set to zero */ inf_acl_mask_and( &default_sheet->perms, &default_sheet->mask, &default_sheet->perms ); /* Next, set the masked out bits to their default values */ inf_acl_mask_neg(&default_mask, &default_mask); inf_acl_mask_and( &default_mask, &INF_ACL_MASK_DEFAULT, &default_mask ); inf_acl_mask_or( &default_sheet->perms, &default_mask, &default_sheet->perms ); default_sheet->mask = INF_ACL_MASK_ALL; } } node->acl = inf_acl_sheet_set_merge_sheets(node->acl, sheet_set); infc_browser_enforce_acl(browser, node, request, NULL); inf_browser_acl_changed( INF_BROWSER(browser), &iter, sheet_set, INF_REQUEST(request) ); } inf_acl_sheet_set_free(sheet_set); } if(request != NULL) { g_object_get(G_OBJECT(request), "type", &request_type, NULL); if(strcmp(request_type, "query-acl") == 0) { infc_request_manager_finish_request( priv->request_manager, request, inf_request_result_make_query_acl( INF_BROWSER(browser), &iter, node->acl ) ); } else { infc_request_manager_finish_request( priv->request_manager, request, inf_request_result_make_set_acl(INF_BROWSER(browser), &iter) ); } g_free(request_type); } return TRUE; } static gboolean infc_browser_handle_request_failed(InfcBrowser* browser, InfXmlConnection* connection, xmlNodePtr xml, GError** error) { InfcBrowserPrivate* priv; InfcBrowserClass* browserc_class; InfcRequest* request; xmlChar* domain; gboolean has_code; guint code; GError* req_error; priv = INFC_BROWSER_PRIVATE(browser); browserc_class = INFC_BROWSER_GET_CLASS(browser); request = infc_request_manager_get_request_by_xml_required( priv->request_manager, NULL, xml, error ); if(request == NULL) return FALSE; has_code = inf_xml_util_get_attribute_uint_required( xml, "code", &code, error ); if(has_code == FALSE) return FALSE; domain = inf_xml_util_get_attribute_required(xml, "domain", error); if(domain == NULL) return FALSE; req_error = NULL; if(g_quark_from_string((gchar*)domain) == inf_directory_error_quark()) { g_set_error_literal( &req_error, inf_directory_error_quark(), code, inf_directory_strerror(code) ); } else if(g_quark_from_string((gchar*)domain) == inf_request_error_quark()) { g_set_error_literal( &req_error, inf_request_error_quark(), code, inf_request_strerror(code) ); } else { /* TODO: Look whether server has sent a human-readable error message * (which we cannot localize in that case, of course, but it is * probably better than nothing). */ g_set_error( &req_error, inf_request_error_quark(), INF_REQUEST_ERROR_UNKNOWN_DOMAIN, _("Error comes from unknown error domain '%s' (code %u)"), (const gchar*)domain, code ); } xmlFree(domain); infc_request_manager_fail_request( priv->request_manager, request, req_error ); g_error_free(req_error); return TRUE; } /* * InfCommunicationObject implementation */ static InfCommunicationScope infc_browser_communication_object_received(InfCommunicationObject* object, InfXmlConnection* connection, xmlNodePtr node) { InfcBrowser* browser; InfcBrowserPrivate* priv; GError* local_error; GError* seq_error; InfcRequest* request; browser = INFC_BROWSER(object); priv = INFC_BROWSER_PRIVATE(browser); local_error = NULL; if(priv->status == INF_BROWSER_OPENING && strcmp((const gchar*)node->name, "welcome") == 0) { if(priv->welcome_timeout != NULL) { inf_io_remove_timeout(priv->io, priv->welcome_timeout); priv->welcome_timeout = NULL; } if(!infc_browser_handle_welcome(browser, connection, node, &local_error)) { inf_browser_error(INF_BROWSER(browser), local_error); g_error_free(local_error); local_error = NULL; priv->status = INF_BROWSER_CLOSED; g_object_notify(G_OBJECT(browser), "status"); } } else if(strcmp((const gchar*)node->name, "request-failed") == 0) { infc_browser_handle_request_failed( browser, connection, node, &local_error ); } else if(strcmp((const gchar*)node->name, "explore-begin") == 0) { infc_browser_handle_explore_begin( browser, connection, node, &local_error ); } else if(strcmp((const gchar*)node->name, "explore-end") == 0) { infc_browser_handle_explore_end( browser, connection, node, &local_error ); } else if(strcmp((const gchar*)node->name, "add-node") == 0) { infc_browser_handle_add_node( browser, connection, node, &local_error ); } else if(strcmp((const gchar*)node->name, "sync-in") == 0) { infc_browser_handle_sync_in( browser, connection, node, &local_error ); } else if(strcmp((const gchar*)node->name, "remove-node") == 0) { infc_browser_handle_remove_node( browser, connection, node, &local_error ); } else if(strcmp((const gchar*)node->name, "subscribe-session") == 0) { infc_browser_handle_subscribe_session( browser, connection, node, &local_error ); } else if(strcmp((const gchar*)node->name, "subscribe-chat") == 0) { infc_browser_handle_subscribe_chat( browser, connection, node, &local_error ); } else if(strcmp((const gchar*)node->name, "save-session-in-progress") == 0) { infc_browser_handle_save_session_in_progress( browser, connection, node, &local_error ); } else if(strcmp((const gchar*)node->name, "saved-session") == 0) { infc_browser_handle_saved_session( browser, connection, node, &local_error ); } else if(strcmp((const gchar*)node->name, "acl-account-list-begin") == 0) { infc_browser_handle_acl_account_list_begin( browser, connection, node, &local_error ); } else if(strcmp((const gchar*)node->name, "acl-account-list-end") == 0) { infc_browser_handle_acl_account_list_end( browser, connection, node, &local_error ); } else if(strcmp((const gchar*)node->name, "add-acl-account") == 0) { infc_browser_handle_add_acl_account( browser, connection, node, &local_error ); } else if(strcmp((const gchar*)node->name, "lookup-acl-accounts") == 0) { infc_browser_handle_lookup_acl_accounts( browser, connection, node, &local_error ); } else if(strcmp((const gchar*)node->name, "change-acl-account") == 0) { infc_browser_handle_change_acl_account( browser, connection, node, &local_error ); } else if(strcmp((const gchar*)node->name, "create-acl-account") == 0) { infc_browser_handle_create_acl_account( browser, connection, node, &local_error ); } else if(strcmp((const gchar*)node->name, "remove-acl-account") == 0) { infc_browser_handle_remove_acl_account( browser, connection, node, &local_error ); } else if(strcmp((const gchar*)node->name, "set-acl") == 0) { infc_browser_handle_set_acl( browser, connection, node, &local_error ); } else { g_set_error( &local_error, inf_directory_error_quark(), INF_DIRECTORY_ERROR_UNEXPECTED_MESSAGE, _("Received unexpected network message \"%s\""), (const gchar*)node->name ); } if(local_error != NULL) { /* If the request had a (valid) seq set, we cancel the corresponding * request because the reply could not be processed. */ request = infc_request_manager_get_request_by_xml( priv->request_manager, NULL, node, NULL ); if(request != NULL) { seq_error = NULL; g_set_error( &seq_error, inf_request_error_quark(), INF_REQUEST_ERROR_REPLY_UNPROCESSED, _("Server reply could not be processed: %s"), local_error->message ); infc_request_manager_fail_request( priv->request_manager, request, seq_error ); g_error_free(seq_error); } inf_browser_error(INF_BROWSER(browser), local_error); g_error_free(local_error); } /* Browser is client-side anyway, so we should not even need to forward * anything. */ return INF_COMMUNICATION_SCOPE_PTP; } static void infc_browser_communication_object_sent(InfCommunicationObject* object, InfXmlConnection* connection, xmlNodePtr xml) { InfcBrowser* browser; InfcBrowserPrivate* priv; InfcBrowserNode* node; gboolean has_id; guint node_id; GSList* item; InfCommunicationJoinedGroup* sync_group; InfcBrowserSubreq* subreq; InfChatBuffer* buffer; InfChatSession* session; InfcSessionProxy* proxy; InfBrowserIter parent_iter; InfBrowserIter iter; /* TODO: Can we do this in enqueued already? */ if(strcmp((const char*)xml->name, "subscribe-ack") == 0) { browser = INFC_BROWSER(object); priv = INFC_BROWSER_PRIVATE(browser); has_id = inf_xml_util_get_attribute_uint(xml, "id", &node_id, NULL); for(item = priv->subscription_requests; item != NULL; item = item->next) { subreq = (InfcBrowserSubreq*)item->data; if( (has_id && subreq->node_id == node_id) || (!has_id && subreq->node_id == 0)) { break; } } /* TODO: Only Assert here, and remove the subreq in * infc_browser_node_free() */ if(item == NULL) return; /*g_assert(item != NULL);*/ infc_browser_unlink_subreq(browser, subreq); switch(subreq->type) { case INFC_BROWSER_SUBREQ_CHAT: g_assert(has_id == FALSE); /* OK, do the subscription */ g_assert(priv->chat_session == NULL); buffer = inf_chat_buffer_new(256); /* Synchronize in subscription group: */ session = inf_chat_session_new( priv->communication_manager, buffer, INF_SESSION_SYNCHRONIZING, INF_COMMUNICATION_GROUP(subreq->shared.chat.subscription_group), connection ); g_object_unref(buffer); proxy = g_object_new(INFC_TYPE_SESSION_PROXY, "session", session, NULL); inf_communication_group_set_target( INF_COMMUNICATION_GROUP(subreq->shared.chat.subscription_group), INF_COMMUNICATION_OBJECT(proxy) ); infc_session_proxy_set_connection( proxy, subreq->shared.chat.subscription_group, connection, priv->seq_id ); g_object_unref(session); inf_browser_subscribe_session( INF_BROWSER(browser), NULL, INF_SESSION_PROXY(proxy), INF_REQUEST(subreq->shared.chat.request) ); if(subreq->shared.chat.request != NULL) { infc_request_manager_finish_request( priv->request_manager, subreq->shared.chat.request, inf_request_result_make_subscribe_chat( INF_BROWSER(browser), INF_SESSION_PROXY(proxy) ) ); } /* The default handler of the subscribe-session signal refs the proxy */ g_object_unref(proxy); break; case INFC_BROWSER_SUBREQ_SESSION: g_assert(has_id == TRUE); if(subreq->shared.session.node != NULL) { g_assert(subreq->shared.session.node->id == node_id); infc_browser_subscribe_session( browser, subreq->shared.session.node, subreq->shared.session.request, subreq->shared.session.subscription_group, connection, TRUE ); if(subreq->shared.session.request != NULL) { iter.node = subreq->shared.session.node; iter.node_id = node_id; g_assert( subreq->shared.session.node->type == INFC_BROWSER_NODE_NOTE_KNOWN ); proxy = subreq->shared.session.node->shared.known.session; g_assert(proxy != NULL); infc_request_manager_finish_request( priv->request_manager, subreq->shared.session.request, inf_request_result_make_subscribe_session( INF_BROWSER(browser), &iter, INF_SESSION_PROXY(proxy) ) ); } } break; case INFC_BROWSER_SUBREQ_ADD_NODE: g_assert(has_id == TRUE); if(subreq->shared.add_node.parent != NULL) { /* Any other attempt at creating a node with this ID should have * failed already. */ g_assert( g_hash_table_lookup(priv->nodes, GUINT_TO_POINTER(node_id)) == NULL ); g_assert(infc_browser_find_subreq(browser, node_id) == NULL); node = infc_browser_node_add_note( browser, subreq->shared.add_node.parent, subreq->shared.add_node.request, node_id, subreq->shared.add_node.name, subreq->shared.add_node.plugin->note_type, subreq->shared.add_node.sheet_set, NULL ); g_assert(node->type == INFC_BROWSER_NODE_NOTE_KNOWN); /* Newly added nodes are normally newly created, so don't sync */ infc_browser_subscribe_session( browser, node, subreq->shared.add_node.request, subreq->shared.add_node.subscription_group, connection, FALSE ); /* Finish request */ if(subreq->shared.add_node.request != NULL) { parent_iter.node_id = subreq->shared.sync_in.parent->id; parent_iter.node = subreq->shared.sync_in.parent; iter.node = node; iter.node_id = node_id; infc_request_manager_finish_request( priv->request_manager, subreq->shared.add_node.request, inf_request_result_make_add_node( INF_BROWSER(browser), &parent_iter, &iter ) ); } } break; case INFC_BROWSER_SUBREQ_SYNC_IN: g_assert(has_id == TRUE); if(subreq->shared.sync_in.parent != NULL) { /* Any other attempt at creating a node with this ID should have * failed already. */ g_assert( g_hash_table_lookup(priv->nodes, GUINT_TO_POINTER(node_id)) == NULL ); g_assert(infc_browser_find_subreq(browser, node_id) == NULL); proxy = g_object_new( INFC_TYPE_SESSION_PROXY, "session", subreq->shared.sync_in.session, NULL ); sync_group = subreq->shared.sync_in.synchronization_group; inf_communication_group_set_target( INF_COMMUNICATION_GROUP(sync_group), INF_COMMUNICATION_OBJECT(proxy) ); inf_session_synchronize_to( subreq->shared.sync_in.session, INF_COMMUNICATION_GROUP(sync_group), connection ); node = infc_browser_node_add_note( browser, subreq->shared.sync_in.parent, subreq->shared.sync_in.request, node_id, subreq->shared.sync_in.name, subreq->shared.sync_in.plugin->note_type, subreq->shared.sync_in.sheet_set, proxy ); g_assert(node->type == INFC_BROWSER_NODE_NOTE_KNOWN); parent_iter.node_id = subreq->shared.sync_in.parent->id; parent_iter.node = subreq->shared.sync_in.parent; iter.node_id = node->id; iter.node = node; if(subreq->shared.sync_in.subscription_group != NULL) { /* Make sure the session is not yet subscribed */ g_assert( inf_session_get_subscription_group( subreq->shared.sync_in.session ) == NULL ); if(subreq->shared.sync_in.subscription_group != sync_group) { inf_communication_group_set_target( INF_COMMUNICATION_GROUP( subreq->shared.sync_in.subscription_group ), INF_COMMUNICATION_OBJECT(proxy) ); } /* Subscribe to the newly created node. We don't need to do all the * stuff infc_browser_subscribe_session() does since we already * created the session and proxy. */ infc_session_proxy_set_connection( proxy, subreq->shared.sync_in.subscription_group, connection, priv->seq_id ); inf_browser_subscribe_session( INF_BROWSER(browser), &iter, INF_SESSION_PROXY(proxy), INF_REQUEST(subreq->shared.sync_in.request) ); } g_object_unref(proxy); /* TODO: Emit a signal, so that others are notified that a sync-in * begins and can show progress or something. */ g_assert(subreq->shared.sync_in.request != NULL); infc_request_manager_finish_request( priv->request_manager, subreq->shared.sync_in.request, inf_request_result_make_add_node( INF_BROWSER(browser), &parent_iter, &iter ) ); } break; default: g_assert_not_reached(); break; } infc_browser_free_subreq(subreq); } } /* * InfBrowser implementation */ static void infc_browser_browser_subscribe_session(InfBrowser* browser, const InfBrowserIter* iter, InfSessionProxy* proxy, InfRequest* request) { InfcBrowserPrivate* priv; InfcBrowserNode* node; InfSession* session; priv = INFC_BROWSER_PRIVATE(browser); g_assert(INFC_IS_SESSION_PROXY(proxy)); g_object_get(G_OBJECT(proxy), "session", &session, NULL); if(iter != NULL) { node = (InfcBrowserNode*)iter->node; g_assert( g_hash_table_lookup(priv->nodes, GUINT_TO_POINTER(iter->node_id)) == node ); g_assert(node->type == INFC_BROWSER_NODE_NOTE_KNOWN); g_assert(node->shared.known.session == NULL); node->shared.known.session = INFC_SESSION_PROXY(proxy); g_object_ref(proxy); /* Associate the iter to the session so that we can remove the proxy * from that item when the session is closed. */ g_object_set_qdata_full( G_OBJECT(session), infc_browser_session_proxy_quark, inf_browser_iter_copy(iter), (GDestroyNotify)inf_browser_iter_free ); } else { g_assert(priv->chat_session == NULL); g_object_ref(proxy); priv->chat_session = INFC_SESSION_PROXY(proxy); g_object_notify(G_OBJECT(browser), "chat-session"); } g_signal_connect( session, "notify::subscription-group", G_CALLBACK(infc_browser_session_notify_subscription_group_cb), browser ); g_object_unref(session); } static gboolean infc_browser_browser_get_root(InfBrowser* browser, InfBrowserIter* iter) { InfcBrowserPrivate* priv; g_return_val_if_fail(INFC_IS_BROWSER(browser), FALSE); g_return_val_if_fail(iter != NULL, FALSE); priv = INFC_BROWSER_PRIVATE(browser); g_return_val_if_fail(priv->status == INF_BROWSER_OPEN, FALSE); g_assert(priv->root != NULL); iter->node_id = priv->root->id; iter->node = priv->root; return TRUE; } static gboolean infc_browser_browser_get_next(InfBrowser* browser, InfBrowserIter* iter) { InfcBrowserNode* node; g_return_val_if_fail(INFC_IS_BROWSER(browser), FALSE); infc_browser_return_val_if_iter_fail(browser, iter, FALSE); node = (InfcBrowserNode*)iter->node; if(node->next != NULL) { iter->node_id = node->next->id; iter->node = node->next; return TRUE; } else { return FALSE; } } static gboolean infc_browser_browser_get_prev(InfBrowser* browser, InfBrowserIter* iter) { InfcBrowserNode* node; g_return_val_if_fail(INFC_IS_BROWSER(browser), FALSE); infc_browser_return_val_if_iter_fail(browser, iter, FALSE); node = (InfcBrowserNode*)iter->node; if(node->prev != NULL) { iter->node_id = node->prev->id; iter->node = node->prev; return TRUE; } else { return FALSE; } } static gboolean infc_browser_browser_get_parent(InfBrowser* browser, InfBrowserIter* iter) { InfcBrowserNode* node; g_return_val_if_fail(INFC_IS_BROWSER(browser), FALSE); infc_browser_return_val_if_iter_fail(browser, iter, FALSE); node = (InfcBrowserNode*)iter->node; if(node->parent != NULL) { iter->node_id = node->parent->id; iter->node = node->parent; return TRUE; } else { return FALSE; } } static gboolean infc_browser_browser_get_child(InfBrowser* browser, InfBrowserIter* iter) { InfcBrowserNode* node; g_return_val_if_fail(INFC_IS_BROWSER(browser), FALSE); infc_browser_return_val_if_iter_fail(browser, iter, FALSE); node = (InfcBrowserNode*)iter->node; g_return_val_if_fail(node->shared.subdir.explored == TRUE, FALSE); if(node->shared.subdir.child != NULL) { iter->node_id = node->shared.subdir.child->id; iter->node = node->shared.subdir.child; return TRUE; } else { return FALSE; } } static InfRequest* infc_browser_browser_explore(InfBrowser* browser, const InfBrowserIter* iter, InfRequestFunc func, gpointer user_data) { InfcBrowserPrivate* priv; InfcBrowserNode* node; InfcRequest* request; xmlNodePtr xml; g_return_val_if_fail(INFC_IS_BROWSER(browser), NULL); infc_browser_return_val_if_iter_fail(browser, iter, NULL); node = (InfcBrowserNode*)iter->node; infc_browser_return_val_if_subdir_fail(node, NULL); g_return_val_if_fail(node->shared.subdir.explored == FALSE, NULL); g_return_val_if_fail( inf_browser_get_pending_request(browser, iter, "explore-node") == NULL, NULL ); priv = INFC_BROWSER_PRIVATE(browser); g_return_val_if_fail(priv->connection != NULL, NULL); g_return_val_if_fail(priv->status == INF_BROWSER_OPEN, NULL); request = infc_request_manager_add_request( priv->request_manager, INFC_TYPE_PROGRESS_REQUEST, "explore-node", G_CALLBACK(func), user_data, "node_id", node->id, NULL ); inf_browser_begin_request(browser, iter, INF_REQUEST(request)); xml = infc_browser_request_to_xml(request); inf_xml_util_set_attribute_uint(xml, "id", node->id); inf_communication_group_send_message( INF_COMMUNICATION_GROUP(priv->group), priv->connection, xml ); return INF_REQUEST(request); } static gboolean infc_browser_browser_get_explored(InfBrowser* browser, const InfBrowserIter* iter) { InfcBrowserNode* node; g_return_val_if_fail(INFC_IS_BROWSER(browser), FALSE); infc_browser_return_val_if_iter_fail(browser, iter, FALSE); node = (InfcBrowserNode*)iter->node; infc_browser_return_val_if_subdir_fail(node, FALSE); return node->shared.subdir.explored; } static gboolean infc_browser_browser_is_subdirectory(InfBrowser* browser, const InfBrowserIter* iter) { InfcBrowserNode* node; g_return_val_if_fail(INFC_IS_BROWSER(browser), FALSE); infc_browser_return_val_if_iter_fail(browser, iter, FALSE); node = (InfcBrowserNode*)iter->node; if(node->type == INFC_BROWSER_NODE_SUBDIRECTORY) return TRUE; return FALSE; } static InfRequest* infc_browser_browser_add_note(InfBrowser* infbrowser, const InfBrowserIter* iter, const char* name, const char* type, const InfAclSheetSet* sheet_set, InfSession* session, gboolean initial_subscribe, InfRequestFunc func, gpointer user_data) { InfcBrowser* browser; InfcBrowserPrivate* priv; InfcBrowserNode* node; const InfcNotePlugin* plugin; InfcRequest* request; xmlNodePtr xml; g_return_val_if_fail(INFC_IS_BROWSER(infbrowser), NULL); browser = INFC_BROWSER(infbrowser); infc_browser_return_val_if_iter_fail(browser, iter, NULL); node = (InfcBrowserNode*)iter->node; infc_browser_return_val_if_subdir_fail(node, NULL); g_return_val_if_fail(node->shared.subdir.explored == TRUE, NULL); priv = INFC_BROWSER_PRIVATE(browser); g_return_val_if_fail(priv->connection != NULL, NULL); g_return_val_if_fail(priv->status == INF_BROWSER_OPEN, NULL); plugin = infc_browser_lookup_plugin(browser, type); g_return_val_if_fail(plugin != NULL, NULL); request = infc_request_manager_add_request( priv->request_manager, INFC_TYPE_REQUEST, "add-node", G_CALLBACK(func), user_data, "node-id", iter->node_id, NULL ); if(session != NULL) { /* TODO: Add a InfcSyncInRequest, deriving from InfcRequest that * carries session and plugin, so we don't need g_object_set_qdata for the * session and plugin. */ g_object_ref(session); g_object_set_qdata_full( G_OBJECT(request), infc_browser_sync_in_session_quark, session, g_object_unref ); g_object_set_qdata( G_OBJECT(request), infc_browser_sync_in_plugin_quark, /* cast away const without warning */ *(gpointer*)(gpointer)&plugin ); } inf_browser_begin_request(INF_BROWSER(browser), iter, INF_REQUEST(request)); xml = infc_browser_request_to_xml(request); inf_xml_util_set_attribute_uint(xml, "parent", node->id); inf_xml_util_set_attribute(xml, "type", type); inf_xml_util_set_attribute(xml, "name", name); if(sheet_set != NULL) inf_acl_sheet_set_to_xml(sheet_set, xml); if(initial_subscribe != FALSE) xmlNewChild(xml, NULL, (const xmlChar*)"subscribe", NULL); if(session != NULL) xmlNewChild(xml, NULL, (const xmlChar*)"sync-in", NULL); inf_communication_group_send_message( INF_COMMUNICATION_GROUP(priv->group), priv->connection, xml ); return INF_REQUEST(request); } static InfRequest* infc_browser_browser_add_subdirectory(InfBrowser* infbrowser, const InfBrowserIter* iter, const char* name, const InfAclSheetSet* sheet_set, InfRequestFunc func, gpointer user_data) { InfcBrowser* browser; InfcBrowserPrivate* priv; InfcBrowserNode* node; InfcRequest* request; xmlNodePtr xml; g_return_val_if_fail(INFC_IS_BROWSER(infbrowser), NULL); browser = INFC_BROWSER(infbrowser); infc_browser_return_val_if_iter_fail(browser, iter, NULL); node = (InfcBrowserNode*)iter->node; infc_browser_return_val_if_subdir_fail(node, NULL); g_return_val_if_fail(node->shared.subdir.explored == TRUE, NULL); priv = INFC_BROWSER_PRIVATE(browser); g_return_val_if_fail(priv->connection != NULL, NULL); g_return_val_if_fail(priv->status == INF_BROWSER_OPEN, NULL); request = infc_request_manager_add_request( priv->request_manager, INFC_TYPE_REQUEST, "add-node", G_CALLBACK(func), user_data, "node-id", iter->node_id, NULL ); inf_browser_begin_request(INF_BROWSER(browser), iter, INF_REQUEST(request)); xml = infc_browser_request_to_xml(request); inf_xml_util_set_attribute_uint(xml, "parent", node->id); inf_xml_util_set_attribute(xml, "type", "InfSubdirectory"); inf_xml_util_set_attribute(xml, "name", name); if(sheet_set != NULL) inf_acl_sheet_set_to_xml(sheet_set, xml); inf_communication_group_send_message( INF_COMMUNICATION_GROUP(priv->group), priv->connection, xml ); return INF_REQUEST(request); } static InfRequest* infc_browser_browser_remove_node(InfBrowser* infbrowser, const InfBrowserIter* iter, InfRequestFunc func, gpointer user_data) { InfcBrowser* browser; InfcBrowserPrivate* priv; InfcBrowserNode* node; InfcRequest* request; xmlNodePtr xml; g_return_val_if_fail(INFC_IS_BROWSER(infbrowser), NULL); browser = INFC_BROWSER(infbrowser); infc_browser_return_val_if_iter_fail(browser, iter, NULL); priv = INFC_BROWSER_PRIVATE(browser); node = (InfcBrowserNode*)iter->node; /* The root node cannot be removed */ g_return_val_if_fail(node->parent != NULL, NULL); /* TODO: Check that there is not a remove-node request already enqueued. */ g_return_val_if_fail(priv->connection != NULL, NULL); g_return_val_if_fail(priv->status == INF_BROWSER_OPEN, NULL); request = infc_request_manager_add_request( priv->request_manager, INFC_TYPE_REQUEST, "remove-node", G_CALLBACK(func), user_data, "node-id", iter->node_id, NULL ); inf_browser_begin_request(INF_BROWSER(browser), iter, INF_REQUEST(request)); xml = infc_browser_request_to_xml(request); inf_xml_util_set_attribute_uint(xml, "id", node->id); inf_communication_group_send_message( INF_COMMUNICATION_GROUP(priv->group), priv->connection, xml ); return INF_REQUEST(request); } static const gchar* infc_browser_browser_get_node_name(InfBrowser* browser, const InfBrowserIter* iter) { InfcBrowserNode* node; g_return_val_if_fail(INFC_IS_BROWSER(browser), NULL); infc_browser_return_val_if_iter_fail(browser, iter, NULL); node = (InfcBrowserNode*)iter->node; return node->name; } static const gchar* infc_browser_browser_get_node_type(InfBrowser* infbrowser, const InfBrowserIter* iter) { InfcBrowser* browser; InfcBrowserPrivate* priv; InfcBrowserNode* node; g_return_val_if_fail(INFC_IS_BROWSER(infbrowser), NULL); browser = INFC_BROWSER(infbrowser); infc_browser_return_val_if_iter_fail(browser, iter, NULL); priv = INFC_BROWSER_PRIVATE(browser); node = (InfcBrowserNode*)iter->node; switch(node->type) { case INFC_BROWSER_NODE_SUBDIRECTORY: g_return_val_if_reached(NULL); return NULL; case INFC_BROWSER_NODE_NOTE_KNOWN: return node->shared.known.plugin->note_type; case INFC_BROWSER_NODE_NOTE_UNKNOWN: return node->shared.unknown.type; default: g_assert_not_reached(); return NULL; } } static InfRequest* infc_browser_browser_subscribe(InfBrowser* browser, const InfBrowserIter* iter, InfRequestFunc func, gpointer user_data) { InfcBrowserPrivate* priv; InfcBrowserNode* node; InfcRequest* request; xmlNodePtr xml; g_return_val_if_fail(INFC_IS_BROWSER(browser), NULL); infc_browser_return_val_if_iter_fail(INFC_BROWSER(browser), iter, NULL); priv = INFC_BROWSER_PRIVATE(browser); node = (InfcBrowserNode*)iter->node; g_return_val_if_fail(priv->connection != NULL, NULL); g_return_val_if_fail(priv->status == INF_BROWSER_OPEN, NULL); g_return_val_if_fail(node->type == INFC_BROWSER_NODE_NOTE_KNOWN, NULL); g_return_val_if_fail(node->shared.known.session == NULL, NULL); g_return_val_if_fail( inf_browser_get_pending_request( browser, iter, "subscribe-session" ) == NULL, NULL ); request = infc_request_manager_add_request( priv->request_manager, INFC_TYPE_REQUEST, "subscribe-session", G_CALLBACK(func), user_data, "node-id", iter->node_id, NULL ); inf_browser_begin_request(browser, iter, INF_REQUEST(request)); xml = infc_browser_request_to_xml(request); inf_xml_util_set_attribute_uint(xml, "id", node->id); inf_communication_group_send_message( INF_COMMUNICATION_GROUP(priv->group), priv->connection, xml ); return INF_REQUEST(request); } static InfSessionProxy* infc_browser_browser_get_session(InfBrowser* browser, const InfBrowserIter* iter) { InfcBrowserPrivate* priv; InfcBrowserNode* node; g_return_val_if_fail(INFC_IS_BROWSER(browser), NULL); infc_browser_return_val_if_iter_fail(browser, iter, NULL); priv = INFC_BROWSER_PRIVATE(browser); node = (InfcBrowserNode*)iter->node; if(node->type != INFC_BROWSER_NODE_NOTE_KNOWN) return NULL; return INF_SESSION_PROXY(node->shared.known.session); } static GSList* infc_browser_browser_list_pending_requests(InfBrowser* browser, const InfBrowserIter* iter, const gchar* request_type) { InfcBrowserPrivate* priv; InfcBrowserListPendingRequestsForeachData data; data.iter = iter; data.result = NULL; g_return_val_if_fail(INFC_IS_BROWSER(browser), NULL); if(iter != NULL) { infc_browser_return_val_if_iter_fail(browser, iter, NULL); } priv = INFC_BROWSER_PRIVATE(browser); if(priv->request_manager != NULL) { if(request_type == NULL) { infc_request_manager_foreach_request( priv->request_manager, infc_browser_browser_list_pending_requests_foreach_func, &data ); } else { infc_request_manager_foreach_named_request( priv->request_manager, request_type, infc_browser_browser_list_pending_requests_foreach_func, &data ); } } return data.result; } static gboolean infc_browser_browser_iter_from_request(InfBrowser* browser, InfRequest* request, InfBrowserIter* iter) { InfcBrowserPrivate* priv; InfcBrowserNode* node; guint node_id; g_return_val_if_fail(INFC_IS_BROWSER(browser), FALSE); g_return_val_if_fail(INFC_IS_REQUEST(request), FALSE); g_return_val_if_fail(iter != NULL, FALSE); priv = INFC_BROWSER_PRIVATE(browser); g_object_get(G_OBJECT(request), "node-id", &node_id, NULL); if(node_id == G_MAXUINT) return FALSE; node = g_hash_table_lookup(priv->nodes, GUINT_TO_POINTER(node_id)); if(node == NULL) return FALSE; iter->node_id = node_id; iter->node = node; return TRUE; } static InfRequest* infc_browser_browser_query_acl_account_list(InfBrowser* browser, InfRequestFunc func, gpointer user_data) { InfcBrowserPrivate* priv; InfcRequest* request; xmlNodePtr xml; InfAclAccount* accounts; guint n_accounts; g_return_val_if_fail(INFC_IS_BROWSER(browser), NULL); priv = INFC_BROWSER_PRIVATE(browser); g_return_val_if_fail(priv->status == INF_BROWSER_OPEN, NULL); g_return_val_if_fail( inf_browser_get_pending_request( INF_BROWSER(browser), NULL, "query-acl-account-list" ) == NULL, NULL ); request = infc_request_manager_add_request( priv->request_manager, INFC_TYPE_PROGRESS_REQUEST, "query-acl-account-list", G_CALLBACK(func), user_data, NULL ); inf_browser_begin_request(browser, NULL, INF_REQUEST(request)); switch(priv->account_list_status) { case INFC_BROWSER_ACCOUNT_LIST_NOT_QUERIED: case INFC_BROWSER_ACCOUNT_LIST_NO_NOTIFICATIONS: xml = infc_browser_request_to_xml(request); inf_communication_group_send_message( INF_COMMUNICATION_GROUP(priv->group), priv->connection, xml ); break; case INFC_BROWSER_ACCOUNT_LIST_NOTIFICATIONS: /* Our cache is up to date, i.e. serve from cache */ accounts = infc_browser_make_acl_account_list( INFC_BROWSER(browser), &n_accounts ); infc_request_manager_finish_request( priv->request_manager, request, inf_request_result_make_query_acl_account_list( INF_BROWSER(browser), accounts, n_accounts, TRUE ) ); g_free(accounts); request = NULL; break; } return INF_REQUEST(request); } static const InfAclAccount* infc_browser_browser_get_acl_default_account(InfBrowser* infbrowser) { InfcBrowser* browser; InfcBrowserPrivate* priv; InfAclAccountId default_id; InfAclAccount* default_account; browser = INFC_BROWSER(infbrowser); priv = INFC_BROWSER_PRIVATE(browser); g_return_val_if_fail(priv->status == INF_BROWSER_OPEN, NULL); default_id = inf_acl_account_id_from_string("default"); default_account = g_hash_table_lookup( priv->accounts, INF_ACL_ACCOUNT_ID_TO_POINTER(default_id) ); g_assert(default_account != NULL); return default_account; } static const InfAclAccount* infc_browser_browser_get_acl_local_account(InfBrowser* infbrowser) { InfcBrowser* browser; InfcBrowserPrivate* priv; browser = INFC_BROWSER(infbrowser); priv = INFC_BROWSER_PRIVATE(browser); g_return_val_if_fail(priv->status == INF_BROWSER_OPEN, NULL); g_assert(priv->local_account != NULL); return priv->local_account; } static InfRequest* infc_browser_browser_lookup_acl_accounts(InfBrowser* infbrowser, const InfAclAccountId* ids, guint n_ids, InfRequestFunc func, gpointer user_data) { InfcBrowser* browser; InfcBrowserPrivate* priv; InfcRequest* request; guint i; const InfAclAccount* account; InfAclAccount* accounts; guint n_accounts; xmlNodePtr xml; InfAclAccountId* ids_req; browser = INFC_BROWSER(infbrowser); priv = INFC_BROWSER_PRIVATE(browser); request = infc_request_manager_add_request( priv->request_manager, INFC_TYPE_REQUEST, "lookup-acl-accounts", G_CALLBACK(func), user_data, NULL ); if(priv->account_list_status != INFC_BROWSER_ACCOUNT_LIST_NOTIFICATIONS) xml = infc_browser_request_to_xml(request); else xml = NULL; accounts = g_malloc(sizeof(InfAclAccount) * n_ids); n_accounts = 0; /* Lookup each account from server that we don't have in our cache */ for(i = 0; i < n_ids; ++i) { account = g_hash_table_lookup( priv->accounts, INF_ACL_ACCOUNT_ID_TO_POINTER(ids[i]) ); if(account != NULL) { accounts[i] = *account; ++n_accounts; } else { accounts[i].id = ids[i]; accounts[i].name = NULL; if(xml != NULL) { xmlNewChild( xml, NULL, (const xmlChar*)"id", (const xmlChar*)inf_acl_account_id_to_string(ids[i]) ); } } } if(xml == NULL || n_accounts == n_ids) { /* All lookup IDs are available from cache */ if(xml != NULL) xmlFreeNode(xml); infc_request_manager_finish_request( priv->request_manager, request, inf_request_result_make_lookup_acl_accounts( INF_BROWSER(browser), accounts, n_ids ) ); request = NULL; } else { /* TODO: Add a InfcLookupAclAccountsRequest, deriving from InfcRequest * that carries ids and n_ids, so we don't need * g_object_set_qdata for the session and plugin. */ /* Remember all IDs that we were asked to look up, also the ones that are * available already, so that we can finish the request in one go when * the server reply is available. */ ids_req = g_malloc(sizeof(InfAclAccountId) * n_ids); for(i = 0; i < n_ids; ++i) ids_req[i] = ids[i]; g_object_set_qdata_full( G_OBJECT(request), infc_browser_lookup_acl_accounts_ids_quark, ids_req, g_free ); g_object_set_qdata( G_OBJECT(request), infc_browser_lookup_acl_accounts_n_ids_quark, GUINT_TO_POINTER(n_ids) ); /* Need to send a request */ inf_communication_group_send_message( INF_COMMUNICATION_GROUP(priv->group), priv->connection, xml ); } g_free(accounts); return INF_REQUEST(request); } static InfRequest* infc_browser_browser_lookup_acl_account_by_name(InfBrowser* infbrowser, const gchar* name, InfRequestFunc func, gpointer user_data) { InfcBrowser* browser; InfcBrowserPrivate* priv; InfcRequest* request; GArray* cached_accounts; InfcBrowserLookupAclAccountByByNameData lookup_data; InfAclAccount result_acc; xmlNodePtr xml; browser = INFC_BROWSER(infbrowser); priv = INFC_BROWSER_PRIVATE(browser); request = infc_request_manager_add_request( priv->request_manager, INFC_TYPE_REQUEST, "lookup-acl-accounts", G_CALLBACK(func), user_data, NULL ); lookup_data.name = name; lookup_data.accounts = g_array_new(FALSE, FALSE, sizeof(InfAclAccount)); g_hash_table_foreach( priv->accounts, infc_browser_browser_lookup_acl_account_by_name_find_func, &lookup_data ); if(lookup_data.accounts->len == 0) { if(priv->account_list_status == INFC_BROWSER_ACCOUNT_LIST_NOTIFICATIONS) { /* We know that the entry does not exist */ result_acc.id = 0; result_acc.name = (gchar*)name; infc_request_manager_finish_request( priv->request_manager, request, inf_request_result_make_lookup_acl_accounts( INF_BROWSER(browser), &result_acc, 1 ) ); request = NULL; } else { /* Make a server request */ xml = infc_browser_request_to_xml(request); xmlNewChild(xml, NULL, (const xmlChar*)"name", (const xmlChar*)name); g_object_set_qdata_full( G_OBJECT(request), infc_browser_lookup_acl_accounts_name_quark, g_strdup(name), g_free ); inf_communication_group_send_message( INF_COMMUNICATION_GROUP(priv->group), priv->connection, xml ); } } else { /* Use cache value */ infc_request_manager_finish_request( priv->request_manager, request, inf_request_result_make_lookup_acl_accounts( INF_BROWSER(browser), (InfAclAccount*)lookup_data.accounts->data, lookup_data.accounts->len ) ); request = NULL; } g_array_free(lookup_data.accounts, TRUE); /* Note that cached account names point to the hash table entries * and have not been copied, so do not need to be freed here. */ return INF_REQUEST(request); } static InfRequest* infc_browser_browser_create_acl_account(InfBrowser* browser, gnutls_x509_crq_t crq, InfRequestFunc func, gpointer user_data) { InfcBrowserPrivate* priv; InfcRequest* request; xmlNodePtr xml; xmlNodePtr crqNode; GError* error; gchar* crq_text; size_t size; int res; priv = INFC_BROWSER_PRIVATE(browser); request = infc_request_manager_add_request( priv->request_manager, INFC_TYPE_REQUEST, "create-acl-account", G_CALLBACK(func), user_data, NULL ); inf_browser_begin_request(INF_BROWSER(browser), NULL, INF_REQUEST(request)); size = 0; res = gnutls_x509_crq_export(crq, GNUTLS_X509_FMT_PEM, NULL, &size); if(res != GNUTLS_E_SHORT_MEMORY_BUFFER) { error = NULL; inf_gnutls_set_error(&error, res); infc_request_manager_fail_request(priv->request_manager, request, error); g_error_free(error); g_object_unref(request); return NULL; } crq_text = g_malloc(size); res = gnutls_x509_crq_export(crq, GNUTLS_X509_FMT_PEM, crq_text, &size); if(res != GNUTLS_E_SUCCESS) { g_free(crq_text); error = NULL; inf_gnutls_set_error(&error, res); infc_request_manager_fail_request(priv->request_manager, request, error); g_error_free(error); g_object_unref(request); return NULL; } xml = infc_browser_request_to_xml(request); crqNode = xmlNewChild(xml, NULL, (const xmlChar*)"crq", NULL); xmlNodeAddContentLen(crqNode, (const xmlChar*)crq_text, size); g_free(crq_text); inf_communication_group_send_message( INF_COMMUNICATION_GROUP(priv->group), priv->connection, xml ); return INF_REQUEST(request); } static InfRequest* infc_browser_browser_remove_acl_account(InfBrowser* browser, InfAclAccountId account, InfRequestFunc func, gpointer user_data) { InfcBrowserPrivate* priv; InfcRequest* request; xmlNodePtr xml; priv = INFC_BROWSER_PRIVATE(browser); request = infc_request_manager_add_request( priv->request_manager, INFC_TYPE_REQUEST, "remove-acl-account", G_CALLBACK(func), user_data, NULL ); inf_browser_begin_request(INF_BROWSER(browser), NULL, INF_REQUEST(request)); xml = infc_browser_request_to_xml(request); inf_xml_util_set_attribute( xml, "id", inf_acl_account_id_to_string(account) ); inf_communication_group_send_message( INF_COMMUNICATION_GROUP(priv->group), priv->connection, xml ); return INF_REQUEST(request); } static InfRequest* infc_browser_browser_query_acl(InfBrowser* browser, const InfBrowserIter* iter, InfRequestFunc func, gpointer user_data) { InfcBrowserPrivate* priv; InfcBrowserNode* node; InfcRequest* request; xmlNodePtr xml; g_return_val_if_fail(INFC_IS_BROWSER(browser), NULL); infc_browser_return_val_if_iter_fail(INFC_BROWSER(browser), iter, NULL); node = (InfcBrowserNode*)iter->node; priv = INFC_BROWSER_PRIVATE(browser); g_return_val_if_fail(priv->connection != NULL, NULL); g_return_val_if_fail(priv->status == INF_BROWSER_OPEN, NULL); g_return_val_if_fail(node->acl_queried == FALSE, NULL); g_return_val_if_fail( inf_browser_get_pending_request(browser, iter, "query-acl") == NULL, NULL ); request = infc_request_manager_add_request( priv->request_manager, INFC_TYPE_REQUEST, "query-acl", G_CALLBACK(func), user_data, "node-id", node->id, NULL ); inf_browser_begin_request(browser, iter, INF_REQUEST(request)); xml = infc_browser_request_to_xml(request); inf_xml_util_set_attribute_uint(xml, "id", node->id); inf_communication_group_send_message( INF_COMMUNICATION_GROUP(priv->group), priv->connection, xml ); return INF_REQUEST(request); } static gboolean infc_browser_browser_has_acl(InfBrowser* browser, const InfBrowserIter* iter, InfAclAccountId account) { InfcBrowserPrivate* priv; InfcBrowserNode* node; InfAclAccountId default_id; g_return_val_if_fail(INFC_IS_BROWSER(browser), FALSE); infc_browser_return_val_if_iter_fail(INFC_BROWSER(browser), iter, FALSE); priv = INFC_BROWSER_PRIVATE(browser); node = (InfcBrowserNode*)iter->node; /* If we have queried the full ACL, everything is available */ if(node->acl_queried == TRUE) return TRUE; /* Otherwise we only have the local user and the default user sheets */ if(account != 0) { if(account == priv->local_account->id) return TRUE; default_id = inf_acl_account_id_from_string("default"); if(account == default_id) return TRUE; } /* So if that's not the case we don't have it */ return FALSE; } static const InfAclSheetSet* infc_browser_browser_get_acl(InfBrowser* browser, const InfBrowserIter* iter) { InfcBrowserPrivate* priv; InfcBrowserNode* node; g_return_val_if_fail(INFC_IS_BROWSER(browser), NULL); infc_browser_return_val_if_iter_fail(INFC_BROWSER(browser), iter, NULL); node = (InfcBrowserNode*)iter->node; return node->acl; } static InfRequest* infc_browser_browser_set_acl(InfBrowser* browser, const InfBrowserIter* iter, const InfAclSheetSet* sheet_set, InfRequestFunc func, gpointer user_data) { InfcBrowserPrivate* priv; InfcBrowserNode* node; InfcRequest* request; xmlNodePtr xml; g_return_val_if_fail(INFC_IS_BROWSER(browser), NULL); infc_browser_return_val_if_iter_fail(INFC_BROWSER(browser), iter, NULL); node = (InfcBrowserNode*)iter->node; priv = INFC_BROWSER_PRIVATE(browser); g_return_val_if_fail(priv->connection != NULL, NULL); g_return_val_if_fail(priv->status == INF_BROWSER_OPEN, NULL); g_return_val_if_fail(node->acl_queried == TRUE, NULL); request = infc_request_manager_add_request( priv->request_manager, INFC_TYPE_REQUEST, "set-acl", G_CALLBACK(func), user_data, "node-id", node->id, NULL ); inf_browser_begin_request(browser, iter, INF_REQUEST(request)); xml = infc_browser_request_to_xml(request); inf_xml_util_set_attribute_uint(xml, "id", node->id); inf_acl_sheet_set_to_xml(sheet_set, xml); inf_communication_group_send_message( INF_COMMUNICATION_GROUP(priv->group), priv->connection, xml ); return INF_REQUEST(request); } /* * GType registration. */ static void infc_browser_class_init(InfcBrowserClass* browser_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(browser_class); object_class->dispose = infc_browser_dispose; object_class->finalize = infc_browser_finalize; object_class->set_property = infc_browser_set_property; object_class->get_property = infc_browser_get_property; infc_browser_session_proxy_quark = g_quark_from_static_string( "infc-browser-session-proxy-quark" ); infc_browser_sync_in_session_quark = g_quark_from_static_string( "infc-browser-sync-in-session-quark" ); infc_browser_sync_in_plugin_quark = g_quark_from_static_string( "infc-browser-sync-in-plugin-quark" ); infc_browser_lookup_acl_accounts_ids_quark = g_quark_from_static_string( "infc-browser-lookup-acl-accounts-ids-quark" ); infc_browser_lookup_acl_accounts_n_ids_quark = g_quark_from_static_string( "infc-browser-lookup-acl-accounts-n-ids-quark" ); infc_browser_lookup_acl_accounts_name_quark = g_quark_from_static_string( "infc-browser-lookup-acl-accounts-name-quark" ); infc_browser_query_acl_account_list_accounts_quark = g_quark_from_static_string( "infc-browser-query-acl-account-list-accounts-quark" ); g_object_class_install_property( object_class, PROP_IO, g_param_spec_object( "io", "IO", "The InfIo to schedule timeouts", INF_TYPE_IO, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_COMMUNICATION_MANAGER, g_param_spec_object( "communication-manager", "Communication manager", "The communication manager for the browser", INF_COMMUNICATION_TYPE_MANAGER, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_CONNECTION, g_param_spec_object( "connection", "Server connection", "Connection to the server exposing the directory to browse", INF_TYPE_XML_CONNECTION, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_CHAT_SESSION, g_param_spec_object( "chat-session", "Chat session", "Active chat session", INFC_TYPE_SESSION_PROXY, G_PARAM_READABLE ) ); g_object_class_override_property(object_class, PROP_STATUS, "status"); } static void infc_browser_communication_object_iface_init( InfCommunicationObjectInterface* iface) { iface->received = infc_browser_communication_object_received; iface->sent = infc_browser_communication_object_sent; } static void infc_browser_browser_iface_init(InfBrowserInterface* iface) { iface->error = NULL; iface->node_added = NULL; iface->node_removed = NULL; iface->subscribe_session = infc_browser_browser_subscribe_session; iface->unsubscribe_session = NULL; iface->begin_request = NULL; iface->acl_account_added = NULL; iface->acl_account_removed = NULL; iface->acl_local_account_changed = NULL; iface->acl_changed = NULL; iface->get_root = infc_browser_browser_get_root; iface->get_next = infc_browser_browser_get_next; iface->get_prev = infc_browser_browser_get_prev; iface->get_parent = infc_browser_browser_get_parent; iface->get_child = infc_browser_browser_get_child; iface->explore = infc_browser_browser_explore; iface->get_explored = infc_browser_browser_get_explored; iface->is_subdirectory = infc_browser_browser_is_subdirectory; iface->add_note = infc_browser_browser_add_note; iface->add_subdirectory = infc_browser_browser_add_subdirectory; iface->remove_node = infc_browser_browser_remove_node; iface->get_node_name = infc_browser_browser_get_node_name; iface->get_node_type = infc_browser_browser_get_node_type; iface->subscribe = infc_browser_browser_subscribe; iface->get_session = infc_browser_browser_get_session; iface->list_pending_requests = infc_browser_browser_list_pending_requests; iface->iter_from_request = infc_browser_browser_iter_from_request; iface->get_acl_default_account = infc_browser_browser_get_acl_default_account; iface->get_acl_local_account = infc_browser_browser_get_acl_local_account; iface->query_acl_account_list = infc_browser_browser_query_acl_account_list; iface->lookup_acl_accounts = infc_browser_browser_lookup_acl_accounts; iface->lookup_acl_account_by_name = infc_browser_browser_lookup_acl_account_by_name; iface->create_acl_account = infc_browser_browser_create_acl_account; iface->remove_acl_account = infc_browser_browser_remove_acl_account; iface->query_acl = infc_browser_browser_query_acl; iface->has_acl = infc_browser_browser_has_acl; iface->get_acl = infc_browser_browser_get_acl; iface->set_acl = infc_browser_browser_set_acl; } /* * Public API. */ /** * infc_browser_new: (constructor) * @io: A #InfIo object used to schedule timeouts. * @comm_manager: A #InfCommunicationManager to register the server connection * and which forwards incoming data to the browser or running sessions. * @connection: Connection to the server. * * Creates a new #InfcBrowser. * * Returns: (transfer full): A new #InfcBrowser. **/ InfcBrowser* infc_browser_new(InfIo* io, InfCommunicationManager* comm_manager, InfXmlConnection* connection) { GObject* object; g_return_val_if_fail(INF_IS_IO(io), NULL); g_return_val_if_fail(INF_COMMUNICATION_IS_MANAGER(comm_manager), NULL); g_return_val_if_fail(INF_IS_XML_CONNECTION(connection), NULL); object = g_object_new( INFC_TYPE_BROWSER, "io", io, "communication-manager", comm_manager, "connection", connection, NULL ); return INFC_BROWSER(object); } /** * infc_browser_get_communication_manager: * @browser: A #InfcBrowser. * * Returns the communication manager of this browser. * * Returns: (transfer none): A #InfCommunicationManager. **/ InfCommunicationManager* infc_browser_get_communication_manager(InfcBrowser* browser) { g_return_val_if_fail(INFC_IS_BROWSER(browser), NULL); return INFC_BROWSER_PRIVATE(browser)->communication_manager; } /** * infc_browser_get_connection: * @browser: A #InfcBrowser. * * Returns the connection to the server. * * Returns: (transfer none): A #InfXmlConnection. **/ InfXmlConnection* infc_browser_get_connection(InfcBrowser* browser) { g_return_val_if_fail(INFC_IS_BROWSER(browser), NULL); return INFC_BROWSER_PRIVATE(browser)->connection; } /** * infc_browser_add_plugin: * @browser: A #InfcBrowser. * @plugin: A #InfcNotePlugin. * * Adds @plugin to @browser. This allows the browser to create sessions of * the plugin's type. Only one plugin of each type can be added to the * directory. * * Returns: (transfer none): Whether the plugin was added successfully. **/ gboolean infc_browser_add_plugin(InfcBrowser* browser, const InfcNotePlugin* plugin) { InfcBrowserPrivate* priv; g_return_val_if_fail(INFC_IS_BROWSER(browser), FALSE); g_return_val_if_fail(plugin != NULL, FALSE); priv = INFC_BROWSER_PRIVATE(browser); if(g_hash_table_lookup(priv->plugins, plugin->note_type) != NULL) return FALSE; g_hash_table_insert( priv->plugins, /* cast const away without warning */ /* take addr -> char const * const * * cast -> void const * * cast -> void * const * * deref -> void * const */ *(const gpointer*)(gconstpointer)&plugin->note_type, *(gpointer*)(gpointer)&plugin ); /* TODO: Check for yet unknown note types and make them known if they * match this plugin. */ return TRUE; } /** * infc_browser_lookup_plugin: * @browser: A #InfcBrowser. * @note_type: A note type, such as "InfText". * * Returns a previously registered plugin (see infc_browser_add_plugin()) for * the given note type, or %NULL if there is no such plugin. * * Returns: (transfer none): A #InfcNotePlugin, or %NULL. **/ const InfcNotePlugin* infc_browser_lookup_plugin(InfcBrowser* browser, const gchar* note_type) { InfcBrowserPrivate* priv; g_return_val_if_fail(INFC_IS_BROWSER(browser), NULL); g_return_val_if_fail(note_type != NULL, NULL); priv = INFC_BROWSER_PRIVATE(browser); return (const InfcNotePlugin*)g_hash_table_lookup(priv->plugins, note_type); } /** * infc_browser_iter_save_session: * @browser: A #InfcBrowser. * @iter: A #InfBrowserIter pointing to a note in @browser. * @func: (scope async): The function to be called when the request finishes, * or %NULL. * @user_data: Additional data to pass to @func. * * Requests that the server saves the note pointed to by @iter into its * background storage. Normally, the server only does this when it is either * shut down or when the there are no more subscriptions to the note. Note that * this is merely a request and the server might decide not to save the * session for whatever reason. * * The request might either finish during the call to this function, in which * case @func will be called and %NULL being returned. If the request does not * finish within the function call, a #InfRequest object is returned, * where @func has been installed for the #InfRequest::finished signal, * so that it is called as soon as the request finishes. * * Returns: (transfer none) (allow-none): A #InfRequest that may be used to * get notified when the request finishes or fails. **/ InfRequest* infc_browser_iter_save_session(InfcBrowser* browser, const InfBrowserIter* iter, InfRequestFunc func, gpointer user_data) { InfcBrowserPrivate* priv; InfcBrowserNode* node; InfcRequest* request; xmlNodePtr xml; g_return_val_if_fail(INFC_IS_BROWSER(browser), NULL); infc_browser_return_val_if_iter_fail(browser, iter, NULL); priv = INFC_BROWSER_PRIVATE(browser); node = (InfcBrowserNode*)iter->node; g_return_val_if_fail(priv->connection != NULL, NULL); g_return_val_if_fail(node->type == INFC_BROWSER_NODE_NOTE_KNOWN, NULL); request = infc_request_manager_add_request( priv->request_manager, INFC_TYPE_REQUEST, "save-session", G_CALLBACK(func), user_data, "node-id", iter->node_id, NULL ); inf_browser_begin_request(INF_BROWSER(browser), iter, INF_REQUEST(request)); xml = infc_browser_request_to_xml(request); inf_xml_util_set_attribute_uint(xml, "id", node->id); inf_communication_group_send_message( INF_COMMUNICATION_GROUP(priv->group), priv->connection, xml ); return INF_REQUEST(request); } /** * infc_browser_iter_get_sync_in: * @browser: A #InfcBrowser. * @iter: A #InfBrowserIter pointing to a note in @browser. * * Returns the #InfcSessionProxy that is used to synchronize the note @iter * points to to the server. Such a node is created by * inf_browser_add_note() with non-%NULL @session parameter. If the client is * subscribed to this note, then this returns the same session as * inf_browser_get_session(). However, it is possible that we * synchronize this node to the server without being subscribed to it. In * this case, this function returns the session that does the synchronization, * while inf_browser_get_session() would return %NULL. * * Returns: (transfer none) (allow-none): A #InfcSessionProxy, or %NULL if we * are currently not synchronizing this node to the server. **/ InfcSessionProxy* infc_browser_iter_get_sync_in(InfcBrowser* browser, const InfBrowserIter* iter) { InfcBrowserPrivate* priv; GSList* item; InfcBrowserSyncIn* sync_in; g_return_val_if_fail(INFC_IS_BROWSER(browser), NULL); infc_browser_return_val_if_iter_fail(browser, iter, NULL); priv = INFC_BROWSER_PRIVATE(browser); for(item = priv->sync_ins; item != NULL; item = item->next) { sync_in = (InfcBrowserSyncIn*)item->data; if(sync_in->node == iter->node) return sync_in->proxy; } return NULL; } /** * infc_browser_iter_get_sync_in_requests: * @browser: A #InfcBrowser. * @iter: A #InfBrowserIter pointing to a subdirectory node in @browser. * * Returns a list of all #InfRequests created with * inf_browser_add_note() with the node @iter points to as * parent. Such requests begin a synchronization to the server when they * have finished. * * Returns: (transfer container) (element-type InfRequest): A list of * #InfRequests. Free with g_slist_free() when done. **/ GSList* infc_browser_iter_get_sync_in_requests(InfcBrowser* browser, const InfBrowserIter* iter) { InfcBrowserPrivate* priv; InfcBrowserNode* node; InfcBrowserIterGetSyncInRequestsForeachData data; data.iter = iter; data.result = NULL; g_return_val_if_fail(INFC_IS_BROWSER(browser), NULL); infc_browser_return_val_if_iter_fail(browser, iter, NULL); node = (InfcBrowserNode*)iter->node; infc_browser_return_val_if_subdir_fail(node, NULL); priv = INFC_BROWSER_PRIVATE(browser); if(priv->request_manager != NULL) { infc_request_manager_foreach_named_request( priv->request_manager, "add-node", infc_browser_iter_get_sync_in_requests_foreach_func, &data ); } return data.result; } /** * infc_browser_iter_is_valid: * @browser: A #InfcBrowser. * @iter: A #InfBrowserIter. * * Returns whether @iter points to a valid node in @browser. This is * generally the case for any #InfBrowserIter returned by one of the * InfcBrowser functions, it gets invalid however as soon as the node it * points to is removed. * * Returns: Whether @iter points to a node in @browser. */ gboolean infc_browser_iter_is_valid(InfcBrowser* browser, const InfBrowserIter* iter) { InfcBrowserPrivate* priv; gpointer node; g_return_val_if_fail(INFC_IS_BROWSER(browser), FALSE); if(!iter) return FALSE; priv = INFC_BROWSER_PRIVATE(browser); node = g_hash_table_lookup(priv->nodes, GUINT_TO_POINTER(iter->node_id)); return node != NULL && node == iter->node; } /** * infc_browser_subscribe_chat: * @browser: A #InfcBrowser. * @func: (scope async): The function to be called when the request * finishes, or %NULL. * @user_data: Additional data to pass to @func. * * Attempts to subscribe to the server's chat. When the operation finishes * infc_browser_get_chat_session() will return a #InfcSessionProxy * representing the chat session. It can be used to read the chat's content. * The request can fail in case the server chat is disabled. * * The request might either finish during the call to this function, in which * case @func will be called and %NULL being returned. If the request does not * finish within the function call, a #InfRequest object is returned, * where @func has been installed for the #InfRequest::finished signal, * so that it is called as soon as the request finishes. * * Returns: (transfer none) (allow-none): A #InfRequest that may be used to * get notified when the request finishes or fails. */ InfRequest* infc_browser_subscribe_chat(InfcBrowser* browser, InfRequestFunc func, gpointer user_data) { InfcBrowserPrivate* priv; InfcRequest* request; xmlNodePtr xml; g_return_val_if_fail(INFC_IS_BROWSER(browser), NULL); g_return_val_if_fail(infc_browser_get_chat_session(browser) == NULL, NULL); g_return_val_if_fail( infc_browser_get_subscribe_chat_request(browser) == NULL, NULL ); priv = INFC_BROWSER_PRIVATE(browser); /* This should really be a separate request type */ request = infc_request_manager_add_request( priv->request_manager, INFC_TYPE_REQUEST, "subscribe-chat", G_CALLBACK(func), user_data, NULL ); inf_browser_begin_request(INF_BROWSER(browser), NULL, INF_REQUEST(request)); xml = infc_browser_request_to_xml(request); inf_communication_group_send_message( INF_COMMUNICATION_GROUP(priv->group), priv->connection, xml ); return INF_REQUEST(request); } /** * infc_browser_get_subscribe_chat_request: * @browser: A #InfcBrowser. * * Returns the #InfRequest that represests the request sent to the server * which attempts to subscribe to its chat. If there is no such request * running, then the function returns %NULL. After such a request finishes, * call infc_browser_get_chat_session() to get the #InfcSessionProxy for the * chat session. To initiate the request, call infc_browser_subscribe_chat(). * * Returns: (transfer none) (allow-none): A #InfRequest, or %NULL. */ InfRequest* infc_browser_get_subscribe_chat_request(InfcBrowser* browser) { InfcBrowserPrivate* priv; InfcBrowserIterGetChatRequestForeachData data; data.result = NULL; g_return_val_if_fail(INFC_IS_BROWSER(browser), NULL); priv = INFC_BROWSER_PRIVATE(browser); if(priv->request_manager != NULL) { infc_request_manager_foreach_named_request( priv->request_manager, "subscribe-chat", infc_browser_get_chat_request_foreach_func, &data ); } return INF_REQUEST(data.result); } /** * infc_browser_get_chat_session: * @browser: A #InfcBrowser. * * Returns the #InfcSessionProxy representing the running chat session if the * local client is subscribed to it, or %NULL otherwise. * * Returns: (transfer none) (allow-none): A #InfcSessionProxy for the chat, * or %NULL. */ InfcSessionProxy* infc_browser_get_chat_session(InfcBrowser* browser) { g_return_val_if_fail(INFC_IS_BROWSER(browser), NULL); return INFC_BROWSER_PRIVATE(browser)->chat_session; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/PaxHeaders.26529/inf-i18n.c0000644000000000000000000000013213034342512017615 xustar0030 mtime=1483851082.041718492 30 atime=1483851082.041718492 30 ctime=1488261589.136138768 libinfinity-0.7.1/libinfinity/inf-i18n.c0000644000175000017500000000327213034342512020353 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include #include #include #include "config.h" static gchar* _inf_gettext_get_locale_dir(void) { #ifdef G_OS_WIN32 gchar* root; gchar* temp; gchar* result; root = g_win32_get_package_installation_directory_of_module(_inf_dll_handle); temp = g_build_filename(root, "share", "locale", NULL); g_free(root); result = g_win32_locale_filename_from_utf8(temp); g_free(temp); return result; #else return g_strdup(INF_LOCALEDIR); #endif } void _inf_gettext_init(void) { gchar* localedir; localedir = _inf_gettext_get_locale_dir(); bindtextdomain(GETTEXT_PACKAGE, localedir); g_free(localedir); bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); } const char* _inf_gettext(const char* msgid) { return dgettext(GETTEXT_PACKAGE, msgid); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/PaxHeaders.26529/InfGnutls-3.0.gir0000644000000000000000000000013213034342512021032 xustar0030 mtime=1483851082.021718383 30 atime=1483851082.021718383 30 ctime=1488261589.136138768 libinfinity-0.7.1/libinfinity/InfGnutls-3.0.gir0000644000175000017500000000213713034342512021567 0ustar00arminarmin00000000000000 libinfinity-0.7.1/libinfinity/PaxHeaders.26529/inf-dll.c0000644000000000000000000000013213034342512017611 xustar0030 mtime=1483851082.041718492 30 atime=1483851082.041718492 30 ctime=1488261589.132138777 libinfinity-0.7.1/libinfinity/inf-dll.c0000644000175000017500000000250113034342512020341 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /* This code saves the DLL Handle of the libinfinity DLL, for use * with g_win32_get_package_installation_directory_of_module */ #include #ifdef G_OS_WIN32 #include HMODULE _inf_dll_handle = NULL; BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved) { switch(fdwReason) { case DLL_PROCESS_ATTACH: _inf_dll_handle = (HMODULE)hinstDLL; break; } return TRUE; } #endif /* G_OS_WIN32 */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/PaxHeaders.26529/inf-signals.c0000644000000000000000000000013213034342512020476 xustar0030 mtime=1483851082.041718492 30 atime=1483851082.041718492 30 ctime=1488261589.136138768 libinfinity-0.7.1/libinfinity/inf-signals.c0000644000175000017500000000667213034342512021243 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #include /** * inf_signal_handlers_disconnect_by_func: * @instance: The instance to remove handlers from. * @func: The C closure callback of the handlers (useless for non-C closures). * @data: The closure data of the handlers' closures. * * Disconnects all handlers on an instance that match @func and @data. This is * basically g_signal_handlers_disconnect_by_func(), except that it does not * cause warnings for implicitly converting a function pointer to a void * pointer. * * Returns: The number of handlers that matched. */ guint inf_signal_handlers_disconnect_by_func(gpointer instance, GCallback func, gpointer data) { return g_signal_handlers_disconnect_by_func(instance, *(gpointer*)&func, data); } /** * inf_signal_handlers_block_by_func: * @instance: The instance to block handlers from. * @func: The C closure callback of the handlers (useless for non-C closures). * @data: The closure data of the handlers' closures. * * Blocks all handlers on an instance that match @func and @data. This is * basically g_signal_handlers_block_by_func(), except that it does not * cause warnings for implicitly converting a function pointer to a void * pointer. * * Returns: The number of handlers that matched. */ guint inf_signal_handlers_block_by_func(gpointer instance, GCallback func, gpointer data) { return g_signal_handlers_block_by_func(instance, *(gpointer*)&func, data); } /** * inf_signal_handlers_unblock_by_func: * @instance: The instance to unblock handlers from. * @func: The C closure callback of the handlers (useless for non-C closures). * @data: The closure data of the handlers' closures. * * Unblocks all handlers on an instance that match @func and @data. This is * basically g_signal_handlers_unblock_by_func(), except that it does not * cause warnings for implicitly converting a function pointer to a void * pointer. * * Returns: The number of handlers that matched. */ guint inf_signal_handlers_unblock_by_func(gpointer instance, GCallback func, gpointer data) { return g_signal_handlers_unblock_by_func(instance, *(gpointer*)&func, data); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/PaxHeaders.26529/inf-dll.h0000644000000000000000000000013213034342512017616 xustar0030 mtime=1483851082.041718492 30 atime=1483851082.041718492 30 ctime=1488261588.996139074 libinfinity-0.7.1/libinfinity/inf-dll.h0000644000175000017500000000207313034342512020352 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_DLL_H__ #define __INF_DLL_H__ #include #ifdef G_OS_WIN32 #include extern HMODULE _inf_dll_handle; #endif /* G_OS_WIN32 */ #endif /* __INF_DLL_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/PaxHeaders.26529/communication0000644000000000000000000000013213055210725020713 xustar0030 mtime=1488261589.104138838 30 atime=1488261588.904139275 30 ctime=1488261589.104138838 libinfinity-0.7.1/libinfinity/communication/0000755000175000017500000000000013055210725021522 5ustar00arminarmin00000000000000libinfinity-0.7.1/libinfinity/communication/PaxHeaders.26529/inf-communication-central-factory.c0000644000000000000000000000013013034342512027641 xustar0029 mtime=1483851082.03771847 29 atime=1483851082.03771847 30 ctime=1488261589.092138864 libinfinity-0.7.1/libinfinity/communication/inf-communication-central-factory.c0000644000175000017500000000727413034342512030407 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-communication-central-factory * @title: InfCommunicationCentralFactory * @short_description: Factory for #InfCommunicationCentralMethod methods * @include: libinfinity/communication/inf-communication-central-factory.h * @stability: Unstable * * #InfCommunicationCentralFactory implements #InfCommunicationFactory. It * supports the "central" method on all networks by instantiating * #InfCommunicationCentralMethod. **/ #include #include #include static void inf_communication_central_factory_factory_iface_init(InfCommunicationFactoryInterface* iface); G_DEFINE_TYPE_WITH_CODE(InfCommunicationCentralFactory, inf_communication_central_factory, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE(INF_COMMUNICATION_TYPE_FACTORY, inf_communication_central_factory_factory_iface_init)) static gboolean inf_communication_central_factory_supports_method(InfCommunicationFactory* fc, const gchar* network, const gchar* method_name) { return strcmp(method_name, "central") == 0; } static InfCommunicationMethod* inf_communication_central_factory_instantiate(InfCommunicationFactory* fc, const gchar* network, const gchar* method_name, InfCommunicationRegistry* reg, InfCommunicationGroup* group) { g_assert(strcmp(method_name, "central") == 0); return g_object_new( INF_COMMUNICATION_TYPE_CENTRAL_METHOD, "registry", reg, "group", group, NULL ); } static void inf_communication_central_factory_init( InfCommunicationCentralFactory* factory) { } static void inf_communication_central_factory_class_init( InfCommunicationCentralFactoryClass* factory_class) { } static void inf_communication_central_factory_factory_iface_init( InfCommunicationFactoryInterface* iface) { iface->supports_method = inf_communication_central_factory_supports_method; iface->instantiate = inf_communication_central_factory_instantiate; } /* * Public API */ /** * inf_communication_central_factory_get_default: * * Returns the default #InfCommunicationCentralFactory. * * Returns: (transfer none): A #InfCommunicationCentralFactory. It should not * be unrefed or freed. */ InfCommunicationFactory* inf_communication_central_factory_get_default(void) { /* TODO: Thread safety */ static InfCommunicationFactory* default_central_factory; if(default_central_factory == NULL) { default_central_factory = g_object_new(INF_COMMUNICATION_TYPE_CENTRAL_FACTORY, NULL); } return default_central_factory; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/communication/PaxHeaders.26529/inf-communication-object.c0000644000000000000000000000013113034342512026013 xustar0030 mtime=1483851082.041718492 29 atime=1483851082.03771847 30 ctime=1488261589.104138838 libinfinity-0.7.1/libinfinity/communication/inf-communication-object.c0000644000175000017500000001342013034342512026546 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-communication-object * @title: InfCommunicationObject * @short_description: Network message destinations * @see_also: #InfCommunicationManager * @include: libinfinity/communication/inf-communication-object.h * @stability: Unstable * * A #InfCommunicationObject is the destination of network messages sent * through the #InfCommunicationManager. Each #InfCommunicationGroup is * associated with #InfCommunicationObject. Requests received by that group * are reported to the #InfCommunicationObject by calling * inf_communication_object_received() on it. Messages sent to a member of * that group (via inf_communication_group_send_message()) are also reported * by calling inf_communication_object_sent(). **/ #include #include static const GEnumValue inf_communication_scope_values[] = { { INF_COMMUNICATION_SCOPE_PTP, "INF_COMMUNICATION_SCOPE_PTP", "ptp" }, { INF_COMMUNICATION_SCOPE_GROUP, "INF_COMMUNICATION_SCOPE_GROUP", "group", }, { 0, NULL, NULL } }; INF_DEFINE_ENUM_TYPE(InfCommunicationScope, inf_communication_scope, inf_communication_scope_values) G_DEFINE_INTERFACE(InfCommunicationObject, inf_communication_object, G_TYPE_OBJECT) static void inf_communication_object_default_init(InfCommunicationObjectInterface* iface) { } /** * inf_communication_object_received: * @object: A #InfCommunicationObject. * @conn: The #InfXmlConnection data was received from. * @node: The received data. * * This function is called when a #InfCommunicationManager received data from * @connection belonging to a group whose communication object is @object. * This function should process the incoming data. If it could not process it, * then it should set @error. * * It should return %INF_COMMUNICATION_SCOPE_GROUP if the message is allowed * to be forwarded to other group members. Since recipients of forwarded * messages don't see the original sender (but just the forwarding host), * forwarding arbitrary messages could lead to a security problem in the worst * case. * * For example, if, in central mode, a client sends an (invalid) * <add-node> request to the whole (InfDirectory) group, and the server * forwarded this to all clients, those clients would try to create a new node * although the server rejected the request. In decentral mode, this is not a * problem since all clients see where the message comes from, and can * themselves reject all messages not coming from the server. * * Return Value: %INF_COMMUNICATION_SCOPE_GROUP if the message is allowed to * be forwarded, %INF_COMMUNICATION_SCOPE_PTP if not. **/ InfCommunicationScope inf_communication_object_received(InfCommunicationObject* object, InfXmlConnection* conn, xmlNodePtr node) { InfCommunicationObjectInterface* iface; g_return_val_if_fail(INF_COMMUNICATION_IS_OBJECT(object), FALSE); /* temporarily commented-out: */ /*g_return_val_if_fail(INF_IS_XML_CONNECTION(conn), FALSE);*/ g_return_val_if_fail(node != NULL, FALSE); iface = INF_COMMUNICATION_OBJECT_GET_IFACE(object); if(iface->received != NULL) return (*iface->received)(object, conn, node); return FALSE; } /** * inf_communication_object_enqueued: * @object: A #InfCommunicationObject. * @conn: A #InfXmlConnection. * @node: The XML data. * * This function is called, when an XML message scheduled to be sent via * inf_communication_group_send_message() or * inf_communication_group_send_group_message() cannot be cancelled anymore, * because it was already passed to @conn. **/ void inf_communication_object_enqueued(InfCommunicationObject* object, InfXmlConnection* conn, xmlNodePtr node) { InfCommunicationObjectInterface* iface; g_return_if_fail(INF_COMMUNICATION_IS_OBJECT(object)); g_return_if_fail(INF_IS_XML_CONNECTION(conn)); g_return_if_fail(node != NULL); iface = INF_COMMUNICATION_OBJECT_GET_IFACE(object); if(iface->enqueued != NULL) (*iface->enqueued)(object, conn, node); } /** * inf_communication_object_sent: * @object: A #InfCommunicationObject. * @conn: A #InfXmlConnection. * @node: The sent data. * * This function is called when a XML message sent via * inf_communication_group_send_message() or * inf_communication_group_send_group_message() has actually been sent out. **/ void inf_communication_object_sent(InfCommunicationObject* object, InfXmlConnection* conn, xmlNodePtr node) { InfCommunicationObjectInterface* iface; g_return_if_fail(INF_COMMUNICATION_IS_OBJECT(object)); g_return_if_fail(INF_IS_XML_CONNECTION(conn)); g_return_if_fail(node != NULL); iface = INF_COMMUNICATION_OBJECT_GET_IFACE(object); if(iface->sent != NULL) (*iface->sent)(object, conn, node); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/communication/PaxHeaders.26529/inf-communication-central-factory.h0000644000000000000000000000013013034342512027646 xustar0029 mtime=1483851082.03771847 29 atime=1483851082.03771847 30 ctime=1488261588.976139118 libinfinity-0.7.1/libinfinity/communication/inf-communication-central-factory.h0000644000175000017500000000543413034342512030410 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_COMMUNICATION_CENTRAL_FACTORY_H__ #define __INF_COMMUNICATION_CENTRAL_FACTORY_H__ #include #include G_BEGIN_DECLS #define INF_COMMUNICATION_TYPE_CENTRAL_FACTORY (inf_communication_central_factory_get_type()) #define INF_COMMUNICATION_CENTRAL_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_COMMUNICATION_TYPE_CENTRAL_FACTORY, InfCommunicationCentralFactory)) #define INF_COMMUNICATION_CENTRAL_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INF_COMMUNICATION_TYPE_CENTRAL_FACTORY, InfCommunicationCentralFactoryClass)) #define INF_COMMUNICATION_IS_CENTRAL_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_COMMUNICATION_TYPE_CENTRAL_FACTORY)) #define INF_COMMUNICATION_IS_CENTRAL_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INF_COMMUNICATION_TYPE_CENTRAL_FACTORY)) #define INF_COMMUNICATION_CENTRAL_FACTORY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INF_COMMUNICATION_TYPE_CENTRAL_FACTORY, InfCommunicationCentralFactoryClass)) typedef struct _InfCommunicationCentralFactory InfCommunicationCentralFactory; typedef struct _InfCommunicationCentralFactoryClass InfCommunicationCentralFactoryClass; /** * InfCommunicationCentralFactoryClass: * * This structure does not contain any public fields. */ struct _InfCommunicationCentralFactoryClass { /*< private >*/ GObjectClass parent; }; /** * InfCommunicationCentralFactory: * * #InfCommunicationCentralFactory is an opaque data type. You should only * access it * via the public API functions. */ struct _InfCommunicationCentralFactory { /*< private >*/ GObject parent_instance; }; GType inf_communication_central_factory_get_type(void) G_GNUC_CONST; InfCommunicationFactory* inf_communication_central_factory_get_default(void); G_END_DECLS #endif /* __INF_COMMUNICATION_CENTRAL_FACTORY_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/communication/PaxHeaders.26529/inf-communication-central-method.c0000644000000000000000000000013013034342512027452 xustar0029 mtime=1483851082.03771847 29 atime=1483851082.03771847 30 ctime=1488261589.096138856 libinfinity-0.7.1/libinfinity/communication/inf-communication-central-method.c0000644000175000017500000004464113034342512030217 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-communication-central-method * @title: InfCommunicationCentralMethod * @short_description: Relying group messages via the publisher * @include: libinfinity/communication/inf-communication-central-method.h * @stability: Unstable * * #InfCommunicationCentralMethod implements #InfCommunicationMethod by * relaying all messages via the group's publisher. If the connection to the * publisher is lost, so is the connection to all other group members. **/ #include #include #include #include typedef struct _InfCommunicationCentralMethodPrivate InfCommunicationCentralMethodPrivate; struct _InfCommunicationCentralMethodPrivate { InfCommunicationRegistry* registry; InfCommunicationGroup* group; gboolean is_publisher; /* Whether the local host is publisher of group */ GSList* connections; }; enum { PROP_0, /* construct only */ PROP_REGISTRY, PROP_GROUP }; #define INF_COMMUNICATION_CENTRAL_METHOD_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INF_COMMUNICATION_TYPE_CENTRAL_METHOD, InfCommunicationCentralMethodPrivate)) static void inf_communication_central_method_method_iface_init(InfCommunicationMethodInterface* iface); G_DEFINE_TYPE_WITH_CODE(InfCommunicationCentralMethod, inf_communication_central_method, G_TYPE_OBJECT, G_ADD_PRIVATE(InfCommunicationCentralMethod) G_IMPLEMENT_INTERFACE(INF_COMMUNICATION_TYPE_METHOD, inf_communication_central_method_method_iface_init)) static void inf_communication_central_method_broadcast(InfCommunicationMethod* method, xmlNodePtr xml, InfXmlConnection* except) { InfCommunicationCentralMethodPrivate* priv; InfCommunicationRegistry* registry; InfCommunicationGroup* group; GSList* connections; GSList* item; InfXmlConnection* connection; gboolean is_registered; InfXmlConnectionStatus status; priv = INF_COMMUNICATION_CENTRAL_METHOD_PRIVATE(method); /* Each of the inf_communication_registry_send() calls can do a callback * which might possibly screw up our connection list completely. So be safe * here by copying all relevant information on the stack. */ g_object_ref(method); registry = g_object_ref(priv->registry); group = g_object_ref(priv->group); connections = g_slist_copy(priv->connections); for(item = connections; item != NULL; item = item->next) g_object_ref(item->data); while(connections) { connection = INF_XML_CONNECTION(connections->data); /* A callback from a prior iteration might have unregistered the * connection. */ is_registered = inf_communication_registry_is_registered( registry, group, connection ); /* in case our remove member was not yet called we also check the * status here, i.e. if we are called in response to a handler of the * notify::status signal that ran before ours. */ g_object_get(G_OBJECT(connection), "status", &status, NULL); if(is_registered && status == INF_XML_CONNECTION_OPEN && connection != except) { if(connections->next != NULL) { /* Keep ownership of XML if there might be more connections we should * send it to. */ inf_communication_registry_send( registry, group, connection, xmlCopyNode(xml, 1) ); } else { /* Pass ownership of XML if this is definitely the last connection * in the list. */ inf_communication_registry_send(registry, group, connection, xml); xml = NULL; } } g_object_unref(connection); connections = g_slist_delete_link(connections, connections); } g_object_unref(method); g_object_unref(registry); g_object_unref(group); if(xml != NULL) xmlFreeNode(xml); } static void inf_communication_central_method_notify_status_cb(GObject* object, GParamSpec* pspec, gpointer user_data) { InfCommunicationCentralMethod* method; InfCommunicationCentralMethodPrivate* priv; InfXmlConnectionStatus status; method = INF_COMMUNICATION_CENTRAL_METHOD(user_data); priv = INF_COMMUNICATION_CENTRAL_METHOD_PRIVATE(method); g_object_get(object, "status", &status, NULL); switch(status) { case INF_XML_CONNECTION_CLOSED: case INF_XML_CONNECTION_CLOSING: g_object_ref(priv->group); inf_communication_method_remove_member( INF_COMMUNICATION_METHOD(method), INF_XML_CONNECTION(object) ); g_object_unref(priv->group); break; case INF_XML_CONNECTION_OPENING: break; case INF_XML_CONNECTION_OPEN: inf_communication_registry_register( priv->registry, priv->group, INF_COMMUNICATION_METHOD(method), INF_XML_CONNECTION(object) ); break; default: g_assert_not_reached(); break; } } static void inf_communication_central_method_add_member(InfCommunicationMethod* method, InfXmlConnection* connection) { InfCommunicationCentralMethodPrivate* priv; InfXmlConnectionStatus status; priv = INF_COMMUNICATION_CENTRAL_METHOD_PRIVATE(method); g_object_get(G_OBJECT(connection), "status", &status, NULL); g_assert(status != INF_XML_CONNECTION_CLOSING && status != INF_XML_CONNECTION_CLOSED); priv->connections = g_slist_prepend(priv->connections, connection); g_signal_connect( connection, "notify::status", G_CALLBACK(inf_communication_central_method_notify_status_cb), method ); if(status == INF_XML_CONNECTION_OPEN) { inf_communication_registry_register( priv->registry, priv->group, method, connection ); } } static void inf_communication_central_method_remove_member(InfCommunicationMethod* method, InfXmlConnection* connection) { InfCommunicationCentralMethodPrivate* priv; InfXmlConnectionStatus status; gboolean is_registered; priv = INF_COMMUNICATION_CENTRAL_METHOD_PRIVATE(method); g_object_get(G_OBJECT(connection), "status", &status, NULL); is_registered = inf_communication_registry_is_registered( priv->registry, priv->group, connection ); /* The connection might not be registered if it never was in * INF_XML_CONNECTION_OPEN status, but still is in * INF_XML_CONNECTION_OPENING, or changed from OPENING directly * to CLOSING or CLOSED. */ if(is_registered) { inf_communication_registry_unregister( priv->registry, priv->group, connection ); } inf_signal_handlers_disconnect_by_func( connection, G_CALLBACK(inf_communication_central_method_notify_status_cb), method ); priv->connections = g_slist_remove(priv->connections, connection); } static gboolean inf_communication_central_method_is_member(InfCommunicationMethod* method, InfXmlConnection* connection) { InfCommunicationCentralMethodPrivate* priv; priv = INF_COMMUNICATION_CENTRAL_METHOD_PRIVATE(method); if(g_slist_find(priv->connections, connection) == NULL) return FALSE; return TRUE; } static void inf_communication_central_method_send_single(InfCommunicationMethod* method, InfXmlConnection* connection, xmlNodePtr xml) { InfCommunicationCentralMethodPrivate* priv; priv = INF_COMMUNICATION_CENTRAL_METHOD_PRIVATE(method); inf_communication_registry_send( priv->registry, priv->group, connection, xml ); } static void inf_communication_central_method_send_all(InfCommunicationMethod* method, xmlNodePtr xml) { inf_communication_central_method_broadcast(method, xml, NULL); } static void inf_communication_central_method_cancel_messages(InfCommunicationMethod* meth, InfXmlConnection* connection) { InfCommunicationCentralMethodPrivate* priv; priv = INF_COMMUNICATION_CENTRAL_METHOD_PRIVATE(meth); inf_communication_registry_cancel_messages( priv->registry, priv->group, connection ); } static InfCommunicationScope inf_communication_central_method_received(InfCommunicationMethod* method, InfXmlConnection* connection, xmlNodePtr xml) { InfCommunicationCentralMethodPrivate* priv; InfCommunicationObject* target; InfCommunicationGroup* group; InfCommunicationScope scope; gchar* remote_id; gchar* publisher_id; GSList* item; priv = INF_COMMUNICATION_CENTRAL_METHOD_PRIVATE(method); target = inf_communication_group_get_target(priv->group); group = priv->group; if(target != NULL) { /* Make sure we stay alive, so we can check our connection list and * publisher flag after the callback. This means we also need to keep * group and target alive, to ensure the correct deinitialization order */ g_object_ref(target); g_object_ref(group); g_object_ref(method); scope = inf_communication_object_received( target, connection, xml ); if(priv->is_publisher && scope == INF_COMMUNICATION_SCOPE_GROUP) { inf_communication_central_method_broadcast( method, xmlCopyNode(xml, 1), connection ); } g_object_unref(method); g_object_unref(group); g_object_unref(target); return scope; } else { /* Without target we don't know what to do with the message, so better * don't relay. */ return INF_COMMUNICATION_SCOPE_PTP; } } static void inf_communication_central_method_enqueued(InfCommunicationMethod* method, InfXmlConnection* connection, xmlNodePtr xml) { InfCommunicationCentralMethodPrivate* priv; InfCommunicationObject* target; priv = INF_COMMUNICATION_CENTRAL_METHOD_PRIVATE(method); target = inf_communication_group_get_target(priv->group); if(target != NULL) inf_communication_object_enqueued(target, connection, xml); } static void inf_communication_central_method_sent(InfCommunicationMethod* method, InfXmlConnection* connection, xmlNodePtr xml) { InfCommunicationCentralMethodPrivate* priv; InfCommunicationObject* target; priv = INF_COMMUNICATION_CENTRAL_METHOD_PRIVATE(method); target = inf_communication_group_get_target(priv->group); if(target != NULL) inf_communication_object_sent(target, connection, xml); } /* Weakref handling. Both group and registry should never be unrefed before * the method is unrefed, but this can help debugging in case one of * them is. */ static void inf_communication_central_method_registry_unrefed(gpointer data, GObject* object) { InfCommunicationCentralMethod* method; InfCommunicationCentralMethodPrivate* priv; method = INF_COMMUNICATION_CENTRAL_METHOD(data); priv = INF_COMMUNICATION_CENTRAL_METHOD_PRIVATE(method); g_warning("A method's registry was unrefed before the method was unrefed"); priv->registry = NULL; } static void inf_communication_central_method_group_unrefed(gpointer data, GObject* where_the_object_was) { InfCommunicationCentralMethod* method; InfCommunicationCentralMethodPrivate* priv; method = INF_COMMUNICATION_CENTRAL_METHOD(data); priv = INF_COMMUNICATION_CENTRAL_METHOD_PRIVATE(method); g_warning("A method's group was unrefed before the method was unrefed"); priv->group = NULL; } static void inf_communication_central_method_set_registry(InfCommunicationCentralMethod* m, InfCommunicationRegistry* reg) { InfCommunicationCentralMethodPrivate* priv; priv = INF_COMMUNICATION_CENTRAL_METHOD_PRIVATE(m); if(priv->registry != NULL) { g_object_weak_unref( G_OBJECT(priv->registry), inf_communication_central_method_registry_unrefed, m ); } priv->registry = reg; if(reg != NULL) { g_object_weak_ref( G_OBJECT(reg), inf_communication_central_method_registry_unrefed, m ); } g_object_notify(G_OBJECT(m), "registry"); } static void inf_communication_central_method_set_group(InfCommunicationCentralMethod* m, InfCommunicationGroup* group) { InfCommunicationCentralMethodPrivate* priv; priv = INF_COMMUNICATION_CENTRAL_METHOD_PRIVATE(m); if(priv->group != NULL) { g_object_weak_unref( G_OBJECT(priv->group), inf_communication_central_method_group_unrefed, m ); priv->is_publisher = FALSE; } priv->group = group; if(group != NULL) { g_object_weak_ref( G_OBJECT(group), inf_communication_central_method_group_unrefed, m ); if(INF_COMMUNICATION_IS_HOSTED_GROUP(group)) priv->is_publisher = TRUE; else priv->is_publisher = FALSE; } g_object_notify(G_OBJECT(m), "group"); } /* * GObject overrides. */ static void inf_communication_central_method_init(InfCommunicationCentralMethod* method) { InfCommunicationCentralMethodPrivate* priv; priv = INF_COMMUNICATION_CENTRAL_METHOD_PRIVATE(method); priv->group = NULL; priv->registry = NULL; priv->is_publisher = FALSE; priv->connections = NULL; } static void inf_communication_central_method_dispose(GObject* object) { InfCommunicationCentralMethod* method; InfCommunicationCentralMethodPrivate* priv; method = INF_COMMUNICATION_CENTRAL_METHOD(object); priv = INF_COMMUNICATION_CENTRAL_METHOD_PRIVATE(method); while(priv->connections != NULL) { inf_communication_method_remove_member( INF_COMMUNICATION_METHOD(method), INF_XML_CONNECTION(priv->connections->data) ); } inf_communication_central_method_set_group(method, NULL); inf_communication_central_method_set_registry(method, NULL); G_OBJECT_CLASS(inf_communication_central_method_parent_class)->dispose(object); } static void inf_communication_central_method_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfCommunicationCentralMethod* method; InfCommunicationCentralMethodPrivate* priv; method = INF_COMMUNICATION_CENTRAL_METHOD(object); priv = INF_COMMUNICATION_CENTRAL_METHOD_PRIVATE(method); switch(prop_id) { case PROP_REGISTRY: g_assert(priv->registry == NULL); /* construct only */ inf_communication_central_method_set_registry( method, INF_COMMUNICATION_REGISTRY(g_value_get_object(value)) ); break; case PROP_GROUP: g_assert(priv->group == NULL); /* construct only */ inf_communication_central_method_set_group( method, INF_COMMUNICATION_GROUP(g_value_get_object(value)) ); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void inf_communication_central_method_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfCommunicationCentralMethod* method; InfCommunicationCentralMethodPrivate* priv; method = INF_COMMUNICATION_CENTRAL_METHOD(object); priv = INF_COMMUNICATION_CENTRAL_METHOD_PRIVATE(method); switch(prop_id) { case PROP_REGISTRY: g_value_set_object(value, priv->registry); break; case PROP_GROUP: g_value_set_object(value, priv->group); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } /* * GType registration. */ static void inf_communication_central_method_class_init( InfCommunicationCentralMethodClass* method_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(method_class); object_class->dispose = inf_communication_central_method_dispose; object_class->set_property = inf_communication_central_method_set_property; object_class->get_property = inf_communication_central_method_get_property; g_object_class_install_property( object_class, PROP_REGISTRY, g_param_spec_object( "registry", "Registry", "The communication registry to register connections with", INF_COMMUNICATION_TYPE_REGISTRY, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_GROUP, g_param_spec_object( "group", "Group", "The communication group for which to handle messages", INF_COMMUNICATION_TYPE_GROUP, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); } static void inf_communication_central_method_method_iface_init( InfCommunicationMethodInterface* iface) { iface->add_member = inf_communication_central_method_add_member; iface->remove_member = inf_communication_central_method_remove_member; iface->is_member = inf_communication_central_method_is_member; iface->send_single = inf_communication_central_method_send_single; iface->send_all = inf_communication_central_method_send_all; iface->cancel_messages = inf_communication_central_method_cancel_messages; iface->received = inf_communication_central_method_received; iface->enqueued = inf_communication_central_method_enqueued; iface->sent = inf_communication_central_method_sent; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/communication/PaxHeaders.26529/inf-communication-hosted-group.h0000644000000000000000000000013013034342512027171 xustar0029 mtime=1483851082.03771847 29 atime=1483851082.03771847 30 ctime=1488261588.980139109 libinfinity-0.7.1/libinfinity/communication/inf-communication-hosted-group.h0000644000175000017500000000614313034342512027731 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_COMMUNICATION_HOSTED_GROUP_H__ #define __INF_COMMUNICATION_HOSTED_GROUP_H__ #include #include G_BEGIN_DECLS #define INF_COMMUNICATION_TYPE_HOSTED_GROUP (inf_communication_hosted_group_get_type()) #define INF_COMMUNICATION_HOSTED_GROUP(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_COMMUNICATION_TYPE_HOSTED_GROUP, InfCommunicationHostedGroup)) #define INF_COMMUNICATION_HOSTED_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INF_COMMUNICATION_TYPE_HOSTED_GROUP, InfCommunicationHostedGroupClass)) #define INF_COMMUNICATION_IS_HOSTED_GROUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_COMMUNICATION_TYPE_HOSTED_GROUP)) #define INF_COMMUNICATION_IS_HOSTED_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INF_COMMUNICATION_TYPE_HOSTED_GROUP)) #define INF_COMMUNICATION_HOSTED_GROUP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INF_COMMUNICATION_TYPE_HOSTED_GROUP, InfCommunicationHostedGroupClass)) typedef struct _InfCommunicationHostedGroup InfCommunicationHostedGroup; typedef struct _InfCommunicationHostedGroupClass InfCommunicationHostedGroupClass; /** * InfCommunicationHostedGroupClass: * * This structure does not contain any public fields. */ struct _InfCommunicationHostedGroupClass { /*< private >*/ InfCommunicationGroupClass parent; }; /** * InfCommunicationHostedGroup: * * #InfCommunicationHostedGroup is an opaque data type. You should only * access it via the public API functions. */ struct _InfCommunicationHostedGroup { /*< private >*/ InfCommunicationGroup parent_instance; }; GType inf_communication_hosted_group_get_type(void) G_GNUC_CONST; void inf_communication_hosted_group_add_method(InfCommunicationHostedGroup* group, const gchar* method); void inf_communication_hosted_group_add_member(InfCommunicationHostedGroup* group, InfXmlConnection* connection); void inf_communication_hosted_group_remove_member(InfCommunicationHostedGroup* grp, InfXmlConnection* connection); G_END_DECLS #endif /* __INF_COMMUNICATION_HOSTED_GROUP_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/communication/PaxHeaders.26529/inf-communication-joined-group.h0000644000000000000000000000013013034342512027153 xustar0029 mtime=1483851082.03771847 29 atime=1483851082.03771847 30 ctime=1488261588.980139109 libinfinity-0.7.1/libinfinity/communication/inf-communication-joined-group.h0000644000175000017500000000562313034342512027715 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_COMMUNICATION_JOINED_GROUP_H__ #define __INF_COMMUNICATION_JOINED_GROUP_H__ #include #include G_BEGIN_DECLS #define INF_COMMUNICATION_TYPE_JOINED_GROUP (inf_communication_joined_group_get_type()) #define INF_COMMUNICATION_JOINED_GROUP(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_COMMUNICATION_TYPE_JOINED_GROUP, InfCommunicationJoinedGroup)) #define INF_COMMUNICATION_JOINED_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INF_COMMUNICATION_TYPE_JOINED_GROUP, InfCommunicationJoinedGroupClass)) #define INF_COMMUNICATION_IS_JOINED_GROUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_COMMUNICATION_TYPE_JOINED_GROUP)) #define INF_COMMUNICATION_IS_JOINED_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INF_COMMUNICATION_TYPE_JOINED_GROUP)) #define INF_COMMUNICATION_JOINED_GROUP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INF_COMMUNICATION_TYPE_JOINED_GROUP, InfCommunicationJoinedGroupClass)) typedef struct _InfCommunicationJoinedGroup InfCommunicationJoinedGroup; typedef struct _InfCommunicationJoinedGroupClass InfCommunicationJoinedGroupClass; /** * InfCommunicationJoinedGroupClass: * * This structure does not contain any public fields. */ struct _InfCommunicationJoinedGroupClass { /*< private >*/ InfCommunicationGroupClass parent; }; /** * InfCommunicationJoinedGroup: * * #InfCommunicationJoinedGroup is an opaque data type. You should only * access it via the public API functions. */ struct _InfCommunicationJoinedGroup { /*< private >*/ InfCommunicationGroup parent_instance; }; GType inf_communication_joined_group_get_type(void) G_GNUC_CONST; void inf_communication_joined_group_remove_member(InfCommunicationJoinedGroup* grp, InfXmlConnection* connection); InfXmlConnection* inf_communication_joined_group_get_publisher(InfCommunicationJoinedGroup* g); G_END_DECLS #endif /* __INF_COMMUNICATION_JOINED_GROUP_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/communication/PaxHeaders.26529/inf-communication-group.h0000644000000000000000000000013013034342512025705 xustar0029 mtime=1483851082.03771847 29 atime=1483851082.03771847 30 ctime=1488261588.980139109 libinfinity-0.7.1/libinfinity/communication/inf-communication-group.h0000644000175000017500000001155613034342512026451 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_COMMUNICATION_GROUP_H__ #define __INF_COMMUNICATION_GROUP_H__ #include #include #include #include G_BEGIN_DECLS #define INF_COMMUNICATION_TYPE_GROUP (inf_communication_group_get_type()) #define INF_COMMUNICATION_GROUP(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_COMMUNICATION_TYPE_GROUP, InfCommunicationGroup)) #define INF_COMMUNICATION_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INF_COMMUNICATION_TYPE_GROUP, InfCommunicationGroupClass)) #define INF_COMMUNICATION_IS_GROUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_COMMUNICATION_TYPE_GROUP)) #define INF_COMMUNICATION_IS_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INF_COMMUNICATION_TYPE_GROUP)) #define INF_COMMUNICATION_GROUP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INF_COMMUNICATION_TYPE_GROUP, InfCommunicationGroupClass)) typedef struct _InfCommunicationGroup InfCommunicationGroup; typedef struct _InfCommunicationGroupClass InfCommunicationGroupClass; /** * InfCommunicationGroupClass: * @member_added: Default signal handler of the * #InfCommunicationGroup::member-added signal. * @member_removed: Default signal handler of the * #InfCommunicationGroup::member-removed signal. * @get_method: Virtual function to determine the methods to use for the * group, in order of priority. * @get_publisher_id: Virtual function to obtain the ID of the publishing * host of this group. * * The virtual methods and default signal handlers of #InfCommunicationGroup. */ struct _InfCommunicationGroupClass { /*< private >*/ GObjectClass parent; /*< public >*/ /* Signals */ void (*member_added)(InfCommunicationGroup* group, InfXmlConnection* connection); void (*member_removed)(InfCommunicationGroup* group, InfXmlConnection* connection); /* Virtual functions */ /* TODO: Should this be const gchar* const* get_methods? */ const gchar* (*get_method)(InfCommunicationGroup* group, unsigned int index); gchar* (*get_publisher_id)(InfCommunicationGroup* group, InfXmlConnection* for_connection); }; /** * InfCommunicationGroup: * * #InfCommunicationGroup is an opaque data type. You should only access it * via the public API functions. */ struct _InfCommunicationGroup { /*< private >*/ GObject parent_instance; }; GType inf_communication_group_get_type(void) G_GNUC_CONST; const gchar* inf_communication_group_get_name(InfCommunicationGroup* group); InfCommunicationObject* inf_communication_group_get_target(InfCommunicationGroup* group); void inf_communication_group_set_target(InfCommunicationGroup* group, InfCommunicationObject* target); gboolean inf_communication_group_is_member(InfCommunicationGroup* group, InfXmlConnection* connection); void inf_communication_group_send_message(InfCommunicationGroup* group, InfXmlConnection* connection, xmlNodePtr xml); void inf_communication_group_send_group_message(InfCommunicationGroup* group, xmlNodePtr xml); void inf_communication_group_cancel_messages(InfCommunicationGroup* group, InfXmlConnection* connection); const gchar* inf_communication_group_get_method_for_network(InfCommunicationGroup* group, const gchar* network); const gchar* inf_communication_group_get_method_for_connection(InfCommunicationGroup* grp, InfXmlConnection* conn); gchar* inf_communication_group_get_publisher_id(InfCommunicationGroup* group, InfXmlConnection* for_connection); G_END_DECLS #endif /* __INF_COMMUNICATION_GROUP_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/communication/PaxHeaders.26529/inf-communication-method.h0000644000000000000000000000012613034342512026036 xustar0029 mtime=1483851082.03771847 29 atime=1483851082.03771847 28 ctime=1488261588.9841391 libinfinity-0.7.1/libinfinity/communication/inf-communication-method.h0000644000175000017500000001344313034342512026572 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_COMMUNICATION_METHOD_H__ #define __INF_COMMUNICATION_METHOD_H__ #include #include #include #include G_BEGIN_DECLS #define INF_COMMUNICATION_TYPE_METHOD (inf_communication_method_get_type()) #define INF_COMMUNICATION_METHOD(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_COMMUNICATION_TYPE_METHOD, InfCommunicationMethod)) #define INF_COMMUNICATION_IS_METHOD(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_COMMUNICATION_TYPE_METHOD)) #define INF_COMMUNICATION_METHOD_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), INF_COMMUNICATION_TYPE_METHOD, InfCommunicationMethodInterface)) /** * InfCommunicationMethod: * * #InfCommunicationMethod is an opaque data type. You should only access it * via the public API functions. */ typedef struct _InfCommunicationMethod InfCommunicationMethod; typedef struct _InfCommunicationMethodInterface InfCommunicationMethodInterface; /** * InfCommunicationMethodInterface: * @add_member: Default signal handler of the * #InfCommunicationMethod::add-member signal. * @remove_member: Default signal handler of the * #InfCommunicationMethod::remove-member signal. * @is_member: Returns whether the given connection is a member of the group. * @send_single: Sends a message to a single connection. Takes ownership of * @xml. * @send_all: Sends a message to all group members, except @except. Takes * ownership of @xml. * @cancel_messages: Cancel sending messages that have not yet been sent * to the given connection. * @received: Handles reception of a message from a registered connection. * This normally includes informing a group's NetObject and forwarding the * message to other group members. * @enqueued: Handles when a message has been enqueued to be sent on a * registered connection. * @sent: Handles when a message has been sent to a registered connection. * * The default signal handlers of virtual methods of #InfCommunicationMethod. * These implement communication within a #InfCommunicationGroup. */ struct _InfCommunicationMethodInterface { /*< private >*/ GTypeInterface parent; /*< public >*/ /* Signals */ void (*add_member)(InfCommunicationMethod* method, InfXmlConnection* connection); void (*remove_member)(InfCommunicationMethod* method, InfXmlConnection* connection); /* Virtual functions */ gboolean (*is_member)(InfCommunicationMethod* method, InfXmlConnection* connection); void (*send_single)(InfCommunicationMethod* method, InfXmlConnection* connection, xmlNodePtr xml); void (*send_all)(InfCommunicationMethod* method, xmlNodePtr xml); void (*cancel_messages)(InfCommunicationMethod* method, InfXmlConnection* connection); InfCommunicationScope (*received)(InfCommunicationMethod* method, InfXmlConnection* connection, xmlNodePtr xml); void (*enqueued)(InfCommunicationMethod* method, InfXmlConnection* connection, xmlNodePtr xml); void (*sent)(InfCommunicationMethod* method, InfXmlConnection* connection, xmlNodePtr xml); }; GType inf_communication_method_get_type(void) G_GNUC_CONST; void inf_communication_method_add_member(InfCommunicationMethod* method, InfXmlConnection* connection); void inf_communication_method_remove_member(InfCommunicationMethod* method, InfXmlConnection* connection); gboolean inf_communication_method_is_member(InfCommunicationMethod* method, InfXmlConnection* connection); void inf_communication_method_send_single(InfCommunicationMethod* method, InfXmlConnection* connection, xmlNodePtr xml); void inf_communication_method_send_all(InfCommunicationMethod* method, xmlNodePtr xml); void inf_communication_method_cancel_messages(InfCommunicationMethod* method, InfXmlConnection* connection); InfCommunicationScope inf_communication_method_received(InfCommunicationMethod* method, InfXmlConnection* connection, xmlNodePtr xml); void inf_communication_method_enqueued(InfCommunicationMethod* method, InfXmlConnection* connection, xmlNodePtr xml); void inf_communication_method_sent(InfCommunicationMethod* method, InfXmlConnection* connection, xmlNodePtr xml); G_END_DECLS #endif /* __INF_COMMUNICATION_METHOD_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/communication/PaxHeaders.26529/inf-communication-manager.h0000644000000000000000000000012613034342512026170 xustar0029 mtime=1483851082.03771847 29 atime=1483851082.03771847 28 ctime=1488261588.9841391 libinfinity-0.7.1/libinfinity/communication/inf-communication-manager.h0000644000175000017500000000723413034342512026725 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_COMMUNICATION_MANAGER_H__ #define __INF_COMMUNICATION_MANAGER_H__ #include #include #include #include G_BEGIN_DECLS #define INF_COMMUNICATION_TYPE_MANAGER (inf_communication_manager_get_type()) #define INF_COMMUNICATION_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_COMMUNICATION_TYPE_MANAGER, InfCommunicationManager)) #define INF_COMMUNICATION_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INF_COMMUNICATION_TYPE_MANAGER, InfCommunicationManagerClass)) #define INF_COMMUNICATION_IS_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_COMMUNICATION_TYPE_MANAGER)) #define INF_COMMUNICATION_IS_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INF_COMMUNICATION_TYPE_MANAGER)) #define INF_COMMUNICATION_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INF_COMMUNICATION_TYPE_MANAGER, InfCommunicationManagerClass)) typedef struct _InfCommunicationManager InfCommunicationManager; typedef struct _InfCommunicationManagerClass InfCommunicationManagerClass; /** * InfCommunicationManagerClass: * * This structure does not contain any public fields. */ struct _InfCommunicationManagerClass { /*< private >*/ GObjectClass parent; }; /** * InfCommunicationManager: * * #InfCommunicationManager is an opaque data type. You should only access it * via the public API functions. */ struct _InfCommunicationManager { /*< private >*/ GObject parent_instance; }; GType inf_communication_manager_get_type(void) G_GNUC_CONST; InfCommunicationManager* inf_communication_manager_new(void); InfCommunicationHostedGroup* inf_communication_manager_open_group(InfCommunicationManager* manager, const gchar* group_name, /* methods[0] primary, others fallback */ const gchar* const* methods); InfCommunicationJoinedGroup* inf_communication_manager_join_group(InfCommunicationManager* manager, const gchar* group_name, InfXmlConnection* publisher_conn, const gchar* method); void inf_communication_manager_add_factory(InfCommunicationManager* manager, InfCommunicationFactory* factory); InfCommunicationFactory* inf_communication_manager_get_factory_for(InfCommunicationManager* manager, const gchar* network, const gchar* method_name); G_END_DECLS #endif /* __INF_COMMUNICATION_MANAGER_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/communication/PaxHeaders.26529/inf-communication-factory.h0000644000000000000000000000013013034342512026220 xustar0029 mtime=1483851082.03771847 29 atime=1483851082.03771847 30 ctime=1488261588.976139118 libinfinity-0.7.1/libinfinity/communication/inf-communication-factory.h0000644000175000017500000000724013034342512026757 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_COMMUNICATION_FACTORY_H__ #define __INF_COMMUNICATION_FACTORY_H__ #include #include #include G_BEGIN_DECLS #define INF_COMMUNICATION_TYPE_FACTORY (inf_communication_factory_get_type()) #define INF_COMMUNICATION_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_COMMUNICATION_TYPE_FACTORY, InfCommunicationFactory)) #define INF_COMMUNICATION_IS_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_COMMUNICATION_TYPE_FACTORY)) #define INF_COMMUNICATION_FACTORY_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), INF_COMMUNICATION_TYPE_FACTORY, InfCommunicationFactoryInterface)) /** * InfCommunicationFactory: * * #InfCommunicationFactory is an opaque data type. You should only access it * via the public API functions. */ typedef struct _InfCommunicationFactory InfCommunicationFactory; typedef struct _InfCommunicationFactoryInterface InfCommunicationFactoryInterface; /** * InfCommunicationFactoryInterface: * @supports_method: Returns whether the given method_name is supported for * the network in question by the factory. * @instantiate: Instantiates a communication method for the given method * name, handling communication for the passed group. * * The virtual methods of #InfCommunicationFactory. These handle instantiating * a #InfCommunicationMethod for a #InfCommunicationGroup. */ struct _InfCommunicationFactoryInterface { /*< private >*/ GTypeInterface parent; /*< public >*/ gboolean (*supports_method)(InfCommunicationFactory* factory, const gchar* network, const gchar* method_name); InfCommunicationMethod* (*instantiate)(InfCommunicationFactory* factory, const gchar* network, const gchar* method_name, InfCommunicationRegistry* registry, InfCommunicationGroup* group); }; GType inf_communication_factory_get_type(void) G_GNUC_CONST; gboolean inf_communication_factory_supports_method(InfCommunicationFactory* factory, const gchar* network, const gchar* method_name); InfCommunicationMethod* inf_communication_factory_instantiate(InfCommunicationFactory* factory, const gchar* network, const gchar* method_name, InfCommunicationRegistry* registry, InfCommunicationGroup* group); G_END_DECLS #endif /* __INF_COMMUNICATION_FACTORY_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/communication/PaxHeaders.26529/inf-communication-hosted-group.c0000644000000000000000000000013013034342512027164 xustar0029 mtime=1483851082.03771847 29 atime=1483851082.03771847 30 ctime=1488261589.100138847 libinfinity-0.7.1/libinfinity/communication/inf-communication-hosted-group.c0000644000175000017500000001577213034342512027734 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-communication-hosted-group * @title: InfCommunicationHostedGroup * @short_description: Communication group opened by the local host * @include: libinfinity/communication/inf-communication-hosted-group.h * @stability: Unstable * @see_also: #InfCommunicationGroup, #InfCommunicationManager * * #InfCommunicationHostedGroup is a #InfCommunicationHostedGroup opened on * the local host. It allows adding other hosts to the group via * inf_communication_hosted_group_add_member(), and to remove hosts via * inf_communication_hosted_group_remove_member(). **/ #include #include typedef struct _InfCommunicationHostedGroupPrivate InfCommunicationHostedGroupPrivate; struct _InfCommunicationHostedGroupPrivate { GPtrArray* methods; }; #define INF_COMMUNICATION_HOSTED_GROUP_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INF_COMMUNICATION_TYPE_HOSTED_GROUP, InfCommunicationHostedGroupPrivate)) G_DEFINE_TYPE_WITH_CODE(InfCommunicationHostedGroup, inf_communication_hosted_group, INF_COMMUNICATION_TYPE_GROUP, G_ADD_PRIVATE(InfCommunicationHostedGroup)) static const gchar* inf_communication_hosted_group_get_method(InfCommunicationGroup* group, unsigned int index) { InfCommunicationHostedGroup* hosted_group; InfCommunicationHostedGroupPrivate* priv; hosted_group = INF_COMMUNICATION_HOSTED_GROUP(group); priv = INF_COMMUNICATION_HOSTED_GROUP_PRIVATE(hosted_group); if(index < priv->methods->len) return g_ptr_array_index(priv->methods, index); /* fallback to central method */ if(index == priv->methods->len) return "central"; return NULL; } static gchar* inf_communication_hosted_group_get_publisher_id(InfCommunicationGroup* group, InfXmlConnection* for_conn) { gchar* local_id; g_object_get(G_OBJECT(for_conn), "local-id", &local_id, NULL); return local_id; } /* * GObject overrides. */ static void inf_communication_hosted_group_init(InfCommunicationHostedGroup* group) { InfCommunicationHostedGroupPrivate* priv; priv = INF_COMMUNICATION_HOSTED_GROUP_PRIVATE(group); priv->methods = g_ptr_array_new(); } static void inf_communication_hosted_group_finalize(GObject* object) { InfCommunicationHostedGroup* group; InfCommunicationHostedGroupPrivate* priv; guint i; group = INF_COMMUNICATION_HOSTED_GROUP(object); priv = INF_COMMUNICATION_HOSTED_GROUP_PRIVATE(group); for(i = 0; i < priv->methods->len; ++ i) g_free(g_ptr_array_index(priv->methods, i)); g_ptr_array_free(priv->methods, TRUE); G_OBJECT_CLASS(inf_communication_hosted_group_parent_class)->finalize(object); } /* * GType registration. */ static void inf_communication_hosted_group_class_init( InfCommunicationHostedGroupClass* hosted_group_class) { GObjectClass* object_class; InfCommunicationGroupClass* group_class; object_class = G_OBJECT_CLASS(hosted_group_class); group_class = INF_COMMUNICATION_GROUP_CLASS(hosted_group_class); object_class->finalize = inf_communication_hosted_group_finalize; group_class->get_method = inf_communication_hosted_group_get_method; group_class->get_publisher_id = inf_communication_hosted_group_get_publisher_id; } /* * Public API. */ /** * inf_communication_hosted_group_add_method: * @group: A #InfCommunicationHostedGroup. * @method: The method name to add. * * Adds a method to the hosted group. When a connection from a given network * is added to the group the first time, a #InfCommunicationMethod is * instantiated to handle messaging for the group within this network. * The first method added will be tried first. If the communication manager * does support it (meaning inf_communication_manager_get_factory_for() for * the connection's network and the chosen method returns non-%NULL), then it * will be used, otherwise the next method will be tried, etc. If no method * is supported, or no methods are added to the group, then the "central" * method will be used as a fallback. */ void inf_communication_hosted_group_add_method(InfCommunicationHostedGroup* group, const gchar* method) { InfCommunicationHostedGroupPrivate* priv; g_return_if_fail(INF_COMMUNICATION_IS_HOSTED_GROUP(group)); g_return_if_fail(method != NULL); priv = INF_COMMUNICATION_HOSTED_GROUP_PRIVATE(group); g_ptr_array_add(priv->methods, g_strdup(method)); } /** * inf_communication_hosted_group_add_member: * @group: A #InfCommunicationGroup. * @connection: A #InfXmlConnection to add to group. * * Adds @connection as a member to @group. On the remote site, a * #InfCommunicationJoinedGroup with the same name and method used for * @connection (see inf_communication_group_get_method_for_connection()) * needs to be created for successful communication. */ void inf_communication_hosted_group_add_member(InfCommunicationHostedGroup* group, InfXmlConnection* connection) { g_return_if_fail(INF_COMMUNICATION_IS_HOSTED_GROUP(group)); g_return_if_fail(INF_IS_XML_CONNECTION(connection)); g_return_if_fail( !inf_communication_group_is_member( INF_COMMUNICATION_GROUP(group), connection ) ); _inf_communication_group_add_member( INF_COMMUNICATION_GROUP(group), connection ); } /** * inf_communication_hosted_group_remove_member: * @grp: A #InfCommunicationGroup. * @connection: The @InfXmlConnection to remove from the group. * * Removes @connection's membership from @group. On the remote site, the * corresponding #InfCommunicationJoinedGroup needs to be freed. */ void inf_communication_hosted_group_remove_member(InfCommunicationHostedGroup* grp, InfXmlConnection* connection) { g_return_if_fail(INF_COMMUNICATION_IS_HOSTED_GROUP(grp)); g_return_if_fail(INF_IS_XML_CONNECTION(connection)); g_return_if_fail( inf_communication_group_is_member( INF_COMMUNICATION_GROUP(grp), connection ) ); _inf_communication_group_remove_member( INF_COMMUNICATION_GROUP(grp), connection ); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/communication/PaxHeaders.26529/inf-communication-group-private.h0000644000000000000000000000013013034342512027355 xustar0029 mtime=1483851082.03771847 29 atime=1483851082.03771847 30 ctime=1488261588.992139083 libinfinity-0.7.1/libinfinity/communication/inf-communication-group-private.h0000644000175000017500000000342513034342512030115 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_COMMUNICATION_GROUP_PRIVATE_H__ #define __INF_COMMUNICATION_GROUP_PRIVATE_H__ #include #include typedef void(*InfCommunicationGroupForeachFunc)(InfCommunicationMethod* meth, gpointer user_data); void _inf_communication_group_add_member(InfCommunicationGroup* group, InfXmlConnection* connection); void _inf_communication_group_remove_member(InfCommunicationGroup* group, InfXmlConnection* connection); void _inf_communication_group_foreach_method(InfCommunicationGroup* group, InfCommunicationGroupForeachFunc func, gpointer user_data); #endif /* __INF_COMMUNICATION_GROUP_PRIVATE_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/communication/PaxHeaders.26529/inf-communication-central-method.h0000644000000000000000000000013013034342512027457 xustar0029 mtime=1483851082.03771847 29 atime=1483851082.03771847 30 ctime=1488261588.976139118 libinfinity-0.7.1/libinfinity/communication/inf-communication-central-method.h0000644000175000017500000000515713034342512030223 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_COMMUNICATION_CENTRAL_METHOD_H__ #define __INF_COMMUNICATION_CENTRAL_METHOD_H__ #include G_BEGIN_DECLS #define INF_COMMUNICATION_TYPE_CENTRAL_METHOD (inf_communication_central_method_get_type()) #define INF_COMMUNICATION_CENTRAL_METHOD(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_COMMUNICATION_TYPE_CENTRAL_METHOD, InfCommunicationCentralMethod)) #define INF_COMMUNICATION_CENTRAL_METHOD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INF_COMMUNICATION_TYPE_CENTRAL_METHOD, InfCommunicationCentralMethodClass)) #define INF_COMMUNICATION_IS_CENTRAL_METHOD(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_COMMUNICATION_TYPE_CENTRAL_METHOD)) #define INF_COMMUNICATION_IS_CENTRAL_METHOD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INF_COMMUNICATION_TYPE_CENTRAL_METHOD)) #define INF_COMMUNICATION_CENTRAL_METHOD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INF_COMMUNICATION_TYPE_CENTRAL_METHOD, InfCommunicationCentralMethodClass)) typedef struct _InfCommunicationCentralMethod InfCommunicationCentralMethod; typedef struct _InfCommunicationCentralMethodClass InfCommunicationCentralMethodClass; /** * InfCommunicationCentralMethodClass: * * This structure does not contain any public fields. */ struct _InfCommunicationCentralMethodClass { /*< private >*/ GObjectClass parent; }; /** * InfCommunicationCentralMethod: * * #InfCommunicationCentralMethod is an opaque data type. You should only * access it * via the public API functions. */ struct _InfCommunicationCentralMethod { /*< private >*/ GObject parent_instance; }; GType inf_communication_central_method_get_type(void) G_GNUC_CONST; G_END_DECLS #endif /* __INF_COMMUNICATION_CENTRAL_METHOD_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/communication/PaxHeaders.26529/inf-communication-joined-group.c0000644000000000000000000000013013034342512027146 xustar0029 mtime=1483851082.03771847 29 atime=1483851082.03771847 30 ctime=1488261589.100138847 libinfinity-0.7.1/libinfinity/communication/inf-communication-joined-group.c0000644000175000017500000002566613034342512027721 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-communication-joined-group * @title: InfCommunicationJoinedGroup * @short_description: Communication group opened by a remote host * @include: libinfinity/communication/inf-communication-joined-group.h * @stability: Unstable * @see_also: #InfCommunicationGroup, #InfCommunicationManager * * #InfCommunicationJoinedGroup represents membership of the local host on a * #InfCommunicationGroup opened on a remote host. * * There is no API to add a member to a joined group. This is because new * members can only join via the group's publisher. It is the job of the * #InfCommunicationMethod to tell the joined group about the new member in * which case, the #InfCommunicationGroup::member-added signal will be * emitted. **/ #include #include #include typedef struct _InfCommunicationJoinedGroupPrivate InfCommunicationJoinedGroupPrivate; struct _InfCommunicationJoinedGroupPrivate { InfXmlConnection* publisher_conn; gchar* publisher_id; gchar* method; }; enum { PROP_0, PROP_PUBLISHER, PROP_METHOD }; #define INF_COMMUNICATION_JOINED_GROUP_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INF_COMMUNICATION_TYPE_JOINED_GROUP, InfCommunicationJoinedGroupPrivate)) G_DEFINE_TYPE_WITH_CODE(InfCommunicationJoinedGroup, inf_communication_joined_group, INF_COMMUNICATION_TYPE_GROUP, G_ADD_PRIVATE(InfCommunicationJoinedGroup)) /* Required by inf_communication_joined_group_publisher_notify_status_cb() */ static void inf_communication_joined_group_set_publisher(InfCommunicationJoinedGroup* grp, InfXmlConnection* connection); static void inf_communication_joined_group_publisher_notify_status_cb(GObject* object, GParamSpec* pspec, gpointer user_data) { InfXmlConnectionStatus status; g_object_get(G_OBJECT(object), "status", &status, NULL); if(status == INF_XML_CONNECTION_CLOSING || status == INF_XML_CONNECTION_CLOSED) { /* Don't remove from group, the method will do this by itself */ inf_communication_joined_group_set_publisher( INF_COMMUNICATION_JOINED_GROUP(user_data), NULL ); } } static void inf_communication_joined_group_set_publisher(InfCommunicationJoinedGroup* grp, InfXmlConnection* connection) { InfCommunicationJoinedGroupPrivate* priv; priv = INF_COMMUNICATION_JOINED_GROUP_PRIVATE(grp); if(priv->publisher_conn != NULL) { inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->publisher_conn), G_CALLBACK(inf_communication_joined_group_publisher_notify_status_cb), grp ); g_object_unref(priv->publisher_conn); } priv->publisher_conn = connection; if(connection != NULL) { g_object_ref(connection); g_signal_connect( G_OBJECT(connection), "notify::status", G_CALLBACK(inf_communication_joined_group_publisher_notify_status_cb), grp ); } g_object_notify(G_OBJECT(grp), "publisher"); } static const gchar* inf_communication_joined_group_get_method(InfCommunicationGroup* group, unsigned int index) { InfCommunicationJoinedGroup* joined_group; InfCommunicationJoinedGroupPrivate* priv; joined_group = INF_COMMUNICATION_JOINED_GROUP(group); priv = INF_COMMUNICATION_JOINED_GROUP_PRIVATE(joined_group); if(index == 0) return priv->method; return NULL; } static gchar* inf_communication_joined_group_get_publisher_id(InfCommunicationGroup* group, InfXmlConnection* for_conn) { InfCommunicationJoinedGroup* joined_group; InfCommunicationJoinedGroupPrivate* priv; joined_group = INF_COMMUNICATION_JOINED_GROUP(group); priv = INF_COMMUNICATION_JOINED_GROUP_PRIVATE(joined_group); return g_strdup(priv->publisher_id); } /* * GObject overrides. */ static void inf_communication_joined_group_init(InfCommunicationJoinedGroup* group) { InfCommunicationJoinedGroupPrivate* priv; priv = INF_COMMUNICATION_JOINED_GROUP_PRIVATE(group); priv->publisher_conn = NULL; priv->publisher_id = NULL; priv->method = NULL; } static void inf_communication_joined_group_constructed(GObject* object) { InfCommunicationJoinedGroupPrivate* priv; priv = INF_COMMUNICATION_JOINED_GROUP_PRIVATE(object); G_OBJECT_CLASS(inf_communication_joined_group_parent_class)->constructed( object ); g_assert(priv->publisher_conn != NULL); g_assert(priv->method != NULL); g_object_get( G_OBJECT(priv->publisher_conn), "remote-id", &priv->publisher_id, NULL ); /* method on publisher_conn's network must be supported, otherwise this * call will fail. */ _inf_communication_group_add_member( INF_COMMUNICATION_GROUP(object), priv->publisher_conn ); } static void inf_communication_joined_group_dispose(GObject* object) { InfCommunicationJoinedGroup* group; InfCommunicationJoinedGroupPrivate* priv; group = INF_COMMUNICATION_JOINED_GROUP(object); priv = INF_COMMUNICATION_JOINED_GROUP_PRIVATE(group); inf_communication_joined_group_set_publisher(group, NULL); G_OBJECT_CLASS(inf_communication_joined_group_parent_class)->dispose( object ); } static void inf_communication_joined_group_finalize(GObject* object) { InfCommunicationJoinedGroup* group; InfCommunicationJoinedGroupPrivate* priv; group = INF_COMMUNICATION_JOINED_GROUP(object); priv = INF_COMMUNICATION_JOINED_GROUP_PRIVATE(group); g_free(priv->publisher_id); g_free(priv->method); G_OBJECT_CLASS(inf_communication_joined_group_parent_class)->finalize( object ); } static void inf_communication_joined_group_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfCommunicationJoinedGroup* group; InfCommunicationJoinedGroupPrivate* priv; group = INF_COMMUNICATION_JOINED_GROUP(object); priv = INF_COMMUNICATION_JOINED_GROUP_PRIVATE(group); switch(prop_id) { case PROP_PUBLISHER: g_assert(priv->publisher_conn == NULL); /* construct only */ inf_communication_joined_group_set_publisher( group, INF_XML_CONNECTION(g_value_get_object(value)) ); break; case PROP_METHOD: g_assert(priv->method == NULL); /* construct only */ priv->method = g_value_dup_string(value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void inf_communication_joined_group_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfCommunicationJoinedGroup* group; InfCommunicationJoinedGroupPrivate* priv; group = INF_COMMUNICATION_JOINED_GROUP(object); priv = INF_COMMUNICATION_JOINED_GROUP_PRIVATE(group); switch(prop_id) { case PROP_PUBLISHER: g_value_set_object(value, priv->publisher_conn); break; case PROP_METHOD: g_value_set_string(value, priv->method); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } /* * GType registration. */ static void inf_communication_joined_group_class_init( InfCommunicationJoinedGroupClass* joined_group_class) { GObjectClass* object_class; InfCommunicationGroupClass* group_class; object_class = G_OBJECT_CLASS(joined_group_class); group_class = INF_COMMUNICATION_GROUP_CLASS(joined_group_class); object_class->constructed = inf_communication_joined_group_constructed; object_class->dispose = inf_communication_joined_group_dispose; object_class->finalize = inf_communication_joined_group_finalize; object_class->set_property = inf_communication_joined_group_set_property; object_class->get_property = inf_communication_joined_group_get_property; group_class->get_method = inf_communication_joined_group_get_method; group_class->get_publisher_id = inf_communication_joined_group_get_publisher_id; g_object_class_install_property( object_class, PROP_PUBLISHER, g_param_spec_object( "publisher", "Publisher", "A connection to the group's publisher", INF_TYPE_XML_CONNECTION, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_METHOD, g_param_spec_string( "method", "Method", "The communication method to use for this group", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); } /* * Public API. */ /** * inf_communication_joined_group_remove_member: * @grp: A #InfCommunicationJoinedGroup. * @connection: A connection to a member of @grp. * * Removes @connection as @grp's member. On the remote site, the * corresponding #InfCommunicationGroup needs to be freed (which may be a * #InfCommunicationJoinedGroup or a #InfCommunicationHostedGroup). */ void inf_communication_joined_group_remove_member(InfCommunicationJoinedGroup* grp, InfXmlConnection* connection) { g_return_if_fail(INF_COMMUNICATION_IS_JOINED_GROUP(grp)); g_return_if_fail(INF_IS_XML_CONNECTION(connection)); g_return_if_fail( inf_communication_group_is_member( INF_COMMUNICATION_GROUP(grp), connection ) ); _inf_communication_group_remove_member( INF_COMMUNICATION_GROUP(grp), connection ); } /** * inf_communication_joined_group_get_publisher: * @g: A #InfCommunicationJoinedGroup. * * Returns a #InfXmlConnection to the group's publisher, or %NULL if the * publisher is no longer a group member. * * Returns: (transfer none) (allow-none): A #InfXmlConnection, or %NULL. */ InfXmlConnection* inf_communication_joined_group_get_publisher(InfCommunicationJoinedGroup* g) { g_return_val_if_fail(INF_COMMUNICATION_IS_JOINED_GROUP(g), NULL); return INF_COMMUNICATION_JOINED_GROUP_PRIVATE(g)->publisher_conn; } libinfinity-0.7.1/libinfinity/communication/PaxHeaders.26529/inf-communication-factory.c0000644000000000000000000000013013034342512026213 xustar0029 mtime=1483851082.03771847 29 atime=1483851082.03771847 30 ctime=1488261589.096138856 libinfinity-0.7.1/libinfinity/communication/inf-communication-factory.c0000644000175000017500000001074213034342512026753 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-communication-factory * @title: InfCommunicationFactory * @short_description: Creation of communication methods * @see_also: #InfCommunicationManager * @include: libinfinity/communication/inf-communication-factory.h * @stability: Unstable * * A #InfCommunicationFactory is used by the communication manager to create * #InfCommunicationMethods. All a factory has to do is to tell * whether it supports a specific network and method name combination, and * create a corresponding #InfCommunicationMethod if it does. * * #InfCommunicationFactorys are added to a communication manager via * inf_communication_manager_add_factory(). The communication manager will * automatically use the factory if it needs to create a method it supports. **/ #include G_DEFINE_INTERFACE(InfCommunicationFactory, inf_communication_factory, G_TYPE_OBJECT) static void inf_communication_factory_default_init( InfCommunicationFactoryInterface* iface) { } /** * inf_communication_factory_supports_method: * @factory: A #InfCommunicationFactory. * @network: A network specifier, such as "tcp/ip" or "jabber". * @method_name: A method identifier, such as "central" or "groupchat". * * Returns whether @factory supports creating methods that implement * @method_name as communication method for connections on @network * (see #InfXmlConnection:network). * * Returns: Whether @factory supports the given network and method name. */ gboolean inf_communication_factory_supports_method(InfCommunicationFactory* factory, const gchar* network, const gchar* method_name) { InfCommunicationFactoryInterface* iface; g_return_val_if_fail(INF_COMMUNICATION_IS_FACTORY(factory), FALSE); g_return_val_if_fail(network != NULL, FALSE); g_return_val_if_fail(method_name != NULL, FALSE); iface = INF_COMMUNICATION_FACTORY_GET_IFACE(factory); g_return_val_if_fail(iface->supports_method != NULL, FALSE); return iface->supports_method(factory, network, method_name); } /** * inf_communication_factory_instantiate: * @factory: A #InfCommunicationFactory. * @network: A network specifier, such as "tcp/ip" or "jabber". * @method_name: A method identifier, such as "central" or "groupchat". * @registry: A #InfCommunicationRegistry at which the created method can * register connections. * @group: The #InfCommunicationGroup for which to create the method. * * Creates a new #InfCommunicationMethod for @network and @method_name. The * factory needs to support that method, see * inf_communication_factory_supports_method(). * * Returns: (transfer full): A new #InfCommunicationMethod. */ InfCommunicationMethod* inf_communication_factory_instantiate(InfCommunicationFactory* factory, const gchar* network, const gchar* method_name, InfCommunicationRegistry* registry, InfCommunicationGroup* group) { InfCommunicationFactoryInterface* iface; g_return_val_if_fail(INF_COMMUNICATION_IS_FACTORY(factory), NULL); g_return_val_if_fail(network != NULL, NULL); g_return_val_if_fail(method_name != NULL, NULL); g_return_val_if_fail(INF_COMMUNICATION_IS_REGISTRY(registry), NULL); g_return_val_if_fail(INF_COMMUNICATION_IS_GROUP(group), NULL); iface = INF_COMMUNICATION_FACTORY_GET_IFACE(factory); g_return_val_if_fail(iface->instantiate != NULL, NULL); return iface->instantiate(factory, network, method_name, registry, group); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/communication/PaxHeaders.26529/inf-communication-manager.c0000644000000000000000000000013013034342512026156 xustar0029 mtime=1483851082.03771847 29 atime=1483851082.03771847 30 ctime=1488261589.100138847 libinfinity-0.7.1/libinfinity/communication/inf-communication-manager.c0000644000175000017500000003700513034342512026717 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-communication-manager * @title: InfCommunicationManager * @short_description: Handling multiple communication sessions * @include: libinfinity/communication/inf-communication-manager.h * @stability: Unstable * * #InfCommunicationManager manages multiple communication sessions * represented by #InfCommunicationGroup. A #InfCommunicationGroup provides an * easy way to send messages between group members, possibly sharing * connections with other groups handled by the same #InfCommunicationManager. **/ #include #include #include typedef struct _InfCommunicationManagerJoinedKey InfCommunicationManagerJoinedKey; struct _InfCommunicationManagerJoinedKey { /* We can uniquely identify joined groups by network, * publisher ID and group name. */ gchar* network; gchar* publisher_id; const gchar* group_name; }; typedef struct _InfCommunicationManagerPrivate InfCommunicationManagerPrivate; struct _InfCommunicationManagerPrivate { InfCommunicationRegistry* registry; GPtrArray* factories; GHashTable* hosted_groups; GHashTable* joined_groups; }; #define INF_COMMUNICATION_MANAGER_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INF_COMMUNICATION_TYPE_MANAGER, InfCommunicationManagerPrivate)) G_DEFINE_TYPE_WITH_CODE(InfCommunicationManager, inf_communication_manager, G_TYPE_OBJECT, G_ADD_PRIVATE(InfCommunicationManager)) static void inf_communication_manager_joined_key_free(gpointer key_) { InfCommunicationManagerJoinedKey* key; key = (InfCommunicationManagerJoinedKey*)key_; g_free(key->network); g_free(key->publisher_id); g_slice_free(InfCommunicationManagerJoinedKey, key); } static int inf_communication_manager_joined_key_cmp(gconstpointer first, gconstpointer second) { const InfCommunicationManagerJoinedKey* first_key; const InfCommunicationManagerJoinedKey* second_key; int res; first_key = (const InfCommunicationManagerJoinedKey*)first; second_key = (const InfCommunicationManagerJoinedKey*)second; res = strcmp(first_key->group_name, second_key->group_name); if(res != 0) return res; res = strcmp(first_key->publisher_id, second_key->publisher_id); if(res != 0) return res; return strcmp(first_key->network, second_key->network); } static gboolean inf_communication_manager_joined_key_equal(gconstpointer first, gconstpointer second) { return inf_communication_manager_joined_key_cmp(first, second) == 0; } static guint inf_communication_manager_joined_key_hash(gconstpointer key_) { const InfCommunicationManagerJoinedKey* key; key = (const InfCommunicationManagerJoinedKey*)key_; /* TODO: Is this a good hash function? */ return g_str_hash(key->network) ^ g_str_hash(key->publisher_id) ^ g_str_hash(key->group_name); } static void inf_communication_manager_hosted_group_unrefed(gpointer data, GObject* where_the_object_was) { InfCommunicationManager* manager; InfCommunicationManagerPrivate* priv; GHashTableIter iter; gpointer value; manager = INF_COMMUNICATION_MANAGER(data); priv = INF_COMMUNICATION_MANAGER_PRIVATE(manager); g_hash_table_iter_init(&iter, priv->hosted_groups); /* We don't have the key here. If we had, then we could still not use it * because we wouldn't have the communication manager then. If we would * want to have both, we would need to dynamically allocate a structure * containing both, and also storing that somewhere to be able to * g_weak_unref in dispose() which is pretty much hassle. */ /* TODO: Let the groups strong-ref the manager, then dispose simply can't * run until all groups are freed. */ while(g_hash_table_iter_next(&iter, NULL, &value)) { if(value == where_the_object_was) { g_hash_table_iter_remove(&iter); break; } } } static void inf_communication_manager_joined_group_unrefed(gpointer data, GObject* where_the_object_was) { InfCommunicationManager* manager; InfCommunicationManagerPrivate* priv; GHashTableIter iter; gpointer value; manager = INF_COMMUNICATION_MANAGER(data); priv = INF_COMMUNICATION_MANAGER_PRIVATE(manager); g_hash_table_iter_init(&iter, priv->joined_groups); /* We don't have the key here. If we had, then we could still not use it * because we wouldn't have the communication manager then. If we would * want to have both, we would need to dynamically allocate a structure * containing both, and also storing that somewhere to be able to * g_weak_unref in dispose() which is pretty much hassle. */ /* TODO: Let the groups strong-ref the manager, then dispose simply can't * run until all groups are freed. */ while(g_hash_table_iter_next(&iter, NULL, &value)) { if(value == where_the_object_was) { g_hash_table_iter_remove(&iter); break; } } } /* * GObject overrides. */ static void inf_communication_manager_init(InfCommunicationManager* manager) { InfCommunicationManagerPrivate* priv; priv = INF_COMMUNICATION_MANAGER_PRIVATE(manager); priv->registry = g_object_new(INF_COMMUNICATION_TYPE_REGISTRY, NULL); priv->factories = g_ptr_array_new(); priv->hosted_groups = g_hash_table_new(g_str_hash, g_str_equal); priv->joined_groups = g_hash_table_new_full( inf_communication_manager_joined_key_hash, inf_communication_manager_joined_key_equal, inf_communication_manager_joined_key_free, NULL ); /* We always support the "central" method. This is used as a fallback for * hosted groups. */ g_ptr_array_add( priv->factories, g_object_ref(inf_communication_central_factory_get_default()) ); } static void inf_communication_manager_dispose(GObject* object) { InfCommunicationManager* manager; InfCommunicationManagerPrivate* priv; manager = INF_COMMUNICATION_MANAGER(object); priv = INF_COMMUNICATION_MANAGER_PRIVATE(manager); /* TODO: weak unref the groups */ if(g_hash_table_size(priv->hosted_groups) > 0) { g_warning("Communication manager containing hosted groups was unrefed"); } if(g_hash_table_size(priv->joined_groups) > 0) { g_warning("Communication manager containing joined groups was unrefed"); } g_hash_table_unref(priv->hosted_groups); g_hash_table_unref(priv->joined_groups); g_ptr_array_foreach(priv->factories, (GFunc)g_object_unref, NULL); g_ptr_array_free(priv->factories, TRUE); if(priv->registry != NULL) { g_object_unref(priv->registry); priv->registry = NULL; } G_OBJECT_CLASS(inf_communication_manager_parent_class)->dispose(object); } static void inf_communication_manager_class_init( InfCommunicationManagerClass* manager_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(manager_class); object_class->dispose = inf_communication_manager_dispose; } /** * inf_communication_manager_new: (constructor) * * Creates a new #InfCommunicationManager. * * Returns: (transfer full): A new #InfCommunicationManager. */ InfCommunicationManager* inf_communication_manager_new(void) { return g_object_new(INF_COMMUNICATION_TYPE_MANAGER, NULL); } /** * inf_communication_manager_open_group: * @manager: A #InfCommunicationManager. * @group_name: A name for the new group. * @methods: (allow-none) (array zero-terminated=1): Methods to support, or * %NULL. * * Opens a new communication group published by the local host. @group_name * is an identifier for the group via which other hosts can join the group * using inf_communication_manager_join_group(). It needs to be unique among * all groups opened by the local host. * * @methods specifies what communication methods the group should use, in * order of priority. If a method is not supported for a given network, then * the next one in the array is tried. If none is supported, then the * "central" method will be used, which is guaranteed to be supported for * all networks. * * Returns: (transfer full): A #InfCommunicationHostedGroup. Free with * g_object_unref() to leave the group. */ InfCommunicationHostedGroup* inf_communication_manager_open_group(InfCommunicationManager* manager, const gchar* group_name, const gchar* const* methods) { InfCommunicationManagerPrivate* priv; InfCommunicationHostedGroup* group; const gchar* const* method; g_return_val_if_fail(INF_COMMUNICATION_IS_MANAGER(manager), NULL); g_return_val_if_fail(group_name != NULL, NULL); priv = INF_COMMUNICATION_MANAGER_PRIVATE(manager); g_return_val_if_fail( g_hash_table_lookup(priv->hosted_groups, group_name) == NULL, NULL ); group = g_object_new( INF_COMMUNICATION_TYPE_HOSTED_GROUP, "communication-manager", manager, "communication-registry", priv->registry, "name", group_name, NULL ); if(methods != NULL) { for(method = methods; *method != NULL; ++ method) inf_communication_hosted_group_add_method(group, *method); } g_hash_table_insert( priv->hosted_groups, *(gpointer*) (gpointer) &group_name, /* cast const away without warning */ group ); g_object_weak_ref( G_OBJECT(group), inf_communication_manager_hosted_group_unrefed, manager ); return group; } /** * inf_communication_manager_join_group: * @manager: A #InfCommunicationManager. * @group_name: The group to join. * @publisher_conn: A #InfXmlConnection to the publishing host. * @method: The communication method to use. * * Joins a communication group published by a remote host. @publisher_conn * needs to be a to the publishing host with status %INF_XML_CONNECTION_OPEN * or %INF_XML_CONNECTION_OPENING. @group_name specifies the name of the group * to join. * * @method specifies the communication method to use. It must match the * communication method the publisher has chosen for @publisher_conn's network * (see inf_communication_group_get_method_for_network()). The function * returns %NULL if @method is not supported (which means * inf_communication_manager_get_factory_for() for @publisher_conn's network * and @method returns %NULL). * * Returns: (transfer full) (allow-none): A new #InfCommunicationJoinedGroup, * or %NULL. Free with g_object_unref() to leave the group. */ InfCommunicationJoinedGroup* inf_communication_manager_join_group(InfCommunicationManager* manager, const gchar* group_name, InfXmlConnection* publisher_conn, const gchar* method) { InfCommunicationManagerPrivate* priv; InfCommunicationManagerJoinedKey* key; gchar* network; gchar* publisher_id; InfXmlConnectionStatus status; InfCommunicationJoinedGroup* group; g_return_val_if_fail(INF_COMMUNICATION_IS_MANAGER(manager), NULL); g_return_val_if_fail(group_name != NULL, NULL); g_return_val_if_fail(INF_IS_XML_CONNECTION(publisher_conn), NULL); g_return_val_if_fail(method != NULL, NULL); priv = INF_COMMUNICATION_MANAGER_PRIVATE(manager); g_object_get( G_OBJECT(publisher_conn), "network", &network, "remote-id", &publisher_id, "status", &status, NULL ); /* TODO: Do we need to support OPENING somewhere? I don't think it's a good * idea to do here. When we change this remember to change docs above. */ if(status == INF_XML_CONNECTION_CLOSING || status == INF_XML_CONNECTION_CLOSED) { g_free(network); g_free(publisher_id); g_return_val_if_reached(NULL); } key = g_slice_new(InfCommunicationManagerJoinedKey); key->network = network; key->publisher_id = publisher_id; key->group_name = group_name; group = g_hash_table_lookup(priv->joined_groups, key); if(group != NULL) { inf_communication_manager_joined_key_free(key); g_return_val_if_reached(NULL); } if(!inf_communication_manager_get_factory_for(manager, network, method)) { inf_communication_manager_joined_key_free(key); return NULL; /* ordinary failure for now */ } group = g_object_new( INF_COMMUNICATION_TYPE_JOINED_GROUP, "communication-manager", manager, "communication-registry", priv->registry, "name", group_name, "publisher", publisher_conn, "method", method, NULL ); key->group_name = inf_communication_group_get_name(INF_COMMUNICATION_GROUP(group)); g_hash_table_insert(priv->joined_groups, key, group); g_object_weak_ref( G_OBJECT(group), inf_communication_manager_joined_group_unrefed, manager ); return group; } /** * inf_communication_manager_add_factory: * @manager: A #InfCommunicationManager. * @factory: The #InfCommunicationFactory to add. * * Adds a new #InfCommunicationFactory to @manager. This makes @manager * support all method/network combinations that @factory supports. If multiple * added factories support the same combination, the one which was added first * will be used to instantiate the #InfCommunicationMethod. */ void inf_communication_manager_add_factory(InfCommunicationManager* manager, InfCommunicationFactory* factory) { InfCommunicationManagerPrivate* priv; g_return_if_fail(INF_COMMUNICATION_IS_MANAGER(manager)); g_return_if_fail(INF_COMMUNICATION_IS_FACTORY(factory)); priv = INF_COMMUNICATION_MANAGER_PRIVATE(manager); g_ptr_array_add(priv->factories, factory); g_object_ref(factory); } /** * inf_communication_manager_get_factory_for: * @manager: A #InfCommunicationManager. * @network: A network identifier. * @method_name: A method name. * * Returns the #InfCommunicationFactory that @manager will use to instantiate * a #InfCommunicationMethod for @method_name on @network, or %NULL if the * network/method combination is not supported. * * Returns: (transfer none) (allow-none): A #InfCommunicationFactory, * or %NULL. */ InfCommunicationFactory* inf_communication_manager_get_factory_for(InfCommunicationManager* manager, const gchar* network, const gchar* method_name) { InfCommunicationManagerPrivate* priv; InfCommunicationFactory* factory; gboolean supported; guint i; g_return_val_if_fail(INF_COMMUNICATION_IS_MANAGER(manager), NULL); g_return_val_if_fail(network != NULL, NULL); g_return_val_if_fail(method_name != NULL, NULL); priv = INF_COMMUNICATION_MANAGER_PRIVATE(manager); for(i = 0; i < priv->factories->len; ++ i) { factory = g_ptr_array_index(priv->factories, i); supported = inf_communication_factory_supports_method( factory, network, method_name ); if(supported == TRUE) return factory; } return NULL; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/communication/PaxHeaders.26529/inf-communication-object.h0000644000000000000000000000013013034342512026017 xustar0030 mtime=1483851082.041718492 30 atime=1483851082.041718492 28 ctime=1488261588.9841391 libinfinity-0.7.1/libinfinity/communication/inf-communication-object.h0000644000175000017500000001024213034342512026552 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_COMMUNICATION_OBJECT_H__ #define __INF_COMMUNICATION_OBJECT_H__ #include #include #include G_BEGIN_DECLS #define INF_COMMUNICATION_TYPE_OBJECT (inf_communication_object_get_type()) #define INF_COMMUNICATION_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_COMMUNICATION_TYPE_OBJECT, InfCommunicationObject)) #define INF_COMMUNICATION_IS_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_COMMUNICATION_TYPE_OBJECT)) #define INF_COMMUNICATION_OBJECT_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE((inst), INF_COMMUNICATION_TYPE_OBJECT, InfCommunicationObjectInterface)) #define INF_COMMUNICATION_TYPE_SCOPE (inf_communication_scope_get_type()) /** * InfCommunicationScope: * @INF_COMMUNICATION_SCOPE_PTP: The message is sent from one group member to * another. * @INF_COMMUNICATION_SCOPE_GROUP: The message is sent to all group members. * * #InfCommunicationScope specifies to which hosts a message belongs. */ typedef enum _InfCommunicationScope { INF_COMMUNICATION_SCOPE_PTP, INF_COMMUNICATION_SCOPE_GROUP } InfCommunicationScope; /** * InfCommunicationObject: * * #InfCommunicationObject is an opaque data type. You should only access it * via the public API functions. */ typedef struct _InfCommunicationObject InfCommunicationObject; typedef struct _InfCommunicationObjectInterface InfCommunicationObjectInterface; /** * InfCommunicationObjectInterface: * @received: Called when a message for the group related to this * #InfCommunicationObject was received. * @enqueued: Called when a message to be sent to another group member has * been enqueued, which means sending it can no longer be cancelled via * inf_communication_group_cancel_messages(). * @sent: Called when a message has been sent to another group member of the * group related no this #InfCommunicationObject. * * The virtual methods of #InfCommunicationObject. These are called by the * #InfCommunicationMethod when appropriate. */ struct _InfCommunicationObjectInterface { /*< private >*/ GTypeInterface parent; /*< public >*/ InfCommunicationScope (*received)(InfCommunicationObject* object, InfXmlConnection* conn, xmlNodePtr node); void (*enqueued)(InfCommunicationObject* object, InfXmlConnection* conn, xmlNodePtr node); void (*sent)(InfCommunicationObject* object, InfXmlConnection* conn, xmlNodePtr node); }; GType inf_communication_scope_get_type(void) G_GNUC_CONST; GType inf_communication_object_get_type(void) G_GNUC_CONST; InfCommunicationScope inf_communication_object_received(InfCommunicationObject* object, InfXmlConnection* conn, xmlNodePtr node); void inf_communication_object_enqueued(InfCommunicationObject* object, InfXmlConnection* conn, xmlNodePtr node); void inf_communication_object_sent(InfCommunicationObject* object, InfXmlConnection* conn, xmlNodePtr node); G_END_DECLS #endif /* __INF_COMMUNICATION_OBJECT_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/communication/PaxHeaders.26529/inf-communication-group.c0000644000000000000000000000013013034342512025700 xustar0029 mtime=1483851082.03771847 29 atime=1483851082.03771847 30 ctime=1488261589.096138856 libinfinity-0.7.1/libinfinity/communication/inf-communication-group.c0000644000175000017500000006426313034342512026447 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-communication-group * @title: InfCommunicationGroup * @short_description: Communication channel for mulitple connections * @include: libinfinity/communication/inf-communication-group.h * @stability: Unstable * * #InfCommunicationGroup represents a group of different hosts. The group * supports sending messages between group members and to the whole group. * * A communication group supports multiple networks. Each connection belongs * to a network, identified by the #InfXmlConnection:network property. It is * assumed that hosts on different networks can't directly communicate with * each other. Examples for networks are "tcp/ip" or "jabber". * * All communication for a given network is performed by a * #InfCommunicationMethod. The method defines how data is sent is sent * to the group. For example, a method could choose to relay all data via * a central server, or to send all data directly between the hosts, or in * case of a jabber network, use jabber groupchat functionality. **/ /* TODO: Add private API to query the registry from the manager, and use this * instead of an own group property */ #include #include #include #include typedef struct _InfCommunicationGroupPrivate InfCommunicationGroupPrivate; struct _InfCommunicationGroupPrivate { InfCommunicationManager* communication_manager; InfCommunicationRegistry* communication_registry; gchar* name; InfCommunicationObject* target; GHashTable* methods; }; enum { PROP_0, /* construct only */ PROP_COMMUNICATION_MANAGER, PROP_COMMUNICATION_REGISTRY, PROP_NAME, PROP_TARGET }; enum { MEMBER_ADDED, MEMBER_REMOVED, LAST_SIGNAL }; #define INF_COMMUNICATION_GROUP_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INF_COMMUNICATION_TYPE_GROUP, InfCommunicationGroupPrivate)) static guint group_signals[LAST_SIGNAL]; G_DEFINE_TYPE_EXTENDED(InfCommunicationGroup, inf_communication_group, G_TYPE_OBJECT, G_TYPE_FLAG_ABSTRACT, G_ADD_PRIVATE(InfCommunicationGroup)) /* * Signal handlers */ static void inf_communication_group_method_add_member_cb(InfCommunicationMethod* method, InfXmlConnection* connection, gpointer user_data) { InfCommunicationGroup* group; group = INF_COMMUNICATION_GROUP(user_data); g_signal_emit(G_OBJECT(group), group_signals[MEMBER_ADDED], 0, connection); } static void inf_communication_group_method_remove_member_cb(InfCommunicationMethod* meth, InfXmlConnection* conn, gpointer user_data) { InfCommunicationGroup* group; group = INF_COMMUNICATION_GROUP(user_data); g_signal_emit(G_OBJECT(group), group_signals[MEMBER_REMOVED], 0, conn); } static InfCommunicationFactory* inf_communication_group_get_factory_for_network(InfCommunicationGroup* group, const gchar* network, const gchar** method) { InfCommunicationGroupPrivate* priv; InfCommunicationGroupClass* klass; const gchar* method_name; const gchar* split_pos; unsigned int i; InfCommunicationFactory* factory; priv = INF_COMMUNICATION_GROUP_PRIVATE(group); klass = INF_COMMUNICATION_GROUP_GET_CLASS(group); g_assert(klass->get_method != NULL); i = 0; for(i = 0; (method_name = klass->get_method(group, i)) != NULL; ++ i) { split_pos = strstr(method_name, "::"); if(split_pos != NULL) { if(strncmp(method_name, network, split_pos - method_name) != 0) continue; method_name = split_pos + 2; } /* Check for support */ factory = inf_communication_manager_get_factory_for( priv->communication_manager, network, method_name ); if(factory != NULL) { if(method != NULL) *method = method_name; return factory; } } return NULL; } /* * Utility functions */ static InfCommunicationMethod* inf_communication_group_lookup_method_for_network(InfCommunicationGroup* grp, const gchar* network) { InfCommunicationGroupPrivate* priv; InfCommunicationMethod* method; priv = INF_COMMUNICATION_GROUP_PRIVATE(grp); method = g_hash_table_lookup(priv->methods, network); return method; } static InfCommunicationMethod* inf_communication_group_lookup_method_for_connection(InfCommunicationGroup* g, InfXmlConnection* conn) { InfCommunicationMethod* method; gchar* network; g_object_get(G_OBJECT(conn), "network", &network, NULL); method = inf_communication_group_lookup_method_for_network(g, network); g_free(network); return method; } /* * Weak ref handling */ /* TODO: Can we strong-ref the communicationmanager and registry? */ static void inf_communication_group_target_unrefed(gpointer data, GObject* where_the_object_was) { InfCommunicationGroup* group; InfCommunicationGroupPrivate* priv; group = INF_COMMUNICATION_GROUP(data); priv = INF_COMMUNICATION_GROUP_PRIVATE(group); g_warning( "The target of communication group \"%s\" was released before the group " "itself was released.", priv->name ); priv->target = NULL; g_object_notify(G_OBJECT(group), "target"); } static void inf_communication_group_manager_unrefed(gpointer data, GObject* where_the_object_was) { InfCommunicationGroup* group; InfCommunicationGroupPrivate* priv; group = INF_COMMUNICATION_GROUP(data); priv = INF_COMMUNICATION_GROUP_PRIVATE(group); g_warning( "The communication manager of group \"%s\" was released before the group " "itself was released.", priv->name ); priv->communication_manager = NULL; g_object_notify(G_OBJECT(group), "communication-manager"); } static void inf_communication_group_registry_unrefed(gpointer data, GObject* where_the_object_was) { InfCommunicationGroup* group; InfCommunicationGroupPrivate* priv; group = INF_COMMUNICATION_GROUP(data); priv = INF_COMMUNICATION_GROUP_PRIVATE(group); g_warning( "The communication registry of group \"%s\" was released before the " "group itself was released.", priv->name ); priv->communication_registry = NULL; g_object_notify(G_OBJECT(group), "communication-registry"); } static void inf_communication_group_set_manager(InfCommunicationGroup* group, InfCommunicationManager* manager) { InfCommunicationGroupPrivate* priv; priv = INF_COMMUNICATION_GROUP_PRIVATE(group); if(priv->communication_manager != NULL) { g_object_weak_unref( G_OBJECT(priv->communication_manager), inf_communication_group_manager_unrefed, group ); } priv->communication_manager = manager; if(manager != NULL) { g_object_weak_ref( G_OBJECT(manager), inf_communication_group_manager_unrefed, group ); } g_object_notify(G_OBJECT(group), "communication-manager"); } static void inf_communication_group_set_registry(InfCommunicationGroup* group, InfCommunicationRegistry* registry) { InfCommunicationGroupPrivate* priv; priv = INF_COMMUNICATION_GROUP_PRIVATE(group); if(priv->communication_registry != NULL) { g_object_weak_unref( G_OBJECT(priv->communication_registry), inf_communication_group_registry_unrefed, group ); } priv->communication_registry = registry; if(registry != NULL) { g_object_weak_ref( G_OBJECT(registry), inf_communication_group_registry_unrefed, group ); } g_object_notify(G_OBJECT(group), "communication-registry"); } /* * GObject overrides. */ static void inf_communication_group_init(InfCommunicationGroup* group) { InfCommunicationGroupPrivate* priv; priv = INF_COMMUNICATION_GROUP_PRIVATE(group); priv->communication_manager = NULL; priv->communication_registry = NULL; priv->name = NULL; priv->target = NULL; priv->methods = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_object_unref); } static void inf_communication_group_dispose(GObject* object) { InfCommunicationGroup* group; InfCommunicationGroupPrivate* priv; group = INF_COMMUNICATION_GROUP(object); priv = INF_COMMUNICATION_GROUP_PRIVATE(group); if(priv->methods != NULL) { g_hash_table_unref(priv->methods); priv->methods = NULL; } inf_communication_group_set_registry(group, NULL); inf_communication_group_set_manager(group, NULL); inf_communication_group_set_target(group, NULL); G_OBJECT_CLASS(inf_communication_group_parent_class)->dispose(object); } static void inf_communication_group_finalize(GObject* object) { InfCommunicationGroup* group; InfCommunicationGroupPrivate* priv; group = INF_COMMUNICATION_GROUP(object); priv = INF_COMMUNICATION_GROUP_PRIVATE(group); g_free(priv->name); G_OBJECT_CLASS(inf_communication_group_parent_class)->finalize(object); } static void inf_communication_group_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfCommunicationGroup* group; InfCommunicationGroupPrivate* priv; group = INF_COMMUNICATION_GROUP(object); priv = INF_COMMUNICATION_GROUP_PRIVATE(group); switch(prop_id) { case PROP_COMMUNICATION_MANAGER: g_assert(priv->communication_manager == NULL); /* construct only */ inf_communication_group_set_manager( group, INF_COMMUNICATION_MANAGER(g_value_get_object(value)) ); break; case PROP_COMMUNICATION_REGISTRY: g_assert(priv->communication_registry == NULL); /* construct only */ inf_communication_group_set_registry( group, INF_COMMUNICATION_REGISTRY(g_value_get_object(value)) ); break; case PROP_NAME: g_assert(priv->name == NULL); /* construct only */ priv->name = g_value_dup_string(value); break; case PROP_TARGET: inf_communication_group_set_target( group, INF_COMMUNICATION_OBJECT(g_value_get_object(value)) ); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void inf_communication_group_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfCommunicationGroup* group; InfCommunicationGroupPrivate* priv; group = INF_COMMUNICATION_GROUP(object); priv = INF_COMMUNICATION_GROUP_PRIVATE(group); switch(prop_id) { case PROP_NAME: g_value_set_string(value, priv->name); break; case PROP_TARGET: g_value_set_object(value, G_OBJECT(priv->target)); break; case PROP_COMMUNICATION_MANAGER: /* write-only: */ /*g_value_set_object(value, G_OBJECT(priv->communication_manager)); break;*/ case PROP_COMMUNICATION_REGISTRY: /* write-only: */ /*g_value_set_object(value, G_OBJECT(priv->communication_registry)); break;*/ default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } /* * GType registration. */ static void inf_communication_group_class_init(InfCommunicationGroupClass* group_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(group_class); object_class->dispose = inf_communication_group_dispose; object_class->finalize = inf_communication_group_finalize; object_class->set_property = inf_communication_group_set_property; object_class->get_property = inf_communication_group_get_property; group_class->member_added = NULL; group_class->member_removed = NULL; group_class->get_method = NULL; group_class->get_publisher_id = NULL; g_object_class_install_property( object_class, PROP_COMMUNICATION_MANAGER, g_param_spec_object( "communication-manager", "Communication manager", "The communication manager used for sending requests", INF_COMMUNICATION_TYPE_MANAGER, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_COMMUNICATION_REGISTRY, g_param_spec_object( "communication-registry", "Communication registry", "The registry to register connections with", INF_COMMUNICATION_TYPE_REGISTRY, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_NAME, g_param_spec_string( "name", "Name", "The name of the group", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_TARGET, g_param_spec_object( "target", "Target", "The communication object to call on received and sent data", INF_COMMUNICATION_TYPE_OBJECT, G_PARAM_READWRITE ) ); /** * InfCommunicationGroup::member-added: * @group: The #InfCommunicationGroup emitting the signal. * @connection: The newly joined connection. * * This signal is emitted when a connection has been added to the group. */ group_signals[MEMBER_ADDED] = g_signal_new( "member-added", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfCommunicationGroupClass, member_added), NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, INF_TYPE_XML_CONNECTION ); /** * InfCommunicationGroup::member-removed: * @group: The #InfCommunicationGroup emitting the signal. * @connection: The connection that was removed * * This signal is emitted when a connection has been removed from the group. */ group_signals[MEMBER_REMOVED] = g_signal_new( "member-removed", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfCommunicationGroupClass, member_removed), NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, INF_TYPE_XML_CONNECTION ); } /* * Public API. */ /** * inf_communication_group_get_name: * @group: A #InfCommunicationGroup. * * Returns the name of the group. * * Returns: The name of the group. The returned string is owned by the group, * you don't need to free it. */ const gchar* inf_communication_group_get_name(InfCommunicationGroup* group) { g_return_val_if_fail(INF_COMMUNICATION_IS_GROUP(group), NULL); return INF_COMMUNICATION_GROUP_PRIVATE(group)->name; } /** * inf_communication_group_get_target: * @group: A #InfCommunicationGroup. * * Returns the group's target. The target of a group is the * #InfCommunicationObject to which received and sent messages are reported. * * Returns: (transfer none) (allow-none): A #InfCommunicationGroup, or %NULL. */ InfCommunicationObject* inf_communication_group_get_target(InfCommunicationGroup* group) { g_return_val_if_fail(INF_COMMUNICATION_IS_GROUP(group), NULL); return INF_COMMUNICATION_GROUP_PRIVATE(group)->target; } /** * inf_communication_group_set_target: * @group: A #InfCommunicationGroup. * @target: A #InfCommunicationObject, or %NULL. * * Sets the group's target. The target of a group is the * #InfCommunicationObject to which received and sent messages are reported. * If @target is %NULL, then the target will be unset. * * You can safely call this function with an object that holds a reference on * the group since the #InfCommunicationGroup only holds a weak reference to * its @target. This means that you need to keep a reference on @target * yourself. */ void inf_communication_group_set_target(InfCommunicationGroup* group, InfCommunicationObject* object) { InfCommunicationGroupPrivate* priv; g_return_if_fail(INF_COMMUNICATION_IS_GROUP(group)); g_return_if_fail(object == NULL || INF_COMMUNICATION_IS_OBJECT(object)); priv = INF_COMMUNICATION_GROUP_PRIVATE(group); if(priv->target != object) { if(priv->target != NULL) { g_object_weak_unref( G_OBJECT(priv->target), inf_communication_group_target_unrefed, group ); } priv->target = object; if(object != NULL) { g_object_weak_ref( G_OBJECT(object), inf_communication_group_target_unrefed, group ); } g_object_notify(G_OBJECT(group), "target"); } } /** * inf_communication_group_is_member: * @group: A #InfCommunicationGroup. * @connection: A #InfXmlConnection. * * Returns whether @connection is a member of @group. * * Returns: %TRUE if @connection is a member of @group, %FALSE otherwise. */ gboolean inf_communication_group_is_member(InfCommunicationGroup* group, InfXmlConnection* connection) { InfCommunicationMethod* method; g_return_val_if_fail(INF_COMMUNICATION_IS_GROUP(group), FALSE); g_return_val_if_fail(INF_IS_XML_CONNECTION(connection), FALSE); method = inf_communication_group_lookup_method_for_connection( group, connection ); if(method != NULL) return inf_communication_method_is_member(method, connection); else return FALSE; } /** * inf_communication_group_send_message: * @group: A #InfCommunicationGroup. * @connection: The #InfXmlConnection to which to send the message. * @xml: (transfer full): The message to send. * * Sends a message @connection which must be a member of @group. @connection * needs to be a member of this group. This function takes ownership of @xml. */ void inf_communication_group_send_message(InfCommunicationGroup* group, InfXmlConnection* connection, xmlNodePtr xml) { InfCommunicationMethod* method; g_return_if_fail(INF_COMMUNICATION_IS_GROUP(group)); g_return_if_fail(INF_IS_XML_CONNECTION(connection)); g_return_if_fail(xml != NULL); method = inf_communication_group_lookup_method_for_connection( group, connection ); g_return_if_fail(method != NULL); inf_communication_method_send_single(method, connection, xml); } /** * inf_communication_group_send_group_message: * @group: A #InfCommunicationGroup. * @xml: (transfer full): The message to send. * * Sends a message to all members of @group. This function takes ownership * of @xml. */ void inf_communication_group_send_group_message(InfCommunicationGroup* group, xmlNodePtr xml) { InfCommunicationGroupPrivate* priv; GHashTableIter iter; gpointer value; InfCommunicationMethod* method; gboolean has_next; g_return_if_fail(INF_COMMUNICATION_IS_GROUP(group)); g_return_if_fail(xml != NULL); priv = INF_COMMUNICATION_GROUP_PRIVATE(group); g_hash_table_iter_init(&iter, priv->methods); has_next = g_hash_table_iter_next(&iter, NULL, &value); if(!has_next) { xmlFreeNode(xml); } else { do { method = INF_COMMUNICATION_METHOD(value); has_next = g_hash_table_iter_next(&iter, NULL, &value); inf_communication_method_send_all( method, has_next ? xmlCopyNode(xml, 1) : xml ); } while(has_next); } } /** * inf_communication_group_cancel_messages: * @group: A #InfCommunicationGroup. * @connection: The #InfXmlConnection for which to cancel messages. * * Stops all messages scheduled to be sent to @connection from being sent. * Messages for which inf_communication_object_enqueued() has already been * called cannot be cancelled anymore. */ void inf_communication_group_cancel_messages(InfCommunicationGroup* group, InfXmlConnection* connection) { InfCommunicationMethod* method; g_return_if_fail(INF_COMMUNICATION_IS_GROUP(group)); g_return_if_fail(INF_IS_XML_CONNECTION(connection)); method = inf_communication_group_lookup_method_for_connection( group, connection ); g_return_if_fail(method != NULL); inf_communication_method_cancel_messages(method, connection); } /** * inf_communication_group_get_method_for_network: * @group: A #InfCommunicationGroup. * @network: A network specifier, such as "tcp/ip" or "jabber". * * Returns the method name of the method used for communication on @network * within @group. * * Returns: A method name. The string is owned by the group, you don't need * to free it. */ const gchar* inf_communication_group_get_method_for_network(InfCommunicationGroup* group, const gchar* network) { InfCommunicationFactory* factory; const gchar* method_name; g_return_val_if_fail(INF_COMMUNICATION_IS_GROUP(group), NULL); g_return_val_if_fail(network != NULL, NULL); factory = inf_communication_group_get_factory_for_network( group, network, &method_name ); if(factory == NULL) return NULL; return method_name; } /** * inf_communication_group_get_method_for_connection: * @grp: A #InfCommunicationGroup. * @conn: The #InfXmlConnection for which to retrieve the method. * * Returns the method name of the method used for communication on @conn's * network within @group. @conn does not need to be a member of @grp for this * function to be called. * * Returns: A method name. The string is owned by the group, you don't need * to free it. */ const gchar* inf_communication_group_get_method_for_connection(InfCommunicationGroup* grp, InfXmlConnection* conn) { gchar* network; const gchar* method; g_return_val_if_fail(INF_COMMUNICATION_IS_GROUP(grp), NULL); g_return_val_if_fail(INF_IS_XML_CONNECTION(conn), NULL); g_object_get(G_OBJECT(conn), "network", &network, NULL); method = inf_communication_group_get_method_for_network(grp, network); g_free(network); return method; } /** * inf_communication_group_get_publisher_id: * @group: A #InfCommunicationGroup. * @for_connection: A #InfXmlConnection. * * Returns a host identifier for the group's publisher (see * #InfXmlConnection:local-id and #InfXmlConnection:remote-id). If the local * host is the publisher, then this will simply return @for_connection's * local ID, otherwise the remote ID of the connection to the publisher on * @for_connection's network is returned. * * Returns: (transfer full): The publisher's host ID. Free with g_free(). */ gchar* inf_communication_group_get_publisher_id(InfCommunicationGroup* group, InfXmlConnection* for_connection) { InfCommunicationGroupClass* group_class; g_return_val_if_fail(INF_COMMUNICATION_IS_GROUP(group), NULL); g_return_val_if_fail(INF_IS_XML_CONNECTION(for_connection), NULL); group_class = INF_COMMUNICATION_GROUP_GET_CLASS(group); g_return_val_if_fail(group_class->get_publisher_id != NULL, NULL); return group_class->get_publisher_id(group, for_connection); } /* * Private API. Don't wrap this in language bindings. */ void _inf_communication_group_add_member(InfCommunicationGroup* group, InfXmlConnection* connection) { InfCommunicationGroupPrivate *priv; InfCommunicationMethod* method; gchar* network; const gchar* method_name; InfCommunicationFactory* factory; priv = INF_COMMUNICATION_GROUP_PRIVATE(group); g_object_get(G_OBJECT(connection), "network", &network, NULL); method = g_hash_table_lookup(priv->methods, network); if(!method) { factory = inf_communication_group_get_factory_for_network( group, network, &method_name ); /* The caller needs to make sure that we have at least one method for * connection's network. */ g_assert(factory != NULL); method = inf_communication_factory_instantiate( factory, network, method_name, priv->communication_registry, group ); g_signal_connect_after( G_OBJECT(method), "add-member", G_CALLBACK(inf_communication_group_method_add_member_cb), group ); g_signal_connect_after( G_OBJECT(method), "remove-member", G_CALLBACK(inf_communication_group_method_remove_member_cb), group ); g_hash_table_insert( priv->methods, network, method ); } else { g_free(network); } inf_communication_method_add_member(method, connection); } void _inf_communication_group_remove_member(InfCommunicationGroup* group, InfXmlConnection* connection) { InfCommunicationGroupPrivate* priv; gchar* network; InfCommunicationMethod* method; priv = INF_COMMUNICATION_GROUP_PRIVATE(group); g_object_get(G_OBJECT(connection), "network", &network, NULL); method = g_hash_table_lookup(priv->methods, network); g_free(network); g_assert(method != NULL); inf_communication_method_remove_member(method, connection); } void _inf_communication_group_foreach_method(InfCommunicationGroup* group, InfCommunicationGroupForeachFunc func, gpointer user_data) { InfCommunicationGroupPrivate* priv; GHashTableIter iter; gpointer value; InfCommunicationMethod* method; gboolean has_next; priv = INF_COMMUNICATION_GROUP_PRIVATE(group); g_hash_table_iter_init(&iter, priv->methods); has_next = g_hash_table_iter_next(&iter, NULL, &value); while(has_next) { method = INF_COMMUNICATION_METHOD(value); has_next = g_hash_table_iter_next(&iter, NULL, &value); func(method, user_data); } } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/communication/PaxHeaders.26529/inf-communication-method.c0000644000000000000000000000013013034342512026024 xustar0029 mtime=1483851082.03771847 29 atime=1483851082.03771847 30 ctime=1488261589.104138838 libinfinity-0.7.1/libinfinity/communication/inf-communication-method.c0000644000175000017500000002432113034342512026562 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-communication-method * @title: InfCommunicationMethod * @short_description: Network communication method * @see_also: #InfCommunicationManager * @include: libinfinity/communication/inf-communication-method.h * @stability: Unstable * * A #InfCommunicationMethod specifies how messages are transferred between * group members on the same network. So one method handles all connections * on a specific network for the group. **/ #include G_DEFINE_INTERFACE(InfCommunicationMethod, inf_communication_method, G_TYPE_OBJECT) enum { ADD_MEMBER, REMOVE_MEMBER, LAST_SIGNAL }; static guint method_signals[LAST_SIGNAL]; static void inf_communication_method_default_init(InfCommunicationMethodInterface* iface) { /** * InfCommunicationMethod::add-member: * @method: The #InfCommunicationMethod emitting the signal. * @connection: The #InfXmlConnection that was added. * * This signal is emitted whenever a new connection has been added to the * group on the network this method handles. */ method_signals[ADD_MEMBER] = g_signal_new( "add-member", INF_COMMUNICATION_TYPE_METHOD, G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfCommunicationMethodInterface, add_member), NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, INF_TYPE_XML_CONNECTION ); /** * InfCommunicationMethod::remove-member: * @method: The #InfCommunicationMethod emitting the signal. * @connection: The #InfXmlConnection that was removed. * * This signal is emitted whenever a connection has been removed from the * group on the network this method handles. */ method_signals[REMOVE_MEMBER] = g_signal_new( "remove-member", INF_COMMUNICATION_TYPE_METHOD, G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfCommunicationMethodInterface, remove_member), NULL, NULL, g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, INF_TYPE_XML_CONNECTION ); } /** * inf_communication_method_add_member: * @method: A #InfCommunicationMethod. * @connection: The #InfXmlConnection to add. * * Adds a new connection to the group. The network of @connection must match * the network the method is handling, and @connection must not already be * a member of the group (see inf_communication_method_is_member()). */ void inf_communication_method_add_member(InfCommunicationMethod* method, InfXmlConnection* connection) { g_return_if_fail(INF_COMMUNICATION_IS_METHOD(method)); g_return_if_fail(INF_IS_XML_CONNECTION(connection)); g_return_if_fail(!inf_communication_method_is_member(method, connection)); g_signal_emit( G_OBJECT(method), method_signals[ADD_MEMBER], 0, connection ); } /** * inf_communication_method_remove_member: * @method: A #InfCommunicationMethod. * @connection: The #InfXmlConnection to remove. * * Removes a connection from the group. @connection needs to be a member of * the group (see inf_communication_method_is_member()). */ void inf_communication_method_remove_member(InfCommunicationMethod* method, InfXmlConnection* connection) { g_return_if_fail(INF_COMMUNICATION_IS_METHOD(method)); g_return_if_fail(INF_IS_XML_CONNECTION(connection)); g_return_if_fail(inf_communication_method_is_member(method, connection)); g_signal_emit( G_OBJECT(method), method_signals[REMOVE_MEMBER], 0, connection ); } /** * inf_communication_method_is_member: * @method: A #InfCommunicationMethod. * @connection: A #InfXmlConnection. * * Returns whether @connection was added to the group via * inf_communication_method_add_member(). * * Returns: Whether @connection is a member of the group. */ gboolean inf_communication_method_is_member(InfCommunicationMethod* method, InfXmlConnection* connection) { InfCommunicationMethodInterface* iface; g_return_val_if_fail(INF_COMMUNICATION_IS_METHOD(method), FALSE); g_return_val_if_fail(INF_IS_XML_CONNECTION(connection), FALSE); iface = INF_COMMUNICATION_METHOD_GET_IFACE(method); g_return_val_if_fail(iface->is_member != NULL, FALSE); return iface->is_member(method, connection); } /** * inf_communication_method_send_single: * @method: A #InfCommunicationMethod. * @connection: A #InfXmlConnection that is a group member. * @xml: (transfer full): The message to send. * * Sends an XML message to @connection. This function takes ownership of @xml. */ void inf_communication_method_send_single(InfCommunicationMethod* method, InfXmlConnection* connection, xmlNodePtr xml) { InfCommunicationMethodInterface* iface; g_return_if_fail(INF_COMMUNICATION_IS_METHOD(method)); g_return_if_fail(INF_IS_XML_CONNECTION(connection)); g_return_if_fail(inf_communication_method_is_member(method, connection)); g_return_if_fail(xml != NULL); iface = INF_COMMUNICATION_METHOD_GET_IFACE(method); g_return_if_fail(iface->send_single != NULL); iface->send_single(method, connection, xml); } /** * inf_communication_method_send_all: * @method: A #InfCommunicationMethod. * @xml: (transfer full): The message to send. * * Sends an XML message to all group members on this network. This function * takes ownership of @xml. */ void inf_communication_method_send_all(InfCommunicationMethod* method, xmlNodePtr xml) { InfCommunicationMethodInterface* iface; g_return_if_fail(INF_COMMUNICATION_IS_METHOD(method)); g_return_if_fail(xml != NULL); iface = INF_COMMUNICATION_METHOD_GET_IFACE(method); g_return_if_fail(iface->send_all != NULL); iface->send_all(method, xml); } /** * inf_communication_method_cancel_messages: * @method: A #InfCommunicationMethod. * @connection: A #InfXmlConnection that is a group member. * * This function stops all messages to be sent to @connection that have not * yet been sent. */ void inf_communication_method_cancel_messages(InfCommunicationMethod* method, InfXmlConnection* connection) { InfCommunicationMethodInterface* iface; g_return_if_fail(INF_COMMUNICATION_IS_METHOD(method)); g_return_if_fail(INF_IS_XML_CONNECTION(connection)); iface = INF_COMMUNICATION_METHOD_GET_IFACE(method); g_return_if_fail(iface->cancel_messages != NULL); iface->cancel_messages(method, connection); } /** * inf_communication_method_received: * @method: A #InfCommunicationMethod. * @connection: A #InfXmlConnection that is a group member. * @xml: The received message. * * This function is called by the #InfCommunicationRegistry if data has been * received on registered connections * (see inf_communication_registry_register()). * * This function returns the scope of the message. If the scope is * %INF_COMMUNICATION_SCOPE_GROUP then the registry relays the message to * other connections on different networks (if any). * * Returns: The scope of the message. */ InfCommunicationScope inf_communication_method_received(InfCommunicationMethod* method, InfXmlConnection* connection, xmlNodePtr xml) { InfCommunicationMethodInterface* iface; g_return_val_if_fail(INF_COMMUNICATION_IS_METHOD(method), 0); g_return_val_if_fail(INF_IS_XML_CONNECTION(connection), 0); g_return_val_if_fail(inf_communication_method_is_member(method, connection), 0); g_return_val_if_fail(xml != NULL, 0); iface = INF_COMMUNICATION_METHOD_GET_IFACE(method); g_return_val_if_fail(iface->received != NULL, 0); return iface->received(method, connection, xml); } /** * inf_communication_method_enqueued: * @method: A #InfCommunicationMethod. * @connection: A #InfXmlConnection. * @xml: The enqueued message. * * This function is called by the #InfCommunicationRegistry if data has been * enqueued on registered connections * (see inf_communication_registry_register()). */ void inf_communication_method_enqueued(InfCommunicationMethod* method, InfXmlConnection* connection, xmlNodePtr xml) { InfCommunicationMethodInterface* iface; g_return_if_fail(INF_COMMUNICATION_IS_METHOD(method)); g_return_if_fail(INF_IS_XML_CONNECTION(connection)); g_return_if_fail(inf_communication_method_is_member(method, connection)); g_return_if_fail(xml != NULL); iface = INF_COMMUNICATION_METHOD_GET_IFACE(method); g_return_if_fail(iface->enqueued != NULL); iface->enqueued(method, connection, xml); } /** * inf_communication_method_sent: * @method: A #InfCommunicationMethod. * @connection: A #InfXmlConnection. * @xml: The sent message. * * This function is called by the #InfCommunicationRegistry if data has been * sent on registered connections (see inf_communication_registry_register()). */ void inf_communication_method_sent(InfCommunicationMethod* method, InfXmlConnection* connection, xmlNodePtr xml) { InfCommunicationMethodInterface* iface; g_return_if_fail(INF_COMMUNICATION_IS_METHOD(method)); g_return_if_fail(INF_IS_XML_CONNECTION(connection)); g_return_if_fail(inf_communication_method_is_member(method, connection)); g_return_if_fail(xml != NULL); iface = INF_COMMUNICATION_METHOD_GET_IFACE(method); g_return_if_fail(iface->sent != NULL); iface->sent(method, connection, xml); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/communication/PaxHeaders.26529/inf-communication-registry.h0000644000000000000000000000013213034342512026423 xustar0030 mtime=1483851082.041718492 30 atime=1483851082.041718492 30 ctime=1488261588.988139092 libinfinity-0.7.1/libinfinity/communication/inf-communication-registry.h0000644000175000017500000000740413034342512027162 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_COMMUNICATION_REGISTRY_H__ #define __INF_COMMUNICATION_REGISTRY_H__ #include #include #include G_BEGIN_DECLS #define INF_COMMUNICATION_TYPE_REGISTRY (inf_communication_registry_get_type()) #define INF_COMMUNICATION_REGISTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_COMMUNICATION_TYPE_REGISTRY, InfCommunicationRegistry)) #define INF_COMMUNICATION_REGISTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INF_COMMUNICATION_TYPE_REGISTRY, InfCommunicationRegistryClass)) #define INF_COMMUNICATION_IS_REGISTRY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_COMMUNICATION_TYPE_REGISTRY)) #define INF_COMMUNICATION_IS_REGISTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INF_COMMUNICATION_TYPE_REGISTRY)) #define INF_COMMUNICATION_REGISTRY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INF_COMMUNICATION_TYPE_REGISTRY, InfCommunicationRegistryClass)) typedef struct _InfCommunicationRegistry InfCommunicationRegistry; typedef struct _InfCommunicationRegistryClass InfCommunicationRegistryClass; /** * InfCommunicationRegistryClass: * * This structure does not contain any public fields. */ struct _InfCommunicationRegistryClass { /*< private >*/ GObjectClass parent; }; /** * InfCommunicationRegistry: * * #InfCommunicationRegistry is an opaque data type. You should only access it * via the public API functions. */ struct _InfCommunicationRegistry { /*< private >*/ GObject parent_instance; }; GType inf_communication_registry_get_type(void) G_GNUC_CONST; void inf_communication_registry_register(InfCommunicationRegistry* registry, InfCommunicationGroup* group, InfCommunicationMethod* method, InfXmlConnection* connection); void inf_communication_registry_unregister(InfCommunicationRegistry* registry, InfCommunicationGroup* group, InfXmlConnection* connection); gboolean inf_communication_registry_is_registered(InfCommunicationRegistry* registry, InfCommunicationGroup* group, InfXmlConnection* connection); void inf_communication_registry_send(InfCommunicationRegistry* registry, InfCommunicationGroup* group, InfXmlConnection* connection, xmlNodePtr xml); void inf_communication_registry_cancel_messages(InfCommunicationRegistry* registry, InfCommunicationGroup* group, InfXmlConnection* connection); G_END_DECLS #endif /* __INF_COMMUNICATION_REGISTRY_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinfinity/communication/PaxHeaders.26529/inf-communication-registry.c0000644000000000000000000000013213034342512026416 xustar0030 mtime=1483851082.041718492 30 atime=1483851082.041718492 30 ctime=1488261589.104138838 libinfinity-0.7.1/libinfinity/communication/inf-communication-registry.c0000644000175000017500000010067513034342512027161 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-communication-registry * @title: InfCommunicationRegistry * @short_description: Sharing connections between multiple groups * @include: libinfinity/communication/inf-communication-registry.h * @stability: Unstable * * #InfCommunicationRegistry provides a way for #InfCommunicationMethod * implementations to share connections with other groups. Before using a * connection, call inf_communication_registry_register(). Then, messages can * be sent to the group via inf_communication_registry_send(). * * The #InfCommunicationRegistry calls inf_communication_method_received() * on your method when it received a message for the group, * inf_communication_method_enqueued() when sending the message cannot be * cancelled anymore via inf_communication_registry_cancel_messages() and * inf_communication_method_sent() when the message has been sent. **/ #include #include #include #include #include /* TODO: Store connection->InfCommunicationRegistryConnection hashtable, * store network and remote_id there, only point to in key. */ typedef struct _InfCommunicationRegistryKey InfCommunicationRegistryKey; struct _InfCommunicationRegistryKey { InfXmlConnection* connection; gchar* publisher_id; const gchar* group_name; }; typedef struct _InfCommunicationRegistryEntry InfCommunicationRegistryEntry; struct _InfCommunicationRegistryEntry { InfCommunicationRegistry* registry; InfCommunicationRegistryKey key; const gchar* publisher_string; InfCommunicationGroup* group; InfCommunicationMethod* method; /* Queue of messages to send */ guint inner_count; xmlNodePtr queue_begin; xmlNodePtr queue_end; /* Activation status */ gboolean registered; guint activation_count; /* # messages to be sent until activation */ xmlNodePtr enqueued_list; xmlNodePtr sent_list; }; typedef struct _InfCommunicationRegistryForeachMethodData InfCommunicationRegistryForeachMethodData; struct _InfCommunicationRegistryForeachMethodData { InfCommunicationMethod* original_method; xmlNodePtr xml; }; typedef struct _InfCommunicationRegistryPrivate InfCommunicationRegistryPrivate; struct _InfCommunicationRegistryPrivate { GHashTable* connections; GHashTable* entries; }; #define INF_COMMUNICATION_REGISTRY_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INF_COMMUNICATION_TYPE_REGISTRY, InfCommunicationRegistryPrivate)) G_DEFINE_TYPE_WITH_CODE(InfCommunicationRegistry, inf_communication_registry, G_TYPE_OBJECT, G_ADD_PRIVATE(InfCommunicationRegistry)) /* Maximum number of messages enqueued at the same time */ static const guint INF_COMMUNICATION_REGISTRY_INNER_QUEUE_LIMIT = 5; static void inf_communication_registry_send_real(InfCommunicationRegistryEntry* entry, guint num_messages) { InfXmlConnection* connection; InfXmlConnectionStatus status; xmlNodePtr container; xmlNodePtr child; xmlNodePtr xml; guint i; container = xmlNewNode(NULL, (const xmlChar*)"group"); if(entry->publisher_string != NULL) { inf_xml_util_set_attribute( container, "publisher", entry->publisher_string ); } inf_xml_util_set_attribute(container, "name", entry->key.group_name); for(i = 0; i < num_messages && ((xml = entry->queue_begin) != NULL); ++ i) { entry->queue_begin = entry->queue_begin->next; if(entry->queue_begin == NULL) entry->queue_end = NULL; ++ entry->inner_count; xmlUnlinkNode(xml); xmlAddChild(container, xml); } /* Keep order of enqueued() calls and inf_xml_connection_send() calls * intact even if this function is run recursively in one of the * functions mentioned above. */ if(entry->enqueued_list != NULL) { entry->enqueued_list->next = container; entry->enqueued_list = container; } else { entry->enqueued_list = container; child = container; connection = entry->key.connection; g_object_ref(connection); g_object_get(G_OBJECT(connection), "status", &status, NULL); g_assert(status == INF_XML_CONNECTION_OPEN); while(child != NULL) { /* TODO: The group could be unset at this point if called from * inf_communication_registry_entry_free() in turn called by * inf_communication_registry_group_unrefed(). This can be removed if * we keep the group alive in that case, refer to the comment below in * inf_communication_registry_entry_free(). */ if(entry->group != NULL) { for(xml = child->children; xml != NULL; xml = xml->next) { inf_communication_method_enqueued(entry->method, connection, xml); } } if(child == entry->enqueued_list) entry->enqueued_list = NULL; xml = child; child = child->next; /* There are two possible cases at this point: * 1) We reached the end of the list. In that case, entry->enqueued_list * has been reset to NULL. This also means that we have sent everything * successfully. We will terminate this function after this call, so * a recursive call can just begin from scratch. * 2) entry->enqueued_list is not NULL. In this case, a recursive call * will simply append to entry->enqueued_list, and we will enqueue and * send the messages within the next iteration(s). */ inf_xml_connection_send(connection, xml); /* Break if sending the data lead to connection closure */ g_object_get(G_OBJECT(connection), "status", &status, NULL); if(status != INF_XML_CONNECTION_OPEN) break; } g_object_unref(connection); } } /* Required by inf_communication_registry_entry_free() */ static void inf_communication_registry_group_unrefed(gpointer user_data, GObject* where_the_object_was); static void inf_communication_registry_entry_free(gpointer data) { InfCommunicationRegistryEntry* entry; InfXmlConnectionStatus status; entry = (InfCommunicationRegistryEntry*)data; /* Send all messages directly as we are freed and can't keep them around * any longer. */ /* TODO: Ref the group on unregistration, so that the group stays alive * until all scheduled messages have been sent. In this case, the entry * will in no cases be freed, ane we can assert() here. When we do this, * we need to take into account the following: * 1) Assert in inf_communication_registry_group_unrefed() that the entry * is registered, as the group cannot be unrefed as long as we hold a * reference. * 2) Unref the group here, as we do with the connection. Do this after the * weak unref. * 3) Allow connection manager to return existing groups on join or host, * as the groups can live longer than people expect. */ g_object_get(G_OBJECT(entry->key.connection), "status", &status, NULL); if(status != INF_XML_CONNECTION_CLOSING && status != INF_XML_CONNECTION_CLOSED) { if(entry->queue_begin != NULL) inf_communication_registry_send_real(entry, G_MAXUINT); } if(entry->group) { g_object_weak_unref( G_OBJECT(entry->group), inf_communication_registry_group_unrefed, entry ); } if(!entry->registered) g_object_unref(entry->key.connection); g_free(entry->key.publisher_id); g_slice_free(InfCommunicationRegistryEntry, entry); } static guint inf_communication_registry_key_hash(gconstpointer key_) { const InfCommunicationRegistryKey* key; key = (const InfCommunicationRegistryKey*)key_; /* TODO: Is this a good hash function? */ return g_direct_hash(key->connection) ^ g_str_hash(key->publisher_id) ^ g_str_hash(key->group_name); } static int inf_communication_registry_key_cmp(gconstpointer first, gconstpointer second) { const InfCommunicationRegistryKey* first_key; const InfCommunicationRegistryKey* second_key; int res; first_key = (const InfCommunicationRegistryKey*)first; second_key = (const InfCommunicationRegistryKey*)second; if(first_key->connection < second_key->connection) return -1; if(first_key->connection > second_key->connection) return 1; res = strcmp(first_key->group_name, second_key->group_name); if(res != 0) return res; return strcmp(first_key->publisher_id, second_key->publisher_id); } static gboolean inf_communication_registry_key_equal(gconstpointer first, gconstpointer second) { return inf_communication_registry_key_cmp(first, second) == 0; } static void inf_communication_registry_foreach_method_func(InfCommunicationMethod* method, gpointer user_data) { InfCommunicationRegistryForeachMethodData* data; data = (InfCommunicationRegistryForeachMethodData*)user_data; /* TODO: Make sure that any callbacks in the send functions do not alter * the hash table which holds the methods in InfCommunicationGroup. */ if(method != data->original_method) inf_communication_method_send_all(method, xmlCopyNode(data->xml, 1)); } static void inf_communication_registry_received_cb(InfXmlConnection* connection, xmlNodePtr xml, gpointer user_data) { InfCommunicationRegistry* registry; InfCommunicationRegistryPrivate* priv; InfCommunicationRegistryKey key; InfCommunicationRegistryEntry* entry; xmlChar* group_name; xmlChar* publisher; xmlNodePtr child; InfCommunicationScope scope; InfCommunicationRegistryForeachMethodData data; registry = INF_COMMUNICATION_REGISTRY(user_data); priv = INF_COMMUNICATION_REGISTRY_PRIVATE(registry); group_name = xmlGetProp(xml, (const xmlChar*)"name"); if(group_name == NULL) return; publisher = xmlGetProp(xml, (const xmlChar*)"publisher"); if(publisher == NULL) { g_object_get(G_OBJECT(connection), "remote-id", &key.publisher_id, NULL); } else if(strcmp((const char*)publisher, "me") == 0) { g_object_get(G_OBJECT(connection), "remote-id", &key.publisher_id, NULL); xmlFree(publisher); publisher = NULL; } else if(strcmp((const char*)publisher, "you") == 0) { g_object_get(G_OBJECT(connection), "local-id", &key.publisher_id, NULL); xmlFree(publisher); publisher = NULL; } else { key.publisher_id = (gchar*)publisher; } key.connection = connection; key.group_name = (const gchar*)group_name; /* Relookup for each child to make sure the entry stays alive */ for(child = xml->children; child != NULL; child = child->next) { entry = g_hash_table_lookup(priv->entries, &key); if(entry != NULL && entry->registered == TRUE) { scope = inf_communication_method_received( entry->method, entry->key.connection, child ); /* If this was a group message then we relay it to any * other networks group is in. */ if(scope == INF_COMMUNICATION_SCOPE_GROUP) { data.original_method = entry->method; data.xml = child; _inf_communication_group_foreach_method( entry->group, inf_communication_registry_foreach_method_func, &data ); } } } if(publisher != NULL) xmlFree(publisher); else g_free(key.publisher_id); xmlFree(group_name); } static void inf_communication_registry_sent_cb(InfXmlConnection* connection, xmlNodePtr xml, gpointer user_data) { InfCommunicationRegistry* registry; InfCommunicationRegistryPrivate* priv; InfCommunicationRegistryEntry* entry; InfCommunicationRegistryKey key; xmlChar* publisher; xmlChar* group_name; xmlNodePtr child; xmlNodePtr cur; registry = INF_COMMUNICATION_REGISTRY(user_data); priv = INF_COMMUNICATION_REGISTRY_PRIVATE(registry); group_name = xmlGetProp(xml, (const xmlChar*)"name"); g_assert(group_name != NULL); publisher = xmlGetProp(xml, (const xmlChar*)"publisher"); if(publisher == NULL) { g_object_get(G_OBJECT(connection), "local-id", &key.publisher_id, NULL); } else if(strcmp((const char*)publisher, "me") == 0) { g_object_get(G_OBJECT(connection), "local-id", &key.publisher_id, NULL); xmlFree(publisher); publisher = NULL; } else if(strcmp((const char*)publisher, "you") == 0) { g_object_get(G_OBJECT(connection), "remote-id", &key.publisher_id, NULL); xmlFree(publisher); publisher = NULL; } else { key.publisher_id = (gchar*)publisher; } key.connection = connection; key.group_name = (const gchar*)group_name; entry = g_hash_table_lookup(priv->entries, &key); if(entry != NULL) { if(entry->sent_list != NULL) { entry->sent_list->next = xmlCopyNode(xml, 1); entry->sent_list = entry->sent_list->next; } else { entry->sent_list = xml; child = xml; while(child != NULL) { for(cur = child->children; cur != NULL; cur = cur->next) { g_assert(entry->inner_count > 0); /* Still registered */ if(entry->activation_count > 0) { -- entry->activation_count; } else { /* Must be registered if activation count is 0 */ g_assert(entry->registered == TRUE); inf_communication_method_sent( entry->method, entry->key.connection, cur ); /* If the callback did unregister us, then the activation count * was set (counting the message for which the callback was * called, since inner_count has not yet been decreased). We do * correct this here. */ if(entry->activation_count > 0) -- entry->activation_count; } -- entry->inner_count; } cur = child; child = child->next; if(cur == entry->sent_list) entry->sent_list = NULL; if(cur != xml) xmlFreeNode(cur); } } /* Messages have been sent, meaning the number of queued messages has * decreased, so we can send more messages now. */ /* Send next bunch of messages if inner_count reached zero, meaning no * more messages have been enqueued, for better packing. */ if(entry->inner_count == 0 && entry->queue_end != NULL) { inf_communication_registry_send_real( entry, INF_COMMUNICATION_REGISTRY_INNER_QUEUE_LIMIT - entry->inner_count ); } /* Free the entry in case all scheduled messages have been sent after * unregistration. */ if(entry->registered == FALSE && entry->activation_count == 0) g_hash_table_remove(priv->entries, &key); } if(publisher == NULL) g_free(key.publisher_id); else xmlFree(publisher); xmlFree(group_name); } static void inf_communication_registry_notify_status_cb(GObject* object, GParamSpec* pspec, gpointer user_data) { InfCommunicationRegistry* registry; InfCommunicationRegistryPrivate* priv; InfXmlConnectionStatus status; InfXmlConnection* connection; GHashTableIter iter; gpointer value; InfCommunicationRegistryEntry* entry; InfCommunicationGroup* group; gboolean registered; registry = INF_COMMUNICATION_REGISTRY(user_data); priv = INF_COMMUNICATION_REGISTRY_PRIVATE(registry); connection = INF_XML_CONNECTION(object); g_object_get(object, "status", &status, NULL); /* Free all entries that have been unregistered if the connection was * closed. */ if(status == INF_XML_CONNECTION_CLOSING || status == INF_XML_CONNECTION_CLOSED) { g_hash_table_iter_init(&iter, priv->entries); while(g_hash_table_iter_next(&iter, NULL, &value)) { entry = (InfCommunicationRegistryEntry*)value; if(entry->key.connection == connection) { group = g_object_ref(entry->group); registered = entry->registered; if(entry->registered == FALSE) g_hash_table_iter_remove(&iter); g_object_unref(group); } } } } static void inf_communication_registry_add_connection(InfCommunicationRegistry* registry, InfXmlConnection* connection) { InfCommunicationRegistryPrivate* priv; gpointer reg; priv = INF_COMMUNICATION_REGISTRY_PRIVATE(registry); reg = g_hash_table_lookup(priv->connections, connection); g_hash_table_steal(priv->connections, connection); if(reg == NULL) { g_hash_table_insert( priv->connections, connection, GUINT_TO_POINTER(1) ); g_object_ref(connection); g_signal_connect_after( G_OBJECT(connection), "received", G_CALLBACK(inf_communication_registry_received_cb), registry ); g_signal_connect_after( G_OBJECT(connection), "sent", G_CALLBACK(inf_communication_registry_sent_cb), registry ); g_signal_connect( G_OBJECT(connection), "notify::status", G_CALLBACK(inf_communication_registry_notify_status_cb), registry ); } else { g_hash_table_insert( priv->connections, connection, GUINT_TO_POINTER(1+GPOINTER_TO_UINT(reg)) ); } } static void inf_communication_registry_remove_connection(InfCommunicationRegistry* rgstry, InfXmlConnection* connection) { InfCommunicationRegistryPrivate* priv; gpointer reg; guint count; priv = INF_COMMUNICATION_REGISTRY_PRIVATE(rgstry); reg = g_hash_table_lookup(priv->connections, connection); g_assert(reg != NULL); g_hash_table_steal(priv->connections, connection); count = GPOINTER_TO_UINT(reg); if(--count > 0) { g_hash_table_insert( priv->connections, connection, GUINT_TO_POINTER(count) ); } else { inf_signal_handlers_disconnect_by_func( G_OBJECT(connection), G_CALLBACK(inf_communication_registry_received_cb), rgstry ); inf_signal_handlers_disconnect_by_func( G_OBJECT(connection), G_CALLBACK(inf_communication_registry_sent_cb), rgstry ); inf_signal_handlers_disconnect_by_func( G_OBJECT(connection), G_CALLBACK(inf_communication_registry_notify_status_cb), rgstry ); g_object_unref(connection); } } static void inf_communication_registry_group_unrefed(gpointer user_data, GObject* where_the_object_was) { InfCommunicationRegistryEntry* entry; InfCommunicationRegistry* registry; InfCommunicationRegistryPrivate* priv; GHashTableIter iter; gpointer value; InfXmlConnection* connection; gboolean registered; entry = (InfCommunicationRegistryEntry*)user_data; registry = entry->registry; priv = INF_COMMUNICATION_REGISTRY_PRIVATE(registry); /* This is completely valid if the connection was unregistered, only * sending final scheduled messages. */ if(entry->registered == TRUE) g_warning("An unrefed group still had registered connections"); /* The group has already been finalized, so we can't remove the group by * key since group_name in the entry's key pointed to group's memory. */ g_hash_table_iter_init(&iter, priv->entries); while(g_hash_table_iter_next(&iter, NULL, &value)) { if(value == entry) { connection = entry->key.connection; registered = entry->registered; /* So inf_communication_registry_entry_free() does not try to weak unref * the non-existing group: */ entry->group = NULL; /* TODO: This relies on entry->key.group_name being still valid. * valgrind suggests it is. However, I don't feel confident with this. * I this can be properly fixed when we keep the group alive for * unregistered connections, refer to the comment in * inf_communication_registry_entry_free(). */ g_hash_table_iter_remove(&iter); if(registered == TRUE) inf_communication_registry_remove_connection(registry, connection); break; } } } /* * GObject overrides. */ static void inf_communication_registry_init(InfCommunicationRegistry* registry) { InfCommunicationRegistryPrivate* priv; priv = INF_COMMUNICATION_REGISTRY_PRIVATE(registry); priv->connections = g_hash_table_new(NULL, NULL); priv->entries = g_hash_table_new_full( inf_communication_registry_key_hash, inf_communication_registry_key_equal, NULL, inf_communication_registry_entry_free ); } static void inf_communication_registry_dispose(GObject* object) { InfCommunicationRegistry* registry; InfCommunicationRegistryPrivate* priv; GHashTableIter iter; gpointer key; registry = INF_COMMUNICATION_REGISTRY(object); priv = INF_COMMUNICATION_REGISTRY_PRIVATE(registry); if(g_hash_table_size(priv->connections)) { g_warning( "There are still registered connections on communication " "registry dispose" ); /* Release all connections. We can't rely on a key FreeFunc since * the signal handlers cannot be disconnected easily this way as we * don't have access to the registry in the FreeFunc. */ g_hash_table_iter_init(&iter, priv->connections); while(g_hash_table_iter_next(&iter, &key, NULL)) { inf_signal_handlers_disconnect_by_func( G_OBJECT(key), G_CALLBACK(inf_communication_registry_received_cb), registry ); inf_signal_handlers_disconnect_by_func( G_OBJECT(key), G_CALLBACK(inf_communication_registry_sent_cb), registry ); inf_signal_handlers_disconnect_by_func( G_OBJECT(key), G_CALLBACK(inf_communication_registry_notify_status_cb), registry ); g_object_unref(key); } } g_hash_table_unref(priv->connections); g_hash_table_unref(priv->entries); G_OBJECT_CLASS(inf_communication_registry_parent_class)->dispose(object); } static void inf_communication_registry_class_init( InfCommunicationRegistryClass* registry_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(registry_class); object_class->dispose = inf_communication_registry_dispose; } /** * inf_communication_registry_register: * @registry: A #InfCommunicationRegistry. * @group: The group for which to register a connection. * @method: The #InfCommunicationMethod used. * @connection: The connection to register. * * Registers connection with @group. This allows sending messages to * @connection via inf_communication_registry_send(). For received messages, * inf_communication_method_received() is called on @method. * * @connection must have status %INF_XML_CONNECTION_OPEN. */ void inf_communication_registry_register(InfCommunicationRegistry* registry, InfCommunicationGroup* group, InfCommunicationMethod* method, InfXmlConnection* connection) { InfCommunicationRegistryPrivate* priv; InfCommunicationRegistryKey key; InfCommunicationRegistryEntry* entry; InfXmlConnectionStatus status; gchar* local_id; gchar* remote_id; g_return_if_fail(INF_COMMUNICATION_IS_REGISTRY(registry)); g_return_if_fail(INF_COMMUNICATION_IS_GROUP(group)); g_return_if_fail(INF_COMMUNICATION_IS_METHOD(method)); g_return_if_fail(INF_IS_XML_CONNECTION(connection)); g_object_get(G_OBJECT(connection), "status", &status, NULL); g_return_if_fail(status == INF_XML_CONNECTION_OPEN); priv = INF_COMMUNICATION_REGISTRY_PRIVATE(registry); key.connection = connection; key.publisher_id = inf_communication_group_get_publisher_id(group, connection); key.group_name = inf_communication_group_get_name(group); inf_communication_registry_add_connection(registry, connection); entry = g_hash_table_lookup(priv->entries, &key); if(entry != NULL) { /* Reactivation */ g_assert(entry->registered == FALSE); entry->registered = TRUE; } else { entry = g_slice_new(InfCommunicationRegistryEntry); entry->registry = registry; entry->key = key; g_object_get( G_OBJECT(connection), "remote-id", &remote_id, "local-id", &local_id, NULL ); if(strcmp(remote_id, key.publisher_id) == 0) entry->publisher_string = "you"; else if(strcmp(local_id, key.publisher_id) == 0) entry->publisher_string = NULL; /* "me" */ else entry->publisher_string = entry->key.publisher_id; g_free(remote_id); g_free(local_id); entry->group = group; entry->method = method; entry->inner_count = 0; entry->queue_begin = NULL; entry->queue_end = NULL; entry->registered = TRUE; entry->activation_count = 0; entry->enqueued_list = NULL; entry->sent_list = NULL; g_object_weak_ref( G_OBJECT(group), inf_communication_registry_group_unrefed, entry ); g_hash_table_insert(priv->entries, &entry->key, entry); } } /** * inf_communication_registry_unregister: * @registry: A #InfCommunicationRegistry. * @group: The group for which to unregister a connection. * @connection: The connection to unregister. * * Unregisters @connection from @group. Incoming messages are no longer * reported to group's method, and inf_communication_registry_send() can * no longer be called for @connection. */ void inf_communication_registry_unregister(InfCommunicationRegistry* registry, InfCommunicationGroup* group, InfXmlConnection* connection) { InfCommunicationRegistryPrivate* priv; InfCommunicationRegistryKey key; InfCommunicationRegistryEntry* entry; InfXmlConnectionStatus status; xmlNodePtr xml; g_return_if_fail(INF_COMMUNICATION_IS_REGISTRY(registry)); g_return_if_fail(INF_COMMUNICATION_IS_GROUP(group)); g_return_if_fail(INF_IS_XML_CONNECTION(connection)); g_object_get(G_OBJECT(connection), "status", &status, NULL); priv = INF_COMMUNICATION_REGISTRY_PRIVATE(registry); key.connection = connection; key.publisher_id = inf_communication_group_get_publisher_id(group, connection); key.group_name = inf_communication_group_get_name(group); entry = g_hash_table_lookup(priv->entries, &key); g_assert(entry != NULL && entry->registered == TRUE); if( (entry->queue_end != NULL || entry->inner_count > 0) && status != INF_XML_CONNECTION_CLOSING && status != INF_XML_CONNECTION_CLOSED) { /* The entry has still messages to send, so don't remove it right now * but wait until all scheduled messages have been sent. */ entry->registered = FALSE; entry->activation_count = entry->inner_count; for(xml = entry->queue_begin; xml != NULL; xml = xml->next) ++ entry->activation_count; g_assert(entry->activation_count > 0); /* Keep an additional reference on the connection as the connection will * be unregistered below. */ g_object_ref(connection); } else { /* No scheduled messages, remove entry */ g_hash_table_remove(priv->entries, &key); } g_free(key.publisher_id); inf_communication_registry_remove_connection(registry, connection); } /** * inf_communication_registry_is_registered: * @registry: A #InfCommunicationRegistry. * @group: The group for which to check whether @connection is registered. * @connection: The connection to check for registration. * * Returns whether @connection has been registered for @group with * inf_communication_registry_register(). * * Returns: %TRUE if @connection has been registered, or %FALSE otherwise. */ gboolean inf_communication_registry_is_registered(InfCommunicationRegistry* registry, InfCommunicationGroup* group, InfXmlConnection* connection) { InfCommunicationRegistryPrivate* priv; InfCommunicationRegistryKey key; InfCommunicationRegistryEntry* entry; g_return_val_if_fail(INF_COMMUNICATION_IS_REGISTRY(registry), FALSE); g_return_val_if_fail(INF_COMMUNICATION_IS_GROUP(group), FALSE); g_return_val_if_fail(INF_IS_XML_CONNECTION(connection), FALSE); priv = INF_COMMUNICATION_REGISTRY_PRIVATE(registry); key.connection = connection; key.publisher_id = inf_communication_group_get_publisher_id(group, connection); key.group_name = inf_communication_group_get_name(group); entry = g_hash_table_lookup(priv->entries, &key); g_free(key.publisher_id); return entry != NULL && entry->registered == TRUE; } /** * inf_communication_registry_send: * @registry: A #InfCommunicationRegistry. * @group: The group for which to send the message #InfCommunicationGroup. * @connection: A registered #InfXmlConnection. * @xml: (transfer full): The message to send. * * Sends an XML message to @connection. @connection must have been registered * with inf_communication_registry_register() before. If the message has been * sent, inf_communication_method_sent() is called on the method the * connection was registered with. inf_communication_method_enqueued() is * called when sending the message can no longer be cancelled via * inf_communication_registry_cancel_messages(). * * This function takes ownership of @xml. */ void inf_communication_registry_send(InfCommunicationRegistry* registry, InfCommunicationGroup* group, InfXmlConnection* connection, xmlNodePtr xml) { InfCommunicationRegistryPrivate* priv; InfCommunicationRegistryKey key; InfCommunicationRegistryEntry* entry; g_return_if_fail(INF_COMMUNICATION_IS_REGISTRY(registry)); g_return_if_fail(INF_COMMUNICATION_IS_GROUP(group)); g_return_if_fail(INF_IS_XML_CONNECTION(connection)); g_return_if_fail(xml != NULL); priv = INF_COMMUNICATION_REGISTRY_PRIVATE(registry); key.connection = connection; key.publisher_id = inf_communication_group_get_publisher_id(group, connection); key.group_name = inf_communication_group_get_name(group); entry = g_hash_table_lookup(priv->entries, &key); g_assert(entry != NULL && entry->registered == TRUE); xmlUnlinkNode(xml); if(entry->queue_end == NULL) { entry->queue_begin = xml; entry->queue_end = xml; } else { entry->queue_end->next = xml; entry->queue_end = xml; } /* If there is something in the inner queue, don't send directly but wait * until the message has been sent, for better packing. */ if(entry->inner_count == 0) { inf_communication_registry_send_real( entry, INF_COMMUNICATION_REGISTRY_INNER_QUEUE_LIMIT - entry->inner_count ); } g_free(key.publisher_id); } /** * inf_communication_registry_cancel_messages: * @registry: A #InfCommunicationRegistry. * @group: The group for which to cancel messages. * @connection: A registered #InfXmlConnection. * * Stops all messages scheduled to be sent to @connection in @group from being * sent. */ void inf_communication_registry_cancel_messages(InfCommunicationRegistry* registry, InfCommunicationGroup* group, InfXmlConnection* connection) { InfCommunicationRegistryPrivate* priv; InfCommunicationRegistryKey key; InfCommunicationRegistryEntry* entry; g_return_if_fail(INF_COMMUNICATION_IS_REGISTRY(registry)); g_return_if_fail(INF_COMMUNICATION_IS_GROUP(group)); g_return_if_fail(INF_IS_XML_CONNECTION(connection)); priv = INF_COMMUNICATION_REGISTRY_PRIVATE(registry); key.connection = connection; key.publisher_id = inf_communication_group_get_publisher_id(group, connection); key.group_name = inf_communication_group_get_name(group); entry = g_hash_table_lookup(priv->entries, &key); g_assert(entry != NULL && entry->registered == TRUE); /* TODO: Don't cancel messages prior activation? */ xmlFreeNodeList(entry->queue_begin); entry->queue_begin = NULL; entry->queue_end = NULL; g_free(key.publisher_id); } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/PaxHeaders.26529/libinfinity.pc.in0000644000000000000000000000013213034342512017051 xustar0030 mtime=1483851082.021718383 30 atime=1483851082.021718383 30 ctime=1488261588.756139598 libinfinity-0.7.1/libinfinity.pc.in0000644000175000017500000000053213034342512017603 0ustar00arminarmin00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: libinfinity Description: Infinote core library Requires: glib-2.0 >= 2.38 gobject-2.0 >= 2.38 libxml-2.0 gnutls libgsasl Version: @VERSION@ Libs: -L${libdir} -linfinity-@LIBINFINITY_API_VERSION@ Cflags: -I${includedir}/libinfinity-@LIBINFINITY_API_VERSION@ libinfinity-0.7.1/PaxHeaders.26529/m40000644000000000000000000000013213055210724014045 xustar0030 mtime=1488261588.748139616 30 atime=1488261588.732139651 30 ctime=1488261588.748139616 libinfinity-0.7.1/m4/0000755000175000017500000000000013055210724014654 5ustar00arminarmin00000000000000libinfinity-0.7.1/m4/PaxHeaders.26529/ltversion.m40000644000000000000000000000013213036062675016422 xustar0030 mtime=1484285373.379887415 30 atime=1484285373.379887415 30 ctime=1488261588.748139616 libinfinity-0.7.1/m4/ltversion.m40000644000175000017500000000127313036062675017157 0ustar00arminarmin00000000000000# ltversion.m4 -- version numbers -*- Autoconf -*- # # Copyright (C) 2004, 2011-2015 Free Software Foundation, Inc. # Written by Scott James Remnant, 2004 # # This file 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. # @configure_input@ # serial 4179 ltversion.m4 # This file is part of GNU Libtool m4_define([LT_PACKAGE_VERSION], [2.4.6]) m4_define([LT_PACKAGE_REVISION], [2.4.6]) AC_DEFUN([LTVERSION_VERSION], [macro_version='2.4.6' macro_revision='2.4.6' _LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) _LT_DECL(, macro_revision, 0) ]) libinfinity-0.7.1/m4/PaxHeaders.26529/lt~obsolete.m40000644000000000000000000000013213036062675016747 xustar0030 mtime=1484285373.391887424 30 atime=1484285373.391887424 30 ctime=1488261588.748139616 libinfinity-0.7.1/m4/lt~obsolete.m40000644000175000017500000001377413036062675017515 0ustar00arminarmin00000000000000# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- # # Copyright (C) 2004-2005, 2007, 2009, 2011-2015 Free Software # Foundation, Inc. # Written by Scott James Remnant, 2004. # # This file 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. # serial 5 lt~obsolete.m4 # These exist entirely to fool aclocal when bootstrapping libtool. # # In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN), # which have later been changed to m4_define as they aren't part of the # exported API, or moved to Autoconf or Automake where they belong. # # The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN # in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us # using a macro with the same name in our local m4/libtool.m4 it'll # pull the old libtool.m4 in (it doesn't see our shiny new m4_define # and doesn't know about Autoconf macros at all.) # # So we provide this file, which has a silly filename so it's always # included after everything else. This provides aclocal with the # AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything # because those macros already exist, or will be overwritten later. # We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. # # Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. # Yes, that means every name once taken will need to remain here until # we give up compatibility with versions before 1.7, at which point # we need to keep only those names which we still refer to. # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) libinfinity-0.7.1/m4/PaxHeaders.26529/libtool.m40000644000000000000000000000013213036062675016041 xustar0030 mtime=1484285373.339887382 30 atime=1484285373.339887382 30 ctime=1488261588.744139625 libinfinity-0.7.1/m4/libtool.m40000644000175000017500000112617113036062675016604 0ustar00arminarmin00000000000000# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- # # Copyright (C) 1996-2001, 2003-2015 Free Software Foundation, Inc. # Written by Gordon Matzigkeit, 1996 # # This file 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. m4_define([_LT_COPYING], [dnl # Copyright (C) 2014 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # GNU Libtool is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of of the License, or # (at your option) any later version. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program or library that is built # using GNU Libtool, you may include this file under the same # distribution terms that you use for the rest of that program. # # GNU Libtool is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ]) # serial 58 LT_INIT # LT_PREREQ(VERSION) # ------------------ # Complain and exit if this libtool version is less that VERSION. m4_defun([LT_PREREQ], [m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, [m4_default([$3], [m4_fatal([Libtool version $1 or higher is required], 63)])], [$2])]) # _LT_CHECK_BUILDDIR # ------------------ # Complain if the absolute build directory name contains unusual characters m4_defun([_LT_CHECK_BUILDDIR], [case `pwd` in *\ * | *\ *) AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; esac ]) # LT_INIT([OPTIONS]) # ------------------ AC_DEFUN([LT_INIT], [AC_PREREQ([2.62])dnl We use AC_PATH_PROGS_FEATURE_CHECK AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl AC_BEFORE([$0], [LT_LANG])dnl AC_BEFORE([$0], [LT_OUTPUT])dnl AC_BEFORE([$0], [LTDL_INIT])dnl m4_require([_LT_CHECK_BUILDDIR])dnl dnl Autoconf doesn't catch unexpanded LT_ macros by default: m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 dnl unless we require an AC_DEFUNed macro: AC_REQUIRE([LTOPTIONS_VERSION])dnl AC_REQUIRE([LTSUGAR_VERSION])dnl AC_REQUIRE([LTVERSION_VERSION])dnl AC_REQUIRE([LTOBSOLETE_VERSION])dnl m4_require([_LT_PROG_LTMAIN])dnl _LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) dnl Parse OPTIONS _LT_SET_OPTIONS([$0], [$1]) # This can be used to rebuild libtool when needed LIBTOOL_DEPS=$ltmain # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' AC_SUBST(LIBTOOL)dnl _LT_SETUP # Only expand once: m4_define([LT_INIT]) ])# LT_INIT # Old names: AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PROG_LIBTOOL], []) dnl AC_DEFUN([AM_PROG_LIBTOOL], []) # _LT_PREPARE_CC_BASENAME # ----------------------- m4_defun([_LT_PREPARE_CC_BASENAME], [ # Calculate cc_basename. Skip known compiler wrappers and cross-prefix. func_cc_basename () { for cc_temp in @S|@*""; do case $cc_temp in compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; \-*) ;; *) break;; esac done func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` } ])# _LT_PREPARE_CC_BASENAME # _LT_CC_BASENAME(CC) # ------------------- # It would be clearer to call AC_REQUIREs from _LT_PREPARE_CC_BASENAME, # but that macro is also expanded into generated libtool script, which # arranges for $SED and $ECHO to be set by different means. m4_defun([_LT_CC_BASENAME], [m4_require([_LT_PREPARE_CC_BASENAME])dnl AC_REQUIRE([_LT_DECL_SED])dnl AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl func_cc_basename $1 cc_basename=$func_cc_basename_result ]) # _LT_FILEUTILS_DEFAULTS # ---------------------- # It is okay to use these file commands and assume they have been set # sensibly after 'm4_require([_LT_FILEUTILS_DEFAULTS])'. m4_defun([_LT_FILEUTILS_DEFAULTS], [: ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} ])# _LT_FILEUTILS_DEFAULTS # _LT_SETUP # --------- m4_defun([_LT_SETUP], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl _LT_DECL([], [PATH_SEPARATOR], [1], [The PATH separator for the build system])dnl dnl _LT_DECL([], [host_alias], [0], [The host system])dnl _LT_DECL([], [host], [0])dnl _LT_DECL([], [host_os], [0])dnl dnl _LT_DECL([], [build_alias], [0], [The build system])dnl _LT_DECL([], [build], [0])dnl _LT_DECL([], [build_os], [0])dnl dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl dnl AC_REQUIRE([AC_PROG_LN_S])dnl test -z "$LN_S" && LN_S="ln -s" _LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl dnl AC_REQUIRE([LT_CMD_MAX_LEN])dnl _LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl _LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl m4_require([_LT_PATH_CONVERSION_FUNCTIONS])dnl m4_require([_LT_CMD_RELOAD])dnl m4_require([_LT_CHECK_MAGIC_METHOD])dnl m4_require([_LT_CHECK_SHAREDLIB_FROM_LINKLIB])dnl m4_require([_LT_CMD_OLD_ARCHIVE])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_WITH_SYSROOT])dnl m4_require([_LT_CMD_TRUNCATE])dnl _LT_CONFIG_LIBTOOL_INIT([ # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi ]) if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi _LT_CHECK_OBJDIR m4_require([_LT_TAG_COMPILER])dnl case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a '.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a with_gnu_ld=$lt_cv_prog_gnu_ld old_CC=$CC old_CFLAGS=$CFLAGS # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o _LT_CC_BASENAME([$compiler]) # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then _LT_PATH_MAGIC fi ;; esac # Use C for the default configuration in the libtool script LT_SUPPORTED_TAG([CC]) _LT_LANG_C_CONFIG _LT_LANG_DEFAULT_CONFIG _LT_CONFIG_COMMANDS ])# _LT_SETUP # _LT_PREPARE_SED_QUOTE_VARS # -------------------------- # Define a few sed substitution that help us do robust quoting. m4_defun([_LT_PREPARE_SED_QUOTE_VARS], [# Backslashify metacharacters that are still active within # double-quoted strings. sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\([["`\\]]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' ]) # _LT_PROG_LTMAIN # --------------- # Note that this code is called both from 'configure', and 'config.status' # now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, # 'config.status' has no value for ac_aux_dir unless we are using Automake, # so we pass a copy along to make sure it has a sensible value anyway. m4_defun([_LT_PROG_LTMAIN], [m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl _LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) ltmain=$ac_aux_dir/ltmain.sh ])# _LT_PROG_LTMAIN ## ------------------------------------- ## ## Accumulate code for creating libtool. ## ## ------------------------------------- ## # So that we can recreate a full libtool script including additional # tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS # in macros and then make a single call at the end using the 'libtool' # label. # _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) # ---------------------------------------- # Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL_INIT], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_INIT], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_INIT]) # _LT_CONFIG_LIBTOOL([COMMANDS]) # ------------------------------ # Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. m4_define([_LT_CONFIG_LIBTOOL], [m4_ifval([$1], [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], [$1 ])])]) # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) # _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) # ----------------------------------------------------- m4_defun([_LT_CONFIG_SAVE_COMMANDS], [_LT_CONFIG_LIBTOOL([$1]) _LT_CONFIG_LIBTOOL_INIT([$2]) ]) # _LT_FORMAT_COMMENT([COMMENT]) # ----------------------------- # Add leading comment marks to the start of each line, and a trailing # full-stop to the whole comment if one is not present already. m4_define([_LT_FORMAT_COMMENT], [m4_ifval([$1], [ m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) )]) ## ------------------------ ## ## FIXME: Eliminate VARNAME ## ## ------------------------ ## # _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) # ------------------------------------------------------------------- # CONFIGNAME is the name given to the value in the libtool script. # VARNAME is the (base) name used in the configure script. # VALUE may be 0, 1 or 2 for a computed quote escaped value based on # VARNAME. Any other value will be used directly. m4_define([_LT_DECL], [lt_if_append_uniq([lt_decl_varnames], [$2], [, ], [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], [m4_ifval([$1], [$1], [$2])]) lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) m4_ifval([$4], [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) lt_dict_add_subkey([lt_decl_dict], [$2], [tagged?], [m4_ifval([$5], [yes], [no])])]) ]) # _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) # -------------------------------------------------------- m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) # lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_tag_varnames], [_lt_decl_filter([tagged?], [yes], $@)]) # _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) # --------------------------------------------------------- m4_define([_lt_decl_filter], [m4_case([$#], [0], [m4_fatal([$0: too few arguments: $#])], [1], [m4_fatal([$0: too few arguments: $#: $1])], [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], [lt_dict_filter([lt_decl_dict], $@)])[]dnl ]) # lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) # -------------------------------------------------- m4_define([lt_decl_quote_varnames], [_lt_decl_filter([value], [1], $@)]) # lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_dquote_varnames], [_lt_decl_filter([value], [2], $@)]) # lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) # --------------------------------------------------- m4_define([lt_decl_varnames_tagged], [m4_assert([$# <= 2])dnl _$0(m4_quote(m4_default([$1], [[, ]])), m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) m4_define([_lt_decl_varnames_tagged], [m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) # lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) # ------------------------------------------------ m4_define([lt_decl_all_varnames], [_$0(m4_quote(m4_default([$1], [[, ]])), m4_if([$2], [], m4_quote(lt_decl_varnames), m4_quote(m4_shift($@))))[]dnl ]) m4_define([_lt_decl_all_varnames], [lt_join($@, lt_decl_varnames_tagged([$1], lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl ]) # _LT_CONFIG_STATUS_DECLARE([VARNAME]) # ------------------------------------ # Quote a variable value, and forward it to 'config.status' so that its # declaration there will have the same value as in 'configure'. VARNAME # must have a single quote delimited value for this to work. m4_define([_LT_CONFIG_STATUS_DECLARE], [$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) # _LT_CONFIG_STATUS_DECLARATIONS # ------------------------------ # We delimit libtool config variables with single quotes, so when # we write them to config.status, we have to be sure to quote all # embedded single quotes properly. In configure, this macro expands # each variable declared with _LT_DECL (and _LT_TAGDECL) into: # # ='`$ECHO "$" | $SED "$delay_single_quote_subst"`' m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], [m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAGS # ---------------- # Output comment and list of tags supported by the script m4_defun([_LT_LIBTOOL_TAGS], [_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl available_tags='_LT_TAGS'dnl ]) # _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) # ----------------------------------- # Extract the dictionary values for VARNAME (optionally with TAG) and # expand to a commented shell variable setting: # # # Some comment about what VAR is for. # visible_name=$lt_internal_name m4_define([_LT_LIBTOOL_DECLARE], [_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [description])))[]dnl m4_pushdef([_libtool_name], m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), [0], [_libtool_name=[$]$1], [1], [_libtool_name=$lt_[]$1], [2], [_libtool_name=$lt_[]$1], [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl ]) # _LT_LIBTOOL_CONFIG_VARS # ----------------------- # Produce commented declarations of non-tagged libtool config variables # suitable for insertion in the LIBTOOL CONFIG section of the 'libtool' # script. Tagged libtool config variables (even for the LIBTOOL CONFIG # section) are produced by _LT_LIBTOOL_TAG_VARS. m4_defun([_LT_LIBTOOL_CONFIG_VARS], [m4_foreach([_lt_var], m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) # _LT_LIBTOOL_TAG_VARS(TAG) # ------------------------- m4_define([_LT_LIBTOOL_TAG_VARS], [m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) # _LT_TAGVAR(VARNAME, [TAGNAME]) # ------------------------------ m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) # _LT_CONFIG_COMMANDS # ------------------- # Send accumulated output to $CONFIG_STATUS. Thanks to the lists of # variables for single and double quote escaping we saved from calls # to _LT_DECL, we can put quote escaped variables declarations # into 'config.status', and then the shell code to quote escape them in # for loops in 'config.status'. Finally, any additional code accumulated # from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. m4_defun([_LT_CONFIG_COMMANDS], [AC_PROVIDE_IFELSE([LT_OUTPUT], dnl If the libtool generation code has been placed in $CONFIG_LT, dnl instead of duplicating it all over again into config.status, dnl then we will have config.status run $CONFIG_LT later, so it dnl needs to know what name is stored there: [AC_CONFIG_COMMANDS([libtool], [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], dnl If the libtool generation code is destined for config.status, dnl expand the accumulated commands and init code now: [AC_CONFIG_COMMANDS([libtool], [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) ])#_LT_CONFIG_COMMANDS # Initialize. m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], [ # The HP-UX ksh and POSIX shell print the target directory to stdout # if CDPATH is set. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' _LT_CONFIG_STATUS_DECLARATIONS LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$[]1 _LTECHO_EOF' } # Quote evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_quote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_dquote_varnames); do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done _LT_OUTPUT_LIBTOOL_INIT ]) # _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) # ------------------------------------ # Generate a child script FILE with all initialization necessary to # reuse the environment learned by the parent script, and make the # file executable. If COMMENT is supplied, it is inserted after the # '#!' sequence but before initialization text begins. After this # macro, additional text can be appended to FILE to form the body of # the child script. The macro ends with non-zero status if the # file could not be fully written (such as if the disk is full). m4_ifdef([AS_INIT_GENERATED], [m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], [m4_defun([_LT_GENERATED_FILE_INIT], [m4_require([AS_PREPARE])]dnl [m4_pushdef([AS_MESSAGE_LOG_FD])]dnl [lt_write_fail=0 cat >$1 <<_ASEOF || lt_write_fail=1 #! $SHELL # Generated by $as_me. $2 SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$1 <<\_ASEOF || lt_write_fail=1 AS_SHELL_SANITIZE _AS_PREPARE exec AS_MESSAGE_FD>&1 _ASEOF test 0 = "$lt_write_fail" && chmod +x $1[]dnl m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT # LT_OUTPUT # --------- # This macro allows early generation of the libtool script (before # AC_OUTPUT is called), incase it is used in configure for compilation # tests. AC_DEFUN([LT_OUTPUT], [: ${CONFIG_LT=./config.lt} AC_MSG_NOTICE([creating $CONFIG_LT]) _LT_GENERATED_FILE_INIT(["$CONFIG_LT"], [# Run this file to recreate a libtool stub with the current configuration.]) cat >>"$CONFIG_LT" <<\_LTEOF lt_cl_silent=false exec AS_MESSAGE_LOG_FD>>config.log { echo AS_BOX([Running $as_me.]) } >&AS_MESSAGE_LOG_FD lt_cl_help="\ '$as_me' creates a local libtool stub from the current configuration, for use in further configure time tests before the real libtool is generated. Usage: $[0] [[OPTIONS]] -h, --help print this help, then exit -V, --version print version number, then exit -q, --quiet do not print progress messages -d, --debug don't remove temporary files Report bugs to ." lt_cl_version="\ m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) configured by $[0], generated by m4_PACKAGE_STRING. Copyright (C) 2011 Free Software Foundation, Inc. This config.lt script is free software; the Free Software Foundation gives unlimited permision to copy, distribute and modify it." while test 0 != $[#] do case $[1] in --version | --v* | -V ) echo "$lt_cl_version"; exit 0 ;; --help | --h* | -h ) echo "$lt_cl_help"; exit 0 ;; --debug | --d* | -d ) debug=: ;; --quiet | --q* | --silent | --s* | -q ) lt_cl_silent=: ;; -*) AC_MSG_ERROR([unrecognized option: $[1] Try '$[0] --help' for more information.]) ;; *) AC_MSG_ERROR([unrecognized argument: $[1] Try '$[0] --help' for more information.]) ;; esac shift done if $lt_cl_silent; then exec AS_MESSAGE_FD>/dev/null fi _LTEOF cat >>"$CONFIG_LT" <<_LTEOF _LT_OUTPUT_LIBTOOL_COMMANDS_INIT _LTEOF cat >>"$CONFIG_LT" <<\_LTEOF AC_MSG_NOTICE([creating $ofile]) _LT_OUTPUT_LIBTOOL_COMMANDS AS_EXIT(0) _LTEOF chmod +x "$CONFIG_LT" # configure is writing to config.log, but config.lt does its own redirection, # appending to config.log, which fails on DOS, as config.log is still kept # open by configure. Here we exec the FD to /dev/null, effectively closing # config.log, so it can be properly (re)opened and appended to by config.lt. lt_cl_success=: test yes = "$silent" && lt_config_lt_args="$lt_config_lt_args --quiet" exec AS_MESSAGE_LOG_FD>/dev/null $SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false exec AS_MESSAGE_LOG_FD>>config.log $lt_cl_success || AS_EXIT(1) ])# LT_OUTPUT # _LT_CONFIG(TAG) # --------------- # If TAG is the built-in tag, create an initial libtool script with a # default configuration from the untagged config vars. Otherwise add code # to config.status for appending the configuration named by TAG from the # matching tagged config vars. m4_defun([_LT_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_CONFIG_SAVE_COMMANDS([ m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl m4_if(_LT_TAG, [C], [ # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi cfgfile=${ofile}T trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # Generated automatically by $as_me ($PACKAGE) $VERSION # NOTE: Changes made to this file will be lost: look at ltmain.sh. # Provide generalized library-building support services. # Written by Gordon Matzigkeit, 1996 _LT_COPYING _LT_LIBTOOL_TAGS # Configured defaults for sys_lib_dlsearch_path munging. : \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} # ### BEGIN LIBTOOL CONFIG _LT_LIBTOOL_CONFIG_VARS _LT_LIBTOOL_TAG_VARS # ### END LIBTOOL CONFIG _LT_EOF cat <<'_LT_EOF' >> "$cfgfile" # ### BEGIN FUNCTIONS SHARED WITH CONFIGURE _LT_PREPARE_MUNGE_PATH_LIST _LT_PREPARE_CC_BASENAME # ### END FUNCTIONS SHARED WITH CONFIGURE _LT_EOF case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac _LT_PROG_LTMAIN # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" ], [cat <<_LT_EOF >> "$ofile" dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded dnl in a comment (ie after a #). # ### BEGIN LIBTOOL TAG CONFIG: $1 _LT_LIBTOOL_TAG_VARS(_LT_TAG) # ### END LIBTOOL TAG CONFIG: $1 _LT_EOF ])dnl /m4_if ], [m4_if([$1], [], [ PACKAGE='$PACKAGE' VERSION='$VERSION' RM='$RM' ofile='$ofile'], []) ])dnl /_LT_CONFIG_SAVE_COMMANDS ])# _LT_CONFIG # LT_SUPPORTED_TAG(TAG) # --------------------- # Trace this macro to discover what tags are supported by the libtool # --tag option, using: # autoconf --trace 'LT_SUPPORTED_TAG:$1' AC_DEFUN([LT_SUPPORTED_TAG], []) # C support is built-in for now m4_define([_LT_LANG_C_enabled], []) m4_define([_LT_TAGS], []) # LT_LANG(LANG) # ------------- # Enable libtool support for the given language if not already enabled. AC_DEFUN([LT_LANG], [AC_BEFORE([$0], [LT_OUTPUT])dnl m4_case([$1], [C], [_LT_LANG(C)], [C++], [_LT_LANG(CXX)], [Go], [_LT_LANG(GO)], [Java], [_LT_LANG(GCJ)], [Fortran 77], [_LT_LANG(F77)], [Fortran], [_LT_LANG(FC)], [Windows Resource], [_LT_LANG(RC)], [m4_ifdef([_LT_LANG_]$1[_CONFIG], [_LT_LANG($1)], [m4_fatal([$0: unsupported language: "$1"])])])dnl ])# LT_LANG # _LT_LANG(LANGNAME) # ------------------ m4_defun([_LT_LANG], [m4_ifdef([_LT_LANG_]$1[_enabled], [], [LT_SUPPORTED_TAG([$1])dnl m4_append([_LT_TAGS], [$1 ])dnl m4_define([_LT_LANG_]$1[_enabled], [])dnl _LT_LANG_$1_CONFIG($1)])dnl ])# _LT_LANG m4_ifndef([AC_PROG_GO], [ ############################################################ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_GO. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # ############################################################ m4_defun([AC_PROG_GO], [AC_LANG_PUSH(Go)dnl AC_ARG_VAR([GOC], [Go compiler command])dnl AC_ARG_VAR([GOFLAGS], [Go compiler flags])dnl _AC_ARG_VAR_LDFLAGS()dnl AC_CHECK_TOOL(GOC, gccgo) if test -z "$GOC"; then if test -n "$ac_tool_prefix"; then AC_CHECK_PROG(GOC, [${ac_tool_prefix}gccgo], [${ac_tool_prefix}gccgo]) fi fi if test -z "$GOC"; then AC_CHECK_PROG(GOC, gccgo, gccgo, false) fi ])#m4_defun ])#m4_ifndef # _LT_LANG_DEFAULT_CONFIG # ----------------------- m4_defun([_LT_LANG_DEFAULT_CONFIG], [AC_PROVIDE_IFELSE([AC_PROG_CXX], [LT_LANG(CXX)], [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) AC_PROVIDE_IFELSE([AC_PROG_F77], [LT_LANG(F77)], [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) AC_PROVIDE_IFELSE([AC_PROG_FC], [LT_LANG(FC)], [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal dnl pulling things in needlessly. AC_PROVIDE_IFELSE([AC_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], [LT_LANG(GCJ)], [AC_PROVIDE_IFELSE([LT_PROG_GCJ], [LT_LANG(GCJ)], [m4_ifdef([AC_PROG_GCJ], [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([A][M_PROG_GCJ], [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) m4_ifdef([LT_PROG_GCJ], [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) AC_PROVIDE_IFELSE([AC_PROG_GO], [LT_LANG(GO)], [m4_define([AC_PROG_GO], defn([AC_PROG_GO])[LT_LANG(GO)])]) AC_PROVIDE_IFELSE([LT_PROG_RC], [LT_LANG(RC)], [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) ])# _LT_LANG_DEFAULT_CONFIG # Obsolete macros: AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_CXX], []) dnl AC_DEFUN([AC_LIBTOOL_F77], []) dnl AC_DEFUN([AC_LIBTOOL_FC], []) dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) dnl AC_DEFUN([AC_LIBTOOL_RC], []) # _LT_TAG_COMPILER # ---------------- m4_defun([_LT_TAG_COMPILER], [AC_REQUIRE([AC_PROG_CC])dnl _LT_DECL([LTCC], [CC], [1], [A C compiler])dnl _LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl _LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl _LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC ])# _LT_TAG_COMPILER # _LT_COMPILER_BOILERPLATE # ------------------------ # Check for compiler boilerplate output or warnings with # the simple compiler test code. m4_defun([_LT_COMPILER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ])# _LT_COMPILER_BOILERPLATE # _LT_LINKER_BOILERPLATE # ---------------------- # Check for linker boilerplate output or warnings with # the simple link test code. m4_defun([_LT_LINKER_BOILERPLATE], [m4_require([_LT_DECL_SED])dnl ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* ])# _LT_LINKER_BOILERPLATE # _LT_REQUIRED_DARWIN_CHECKS # ------------------------- m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ case $host_os in rhapsody* | darwin*) AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) AC_CHECK_TOOL([LIPO], [lipo], [:]) AC_CHECK_TOOL([OTOOL], [otool], [:]) AC_CHECK_TOOL([OTOOL64], [otool64], [:]) _LT_DECL([], [DSYMUTIL], [1], [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) _LT_DECL([], [NMEDIT], [1], [Tool to change global to local symbols on Mac OS X]) _LT_DECL([], [LIPO], [1], [Tool to manipulate fat objects and archives on Mac OS X]) _LT_DECL([], [OTOOL], [1], [ldd/readelf like tool for Mach-O binaries on Mac OS X]) _LT_DECL([], [OTOOL64], [1], [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], [lt_cv_apple_cc_single_mod=no if test -z "$LT_MULTI_MODULE"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? # If there is a non-empty error log, and "single_module" # appears in it, assume the flag caused a linker warning if test -s conftest.err && $GREP single_module conftest.err; then cat conftest.err >&AS_MESSAGE_LOG_FD # Otherwise, if the output was created with a 0 exit code from # the compiler, it worked. elif test -f libconftest.dylib && test 0 = "$_lt_result"; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&AS_MESSAGE_LOG_FD fi rm -rf libconftest.dylib* rm -f conftest.* fi]) AC_CACHE_CHECK([for -exported_symbols_list linker flag], [lt_cv_ld_exported_symbols_list], [lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [lt_cv_ld_exported_symbols_list=yes], [lt_cv_ld_exported_symbols_list=no]) LDFLAGS=$save_LDFLAGS ]) AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], [lt_cv_ld_force_load=no cat > conftest.c << _LT_EOF int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD cat > conftest.c << _LT_EOF int main() { return 0;} _LT_EOF echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err _lt_result=$? if test -s conftest.err && $GREP force_load conftest.err; then cat conftest.err >&AS_MESSAGE_LOG_FD elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then lt_cv_ld_force_load=yes else cat conftest.err >&AS_MESSAGE_LOG_FD fi rm -f conftest.err libconftest.a conftest conftest.c rm -rf conftest.dSYM ]) case $host_os in rhapsody* | darwin1.[[012]]) _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; 10.[[012]][[,.]]*) _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; 10.*) _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test yes = "$lt_cv_apple_cc_single_mod"; then _lt_dar_single_mod='$single_module' fi if test yes = "$lt_cv_ld_exported_symbols_list"; then _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' fi if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac ]) # _LT_DARWIN_LINKER_FEATURES([TAG]) # --------------------------------- # Checks for linker and compiler features on darwin m4_defun([_LT_DARWIN_LINKER_FEATURES], [ m4_require([_LT_REQUIRED_DARWIN_CHECKS]) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported if test yes = "$lt_cv_ld_force_load"; then _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' m4_case([$1], [F77], [_LT_TAGVAR(compiler_needs_object, $1)=yes], [FC], [_LT_TAGVAR(compiler_needs_object, $1)=yes]) else _LT_TAGVAR(whole_archive_flag_spec, $1)='' fi _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=$_lt_dar_allow_undefined case $cc_basename in ifort*|nagfor*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test yes = "$_lt_dar_can_shared"; then output_verbose_link_cmd=func_echo_all _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" m4_if([$1], [CXX], [ if test yes != "$lt_cv_apple_cc_single_mod"; then _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dsymutil" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \$lib-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$lib-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring$_lt_dar_export_syms$_lt_dsymutil" fi ],[]) else _LT_TAGVAR(ld_shlibs, $1)=no fi ]) # _LT_SYS_MODULE_PATH_AIX([TAGNAME]) # ---------------------------------- # Links a minimal program and checks the executable # for the system default hardcoded library path. In most cases, # this is /usr/lib:/lib, but when the MPI compilers are used # the location of the communication and MPI libs are included too. # If we don't find anything, use the default library path according # to the aix ld manual. # Store the results from the different compilers for each TAGNAME. # Allow to override them for all tags through lt_cv_aix_libpath. m4_defun([_LT_SYS_MODULE_PATH_AIX], [m4_require([_LT_DECL_SED])dnl if test set = "${lt_cv_aix_libpath+set}"; then aix_libpath=$lt_cv_aix_libpath else AC_CACHE_VAL([_LT_TAGVAR([lt_cv_aix_libpath_], [$1])], [AC_LINK_IFELSE([AC_LANG_PROGRAM],[ lt_aix_libpath_sed='[ /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }]' _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi],[]) if test -z "$_LT_TAGVAR([lt_cv_aix_libpath_], [$1])"; then _LT_TAGVAR([lt_cv_aix_libpath_], [$1])=/usr/lib:/lib fi ]) aix_libpath=$_LT_TAGVAR([lt_cv_aix_libpath_], [$1]) fi ])# _LT_SYS_MODULE_PATH_AIX # _LT_SHELL_INIT(ARG) # ------------------- m4_define([_LT_SHELL_INIT], [m4_divert_text([M4SH-INIT], [$1 ])])# _LT_SHELL_INIT # _LT_PROG_ECHO_BACKSLASH # ----------------------- # Find how we can fake an echo command that does not interpret backslash. # In particular, with Autoconf 2.60 or later we add some code to the start # of the generated configure script that will find a shell with a builtin # printf (that we can use as an echo command). m4_defun([_LT_PROG_ECHO_BACKSLASH], [ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO AC_MSG_CHECKING([how to print strings]) # Test print first, because it will be a builtin if present. if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='print -r --' elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='printf %s\n' else # Use this function as a fallback that always works. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $[]1 _LTECHO_EOF' } ECHO='func_fallback_echo' fi # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "$*" } case $ECHO in printf*) AC_MSG_RESULT([printf]) ;; print*) AC_MSG_RESULT([print -r]) ;; *) AC_MSG_RESULT([cat]) ;; esac m4_ifdef([_AS_DETECT_SUGGESTED], [_AS_DETECT_SUGGESTED([ test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || ( ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO PATH=/empty FPATH=/empty; export PATH FPATH test "X`printf %s $ECHO`" = "X$ECHO" \ || test "X`print -r -- $ECHO`" = "X$ECHO" )])]) _LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) _LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) ])# _LT_PROG_ECHO_BACKSLASH # _LT_WITH_SYSROOT # ---------------- AC_DEFUN([_LT_WITH_SYSROOT], [AC_MSG_CHECKING([for sysroot]) AC_ARG_WITH([sysroot], [AS_HELP_STRING([--with-sysroot@<:@=DIR@:>@], [Search for dependent libraries within DIR (or the compiler's sysroot if not specified).])], [], [with_sysroot=no]) dnl lt_sysroot will always be passed unquoted. We quote it here dnl in case the user passed a directory name. lt_sysroot= case $with_sysroot in #( yes) if test yes = "$GCC"; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( /*) lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` ;; #( no|'') ;; #( *) AC_MSG_RESULT([$with_sysroot]) AC_MSG_ERROR([The sysroot must be an absolute path.]) ;; esac AC_MSG_RESULT([${lt_sysroot:-no}]) _LT_DECL([], [lt_sysroot], [0], [The root where to search for ]dnl [dependent libraries, and where our libraries should be installed.])]) # _LT_ENABLE_LOCK # --------------- m4_defun([_LT_ENABLE_LOCK], [AC_ARG_ENABLE([libtool-lock], [AS_HELP_STRING([--disable-libtool-lock], [avoid locking (might break parallel builds)])]) test no = "$enable_libtool_lock" || enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out what ABI is being produced by ac_compile, and set mode # options accordingly. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE=32 ;; *ELF-64*) HPUX_IA64_MODE=64 ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then if test yes = "$lt_cv_prog_gnu_ld"; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; mips64*-*linux*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then emul=elf case `/usr/bin/file conftest.$ac_objext` in *32-bit*) emul="${emul}32" ;; *64-bit*) emul="${emul}64" ;; esac case `/usr/bin/file conftest.$ac_objext` in *MSB*) emul="${emul}btsmip" ;; *LSB*) emul="${emul}ltsmip" ;; esac case `/usr/bin/file conftest.$ac_objext` in *N32*) emul="${emul}n32" ;; esac LD="${LD-ld} -m $emul" fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. Note that the listed cases only cover the # situations where additional linker options are needed (such as when # doing 32-bit compilation for a host where ld defaults to 64-bit, or # vice versa); the common cases where no linker options are needed do # not appear in the list. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) case `/usr/bin/file conftest.o` in *x86-64*) LD="${LD-ld} -m elf32_x86_64" ;; *) LD="${LD-ld} -m elf_i386" ;; esac ;; powerpc64le-*linux*) LD="${LD-ld} -m elf32lppclinux" ;; powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; powerpcle-*linux*) LD="${LD-ld} -m elf64lppc" ;; powerpc-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS=$CFLAGS CFLAGS="$CFLAGS -belf" AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, [AC_LANG_PUSH(C) AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) AC_LANG_POP]) if test yes != "$lt_cv_cc_needs_belf"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS=$SAVE_CFLAGS fi ;; *-*solaris*) # Find out what ABI is being produced by ac_compile, and set linker # options accordingly. echo 'int i;' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) case $host in i?86-*-solaris*|x86_64-*-solaris*) LD="${LD-ld} -m elf_x86_64" ;; sparc*-*-solaris*) LD="${LD-ld} -m elf64_sparc" ;; esac # GNU ld 2.21 introduced _sol2 emulations. Use them if available. if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then LD=${LD-ld}_sol2 fi ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks=$enable_libtool_lock ])# _LT_ENABLE_LOCK # _LT_PROG_AR # ----------- m4_defun([_LT_PROG_AR], [AC_CHECK_TOOLS(AR, [ar], false) : ${AR=ar} : ${AR_FLAGS=cru} _LT_DECL([], [AR], [1], [The archiver]) _LT_DECL([], [AR_FLAGS], [1], [Flags to create an archive]) AC_CACHE_CHECK([for archiver @FILE support], [lt_cv_ar_at_file], [lt_cv_ar_at_file=no AC_COMPILE_IFELSE([AC_LANG_PROGRAM], [echo conftest.$ac_objext > conftest.lst lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&AS_MESSAGE_LOG_FD' AC_TRY_EVAL([lt_ar_try]) if test 0 -eq "$ac_status"; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a AC_TRY_EVAL([lt_ar_try]) if test 0 -ne "$ac_status"; then lt_cv_ar_at_file=@ fi fi rm -f conftest.* libconftest.a ]) ]) if test no = "$lt_cv_ar_at_file"; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file fi _LT_DECL([], [archiver_list_spec], [1], [How to feed a file listing to the archiver]) ])# _LT_PROG_AR # _LT_CMD_OLD_ARCHIVE # ------------------- m4_defun([_LT_CMD_OLD_ARCHIVE], [_LT_PROG_AR AC_CHECK_TOOL(STRIP, strip, :) test -z "$STRIP" && STRIP=: _LT_DECL([], [STRIP], [1], [A symbol stripping program]) AC_CHECK_TOOL(RANLIB, ranlib, :) test -z "$RANLIB" && RANLIB=: _LT_DECL([], [RANLIB], [1], [Commands used to install an old-style archive]) # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in bitrig* | openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" fi case $host_os in darwin*) lock_old_archive_extraction=yes ;; *) lock_old_archive_extraction=no ;; esac _LT_DECL([], [old_postinstall_cmds], [2]) _LT_DECL([], [old_postuninstall_cmds], [2]) _LT_TAGDECL([], [old_archive_cmds], [2], [Commands used to build an old-style archive]) _LT_DECL([], [lock_old_archive_extraction], [0], [Whether to use a lock for old archive extraction]) ])# _LT_CMD_OLD_ARCHIVE # _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------------------- # Check whether the given compiler option works AC_DEFUN([_LT_COMPILER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$3" ## exclude from sc_useless_quotes_in_assignment # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi fi $RM conftest* ]) if test yes = "[$]$2"; then m4_if([$5], , :, [$5]) else m4_if([$6], , :, [$6]) fi ])# _LT_COMPILER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) # _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, # [ACTION-SUCCESS], [ACTION-FAILURE]) # ---------------------------------------------------- # Check whether the given linker option works AC_DEFUN([_LT_LINKER_OPTION], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_SED])dnl AC_CACHE_CHECK([$1], [$2], [$2=no save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS $3" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&AS_MESSAGE_LOG_FD $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then $2=yes fi else $2=yes fi fi $RM -r conftest* LDFLAGS=$save_LDFLAGS ]) if test yes = "[$]$2"; then m4_if([$4], , :, [$4]) else m4_if([$5], , :, [$5]) fi ])# _LT_LINKER_OPTION # Old name: AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) # LT_CMD_MAX_LEN #--------------- AC_DEFUN([LT_CMD_MAX_LEN], [AC_REQUIRE([AC_CANONICAL_HOST])dnl # find the maximum length of command line arguments AC_MSG_CHECKING([the maximum length of command line arguments]) AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl i=0 teststring=ABCD case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; mint*) # On MiNT this can take a long time and run out of memory. lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; os2*) # The test takes a long time on OS/2. lt_cv_sys_max_cmd_len=8192 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len" && \ test undefined != "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while { test X`env echo "$teststring$teststring" 2>/dev/null` \ = "X$teststring$teststring"; } >/dev/null 2>&1 && test 17 != "$i" # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` teststring= # Add a significant safety factor because C++ compilers can tack on # massive amounts of additional arguments before passing them to the # linker. It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac ]) if test -n "$lt_cv_sys_max_cmd_len"; then AC_MSG_RESULT($lt_cv_sys_max_cmd_len) else AC_MSG_RESULT(none) fi max_cmd_len=$lt_cv_sys_max_cmd_len _LT_DECL([], [max_cmd_len], [0], [What is the maximum length of a command?]) ])# LT_CMD_MAX_LEN # Old name: AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) # _LT_HEADER_DLFCN # ---------------- m4_defun([_LT_HEADER_DLFCN], [AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl ])# _LT_HEADER_DLFCN # _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, # ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) # ---------------------------------------------------------------- m4_defun([_LT_TRY_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test yes = "$cross_compiling"; then : [$4] else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF [#line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisibility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; }] _LT_EOF if AC_TRY_EVAL(ac_link) && test -s "conftest$ac_exeext" 2>/dev/null; then (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) $1 ;; x$lt_dlneed_uscore) $2 ;; x$lt_dlunknown|x*) $3 ;; esac else : # compilation failed $3 fi fi rm -fr conftest* ])# _LT_TRY_DLOPEN_SELF # LT_SYS_DLOPEN_SELF # ------------------ AC_DEFUN([LT_SYS_DLOPEN_SELF], [m4_require([_LT_HEADER_DLFCN])dnl if test yes != "$enable_dlopen"; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen=load_add_on lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) lt_cv_dlopen=LoadLibrary lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen=dlopen lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl],[ lt_cv_dlopen=dyld lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ]) ;; tpf*) # Don't try to run any link tests for TPF. We know it's impossible # because TPF is a cross-compiler, and we know how we open DSOs. lt_cv_dlopen=dlopen lt_cv_dlopen_libs= lt_cv_dlopen_self=no ;; *) AC_CHECK_FUNC([shl_load], [lt_cv_dlopen=shl_load], [AC_CHECK_LIB([dld], [shl_load], [lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld], [AC_CHECK_FUNC([dlopen], [lt_cv_dlopen=dlopen], [AC_CHECK_LIB([dl], [dlopen], [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl], [AC_CHECK_LIB([svld], [dlopen], [lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld], [AC_CHECK_LIB([dld], [dld_link], [lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld]) ]) ]) ]) ]) ]) ;; esac if test no = "$lt_cv_dlopen"; then enable_dlopen=no else enable_dlopen=yes fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS=$CPPFLAGS test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS=$LDFLAGS wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS=$LIBS LIBS="$lt_cv_dlopen_libs $LIBS" AC_CACHE_CHECK([whether a program can dlopen itself], lt_cv_dlopen_self, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) ]) if test yes = "$lt_cv_dlopen_self"; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" AC_CACHE_CHECK([whether a statically linked program can dlopen itself], lt_cv_dlopen_self_static, [dnl _LT_TRY_DLOPEN_SELF( lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) ]) fi CPPFLAGS=$save_CPPFLAGS LDFLAGS=$save_LDFLAGS LIBS=$save_LIBS ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi _LT_DECL([dlopen_support], [enable_dlopen], [0], [Whether dlopen is supported]) _LT_DECL([dlopen_self], [enable_dlopen_self], [0], [Whether dlopen of programs is supported]) _LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], [Whether dlopen of statically linked programs is supported]) ])# LT_SYS_DLOPEN_SELF # Old name: AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) # _LT_COMPILER_C_O([TAGNAME]) # --------------------------- # Check to see if options -c and -o are simultaneously supported by compiler. # This macro does not hard code the compiler like AC_PROG_CC_C_O. m4_defun([_LT_COMPILER_C_O], [m4_require([_LT_DECL_SED])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&AS_MESSAGE_LOG_FD echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes fi fi chmod u+w . 2>&AS_MESSAGE_LOG_FD $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* ]) _LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], [Does compiler simultaneously support -c and -o options?]) ])# _LT_COMPILER_C_O # _LT_COMPILER_FILE_LOCKS([TAGNAME]) # ---------------------------------- # Check to see if we can do hard links to lock some files if needed m4_defun([_LT_COMPILER_FILE_LOCKS], [m4_require([_LT_ENABLE_LOCK])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl _LT_COMPILER_C_O([$1]) hard_links=nottested if test no = "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" && test no != "$need_locks"; then # do not overwrite the value of need_locks provided by the user AC_MSG_CHECKING([if we can lock with hard links]) hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no AC_MSG_RESULT([$hard_links]) if test no = "$hard_links"; then AC_MSG_WARN(['$CC' does not support '-c -o', so 'make -j' may be unsafe]) need_locks=warn fi else need_locks=no fi _LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) ])# _LT_COMPILER_FILE_LOCKS # _LT_CHECK_OBJDIR # ---------------- m4_defun([_LT_CHECK_OBJDIR], [AC_CACHE_CHECK([for objdir], [lt_cv_objdir], [rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null]) objdir=$lt_cv_objdir _LT_DECL([], [objdir], [0], [The name of the directory that contains temporary libtool files])dnl m4_pattern_allow([LT_OBJDIR])dnl AC_DEFINE_UNQUOTED([LT_OBJDIR], "$lt_cv_objdir/", [Define to the sub-directory where libtool stores uninstalled libraries.]) ])# _LT_CHECK_OBJDIR # _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) # -------------------------------------- # Check hardcoding attributes. m4_defun([_LT_LINKER_HARDCODE_LIBPATH], [AC_MSG_CHECKING([how to hardcode library paths into programs]) _LT_TAGVAR(hardcode_action, $1)= if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || test -n "$_LT_TAGVAR(runpath_var, $1)" || test yes = "$_LT_TAGVAR(hardcode_automatic, $1)"; then # We can hardcode non-existent directories. if test no != "$_LT_TAGVAR(hardcode_direct, $1)" && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" && test no != "$_LT_TAGVAR(hardcode_minus_L, $1)"; then # Linking always hardcodes the temporary library directory. _LT_TAGVAR(hardcode_action, $1)=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. _LT_TAGVAR(hardcode_action, $1)=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. _LT_TAGVAR(hardcode_action, $1)=unsupported fi AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) if test relink = "$_LT_TAGVAR(hardcode_action, $1)" || test yes = "$_LT_TAGVAR(inherit_rpath, $1)"; then # Fast installation is not supported enable_fast_install=no elif test yes = "$shlibpath_overrides_runpath" || test no = "$enable_shared"; then # Fast installation is not necessary enable_fast_install=needless fi _LT_TAGDECL([], [hardcode_action], [0], [How to hardcode a shared library path into an executable]) ])# _LT_LINKER_HARDCODE_LIBPATH # _LT_CMD_STRIPLIB # ---------------- m4_defun([_LT_CMD_STRIPLIB], [m4_require([_LT_DECL_EGREP]) striplib= old_striplib= AC_MSG_CHECKING([whether stripping libraries is possible]) if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" AC_MSG_RESULT([yes]) else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP"; then striplib="$STRIP -x" old_striplib="$STRIP -S" AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi ;; *) AC_MSG_RESULT([no]) ;; esac fi _LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) _LT_DECL([], [striplib], [1]) ])# _LT_CMD_STRIPLIB # _LT_PREPARE_MUNGE_PATH_LIST # --------------------------- # Make sure func_munge_path_list() is defined correctly. m4_defun([_LT_PREPARE_MUNGE_PATH_LIST], [[# func_munge_path_list VARIABLE PATH # ----------------------------------- # VARIABLE is name of variable containing _space_ separated list of # directories to be munged by the contents of PATH, which is string # having a format: # "DIR[:DIR]:" # string "DIR[ DIR]" will be prepended to VARIABLE # ":DIR[:DIR]" # string "DIR[ DIR]" will be appended to VARIABLE # "DIRP[:DIRP]::[DIRA:]DIRA" # string "DIRP[ DIRP]" will be prepended to VARIABLE and string # "DIRA[ DIRA]" will be appended to VARIABLE # "DIR[:DIR]" # VARIABLE will be replaced by "DIR[ DIR]" func_munge_path_list () { case x@S|@2 in x) ;; *:) eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'` \@S|@@S|@1\" ;; x:*) eval @S|@1=\"\@S|@@S|@1 `$ECHO @S|@2 | $SED 's/:/ /g'`\" ;; *::*) eval @S|@1=\"\@S|@@S|@1\ `$ECHO @S|@2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" eval @S|@1=\"`$ECHO @S|@2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \@S|@@S|@1\" ;; *) eval @S|@1=\"`$ECHO @S|@2 | $SED 's/:/ /g'`\" ;; esac } ]])# _LT_PREPARE_PATH_LIST # _LT_SYS_DYNAMIC_LINKER([TAG]) # ----------------------------- # PORTME Fill in your ld.so characteristics m4_defun([_LT_SYS_DYNAMIC_LINKER], [AC_REQUIRE([AC_CANONICAL_HOST])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_OBJDUMP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CHECK_SHELL_FEATURES])dnl m4_require([_LT_PREPARE_MUNGE_PATH_LIST])dnl AC_MSG_CHECKING([dynamic linker characteristics]) m4_if([$1], [], [ if test yes = "$GCC"; then case $host_os in darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; *) lt_awk_arg='/^libraries:/' ;; esac case $host_os in mingw* | cegcc*) lt_sed_strip_eq='s|=\([[A-Za-z]]:\)|\1|g' ;; *) lt_sed_strip_eq='s|=/|/|g' ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in *\;*) # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` ;; *) lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` ;; esac # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary... lt_tmp_lt_search_path_spec= lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` # ...but if some path component already ends with the multilib dir we assume # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). case "$lt_multi_os_dir; $lt_search_path_spec " in "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) lt_multi_os_dir= ;; esac for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" elif test -n "$lt_multi_os_dir"; then test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' BEGIN {RS = " "; FS = "/|\n";} { lt_foo = ""; lt_count = 0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo = "/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[[lt_foo]]++; } if (lt_freq[[lt_foo]] == 1) { print lt_foo; } }'` # AWK program above erroneously prepends '/' to C:/dos/paths # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ $SED 's|/\([[A-Za-z]]:\)|\1|g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi]) library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=.so postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown AC_ARG_VAR([LT_SYS_LIBRARY_PATH], [User-defined run-time library search path.]) case $host_os in aix3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='$libname$release$shared_ext$major' ;; aix[[4-9]]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes if test ia64 = "$host_cpu"; then # AIX 5 supports IA64 library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line '#! .'. This would cause the generated library to # depend on '.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[[01]] | aix4.[[01]].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # Using Import Files as archive members, it is possible to support # filename-based versioning of shared library archives on AIX. While # this would work for both with and without runtime linking, it will # prevent static linking of such archives. So we do filename-based # shared library versioning with .so extension only, which is used # when both runtime linking and shared linking is enabled. # Unfortunately, runtime linking may impact performance, so we do # not want this to be the default eventually. Also, we use the # versioned .so libs for executables only if there is the -brtl # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. # To allow for filename-based versioning support, we need to create # libNAME.so.V as an archive file, containing: # *) an Import File, referring to the versioned filename of the # archive as well as the shared archive member, telling the # bitwidth (32 or 64) of that shared object, and providing the # list of exported symbols of that shared object, eventually # decorated with the 'weak' keyword # *) the shared object with the F_LOADONLY flag set, to really avoid # it being seen by the linker. # At run time we better use the real file rather than another symlink, # but for link time we create the symlink libNAME.so -> libNAME.so.V case $with_aix_soname,$aix_use_runtimelinking in # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. aix,yes) # traditional libtool dynamic_linker='AIX unversionable lib.so' # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; aix,no) # traditional AIX only dynamic_linker='AIX lib.a[(]lib.so.V[)]' # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' ;; svr4,*) # full svr4 only dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)]" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,yes) # both, prefer svr4 dynamic_linker="AIX lib.so.V[(]$shared_archive_member_spec.o[)], lib.a[(]lib.so.V[)]" library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' # unpreferred sharedlib libNAME.a needs extra handling postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' # We do not specify a path in Import Files, so LIBPATH fires. shlibpath_overrides_runpath=yes ;; *,no) # both, prefer aix dynamic_linker="AIX lib.a[(]lib.so.V[)], lib.so.V[(]$shared_archive_member_spec.o[)]" library_names_spec='$libname$release.a $libname.a' soname_spec='$libname$release$shared_ext$major' # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' ;; esac shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='$libname$shared_ext' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[[45]]*) version_type=linux # correct to gnu/linux during the next big refactor need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl*) # Native MSVC libname_spec='$name' soname_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext' library_names_spec='$libname.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([[a-zA-Z]]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec=$LIB if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC wrapper library_names_spec='$libname`echo $release | $SED -e 's/[[.]]/-/g'`$versuffix$shared_ext $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' soname_spec='$libname$release$major$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[[23]].*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[[01]]* | freebsdelf3.[[01]]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; haiku*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=no sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' if test 32 = "$HPUX_IA64_MODE"; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" sys_lib_dlsearch_path_spec=/usr/lib/hpux32 else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" sys_lib_dlsearch_path_spec=/usr/lib/hpux64 fi ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[[3-9]]*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test yes = "$lt_cv_prog_gnu_ld"; then version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; linux*android*) version_type=none # Android doesn't support versioned libraries. need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext' soname_spec='$libname$release$shared_ext' finish_cmds= shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes dynamic_linker='Android linker' # Don't embed -rpath directories since the linker doesn't support them. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], [lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], [lt_cv_shlibpath_overrides_runpath=yes])]) LDFLAGS=$save_LDFLAGS libdir=$save_libdir ]) shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Ideally, we could use ldconfig to report *all* directores which are # searched for libraries, however this is still not possible. Aside from not # being certain /sbin/ldconfig is available, command # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, # even though it is searched at run-time. Try to do the best guess by # appending ld.so.conf contents (and includes) to the search path. if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsdelf*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='NetBSD ld.elf_so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd* | bitrig*) version_type=sunos sys_lib_dlsearch_path_spec=/usr/lib need_lib_prefix=no if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then need_version=no else need_version=yes fi library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; os2*) libname_spec='$name' version_type=windows shrext_cmds=.dll need_version=no need_lib_prefix=no # OS/2 can only load a DLL with a base name of 8 characters or less. soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; v=$($ECHO $release$versuffix | tr -d .-); n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); $ECHO $n$v`$shared_ext' library_names_spec='${libname}_dll.$libext' dynamic_linker='OS/2 ld.exe' shlibpath_var=BEGINLIBPATH sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec postinstall_cmds='base_file=`basename \$file`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='$libname$release$shared_ext$major' library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test yes = "$with_gnu_ld"; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec; then version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' soname_spec='$libname$shared_ext.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=sco need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test yes = "$with_gnu_ld"; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux # correct to gnu/linux during the next big refactor library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac AC_MSG_RESULT([$dynamic_linker]) test no = "$dynamic_linker" && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test yes = "$GCC"; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec fi if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec fi # remember unaugmented sys_lib_dlsearch_path content for libtool script decls... configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec # ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" # to be used as default LT_SYS_LIBRARY_PATH value in generated libtool configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH _LT_DECL([], [variables_saved_for_relink], [1], [Variables whose values should be saved in libtool wrapper scripts and restored at link time]) _LT_DECL([], [need_lib_prefix], [0], [Do we need the "lib" prefix for modules?]) _LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) _LT_DECL([], [version_type], [0], [Library versioning type]) _LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) _LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) _LT_DECL([], [shlibpath_overrides_runpath], [0], [Is shlibpath searched before the hard-coded library search path?]) _LT_DECL([], [libname_spec], [1], [Format of library name prefix]) _LT_DECL([], [library_names_spec], [1], [[List of archive names. First name is the real one, the rest are links. The last name is the one that the linker finds with -lNAME]]) _LT_DECL([], [soname_spec], [1], [[The coded name of the library, if different from the real name]]) _LT_DECL([], [install_override_mode], [1], [Permission mode override for installation of shared libraries]) _LT_DECL([], [postinstall_cmds], [2], [Command to use after installation of a shared archive]) _LT_DECL([], [postuninstall_cmds], [2], [Command to use after uninstallation of a shared archive]) _LT_DECL([], [finish_cmds], [2], [Commands used to finish a libtool library installation in a directory]) _LT_DECL([], [finish_eval], [1], [[As "finish_cmds", except a single script fragment to be evaled but not shown]]) _LT_DECL([], [hardcode_into_libs], [0], [Whether we should hardcode library paths into libraries]) _LT_DECL([], [sys_lib_search_path_spec], [2], [Compile-time system search path for libraries]) _LT_DECL([sys_lib_dlsearch_path_spec], [configure_time_dlsearch_path], [2], [Detected run-time system search path for libraries]) _LT_DECL([], [configure_time_lt_sys_library_path], [2], [Explicit LT_SYS_LIBRARY_PATH set during ./configure time]) ])# _LT_SYS_DYNAMIC_LINKER # _LT_PATH_TOOL_PREFIX(TOOL) # -------------------------- # find a file program that can recognize shared library AC_DEFUN([_LT_PATH_TOOL_PREFIX], [m4_require([_LT_DECL_EGREP])dnl AC_MSG_CHECKING([for $1]) AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, [case $MAGIC_CMD in [[\\/*] | ?:[\\/]*]) lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD=$MAGIC_CMD lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR dnl $ac_dummy forces splitting on constant user-supplied paths. dnl POSIX.2 word splitting is done only on the output of word expansions, dnl not every word. This closes a longstanding sh security hole. ac_dummy="m4_if([$2], , $PATH, [$2])" for ac_dir in $ac_dummy; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$1"; then lt_cv_path_MAGIC_CMD=$ac_dir/"$1" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD=$lt_cv_path_MAGIC_CMD if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS=$lt_save_ifs MAGIC_CMD=$lt_save_MAGIC_CMD ;; esac]) MAGIC_CMD=$lt_cv_path_MAGIC_CMD if test -n "$MAGIC_CMD"; then AC_MSG_RESULT($MAGIC_CMD) else AC_MSG_RESULT(no) fi _LT_DECL([], [MAGIC_CMD], [0], [Used to examine libraries when file_magic_cmd begins with "file"])dnl ])# _LT_PATH_TOOL_PREFIX # Old name: AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) # _LT_PATH_MAGIC # -------------- # find a file program that can recognize a shared library m4_defun([_LT_PATH_MAGIC], [_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) else MAGIC_CMD=: fi fi ])# _LT_PATH_MAGIC # LT_PATH_LD # ---------- # find the pathname to the GNU or non-GNU linker AC_DEFUN([LT_PATH_LD], [AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PROG_ECHO_BACKSLASH])dnl AC_ARG_WITH([gnu-ld], [AS_HELP_STRING([--with-gnu-ld], [assume the C compiler uses GNU ld @<:@default=no@:>@])], [test no = "$withval" || with_gnu_ld=yes], [with_gnu_ld=no])dnl ac_prog=ld if test yes = "$GCC"; then # Check if gcc -print-prog-name=ld gives a path. AC_MSG_CHECKING([for ld used by $CC]) case $host in *-*-mingw*) # gcc leaves a trailing carriage return, which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [[\\/]]* | ?:[[\\/]]*) re_direlt='/[[^/]][[^/]]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD=$ac_prog ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test yes = "$with_gnu_ld"; then AC_MSG_CHECKING([for GNU ld]) else AC_MSG_CHECKING([for non-GNU ld]) fi AC_CACHE_VAL(lt_cv_path_LD, [if test -z "$LD"; then lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD=$ac_dir/$ac_prog # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &1 conftest.i cat conftest.i conftest.i >conftest2.i : ${lt_DD:=$DD} AC_PATH_PROGS_FEATURE_CHECK([lt_DD], [dd], [if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then cmp -s conftest.i conftest.out \ && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: fi]) rm -f conftest.i conftest2.i conftest.out]) ])# _LT_PATH_DD # _LT_CMD_TRUNCATE # ---------------- # find command to truncate a binary pipe m4_defun([_LT_CMD_TRUNCATE], [m4_require([_LT_PATH_DD]) AC_CACHE_CHECK([how to truncate binary pipes], [lt_cv_truncate_bin], [printf 0123456789abcdef0123456789abcdef >conftest.i cat conftest.i conftest.i >conftest2.i lt_cv_truncate_bin= if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then cmp -s conftest.i conftest.out \ && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" fi rm -f conftest.i conftest2.i conftest.out test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q"]) _LT_DECL([lt_truncate_bin], [lt_cv_truncate_bin], [1], [Command to truncate a binary pipe]) ])# _LT_CMD_TRUNCATE # _LT_CHECK_MAGIC_METHOD # ---------------------- # how to check for library dependencies # -- PORTME fill in with the dynamic library characteristics m4_defun([_LT_CHECK_MAGIC_METHOD], [m4_require([_LT_DECL_EGREP]) m4_require([_LT_DECL_OBJDUMP]) AC_CACHE_CHECK([how to recognize dependent libraries], lt_cv_deplibs_check_method, [lt_cv_file_magic_cmd='$MAGIC_CMD' lt_cv_file_magic_test_file= lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. # 'unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path # that responds to the $file_magic_cmd with a given extended regex. # If you have 'file' or equivalent on your system and you're not sure # whether 'pass_all' will *always* work, you probably want this one. case $host_os in aix[[4-9]]*) lt_cv_deplibs_check_method=pass_all ;; beos*) lt_cv_deplibs_check_method=pass_all ;; bsdi[[45]]*) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)' lt_cv_file_magic_cmd='/usr/bin/file -L' lt_cv_file_magic_test_file=/shlib/libc.so ;; cygwin*) # func_win32_libid is a shell function defined in ltmain.sh lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' ;; mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by # func_win32_libid shell function, so use a weaker test based on 'objdump', # unless we find 'file', for example because we are cross-compiling. if ( file / ) >/dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else # Keep this pattern in sync with the one in func_win32_libid. lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc*) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; haiku*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'] lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[[3-9]]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be glibc/ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) lt_cv_deplibs_check_method=pass_all ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd* | bitrig*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; os2*) lt_cv_deplibs_check_method=pass_all ;; esac ]) file_magic_glob= want_nocaseglob=no if test "$build" = "$host"; then case $host_os in mingw* | pw32*) if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then want_nocaseglob=yes else file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[[\1]]\/[[\1]]\/g;/g"` fi ;; esac fi file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown _LT_DECL([], [deplibs_check_method], [1], [Method to check whether dependent libraries are shared objects]) _LT_DECL([], [file_magic_cmd], [1], [Command to use when deplibs_check_method = "file_magic"]) _LT_DECL([], [file_magic_glob], [1], [How to find potential files when deplibs_check_method = "file_magic"]) _LT_DECL([], [want_nocaseglob], [1], [Find potential files using nocaseglob when deplibs_check_method = "file_magic"]) ])# _LT_CHECK_MAGIC_METHOD # LT_PATH_NM # ---------- # find the pathname to a BSD- or MS-compatible name lister AC_DEFUN([LT_PATH_NM], [AC_REQUIRE([AC_PROG_CC])dnl AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, [if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM=$NM else lt_nm_to_check=${ac_tool_prefix}nm if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. tmp_nm=$ac_dir/$lt_tmp_nm if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then # Check to see if the nm accepts a BSD-compat flag. # Adding the 'sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty case $build_os in mingw*) lt_bad_file=conftest.nm/nofile ;; *) lt_bad_file=/dev/null ;; esac case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in *$lt_bad_file* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break 2 ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break 2 ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS=$lt_save_ifs done : ${lt_cv_path_NM=no} fi]) if test no != "$lt_cv_path_NM"; then NM=$lt_cv_path_NM else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$DUMPBIN"; then : # Let the user override the test. else AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols -headers" ;; *) DUMPBIN=: ;; esac fi AC_SUBST([DUMPBIN]) if test : != "$DUMPBIN"; then NM=$DUMPBIN fi fi test -z "$NM" && NM=nm AC_SUBST([NM]) _LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], [lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&AS_MESSAGE_LOG_FD (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) cat conftest.out >&AS_MESSAGE_LOG_FD if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest*]) ])# LT_PATH_NM # Old names: AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_PROG_NM], []) dnl AC_DEFUN([AC_PROG_NM], []) # _LT_CHECK_SHAREDLIB_FROM_LINKLIB # -------------------------------- # how to determine the name of the shared library # associated with a specific link library. # -- PORTME fill in with the dynamic library characteristics m4_defun([_LT_CHECK_SHAREDLIB_FROM_LINKLIB], [m4_require([_LT_DECL_EGREP]) m4_require([_LT_DECL_OBJDUMP]) m4_require([_LT_DECL_DLLTOOL]) AC_CACHE_CHECK([how to associate runtime and link libraries], lt_cv_sharedlib_from_linklib_cmd, [lt_cv_sharedlib_from_linklib_cmd='unknown' case $host_os in cygwin* | mingw* | pw32* | cegcc*) # two different shell functions defined in ltmain.sh; # decide which one to use based on capabilities of $DLLTOOL case `$DLLTOOL --help 2>&1` in *--identify-strict*) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib ;; *) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback ;; esac ;; *) # fallback: assume linklib IS sharedlib lt_cv_sharedlib_from_linklib_cmd=$ECHO ;; esac ]) sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO _LT_DECL([], [sharedlib_from_linklib_cmd], [1], [Command to associate shared and link libraries]) ])# _LT_CHECK_SHAREDLIB_FROM_LINKLIB # _LT_PATH_MANIFEST_TOOL # ---------------------- # locate the manifest tool m4_defun([_LT_PATH_MANIFEST_TOOL], [AC_CHECK_TOOL(MANIFEST_TOOL, mt, :) test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt AC_CACHE_CHECK([if $MANIFEST_TOOL is a manifest tool], [lt_cv_path_mainfest_tool], [lt_cv_path_mainfest_tool=no echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&AS_MESSAGE_LOG_FD $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out cat conftest.err >&AS_MESSAGE_LOG_FD if $GREP 'Manifest Tool' conftest.out > /dev/null; then lt_cv_path_mainfest_tool=yes fi rm -f conftest*]) if test yes != "$lt_cv_path_mainfest_tool"; then MANIFEST_TOOL=: fi _LT_DECL([], [MANIFEST_TOOL], [1], [Manifest tool])dnl ])# _LT_PATH_MANIFEST_TOOL # _LT_DLL_DEF_P([FILE]) # --------------------- # True iff FILE is a Windows DLL '.def' file. # Keep in sync with func_dll_def_p in the libtool script AC_DEFUN([_LT_DLL_DEF_P], [dnl test DEF = "`$SED -n dnl -e '\''s/^[[ ]]*//'\'' dnl Strip leading whitespace -e '\''/^\(;.*\)*$/d'\'' dnl Delete empty lines and comments -e '\''s/^\(EXPORTS\|LIBRARY\)\([[ ]].*\)*$/DEF/p'\'' dnl -e q dnl Only consider the first "real" line $1`" dnl ])# _LT_DLL_DEF_P # LT_LIB_M # -------- # check for math library AC_DEFUN([LT_LIB_M], [AC_REQUIRE([AC_CANONICAL_HOST])dnl LIBM= case $host in *-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) # These system don't have libm, or don't need it ;; *-ncr-sysv4.3*) AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM=-lmw) AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") ;; *) AC_CHECK_LIB(m, cos, LIBM=-lm) ;; esac AC_SUBST([LIBM]) ])# LT_LIB_M # Old name: AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_CHECK_LIBM], []) # _LT_COMPILER_NO_RTTI([TAGNAME]) # ------------------------------- m4_defun([_LT_COMPILER_NO_RTTI], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= if test yes = "$GCC"; then case $cc_basename in nvcc*) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; *) _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; esac _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], lt_cv_prog_compiler_rtti_exceptions, [-fno-rtti -fno-exceptions], [], [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) fi _LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], [Compiler flag to turn off builtin functions]) ])# _LT_COMPILER_NO_RTTI # _LT_CMD_GLOBAL_SYMBOLS # ---------------------- m4_defun([_LT_CMD_GLOBAL_SYMBOLS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_PROG_CC])dnl AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([LT_PATH_NM])dnl AC_REQUIRE([LT_PATH_LD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_TAG_COMPILER])dnl # Check for command to grab the raw symbol name followed by C symbol from nm. AC_MSG_CHECKING([command to parse $NM output from $compiler object]) AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], [ # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[[BCDEGRST]]' # Regexp to match symbols that can be accessed directly from C. sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[[BCDT]]' ;; cygwin* | mingw* | pw32* | cegcc*) symcode='[[ABCDGISTW]]' ;; hpux*) if test ia64 = "$host_cpu"; then symcode='[[ABCDEGRST]]' fi ;; irix* | nonstopux*) symcode='[[BCDEGRST]]' ;; osf*) symcode='[[BCDEGQRST]]' ;; solaris*) symcode='[[BDRT]]' ;; sco3.2v5*) symcode='[[DT]]' ;; sysv4.2uw2*) symcode='[[DT]]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[[ABDT]]' ;; sysv4) symcode='[[DFNSTU]]' ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[[ABCDGIRSTW]]' ;; esac if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Gets list of data symbols to import. lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" # Adjust the below global symbol transforms to fixup imported variables. lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" lt_c_name_lib_hook="\ -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" else # Disable hooks by default. lt_cv_sys_global_symbol_to_import= lt_cdecl_hook= lt_c_name_hook= lt_c_name_lib_hook= fi # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="sed -n"\ $lt_cdecl_hook\ " -e 's/^T .* \(.*\)$/extern int \1();/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ $lt_c_name_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" # Transform an extracted symbol line into symbol name with lib prefix and # symbol address. lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ $lt_c_name_lib_hook\ " -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ " -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ " -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function, # D for any global variable and I for any imported variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK ['"\ " {last_section=section; section=\$ 3};"\ " /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ " /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ " /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ " {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ " s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx]" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF if AC_TRY_EVAL(ac_compile); then # Now try to grab the symbols. nlist=conftest.nm if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE /* DATA imports from DLLs on WIN32 can't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT@&t@_DLSYM_CONST #elif defined __osf__ /* This system does not cope well with relocations in const data. */ # define LT@&t@_DLSYM_CONST #else # define LT@&t@_DLSYM_CONST const #endif #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ LT@&t@_DLSYM_CONST struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[[]] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS LIBS=conftstm.$ac_objext CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" if AC_TRY_EVAL(ac_link) && test -s conftest$ac_exeext; then pipe_works=yes fi LIBS=$lt_globsym_save_LIBS CFLAGS=$lt_globsym_save_CFLAGS else echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD fi else echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test yes = "$pipe_works"; then break else lt_cv_sys_global_symbol_pipe= fi done ]) if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then AC_MSG_RESULT(failed) else AC_MSG_RESULT(ok) fi # Response file support. if test "$lt_cv_nm_interface" = "MS dumpbin"; then nm_file_list_spec='@' elif $NM --help 2>/dev/null | grep '[[@]]FILE' >/dev/null; then nm_file_list_spec='@' fi _LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], [Take the output of nm and produce a listing of raw symbols and C names]) _LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], [Transform the output of nm in a proper C declaration]) _LT_DECL([global_symbol_to_import], [lt_cv_sys_global_symbol_to_import], [1], [Transform the output of nm into a list of symbols to manually relocate]) _LT_DECL([global_symbol_to_c_name_address], [lt_cv_sys_global_symbol_to_c_name_address], [1], [Transform the output of nm in a C name address pair]) _LT_DECL([global_symbol_to_c_name_address_lib_prefix], [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], [Transform the output of nm in a C name address pair when lib prefix is needed]) _LT_DECL([nm_interface], [lt_cv_nm_interface], [1], [The name lister interface]) _LT_DECL([], [nm_file_list_spec], [1], [Specify filename containing input files for $NM]) ]) # _LT_CMD_GLOBAL_SYMBOLS # _LT_COMPILER_PIC([TAGNAME]) # --------------------------- m4_defun([_LT_COMPILER_PIC], [m4_require([_LT_TAG_COMPILER])dnl _LT_TAGVAR(lt_prog_compiler_wl, $1)= _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)= m4_if([$1], [CXX], [ # C++ specific cases for pic, static, wl, etc. if test yes = "$GXX"; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the '-m68020' flag to GCC prevents building anything better, # like '-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) case $host_os in os2*) _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' ;; esac ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; *djgpp*) # DJGPP does not support shared libraries at all _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. _LT_TAGVAR(lt_prog_compiler_static, $1)= ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac else case $host_os in aix[[4-9]]*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; chorus*) case $cc_basename in cxch68*) # Green Hills C++ Compiler # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" ;; esac ;; mingw* | cygwin* | os2* | pw32* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) ;; dgux*) case $cc_basename in ec++*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; ghcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; freebsd* | dragonfly*) # FreeBSD uses GNU C++ ;; hpux9* | hpux10* | hpux11*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' if test ia64 != "$host_cpu"; then _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' fi ;; aCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac ;; *) ;; esac ;; interix*) # This is c89, which is MS Visual C++ (no shared libs) # Anyone wants to do a port? ;; irix5* | irix6* | nonstopux*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' # CC pic flag -KPIC is the default. ;; *) ;; esac ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # KAI C++ Compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; ecpc* ) # old Intel C++ for x86_64, which still supported -KPIC. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; icpc* ) # Intel C++, used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; pgCC* | pgcpp*) # Portland Group C++ compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; cxx*) # Compaq C++ # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL 8.0, 9.0 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; esac ;; esac ;; lynxos*) ;; m88k*) ;; mvs*) case $cc_basename in cxx*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' ;; *) ;; esac ;; netbsd* | netbsdelf*-gnu) ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' ;; RCC*) # Rational C++ 2.4.1 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; cxx*) # Digital/Compaq C++ _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # Make sure the PIC flag is empty. It appears that all Alpha # Linux and Compaq Tru64 Unix objects are PIC. _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; *) ;; esac ;; psos*) ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' ;; *) ;; esac ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; lcc*) # Lucid _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' ;; *) ;; esac ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) case $cc_basename in CC*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' ;; *) ;; esac ;; vxworks*) ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ], [ if test yes = "$GCC"; then _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' case $host_os in aix*) # All AIX code is PIC. if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the '-m68020' flag to GCC prevents building anything better, # like '-m68040'. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) case $host_os in os2*) _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' ;; esac ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. _LT_TAGVAR(lt_prog_compiler_static, $1)= ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic fi ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac case $cc_basename in nvcc*) # Cuda Compiler Driver 2.2 _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then _LT_TAGVAR(lt_prog_compiler_pic, $1)="-Xcompiler $_LT_TAGVAR(lt_prog_compiler_pic, $1)" fi ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' else _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' fi ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' case $cc_basename in nagfor*) # NAG Fortran compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). m4_if([$1], [GCJ], [], [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) case $host_os in os2*) _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-static' ;; esac ;; hpux9* | hpux10* | hpux11*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? _LT_TAGVAR(lt_prog_compiler_static, $1)='$wl-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # PIC (with -KPIC) is the default. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in # old Intel for x86_64, which still supported -KPIC. ecc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; # Lahey Fortran 8.1. lf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' ;; nagfor*) # NAG Fortran compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,-Wl,,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; tcc*) # Fabrice Bellard et al's Tiny C Compiler _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; ccc*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All Alpha code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; xl* | bgxl* | bgf* | mpixl*) # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [[1-7]].* | *Sun*Fortran*\ 8.[[0-3]]*) # Sun Fortran 8.3 passes all unrecognized flags to the linker _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='' ;; *Sun\ F* | *Sun*Fortran*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' ;; *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' ;; *Intel*\ [[CF]]*Compiler*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' ;; *Portland\ Group*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; esac ;; esac ;; newsos6) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' ;; osf3* | osf4* | osf5*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' # All OSF/1 code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; rdos*) _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; solaris*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' case $cc_basename in f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; *) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; esac ;; sunos4*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; unicos*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; uts4*) _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' ;; *) _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no ;; esac fi ]) case $host_os in # For platforms that do not support PIC, -DPIC is meaningless: *djgpp*) _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" ;; esac AC_CACHE_CHECK([for $compiler option to produce PIC], [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)], [_LT_TAGVAR(lt_cv_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) _LT_TAGVAR(lt_prog_compiler_pic, $1)=$_LT_TAGVAR(lt_cv_prog_compiler_pic, $1) # # Check to make sure the PIC flag actually works. # if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in "" | " "*) ;; *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; esac], [_LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) fi _LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], [Additional compiler flags for building library objects]) _LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], [How to pass a linker flag through the compiler]) # # Check to make sure the static flag actually works. # wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" _LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), $lt_tmp_static_flag, [], [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) _LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], [Compiler flag to prevent dynamic linking]) ])# _LT_COMPILER_PIC # _LT_LINKER_SHLIBS([TAGNAME]) # ---------------------------- # See if the linker supports building shared libraries. m4_defun([_LT_LINKER_SHLIBS], [AC_REQUIRE([LT_PATH_LD])dnl AC_REQUIRE([LT_PATH_NM])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl m4_require([_LT_TAG_COMPILER])dnl AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) m4_if([$1], [CXX], [ _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] case $host_os in aix[[4-9]]*) # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to GNU nm, but means don't demangle to AIX nm. # Without the "-l" option, or with the "-B" option, AIX nm treats # weak defined symbols like other global defined symbols, whereas # GNU nm marks them as "W". # While the 'weak' keyword is ignored in the Export File, we need # it in the Import File for the 'aix-soname' feature, so we have # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi ;; pw32*) _LT_TAGVAR(export_symbols_cmds, $1)=$ltdll_cmds ;; cygwin* | mingw* | cegcc*) case $cc_basename in cl*) _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] ;; esac ;; linux* | k*bsd*-gnu | gnu*) _LT_TAGVAR(link_all_deplibs, $1)=no ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; esac ], [ runpath_var= _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_cmds, $1)= _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(old_archive_from_new_cmds, $1)= _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= _LT_TAGVAR(thread_safe_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list _LT_TAGVAR(include_expsyms, $1)= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ' (' and ')$', so one must not match beginning or # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', # as well as any symbol that contains 'd'. _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. dnl Note also adjust exclude_expsyms for C++ above. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test yes != "$GCC"; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd* | bitrig*) with_gnu_ld=no ;; linux* | k*bsd*-gnu | gnu*) _LT_TAGVAR(link_all_deplibs, $1)=no ;; esac _LT_TAGVAR(ld_shlibs, $1)=yes # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no if test yes = "$with_gnu_ld"; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility # with the native linker. However, as the warning in the GNU ld # block says, versions before 2.19.5* couldn't really create working # shared libraries, regardless of the interface used. case `$LD -v 2>&1` in *\ \(GNU\ Binutils\)\ 2.19.5*) ;; *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;; *\ \(GNU\ Binutils\)\ [[3-9]]*) ;; *) lt_use_gnu_ld_interface=yes ;; esac ;; *) lt_use_gnu_ld_interface=yes ;; esac fi if test yes = "$lt_use_gnu_ld_interface"; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='$wl' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi supports_anon_versioning=no case `$LD -v | $SED -e 's/([^)]\+)\s\+//' 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[[3-9]]*) # On AIX/PPC, the GNU linker is very broken if test ia64 != "$host_cpu"; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.19, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to install binutils *** 2.20 or above, or modify your PATH so that a non-GNU linker is found. *** You will then need to restart the configuration process. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' _LT_TAGVAR(exclude_expsyms, $1)=['[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname'] if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file, use it as # is; otherwise, prepend EXPORTS... _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; haiku*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported shrext_cmds=.dll _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test linux-dietlibc = "$host_os"; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test no = "$tmp_diet" then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 _LT_TAGVAR(whole_archive_flag_spec, $1)= tmp_sharedflag='--shared' ;; nagfor*) # NAGFOR 5.3 tmp_sharedflag='-Wl,-shared' ;; xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' if test yes = "$supports_anon_versioning"; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi case $cc_basename in tcc*) _LT_TAGVAR(export_dynamic_flag_spec, $1)='-rdynamic' ;; xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test yes = "$supports_anon_versioning"; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; sunos4*) _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac if test no = "$_LT_TAGVAR(ld_shlibs, $1)"; then runpath_var= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. _LT_TAGVAR(hardcode_minus_L, $1)=yes if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. _LT_TAGVAR(hardcode_direct, $1)=unsupported fi ;; aix[[4-9]]*) if test ia64 = "$host_cpu"; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag= else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to GNU nm, but means don't demangle to AIX nm. # Without the "-l" option, or with the "-B" option, AIX nm treats # weak defined symbols like other global defined symbols, whereas # GNU nm marks them as "W". # While the 'weak' keyword is ignored in the Export File, we need # it in the Import File for the 'aix-soname' feature, so we have # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='`func_echo_all $NM | $SED -e '\''s/B\([[^B]]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && ([substr](\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # have runtime linking enabled, and use it for executables. # For shared libraries, we enable/disable runtime linking # depending on the kind of the shared library created - # when "with_aix_soname,aix_use_runtimelinking" is: # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables # "aix,yes" lib.so shared, rtl:yes, for executables # lib.a static archive # "both,no" lib.so.V(shr.o) shared, rtl:yes # lib.a(lib.so.V) shared, rtl:no, for executables # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a(lib.so.V) shared, rtl:no # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a static archive case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then aix_use_runtimelinking=yes break fi done if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then # With aix-soname=svr4, we create the lib.so.V shared archives only, # so we don't have lib.a shared libs to link our executables. # We have to force runtime linking in this case. aix_use_runtimelinking=yes LDFLAGS="$LDFLAGS -Wl,-brtl" fi ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='$wl-f,' case $with_aix_soname,$aix_use_runtimelinking in aix,*) ;; # traditional, no import file svr4,* | *,yes) # use import file # The Import File defines what to hardcode. _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no ;; esac if test yes = "$GCC"; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`$CC -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi ;; esac shared_flag='-shared' if test yes = "$aix_use_runtimelinking"; then shared_flag="$shared_flag "'$wl-G' fi # Need to ensure runtime linking is disabled for the traditional # shared library, or the linker may eventually find shared libraries # /with/ Import File - we do not want to mix them. shared_flag_aix='-shared' shared_flag_svr4='-shared $wl-G' else # not using gcc if test ia64 = "$host_cpu"; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test yes = "$aix_use_runtimelinking"; then shared_flag='$wl-G' else shared_flag='$wl-bM:SRE' fi shared_flag_aix='$wl-bM:SRE' shared_flag_svr4='$wl-G' fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. _LT_TAGVAR(always_export_symbols, $1)=yes if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. _LT_TAGVAR(allow_undefined_flag, $1)='-berok' # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else if test ia64 = "$host_cpu"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' # -brtl affects multiple linker settings, -berok does not and is overridden later compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' if test svr4 != "$with_aix_soname"; then # This is similar to how AIX traditionally builds its shared libraries. _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' fi if test aix != "$with_aix_soname"; then _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' else # used by -dlpreopen to get the symbols _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' fi _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='' ;; m68k) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac ;; bsdi[[45]]*) _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. case $cc_basename in cl*) # Native MSVC _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then cp "$export_symbols" "$output_objdir/$soname.def"; echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; else $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes _LT_TAGVAR(exclude_expsyms, $1)='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1,DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile=$lt_outputfile.exe lt_tool_outputfile=$lt_tool_outputfile.exe ;; esac~ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # Assume MSVC wrapper _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' # FIXME: Should let the user specify the lib program. _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; esac ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; dgux*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2.*) _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; hpux9*) if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' ;; hpux10*) if test yes,no = "$GCC,$with_gnu_ld"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test no = "$with_gnu_ld"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes fi ;; hpux11*) if test yes,no = "$GCC,$with_gnu_ld"; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) m4_if($1, [], [ # Older versions of the 11.00 compiler do not understand -b yet # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) _LT_LINKER_OPTION([if $CC understands -b], _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], [_LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) ;; esac fi if test no = "$with_gnu_ld"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. _LT_TAGVAR(hardcode_minus_L, $1)=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. # This should be the same for all languages, so no per-tag cache variable. AC_CACHE_CHECK([whether the $host_os linker accepts -exported_symbol], [lt_cv_irix_exported_symbol], [save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" AC_LINK_IFELSE( [AC_LANG_SOURCE( [AC_LANG_CASE([C], [[int foo (void) { return 0; }]], [C++], [[int foo (void) { return 0; }]], [Fortran 77], [[ subroutine foo end]], [Fortran], [[ subroutine foo end]])])], [lt_cv_irix_exported_symbol=yes], [lt_cv_irix_exported_symbol=no]) LDFLAGS=$save_LDFLAGS]) if test yes = "$lt_cv_irix_exported_symbol"; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' fi _LT_TAGVAR(link_all_deplibs, $1)=no else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes _LT_TAGVAR(link_all_deplibs, $1)=yes ;; linux*) case $cc_basename in tcc*) # Fabrice Bellard et al's Tiny C Compiler _LT_TAGVAR(ld_shlibs, $1)=yes _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; newsos6) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *nto* | *qnx*) ;; openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' fi else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported shrext_cmds=.dll _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; osf3*) if test yes = "$GCC"; then _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test yes = "$GCC"; then _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_separator, $1)=: ;; solaris*) _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' if test yes = "$GCC"; then wlarc='$wl' _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' _LT_TAGVAR(archive_cmds, $1)='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='$wl' _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands '-z linker_flag'. GCC discards it without '$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test yes = "$GCC"; then _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' else _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' fi ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes ;; sunos4*) if test sequent = "$host_vendor"; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4) case $host_vendor in sni) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' _LT_TAGVAR(hardcode_direct, $1)=no ;; motorola) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; sysv4.3*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes _LT_TAGVAR(ld_shlibs, $1)=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We CANNOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' runpath_var='LD_RUN_PATH' if test yes = "$GCC"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(ld_shlibs, $1)=no ;; esac if test sni = "$host_vendor"; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Blargedynsym' ;; esac fi fi ]) AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no _LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld _LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl _LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl _LT_DECL([], [extract_expsyms_cmds], [2], [The commands to extract the exported symbol list from a shared archive]) # # Do we need to explicitly link libc? # case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in x|xyes) # Assume -lc should be added _LT_TAGVAR(archive_cmds_need_lc, $1)=yes if test yes,yes = "$GCC,$enable_shared"; then case $_LT_TAGVAR(archive_cmds, $1) in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. AC_CACHE_CHECK([whether -lc should be explicitly linked in], [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), [$RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if AC_TRY_EVAL(ac_compile) 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) _LT_TAGVAR(allow_undefined_flag, $1)= if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) then lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no else lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes fi _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* ]) _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) ;; esac fi ;; esac _LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], [Whether or not to add -lc for building shared libraries]) _LT_TAGDECL([allow_libtool_libs_with_static_runtimes], [enable_shared_with_static_runtimes], [0], [Whether or not to disallow shared libs when runtime libs are static]) _LT_TAGDECL([], [export_dynamic_flag_spec], [1], [Compiler flag to allow reflexive dlopens]) _LT_TAGDECL([], [whole_archive_flag_spec], [1], [Compiler flag to generate shared objects directly from archives]) _LT_TAGDECL([], [compiler_needs_object], [1], [Whether the compiler copes with passing no objects directly]) _LT_TAGDECL([], [old_archive_from_new_cmds], [2], [Create an old-style archive from a shared archive]) _LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], [Create a temporary old-style archive to link instead of a shared archive]) _LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) _LT_TAGDECL([], [archive_expsym_cmds], [2]) _LT_TAGDECL([], [module_cmds], [2], [Commands used to build a loadable module if different from building a shared archive.]) _LT_TAGDECL([], [module_expsym_cmds], [2]) _LT_TAGDECL([], [with_gnu_ld], [1], [Whether we are building with GNU ld or not]) _LT_TAGDECL([], [allow_undefined_flag], [1], [Flag that allows shared libraries with undefined symbols to be built]) _LT_TAGDECL([], [no_undefined_flag], [1], [Flag that enforces no undefined symbols]) _LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], [Flag to hardcode $libdir into a binary during linking. This must work even if $libdir does not exist]) _LT_TAGDECL([], [hardcode_libdir_separator], [1], [Whether we need a single "-rpath" flag with a separated argument]) _LT_TAGDECL([], [hardcode_direct], [0], [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_direct_absolute], [0], [Set to "yes" if using DIR/libNAME$shared_ext during linking hardcodes DIR into the resulting binary and the resulting library dependency is "absolute", i.e impossible to change by setting $shlibpath_var if the library is relocated]) _LT_TAGDECL([], [hardcode_minus_L], [0], [Set to "yes" if using the -LDIR flag during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_shlibpath_var], [0], [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into the resulting binary]) _LT_TAGDECL([], [hardcode_automatic], [0], [Set to "yes" if building a shared library automatically hardcodes DIR into the library and all subsequent libraries and executables linked against it]) _LT_TAGDECL([], [inherit_rpath], [0], [Set to yes if linker adds runtime paths of dependent libraries to runtime path list]) _LT_TAGDECL([], [link_all_deplibs], [0], [Whether libtool must link a program against all its dependency libraries]) _LT_TAGDECL([], [always_export_symbols], [0], [Set to "yes" if exported symbols are required]) _LT_TAGDECL([], [export_symbols_cmds], [2], [The commands to list exported symbols]) _LT_TAGDECL([], [exclude_expsyms], [1], [Symbols that should not be listed in the preloaded symbols]) _LT_TAGDECL([], [include_expsyms], [1], [Symbols that must always be exported]) _LT_TAGDECL([], [prelink_cmds], [2], [Commands necessary for linking programs (against libraries) with templates]) _LT_TAGDECL([], [postlink_cmds], [2], [Commands necessary for finishing linking programs]) _LT_TAGDECL([], [file_list_spec], [1], [Specify filename containing input files]) dnl FIXME: Not yet implemented dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], dnl [Compiler flag to generate thread safe objects]) ])# _LT_LINKER_SHLIBS # _LT_LANG_C_CONFIG([TAG]) # ------------------------ # Ensure that the configuration variables for a C compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to 'libtool'. m4_defun([_LT_LANG_C_CONFIG], [m4_require([_LT_DECL_EGREP])dnl lt_save_CC=$CC AC_LANG_PUSH(C) # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' _LT_TAG_COMPILER # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) LT_SYS_DLOPEN_SELF _LT_CMD_STRIPLIB # Report what library types will actually be built AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test yes = "$enable_shared" || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_CONFIG($1) fi AC_LANG_POP CC=$lt_save_CC ])# _LT_LANG_C_CONFIG # _LT_LANG_CXX_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a C++ compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to 'libtool'. m4_defun([_LT_LANG_CXX_CONFIG], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_PATH_MANIFEST_TOOL])dnl if test -n "$CXX" && ( test no != "$CXX" && ( (test g++ = "$CXX" && `g++ -v >/dev/null 2>&1` ) || (test g++ != "$CXX"))); then AC_PROG_CXXCPP else _lt_caught_CXX_error=yes fi AC_LANG_PUSH(C++) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(compiler_needs_object, $1)=no _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for C++ test sources. ac_ext=cpp # Object file extension for compiled C++ test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the CXX compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test yes != "$_lt_caught_CXX_error"; then # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_LD=$LD lt_save_GCC=$GCC GCC=$GXX lt_save_with_gnu_ld=$with_gnu_ld lt_save_path_LD=$lt_cv_path_LD if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx else $as_unset lt_cv_prog_gnu_ld fi if test -n "${lt_cv_path_LDCXX+set}"; then lt_cv_path_LD=$lt_cv_path_LDCXX else $as_unset lt_cv_path_LD fi test -z "${LDCXX+set}" || LD=$LDCXX CC=${CXX-"c++"} CFLAGS=$CXXFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then # We don't want -fno-exception when compiling C++ code, so set the # no_builtin_flag separately if test yes = "$GXX"; then _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' else _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= fi if test yes = "$GXX"; then # Set up default GNU C++ configuration LT_PATH_LD # Check if GNU C++ uses GNU ld as the underlying linker, since the # archiving commands below assume that GNU ld is being used. if test yes = "$with_gnu_ld"; then _LT_TAGVAR(archive_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' # If archive_cmds runs LD, not CC, wlarc should be empty # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to # investigate it a little bit more. (MM) wlarc='$wl' # ancient GNU ld didn't support --whole-archive et. al. if eval "`$CC -print-prog-name=ld` --help 2>&1" | $GREP 'no-whole-archive' > /dev/null; then _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else _LT_TAGVAR(whole_archive_flag_spec, $1)= fi else with_gnu_ld=no wlarc= # A generic and very simple default shared library creation # command for GNU C++ for the case where it uses the native # linker, instead of GNU ld. If possible, this setting should # overridden to take advantage of the native linker features on # the platform it is being used on. _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' fi # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else GXX=no with_gnu_ld=no wlarc= fi # PORTME: fill in a description of your system's C++ link characteristics AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) _LT_TAGVAR(ld_shlibs, $1)=yes case $host_os in aix3*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aix[[4-9]]*) if test ia64 = "$host_cpu"; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag= else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # have runtime linking enabled, and use it for executables. # For shared libraries, we enable/disable runtime linking # depending on the kind of the shared library created - # when "with_aix_soname,aix_use_runtimelinking" is: # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables # "aix,yes" lib.so shared, rtl:yes, for executables # lib.a static archive # "both,no" lib.so.V(shr.o) shared, rtl:yes # lib.a(lib.so.V) shared, rtl:no, for executables # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a(lib.so.V) shared, rtl:no # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables # lib.a static archive case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) for ld_flag in $LDFLAGS; do case $ld_flag in *-brtl*) aix_use_runtimelinking=yes break ;; esac done if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then # With aix-soname=svr4, we create the lib.so.V shared archives only, # so we don't have lib.a shared libs to link our executables. # We have to force runtime linking in this case. aix_use_runtimelinking=yes LDFLAGS="$LDFLAGS -Wl,-brtl" fi ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. _LT_TAGVAR(archive_cmds, $1)='' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(file_list_spec, $1)='$wl-f,' case $with_aix_soname,$aix_use_runtimelinking in aix,*) ;; # no import file svr4,* | *,yes) # use import file # The Import File defines what to hardcode. _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no ;; esac if test yes = "$GXX"; then case $host_os in aix4.[[012]]|aix4.[[012]].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`$CC -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 _LT_TAGVAR(hardcode_direct, $1)=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)= fi esac shared_flag='-shared' if test yes = "$aix_use_runtimelinking"; then shared_flag=$shared_flag' $wl-G' fi # Need to ensure runtime linking is disabled for the traditional # shared library, or the linker may eventually find shared libraries # /with/ Import File - we do not want to mix them. shared_flag_aix='-shared' shared_flag_svr4='-shared $wl-G' else # not using gcc if test ia64 = "$host_cpu"; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test yes = "$aix_use_runtimelinking"; then shared_flag='$wl-G' else shared_flag='$wl-bM:SRE' fi shared_flag_aix='$wl-bM:SRE' shared_flag_svr4='$wl-G' fi fi _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to # export. _LT_TAGVAR(always_export_symbols, $1)=yes if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. # The "-G" linker flag allows undefined symbols. _LT_TAGVAR(no_undefined_flag, $1)='-bernotok' # Determine the default libpath from the value encoded in an empty # executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else if test ia64 = "$host_cpu"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $libdir:/usr/lib:/lib' _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. _LT_SYS_MODULE_PATH_AIX([$1]) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' $wl-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-berok' if test yes = "$with_gnu_ld"; then # We only use this code for GNU lds that support --whole-archive. _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes _LT_TAGVAR(archive_expsym_cmds, $1)='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' # -brtl affects multiple linker settings, -berok does not and is overridden later compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([[, ]]\\)%-berok\\1%g"`' if test svr4 != "$with_aix_soname"; then # This is similar to how AIX traditionally builds its shared # libraries. Need -bnortl late, we may have -brtl in LDFLAGS. _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' fi if test aix != "$with_aix_soname"; then _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' else # used by -dlpreopen to get the symbols _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$MV $output_objdir/$realname.d/$soname $output_objdir' fi _LT_TAGVAR(archive_expsym_cmds, $1)="$_LT_TAGVAR(archive_expsym_cmds, $1)"'~$RM -r $output_objdir/$realname.d' fi fi ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then _LT_TAGVAR(allow_undefined_flag, $1)=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; chorus*) case $cc_basename in *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; cygwin* | mingw* | pw32* | cegcc*) case $GXX,$cc_basename in ,cl* | no,cl*) # Native MSVC # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=yes _LT_TAGVAR(file_list_spec, $1)='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=.dll # FIXME: Setting linknames here is a bad hack. _LT_TAGVAR(archive_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then cp "$export_symbols" "$output_objdir/$soname.def"; echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; else $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes # Don't use ranlib _LT_TAGVAR(old_postinstall_cmds, $1)='chmod 644 $oldlib' _LT_TAGVAR(postlink_cmds, $1)='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile=$lt_outputfile.exe lt_tool_outputfile=$lt_tool_outputfile.exe ;; esac~ func_to_tool_file "$lt_outputfile"~ if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # g++ # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file, use it as # is; otherwise, prepend EXPORTS... _LT_TAGVAR(archive_expsym_cmds, $1)='if _LT_DLL_DEF_P([$export_symbols]); then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; darwin* | rhapsody*) _LT_DARWIN_LINKER_FEATURES($1) ;; os2*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported shrext_cmds=.dll _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(archive_expsym_cmds, $1)='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ $ECHO EXPORTS >> $output_objdir/$libname.def~ prefix_cmds="$SED"~ if test EXPORTS = "`$SED 1q $export_symbols`"; then prefix_cmds="$prefix_cmds -e 1d"; fi~ prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ emximp -o $lib $output_objdir/$libname.def' _LT_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes ;; dgux*) case $cc_basename in ec++*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; ghcx*) # Green Hills C++ Compiler # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; freebsd2.*) # C++ shared libraries reported to be fairly broken before # switch to ELF _LT_TAGVAR(ld_shlibs, $1)=no ;; freebsd-elf*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; freebsd* | dragonfly*) # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF # conventions _LT_TAGVAR(ld_shlibs, $1)=yes ;; haiku*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(link_all_deplibs, $1)=yes ;; hpux9*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes = "$GXX"; then _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; hpux10*|hpux11*) if test no = "$with_gnu_ld"; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl+b $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: case $host_cpu in hppa*64*|ia64*) ;; *) _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' ;; esac fi case $host_cpu in hppa*64*|ia64*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no ;; *) _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, # but as the default # location of the library. ;; esac case $cc_basename in CC*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; aCC*) case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes = "$GXX"; then if test no = "$with_gnu_ld"; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC $wl+h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; ia64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' ;; esac fi else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; irix5* | irix6*) case $cc_basename in CC*) # SGI C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' ;; *) if test yes = "$GXX"; then if test no = "$with_gnu_ld"; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` -o $lib' fi fi _LT_TAGVAR(link_all_deplibs, $1)=yes ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: _LT_TAGVAR(inherit_rpath, $1)=yes ;; linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib $wl-retain-symbols-file,$export_symbols; mv \$templib $lib' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' # Archives containing C++ object files must be created using # "CC -Bstatic", where "CC" is the KAI C++ compiler. _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; icpc* | ecpc* ) # Intel C++ with_gnu_ld=yes # version 8.0 and above of icpc choke on multiply defined symbols # if we add $predep_objects and $postdep_objects, however 7.1 and # earlier do not add the objects themselves. case `$CC -V 2>&1` in *"Version 7."*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 8.0 or newer tmp_idyn= case $host_cpu in ia64*) tmp_idyn=' -i_dynamic';; esac _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; esac _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive$convenience $wl--no-whole-archive' ;; pgCC* | pgcpp*) # Portland Group C++ compiler case `$CC -V` in *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ $RANLIB $oldlib' _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; *) # Version 6 and above use weak symbols _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl--rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' ;; cxx*) # Compaq C++ _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname -o $lib $wl-retain-symbols-file $wl$export_symbols' runpath_var=LD_RUN_PATH _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' ;; xl* | mpixl* | bgxl*) # IBM XL 8.0 on PPC, with GNU ld _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl--export-dynamic' _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' if test yes = "$supports_anon_versioning"; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC -qmkshrobj $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C++ 5.9 _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file $wl$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes # Not sure whether something based on # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 # would be better. output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; esac ;; esac ;; lynxos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; m88k*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; mvs*) case $cc_basename in cxx*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' wlarc= _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no fi # Workaround some broken pre-1.5 toolchains output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' ;; *nto* | *qnx*) _LT_TAGVAR(ld_shlibs, $1)=yes ;; openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then _LT_TAGVAR(hardcode_direct, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=yes _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`"; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-retain-symbols-file,$export_symbols -o $lib' _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-E' _LT_TAGVAR(whole_archive_flag_spec, $1)=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' fi output_verbose_link_cmd=func_echo_all else _LT_TAGVAR(ld_shlibs, $1)=no fi ;; osf3* | osf4* | osf5*) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler # KCC will only create a shared library if the output file # ends with ".so" (or ".sl" for HP-UX), so rename the library # to its proper name (with version) after linking. _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\$tempext\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Archives containing C++ object files must be created using # the KAI C++ compiler. case $host in osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; esac ;; RCC*) # Rational C++ 2.4.1 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; cxx*) case $host in osf3*) _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $soname `test -n "$verstring" && func_echo_all "$wl-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' ;; *) _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' _LT_TAGVAR(archive_cmds, $1)='$CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ echo "-hidden">> $lib.exp~ $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname $wl-input $wl$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~ $RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' ;; esac _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. # # There doesn't appear to be a way to prevent this compiler from # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list= ; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test yes,no = "$GXX,$with_gnu_ld"; then _LT_TAGVAR(allow_undefined_flag, $1)=' $wl-expect_unresolved $wl\*' case $host in osf3*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' ;; esac _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-rpath $wl$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no fi ;; esac ;; psos*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; sunos4*) case $cc_basename in CC*) # Sun C++ 4.x # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; lcc*) # Lucid # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; solaris*) case $cc_basename in CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(archive_cmds_need_lc,$1)=yes _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' _LT_TAGVAR(archive_cmds, $1)='$CC -G$allow_undefined_flag -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G$allow_undefined_flag $wl-M $wl$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' _LT_TAGVAR(hardcode_shlibpath_var, $1)=no case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands '-z linker_flag'. # Supported since Solaris 2.6 (maybe 2.5.1?) _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; esac _LT_TAGVAR(link_all_deplibs, $1)=yes output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is # necessary to make sure instantiated templates are included # in the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' ;; gcx*) # Green Hills C++ Compiler _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' # The C++ compiler must be used to create the archive. _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' ;; *) # GNU C++ compiler with Solaris linker if test yes,no = "$GXX,$with_gnu_ld"; then _LT_TAGVAR(no_undefined_flag, $1)=' $wl-z ${wl}defs' if $CC --version | $GREP -v '^2\.7' > /dev/null; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # g++ 2.7 appears to require '-G' NOT '-shared' on this # platform. _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags $wl-h $wl$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G -nostdlib $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R $wl$libdir' case $host_os in solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; *) _LT_TAGVAR(whole_archive_flag_spec, $1)='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' ;; esac fi ;; esac ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We CANNOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. _LT_TAGVAR(no_undefined_flag, $1)='$wl-z,text' _LT_TAGVAR(allow_undefined_flag, $1)='$wl-z,nodefs' _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='$wl-R,$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=':' _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(export_dynamic_flag_spec, $1)='$wl-Bexport' runpath_var='LD_RUN_PATH' case $cc_basename in CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ '"$_LT_TAGVAR(old_archive_cmds, $1)" _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ '"$_LT_TAGVAR(reload_cmds, $1)" ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' ;; esac ;; tandem*) case $cc_basename in NCC*) # NonStop-UX NCC 3.20 # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac ;; vxworks*) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; *) # FIXME: insert proper C++ library support _LT_TAGVAR(ld_shlibs, $1)=no ;; esac AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) test no = "$_LT_TAGVAR(ld_shlibs, $1)" && can_build_shared=no _LT_TAGVAR(GCC, $1)=$GXX _LT_TAGVAR(LD, $1)=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS LDCXX=$LD LD=$lt_save_LD GCC=$lt_save_GCC with_gnu_ld=$lt_save_with_gnu_ld lt_cv_path_LDCXX=$lt_cv_path_LD lt_cv_path_LD=$lt_save_path_LD lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld fi # test yes != "$_lt_caught_CXX_error" AC_LANG_POP ])# _LT_LANG_CXX_CONFIG # _LT_FUNC_STRIPNAME_CNF # ---------------------- # func_stripname_cnf prefix suffix name # strip PREFIX and SUFFIX off of NAME. # PREFIX and SUFFIX must not contain globbing or regex special # characters, hashes, percent signs, but SUFFIX may contain a leading # dot (in which case that matches only a dot). # # This function is identical to the (non-XSI) version of func_stripname, # except this one can be used by m4 code that may be executed by configure, # rather than the libtool script. m4_defun([_LT_FUNC_STRIPNAME_CNF],[dnl AC_REQUIRE([_LT_DECL_SED]) AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH]) func_stripname_cnf () { case @S|@2 in .*) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%\\\\@S|@2\$%%"`;; *) func_stripname_result=`$ECHO "@S|@3" | $SED "s%^@S|@1%%; s%@S|@2\$%%"`;; esac } # func_stripname_cnf ])# _LT_FUNC_STRIPNAME_CNF # _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) # --------------------------------- # Figure out "hidden" library dependencies from verbose # compiler output when linking a shared library. # Parse the compiler output and extract the necessary # objects, libraries and library flags. m4_defun([_LT_SYS_HIDDEN_LIBDEPS], [m4_require([_LT_FILEUTILS_DEFAULTS])dnl AC_REQUIRE([_LT_FUNC_STRIPNAME_CNF])dnl # Dependencies to place before and after the object being linked: _LT_TAGVAR(predep_objects, $1)= _LT_TAGVAR(postdep_objects, $1)= _LT_TAGVAR(predeps, $1)= _LT_TAGVAR(postdeps, $1)= _LT_TAGVAR(compiler_lib_search_path, $1)= dnl we can't use the lt_simple_compile_test_code here, dnl because it contains code intended for an executable, dnl not a library. It's possible we should let each dnl tag define a new lt_????_link_test_code variable, dnl but it's only used here... m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF int a; void foo (void) { a = 0; } _LT_EOF ], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF class Foo { public: Foo (void) { a = 0; } private: int a; }; _LT_EOF ], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer*4 a a=0 return end _LT_EOF ], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF subroutine foo implicit none integer a a=0 return end _LT_EOF ], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF public class foo { private int a; public void bar (void) { a = 0; } }; _LT_EOF ], [$1], [GO], [cat > conftest.$ac_ext <<_LT_EOF package foo func foo() { } _LT_EOF ]) _lt_libdeps_save_CFLAGS=$CFLAGS case "$CC $CFLAGS " in #( *\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; *\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; *\ -fuse-linker-plugin*\ *) CFLAGS="$CFLAGS -fno-use-linker-plugin" ;; esac dnl Parse the compiler output and extract the necessary dnl objects, libraries and library flags. if AC_TRY_EVAL(ac_compile); then # Parse the compiler output and extract the necessary # objects, libraries and library flags. # Sentinel used to keep track of whether or not we are before # the conftest object file. pre_test_object_deps_done=no for p in `eval "$output_verbose_link_cmd"`; do case $prev$p in -L* | -R* | -l*) # Some compilers place space between "-{L,R}" and the path. # Remove the space. if test x-L = "$p" || test x-R = "$p"; then prev=$p continue fi # Expand the sysroot to ease extracting the directories later. if test -z "$prev"; then case $p in -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; esac fi case $p in =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; esac if test no = "$pre_test_object_deps_done"; then case $prev in -L | -R) # Internal compiler library paths should come after those # provided the user. The postdeps already come after the # user supplied libs so there is no need to process them. if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then _LT_TAGVAR(compiler_lib_search_path, $1)=$prev$p else _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} $prev$p" fi ;; # The "-l" case would never come before the object being # linked, so don't bother handling this case. esac else if test -z "$_LT_TAGVAR(postdeps, $1)"; then _LT_TAGVAR(postdeps, $1)=$prev$p else _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} $prev$p" fi fi prev= ;; *.lto.$objext) ;; # Ignore GCC LTO objects *.$objext) # This assumes that the test object file only shows up # once in the compiler output. if test "$p" = "conftest.$objext"; then pre_test_object_deps_done=yes continue fi if test no = "$pre_test_object_deps_done"; then if test -z "$_LT_TAGVAR(predep_objects, $1)"; then _LT_TAGVAR(predep_objects, $1)=$p else _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" fi else if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then _LT_TAGVAR(postdep_objects, $1)=$p else _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" fi fi ;; *) ;; # Ignore the rest. esac done # Clean up. rm -f a.out a.exe else echo "libtool.m4: error: problem compiling $1 test program" fi $RM -f confest.$objext CFLAGS=$_lt_libdeps_save_CFLAGS # PORTME: override above test on systems where it is broken m4_if([$1], [CXX], [case $host_os in interix[[3-9]]*) # Interix 3.5 installs completely hosed .la files for C++, so rather than # hack all around it, let's just trust "g++" to DTRT. _LT_TAGVAR(predep_objects,$1)= _LT_TAGVAR(postdep_objects,$1)= _LT_TAGVAR(postdeps,$1)= ;; esac ]) case " $_LT_TAGVAR(postdeps, $1) " in *" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; esac _LT_TAGVAR(compiler_lib_search_dirs, $1)= if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | $SED -e 's! -L! !g' -e 's!^ !!'` fi _LT_TAGDECL([], [compiler_lib_search_dirs], [1], [The directories searched by this compiler when creating a shared library]) _LT_TAGDECL([], [predep_objects], [1], [Dependencies to place before and after the objects being linked to create a shared library]) _LT_TAGDECL([], [postdep_objects], [1]) _LT_TAGDECL([], [predeps], [1]) _LT_TAGDECL([], [postdeps], [1]) _LT_TAGDECL([], [compiler_lib_search_path], [1], [The library search path used internally by the compiler when linking a shared library]) ])# _LT_SYS_HIDDEN_LIBDEPS # _LT_LANG_F77_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a Fortran 77 compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_F77_CONFIG], [AC_LANG_PUSH(Fortran 77) if test -z "$F77" || test no = "$F77"; then _lt_disable_F77=yes fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for f77 test sources. ac_ext=f # Object file extension for compiled f77 test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the F77 compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test yes != "$_lt_disable_F77"; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${F77-"f77"} CFLAGS=$FFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) GCC=$G77 if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test yes = "$enable_shared" || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)=$G77 _LT_TAGVAR(LD, $1)=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS fi # test yes != "$_lt_disable_F77" AC_LANG_POP ])# _LT_LANG_F77_CONFIG # _LT_LANG_FC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for a Fortran compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_FC_CONFIG], [AC_LANG_PUSH(Fortran) if test -z "$FC" || test no = "$FC"; then _lt_disable_FC=yes fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(archive_expsym_cmds, $1)= _LT_TAGVAR(export_dynamic_flag_spec, $1)= _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_direct_absolute, $1)=no _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_separator, $1)= _LT_TAGVAR(hardcode_minus_L, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=no _LT_TAGVAR(inherit_rpath, $1)=no _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no # Source file extension for fc test sources. ac_ext=${ac_fc_srcext-f} # Object file extension for compiled fc test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # No sense in running all these tests if we already determined that # the FC compiler isn't working. Some variables (like enable_shared) # are currently assumed to apply to all compilers on this platform, # and will be corrupted by setting them based on a non-working compiler. if test yes != "$_lt_disable_FC"; then # Code to be used in simple compile tests lt_simple_compile_test_code="\ subroutine t return end " # Code to be used in simple link tests lt_simple_link_test_code="\ program t end " # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_GCC=$GCC lt_save_CFLAGS=$CFLAGS CC=${FC-"f95"} CFLAGS=$FCFLAGS compiler=$CC GCC=$ac_cv_fc_compiler_gnu _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) if test -n "$compiler"; then AC_MSG_CHECKING([if libtool supports shared libraries]) AC_MSG_RESULT([$can_build_shared]) AC_MSG_CHECKING([whether to build shared libraries]) test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[[4-9]]*) if test ia64 != "$host_cpu"; then case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in yes,aix,yes) ;; # shared object as lib.so file only yes,svr4,*) ;; # shared object as lib.so archive member only yes,*) enable_static=no ;; # shared object in lib.a archive as well esac fi ;; esac AC_MSG_RESULT([$enable_shared]) AC_MSG_CHECKING([whether to build static libraries]) # Make sure either enable_shared or enable_static is yes. test yes = "$enable_shared" || enable_static=yes AC_MSG_RESULT([$enable_static]) _LT_TAGVAR(GCC, $1)=$ac_cv_fc_compiler_gnu _LT_TAGVAR(LD, $1)=$LD ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... _LT_SYS_HIDDEN_LIBDEPS($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_SYS_DYNAMIC_LINKER($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi # test -n "$compiler" GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS fi # test yes != "$_lt_disable_FC" AC_LANG_POP ])# _LT_LANG_FC_CONFIG # _LT_LANG_GCJ_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for the GNU Java Compiler compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_GCJ_CONFIG], [AC_REQUIRE([LT_PROG_GCJ])dnl AC_LANG_SAVE # Source file extension for Java test sources. ac_ext=java # Object file extension for compiled Java test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="class foo {}" # Code to be used in simple link tests lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC=yes CC=${GCJ-"gcj"} CFLAGS=$GCJFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)=$LD _LT_CC_BASENAME([$compiler]) # GCJ did not exist at the time GCC didn't implicitly link libc in. _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi AC_LANG_RESTORE GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_GCJ_CONFIG # _LT_LANG_GO_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for the GNU Go compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_GO_CONFIG], [AC_REQUIRE([LT_PROG_GO])dnl AC_LANG_SAVE # Source file extension for Go test sources. ac_ext=go # Object file extension for compiled Go test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="package main; func main() { }" # Code to be used in simple link tests lt_simple_link_test_code='package main; func main() { }' # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC=yes CC=${GOC-"gccgo"} CFLAGS=$GOFLAGS compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_TAGVAR(LD, $1)=$LD _LT_CC_BASENAME([$compiler]) # Go did not exist at the time GCC didn't implicitly link libc in. _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds _LT_TAGVAR(reload_flag, $1)=$reload_flag _LT_TAGVAR(reload_cmds, $1)=$reload_cmds ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then _LT_COMPILER_NO_RTTI($1) _LT_COMPILER_PIC($1) _LT_COMPILER_C_O($1) _LT_COMPILER_FILE_LOCKS($1) _LT_LINKER_SHLIBS($1) _LT_LINKER_HARDCODE_LIBPATH($1) _LT_CONFIG($1) fi AC_LANG_RESTORE GCC=$lt_save_GCC CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_GO_CONFIG # _LT_LANG_RC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for the Windows resource compiler # are suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to 'libtool'. m4_defun([_LT_LANG_RC_CONFIG], [AC_REQUIRE([LT_PROG_RC])dnl AC_LANG_SAVE # Source file extension for RC test sources. ac_ext=rc # Object file extension for compiled RC test sources. objext=o _LT_TAGVAR(objext, $1)=$objext # Code to be used in simple compile tests lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' # Code to be used in simple link tests lt_simple_link_test_code=$lt_simple_compile_test_code # ltmain only uses $CC for tagged configurations so make sure $CC is set. _LT_TAG_COMPILER # save warnings/boilerplate of simple test code _LT_COMPILER_BOILERPLATE _LT_LINKER_BOILERPLATE # Allow CC to be a program name with arguments. lt_save_CC=$CC lt_save_CFLAGS=$CFLAGS lt_save_GCC=$GCC GCC= CC=${RC-"windres"} CFLAGS= compiler=$CC _LT_TAGVAR(compiler, $1)=$CC _LT_CC_BASENAME([$compiler]) _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes if test -n "$compiler"; then : _LT_CONFIG($1) fi GCC=$lt_save_GCC AC_LANG_RESTORE CC=$lt_save_CC CFLAGS=$lt_save_CFLAGS ])# _LT_LANG_RC_CONFIG # LT_PROG_GCJ # ----------- AC_DEFUN([LT_PROG_GCJ], [m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], [AC_CHECK_TOOL(GCJ, gcj,) test set = "${GCJFLAGS+set}" || GCJFLAGS="-g -O2" AC_SUBST(GCJFLAGS)])])[]dnl ]) # Old name: AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_GCJ], []) # LT_PROG_GO # ---------- AC_DEFUN([LT_PROG_GO], [AC_CHECK_TOOL(GOC, gccgo,) ]) # LT_PROG_RC # ---------- AC_DEFUN([LT_PROG_RC], [AC_CHECK_TOOL(RC, windres,) ]) # Old name: AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_RC], []) # _LT_DECL_EGREP # -------------- # If we don't have a new enough Autoconf to choose the best grep # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_EGREP], [AC_REQUIRE([AC_PROG_EGREP])dnl AC_REQUIRE([AC_PROG_FGREP])dnl test -z "$GREP" && GREP=grep _LT_DECL([], [GREP], [1], [A grep program that handles long lines]) _LT_DECL([], [EGREP], [1], [An ERE matcher]) _LT_DECL([], [FGREP], [1], [A literal string matcher]) dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too AC_SUBST([GREP]) ]) # _LT_DECL_OBJDUMP # -------------- # If we don't have a new enough Autoconf to choose the best objdump # available, choose the one first in the user's PATH. m4_defun([_LT_DECL_OBJDUMP], [AC_CHECK_TOOL(OBJDUMP, objdump, false) test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) AC_SUBST([OBJDUMP]) ]) # _LT_DECL_DLLTOOL # ---------------- # Ensure DLLTOOL variable is set. m4_defun([_LT_DECL_DLLTOOL], [AC_CHECK_TOOL(DLLTOOL, dlltool, false) test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [1], [DLL creation program]) AC_SUBST([DLLTOOL]) ]) # _LT_DECL_SED # ------------ # Check for a fully-functional sed program, that truncates # as few characters as possible. Prefer GNU sed if found. m4_defun([_LT_DECL_SED], [AC_PROG_SED test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" _LT_DECL([], [SED], [1], [A sed program that does not truncate output]) _LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], [Sed that helps us avoid accidentally triggering echo(1) options like -n]) ])# _LT_DECL_SED m4_ifndef([AC_PROG_SED], [ ############################################################ # NOTE: This macro has been submitted for inclusion into # # GNU Autoconf as AC_PROG_SED. When it is available in # # a released version of Autoconf we should remove this # # macro and use it instead. # ############################################################ m4_defun([AC_PROG_SED], [AC_MSG_CHECKING([for a sed that does not truncate output]) AC_CACHE_VAL(lt_cv_path_SED, [# Loop through the user's path and test for sed and gsed. # Then use that list of sed's as ones to test for truncation. as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for lt_ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" fi done done done IFS=$as_save_IFS lt_ac_max=0 lt_ac_count=0 # Add /usr/xpg4/bin/sed as it is typically found on Solaris # along with /bin/sed that truncates output. for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do test ! -f "$lt_ac_sed" && continue cat /dev/null > conftest.in lt_ac_count=0 echo $ECHO_N "0123456789$ECHO_C" >conftest.in # Check for GNU sed and select it if it is found. if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then lt_cv_path_SED=$lt_ac_sed break fi while true; do cat conftest.in conftest.in >conftest.tmp mv conftest.tmp conftest.in cp conftest.in conftest.nl echo >>conftest.nl $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break cmp -s conftest.out conftest.nl || break # 10000 chars as input seems more than enough test 10 -lt "$lt_ac_count" && break lt_ac_count=`expr $lt_ac_count + 1` if test "$lt_ac_count" -gt "$lt_ac_max"; then lt_ac_max=$lt_ac_count lt_cv_path_SED=$lt_ac_sed fi done done ]) SED=$lt_cv_path_SED AC_SUBST([SED]) AC_MSG_RESULT([$SED]) ])#AC_PROG_SED ])#m4_ifndef # Old name: AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([LT_AC_PROG_SED], []) # _LT_CHECK_SHELL_FEATURES # ------------------------ # Find out whether the shell is Bourne or XSI compatible, # or has some other useful features. m4_defun([_LT_CHECK_SHELL_FEATURES], [if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi _LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl # test EBCDIC or ASCII case `echo X|tr X '\101'` in A) # ASCII based system # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac _LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl _LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl ])# _LT_CHECK_SHELL_FEATURES # _LT_PATH_CONVERSION_FUNCTIONS # ----------------------------- # Determine what file name conversion functions should be used by # func_to_host_file (and, implicitly, by func_to_host_path). These are needed # for certain cross-compile configurations and native mingw. m4_defun([_LT_PATH_CONVERSION_FUNCTIONS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl AC_MSG_CHECKING([how to convert $build file names to $host format]) AC_CACHE_VAL(lt_cv_to_host_file_cmd, [case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 ;; esac ;; *-*-cygwin* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_noop ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin ;; esac ;; * ) # unhandled hosts (and "normal" native builds) lt_cv_to_host_file_cmd=func_convert_file_noop ;; esac ]) to_host_file_cmd=$lt_cv_to_host_file_cmd AC_MSG_RESULT([$lt_cv_to_host_file_cmd]) _LT_DECL([to_host_file_cmd], [lt_cv_to_host_file_cmd], [0], [convert $build file names to $host format])dnl AC_MSG_CHECKING([how to convert $build file names to toolchain format]) AC_CACHE_VAL(lt_cv_to_tool_file_cmd, [#assume ordinary cross tools, or native build. lt_cv_to_tool_file_cmd=func_convert_file_noop case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 ;; esac ;; esac ]) to_tool_file_cmd=$lt_cv_to_tool_file_cmd AC_MSG_RESULT([$lt_cv_to_tool_file_cmd]) _LT_DECL([to_tool_file_cmd], [lt_cv_to_tool_file_cmd], [0], [convert $build files to toolchain format])dnl ])# _LT_PATH_CONVERSION_FUNCTIONS libinfinity-0.7.1/m4/PaxHeaders.26529/gtk-doc.m40000644000000000000000000000013013036062665015722 xustar0029 mtime=1484285365.80788136 29 atime=1484285365.80788136 30 ctime=1488261588.740139633 libinfinity-0.7.1/m4/gtk-doc.m40000644000175000017500000000631213036062665016460 0ustar00arminarmin00000000000000dnl -*- mode: autoconf -*- # serial 2 dnl Usage: dnl GTK_DOC_CHECK([minimum-gtk-doc-version]) AC_DEFUN([GTK_DOC_CHECK], [ AC_REQUIRE([PKG_PROG_PKG_CONFIG]) AC_BEFORE([AC_PROG_LIBTOOL],[$0])dnl setup libtool first AC_BEFORE([AM_PROG_LIBTOOL],[$0])dnl setup libtool first ifelse([$1],[],[gtk_doc_requires="gtk-doc"],[gtk_doc_requires="gtk-doc >= $1"]) AC_MSG_CHECKING([for gtk-doc]) PKG_CHECK_EXISTS([$gtk_doc_requires],[have_gtk_doc=yes],[have_gtk_doc=no]) AC_MSG_RESULT($have_gtk_doc) if test "$have_gtk_doc" = "no"; then AC_MSG_WARN([ You will not be able to create source packages with 'make dist' because $gtk_doc_requires is not found.]) fi dnl check for tools we added during development dnl Use AC_CHECK_PROG to avoid the check target using an absolute path that dnl may not be writable by the user. Currently, automake requires that the dnl test name must end in '.test'. dnl https://bugzilla.gnome.org/show_bug.cgi?id=701638 AC_CHECK_PROG([GTKDOC_CHECK],[gtkdoc-check],[gtkdoc-check.test]) AC_PATH_PROG([GTKDOC_CHECK_PATH],[gtkdoc-check]) AC_PATH_PROGS([GTKDOC_REBASE],[gtkdoc-rebase],[true]) AC_PATH_PROG([GTKDOC_MKPDF],[gtkdoc-mkpdf]) dnl for overriding the documentation installation directory AC_ARG_WITH([html-dir], AS_HELP_STRING([--with-html-dir=PATH], [path to installed docs]),, [with_html_dir='${datadir}/gtk-doc/html']) HTML_DIR="$with_html_dir" AC_SUBST([HTML_DIR]) dnl enable/disable documentation building AC_ARG_ENABLE([gtk-doc], AS_HELP_STRING([--enable-gtk-doc], [use gtk-doc to build documentation [[default=no]]]),, [enable_gtk_doc=no]) AC_MSG_CHECKING([whether to build gtk-doc documentation]) AC_MSG_RESULT($enable_gtk_doc) if test "x$enable_gtk_doc" = "xyes" && test "$have_gtk_doc" = "no"; then AC_MSG_ERROR([ You must have $gtk_doc_requires installed to build documentation for $PACKAGE_NAME. Please install gtk-doc or disable building the documentation by adding '--disable-gtk-doc' to '[$]0'.]) fi dnl don't check for glib if we build glib if test "x$PACKAGE_NAME" != "xglib"; then dnl don't fail if someone does not have glib PKG_CHECK_MODULES(GTKDOC_DEPS, glib-2.0 >= 2.10.0 gobject-2.0 >= 2.10.0,,[:]) fi dnl enable/disable output formats AC_ARG_ENABLE([gtk-doc-html], AS_HELP_STRING([--enable-gtk-doc-html], [build documentation in html format [[default=yes]]]),, [enable_gtk_doc_html=yes]) AC_ARG_ENABLE([gtk-doc-pdf], AS_HELP_STRING([--enable-gtk-doc-pdf], [build documentation in pdf format [[default=no]]]),, [enable_gtk_doc_pdf=no]) if test -z "$GTKDOC_MKPDF"; then enable_gtk_doc_pdf=no fi if test -z "$AM_DEFAULT_VERBOSITY"; then AM_DEFAULT_VERBOSITY=1 fi AC_SUBST([AM_DEFAULT_VERBOSITY]) AM_CONDITIONAL([HAVE_GTK_DOC], [test x$have_gtk_doc = xyes]) AM_CONDITIONAL([ENABLE_GTK_DOC], [test x$enable_gtk_doc = xyes]) AM_CONDITIONAL([GTK_DOC_BUILD_HTML], [test x$enable_gtk_doc_html = xyes]) AM_CONDITIONAL([GTK_DOC_BUILD_PDF], [test x$enable_gtk_doc_pdf = xyes]) AM_CONDITIONAL([GTK_DOC_USE_LIBTOOL], [test -n "$LIBTOOL"]) AM_CONDITIONAL([GTK_DOC_USE_REBASE], [test -n "$GTKDOC_REBASE"]) ]) libinfinity-0.7.1/m4/PaxHeaders.26529/ltsugar.m40000644000000000000000000000013213036062675016056 xustar0030 mtime=1484285373.363887402 30 atime=1484285373.363887402 30 ctime=1488261588.744139625 libinfinity-0.7.1/m4/ltsugar.m40000644000175000017500000001044013036062675016607 0ustar00arminarmin00000000000000# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- # # Copyright (C) 2004-2005, 2007-2008, 2011-2015 Free Software # Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file 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. # serial 6 ltsugar.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) # lt_join(SEP, ARG1, [ARG2...]) # ----------------------------- # Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their # associated separator. # Needed until we can rely on m4_join from Autoconf 2.62, since all earlier # versions in m4sugar had bugs. m4_define([lt_join], [m4_if([$#], [1], [], [$#], [2], [[$2]], [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) m4_define([_lt_join], [m4_if([$#$2], [2], [], [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) # lt_car(LIST) # lt_cdr(LIST) # ------------ # Manipulate m4 lists. # These macros are necessary as long as will still need to support # Autoconf-2.59, which quotes differently. m4_define([lt_car], [[$1]]) m4_define([lt_cdr], [m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], [$#], 1, [], [m4_dquote(m4_shift($@))])]) m4_define([lt_unquote], $1) # lt_append(MACRO-NAME, STRING, [SEPARATOR]) # ------------------------------------------ # Redefine MACRO-NAME to hold its former content plus 'SEPARATOR''STRING'. # Note that neither SEPARATOR nor STRING are expanded; they are appended # to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). # No SEPARATOR is output if MACRO-NAME was previously undefined (different # than defined and empty). # # This macro is needed until we can rely on Autoconf 2.62, since earlier # versions of m4sugar mistakenly expanded SEPARATOR but not STRING. m4_define([lt_append], [m4_define([$1], m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) # lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) # ---------------------------------------------------------- # Produce a SEP delimited list of all paired combinations of elements of # PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list # has the form PREFIXmINFIXSUFFIXn. # Needed until we can rely on m4_combine added in Autoconf 2.62. m4_define([lt_combine], [m4_if(m4_eval([$# > 3]), [1], [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl [[m4_foreach([_Lt_prefix], [$2], [m4_foreach([_Lt_suffix], ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) # lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) # ----------------------------------------------------------------------- # Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited # by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. m4_define([lt_if_append_uniq], [m4_ifdef([$1], [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], [lt_append([$1], [$2], [$3])$4], [$5])], [lt_append([$1], [$2], [$3])$4])]) # lt_dict_add(DICT, KEY, VALUE) # ----------------------------- m4_define([lt_dict_add], [m4_define([$1($2)], [$3])]) # lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) # -------------------------------------------- m4_define([lt_dict_add_subkey], [m4_define([$1($2:$3)], [$4])]) # lt_dict_fetch(DICT, KEY, [SUBKEY]) # ---------------------------------- m4_define([lt_dict_fetch], [m4_ifval([$3], m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) # lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) # ----------------------------------------------------------------- m4_define([lt_if_dict_fetch], [m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], [$5], [$6])]) # lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) # -------------------------------------------------------------- m4_define([lt_dict_filter], [m4_if([$5], [], [], [lt_join(m4_quote(m4_default([$4], [[, ]])), lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl ]) libinfinity-0.7.1/m4/PaxHeaders.26529/ltoptions.m40000644000000000000000000000013213036062675016430 xustar0030 mtime=1484285373.351887392 30 atime=1484285373.351887392 30 ctime=1488261588.744139625 libinfinity-0.7.1/m4/ltoptions.m40000644000175000017500000003426213036062675017171 0ustar00arminarmin00000000000000# Helper functions for option handling. -*- Autoconf -*- # # Copyright (C) 2004-2005, 2007-2009, 2011-2015 Free Software # Foundation, Inc. # Written by Gary V. Vaughan, 2004 # # This file 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. # serial 8 ltoptions.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) # _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) # ------------------------------------------ m4_define([_LT_MANGLE_OPTION], [[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) # _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) # --------------------------------------- # Set option OPTION-NAME for macro MACRO-NAME, and if there is a # matching handler defined, dispatch to it. Other OPTION-NAMEs are # saved as a flag. m4_define([_LT_SET_OPTION], [m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), _LT_MANGLE_DEFUN([$1], [$2]), [m4_warning([Unknown $1 option '$2'])])[]dnl ]) # _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) # ------------------------------------------------------------ # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. m4_define([_LT_IF_OPTION], [m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) # _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) # ------------------------------------------------------- # Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME # are set. m4_define([_LT_UNLESS_OPTIONS], [m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), [m4_define([$0_found])])])[]dnl m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 ])[]dnl ]) # _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) # ---------------------------------------- # OPTION-LIST is a space-separated list of Libtool options associated # with MACRO-NAME. If any OPTION has a matching handler declared with # LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about # the unknown option and exit. m4_defun([_LT_SET_OPTIONS], [# Set options m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), [_LT_SET_OPTION([$1], _LT_Option)]) m4_if([$1],[LT_INIT],[ dnl dnl Simply set some default values (i.e off) if boolean options were not dnl specified: _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no ]) _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no ]) dnl dnl If no reference was made to various pairs of opposing options, then dnl we run the default mode handler for the pair. For example, if neither dnl 'shared' nor 'disable-shared' was passed, we enable building of shared dnl archives by default: _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], [_LT_ENABLE_FAST_INSTALL]) _LT_UNLESS_OPTIONS([LT_INIT], [aix-soname=aix aix-soname=both aix-soname=svr4], [_LT_WITH_AIX_SONAME([aix])]) ]) ])# _LT_SET_OPTIONS ## --------------------------------- ## ## Macros to handle LT_INIT options. ## ## --------------------------------- ## # _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) # ----------------------------------------- m4_define([_LT_MANGLE_DEFUN], [[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) # LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) # ----------------------------------------------- m4_define([LT_OPTION_DEFINE], [m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl ])# LT_OPTION_DEFINE # dlopen # ------ LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes ]) AU_DEFUN([AC_LIBTOOL_DLOPEN], [_LT_SET_OPTION([LT_INIT], [dlopen]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'dlopen' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) # win32-dll # --------- # Declare package support for building win32 dll's. LT_OPTION_DEFINE([LT_INIT], [win32-dll], [enable_win32_dll=yes case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) AC_CHECK_TOOL(AS, as, false) AC_CHECK_TOOL(DLLTOOL, dlltool, false) AC_CHECK_TOOL(OBJDUMP, objdump, false) ;; esac test -z "$AS" && AS=as _LT_DECL([], [AS], [1], [Assembler program])dnl test -z "$DLLTOOL" && DLLTOOL=dlltool _LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl test -z "$OBJDUMP" && OBJDUMP=objdump _LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl ])# win32-dll AU_DEFUN([AC_LIBTOOL_WIN32_DLL], [AC_REQUIRE([AC_CANONICAL_HOST])dnl _LT_SET_OPTION([LT_INIT], [win32-dll]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'win32-dll' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) # _LT_ENABLE_SHARED([DEFAULT]) # ---------------------------- # implement the --enable-shared flag, and supports the 'shared' and # 'disable-shared' LT_INIT options. # DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_SHARED], [m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([shared], [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS=$lt_save_ifs ;; esac], [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) _LT_DECL([build_libtool_libs], [enable_shared], [0], [Whether or not to build shared libraries]) ])# _LT_ENABLE_SHARED LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) # Old names: AC_DEFUN([AC_ENABLE_SHARED], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) ]) AC_DEFUN([AC_DISABLE_SHARED], [_LT_SET_OPTION([LT_INIT], [disable-shared]) ]) AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_SHARED], []) dnl AC_DEFUN([AM_DISABLE_SHARED], []) # _LT_ENABLE_STATIC([DEFAULT]) # ---------------------------- # implement the --enable-static flag, and support the 'static' and # 'disable-static' LT_INIT options. # DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_STATIC], [m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([static], [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS=$lt_save_ifs ;; esac], [enable_static=]_LT_ENABLE_STATIC_DEFAULT) _LT_DECL([build_old_libs], [enable_static], [0], [Whether or not to build static libraries]) ])# _LT_ENABLE_STATIC LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) # Old names: AC_DEFUN([AC_ENABLE_STATIC], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) ]) AC_DEFUN([AC_DISABLE_STATIC], [_LT_SET_OPTION([LT_INIT], [disable-static]) ]) AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AM_ENABLE_STATIC], []) dnl AC_DEFUN([AM_DISABLE_STATIC], []) # _LT_ENABLE_FAST_INSTALL([DEFAULT]) # ---------------------------------- # implement the --enable-fast-install flag, and support the 'fast-install' # and 'disable-fast-install' LT_INIT options. # DEFAULT is either 'yes' or 'no'. If omitted, it defaults to 'yes'. m4_define([_LT_ENABLE_FAST_INSTALL], [m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl AC_ARG_ENABLE([fast-install], [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], [p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS=$lt_save_ifs ;; esac], [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) _LT_DECL([fast_install], [enable_fast_install], [0], [Whether or not to optimize for fast installation])dnl ])# _LT_ENABLE_FAST_INSTALL LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) # Old names: AU_DEFUN([AC_ENABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'fast-install' option into LT_INIT's first parameter.]) ]) AU_DEFUN([AC_DISABLE_FAST_INSTALL], [_LT_SET_OPTION([LT_INIT], [disable-fast-install]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'disable-fast-install' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) # _LT_WITH_AIX_SONAME([DEFAULT]) # ---------------------------------- # implement the --with-aix-soname flag, and support the `aix-soname=aix' # and `aix-soname=both' and `aix-soname=svr4' LT_INIT options. DEFAULT # is either `aix', `both' or `svr4'. If omitted, it defaults to `aix'. m4_define([_LT_WITH_AIX_SONAME], [m4_define([_LT_WITH_AIX_SONAME_DEFAULT], [m4_if($1, svr4, svr4, m4_if($1, both, both, aix))])dnl shared_archive_member_spec= case $host,$enable_shared in power*-*-aix[[5-9]]*,yes) AC_MSG_CHECKING([which variant of shared library versioning to provide]) AC_ARG_WITH([aix-soname], [AS_HELP_STRING([--with-aix-soname=aix|svr4|both], [shared library versioning (aka "SONAME") variant to provide on AIX, @<:@default=]_LT_WITH_AIX_SONAME_DEFAULT[@:>@.])], [case $withval in aix|svr4|both) ;; *) AC_MSG_ERROR([Unknown argument to --with-aix-soname]) ;; esac lt_cv_with_aix_soname=$with_aix_soname], [AC_CACHE_VAL([lt_cv_with_aix_soname], [lt_cv_with_aix_soname=]_LT_WITH_AIX_SONAME_DEFAULT) with_aix_soname=$lt_cv_with_aix_soname]) AC_MSG_RESULT([$with_aix_soname]) if test aix != "$with_aix_soname"; then # For the AIX way of multilib, we name the shared archive member # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, # the AIX toolchain works better with OBJECT_MODE set (default 32). if test 64 = "${OBJECT_MODE-32}"; then shared_archive_member_spec=shr_64 else shared_archive_member_spec=shr fi fi ;; *) with_aix_soname=aix ;; esac _LT_DECL([], [shared_archive_member_spec], [0], [Shared archive member basename, for filename based shared library versioning on AIX])dnl ])# _LT_WITH_AIX_SONAME LT_OPTION_DEFINE([LT_INIT], [aix-soname=aix], [_LT_WITH_AIX_SONAME([aix])]) LT_OPTION_DEFINE([LT_INIT], [aix-soname=both], [_LT_WITH_AIX_SONAME([both])]) LT_OPTION_DEFINE([LT_INIT], [aix-soname=svr4], [_LT_WITH_AIX_SONAME([svr4])]) # _LT_WITH_PIC([MODE]) # -------------------- # implement the --with-pic flag, and support the 'pic-only' and 'no-pic' # LT_INIT options. # MODE is either 'yes' or 'no'. If omitted, it defaults to 'both'. m4_define([_LT_WITH_PIC], [AC_ARG_WITH([pic], [AS_HELP_STRING([--with-pic@<:@=PKGS@:>@], [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], [lt_p=${PACKAGE-default} case $withval in yes|no) pic_mode=$withval ;; *) pic_mode=default # Look at the argument we got. We use all the common list separators. lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for lt_pkg in $withval; do IFS=$lt_save_ifs if test "X$lt_pkg" = "X$lt_p"; then pic_mode=yes fi done IFS=$lt_save_ifs ;; esac], [pic_mode=m4_default([$1], [default])]) _LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl ])# _LT_WITH_PIC LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) # Old name: AU_DEFUN([AC_LIBTOOL_PICMODE], [_LT_SET_OPTION([LT_INIT], [pic-only]) AC_DIAGNOSE([obsolete], [$0: Remove this warning and the call to _LT_SET_OPTION when you put the 'pic-only' option into LT_INIT's first parameter.]) ]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) ## ----------------- ## ## LTDL_INIT Options ## ## ----------------- ## m4_define([_LTDL_MODE], []) LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], [m4_define([_LTDL_MODE], [nonrecursive])]) LT_OPTION_DEFINE([LTDL_INIT], [recursive], [m4_define([_LTDL_MODE], [recursive])]) LT_OPTION_DEFINE([LTDL_INIT], [subproject], [m4_define([_LTDL_MODE], [subproject])]) m4_define([_LTDL_TYPE], []) LT_OPTION_DEFINE([LTDL_INIT], [installable], [m4_define([_LTDL_TYPE], [installable])]) LT_OPTION_DEFINE([LTDL_INIT], [convenience], [m4_define([_LTDL_TYPE], [convenience])]) libinfinity-0.7.1/PaxHeaders.26529/libinftextgtk0000644000000000000000000000013213055210725016404 xustar0030 mtime=1488261589.400138191 30 atime=1488261589.352138296 30 ctime=1488261589.400138191 libinfinity-0.7.1/libinftextgtk/0000755000175000017500000000000013055210725017213 5ustar00arminarmin00000000000000libinfinity-0.7.1/libinftextgtk/PaxHeaders.26529/inf-text-gtk-buffer.c0000644000000000000000000000013213034342512022412 xustar0030 mtime=1483851082.049718536 30 atime=1483851082.049718536 30 ctime=1488261589.396138199 libinfinity-0.7.1/libinftextgtk/inf-text-gtk-buffer.c0000644000175000017500000023336013034342512023153 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-text-gtk-buffer * @title: InfTextGtkBuffer * @short_description: Synchronizing a text session with a #GtkTextBuffer * @include: libinftextgtk/inf-text-gtk-buffer.h * @see_also: #InfTextBuffer * @stability: Unstable * * #InfTextGtkBuffer is an implementation of the #InfTextBuffer interface. It * can therefore be used as a backend for #InfTextSessions to store * their text. The buffer is implemented by using a #GtkTextBuffer as * storage. This way the text document can be displayed using a #GtkTextView * such that only one copy of the text is held in memory, which is used both * by the user interface toolkit and the text synchronization functionality. * * If external changes are made to the #GtkTextBuffer, for example by a user * typing into a #GtkTextView, then the text is synchronized to other * participants of the session. For this purpose, * inf_text_gtk_buffer_set_active_user() should be called with a user that * was previously joined into the session using inf_session_proxy_join_user(). * If there is no local user in the session, no modifications to the buffer * must be made because they cannot be synchronized to other participants. * * This class also takes care of setting background colors for the text to * indicate which user wrote what text, by adding corresponding * #GtkTextTags to the document. The function * inf_text_gtk_buffer_set_show_user_colors() to turn on or off the colored * background. Even if background coloring is turned off, the text is still * tagged according to the authorship, so that coloring can be turned on at a * later point or so that the authorship can still be queried for other means, * such as in a "blame" kind of functionality. */ #include #include #include #include /* for strlen() */ struct _InfTextBufferIter { GtkTextIter begin; GtkTextIter end; InfTextUser* user; }; typedef struct _InfTextGtkBufferRecord InfTextGtkBufferRecord; struct _InfTextGtkBufferRecord { gboolean insert; guint char_count; guint position; InfTextChunk* chunk; gboolean applied; InfTextGtkBufferRecord* next; }; typedef struct _InfTextGtkBufferUserTags InfTextGtkBufferUserTags; struct _InfTextGtkBufferUserTags { InfTextGtkBuffer* buffer; InfTextUser* user; GtkTextTag* colored_tag; GtkTextTag* colorless_tag; }; typedef struct _InfTextGtkBufferTagRemove InfTextGtkBufferTagRemove; struct _InfTextGtkBufferTagRemove { GtkTextBuffer* buffer; GtkTextIter begin_iter; GtkTextIter end_iter; InfTextGtkBufferUserTags* ignore_tags; }; typedef struct _InfTextGtkBufferPrivate InfTextGtkBufferPrivate; struct _InfTextGtkBufferPrivate { GtkTextBuffer* buffer; InfUserTable* user_table; GHashTable* user_tags; InfTextGtkBufferRecord* record; gboolean show_user_colors; InfTextUser* active_user; gboolean wake_on_cursor_movement; gdouble saturation; gdouble value; gdouble alpha; }; enum { PROP_0, PROP_BUFFER, PROP_USER_TABLE, PROP_ACTIVE_USER, PROP_WAKE_ON_CURSOR_MOVEMENT, PROP_SHOW_USER_COLORS, PROP_SATURATION, PROP_VALUE, PROP_ALPHA, /* overriden */ PROP_MODIFIED }; #define INF_TEXT_GTK_BUFFER_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INF_TEXT_GTK_TYPE_BUFFER, InfTextGtkBufferPrivate)) static GQuark inf_text_gtk_buffer_tag_user_quark; static void inf_text_gtk_buffer_buffer_iface_init(InfBufferInterface* iface); static void inf_text_gtk_buffer_text_buffer_iface_init(InfTextBufferInterface* iface); G_DEFINE_TYPE_WITH_CODE(InfTextGtkBuffer, inf_text_gtk_buffer, G_TYPE_OBJECT, G_ADD_PRIVATE(InfTextGtkBuffer) G_IMPLEMENT_INTERFACE(INF_TYPE_BUFFER, inf_text_gtk_buffer_buffer_iface_init) G_IMPLEMENT_INTERFACE(INF_TEXT_TYPE_BUFFER, inf_text_gtk_buffer_text_buffer_iface_init)) static void inf_text_gtk_update_tag_color(InfTextGtkBuffer* buffer, GtkTextTag* tag, InfTextUser* user) { InfTextGtkBufferPrivate* priv; gdouble hue; gdouble saturation; gdouble value; GdkRGBA rgba; priv = INF_TEXT_GTK_BUFFER_PRIVATE(buffer); hue = inf_text_user_get_hue(user); saturation = priv->saturation; value = priv->value; gtk_hsv_to_rgb(hue, saturation, value, &rgba.red, &rgba.green, &rgba.blue); rgba.alpha = priv->alpha; g_object_set(G_OBJECT(tag), "background-rgba", &rgba, NULL); } static void inf_text_gtk_user_notify_hue_cb(GObject* object, GParamSpec* pspec, gpointer user_data) { InfTextGtkBuffer* buffer; InfTextGtkBufferPrivate* priv; guint user_id; InfTextGtkBufferUserTags* tags; buffer = INF_TEXT_GTK_BUFFER(user_data); priv = INF_TEXT_GTK_BUFFER_PRIVATE(buffer); user_id = inf_user_get_id(INF_USER(object)); tags = g_hash_table_lookup(priv->user_tags, GUINT_TO_POINTER(user_id)); g_assert(tags != NULL && tags->colored_tag != NULL); inf_text_gtk_update_tag_color( buffer, tags->colored_tag, INF_TEXT_USER(object) ); } static void inf_text_gtk_buffer_user_tags_free(gpointer user_tags) { InfTextGtkBufferUserTags* tags; tags = (InfTextGtkBufferUserTags*)user_tags; if(tags->colored_tag) { inf_signal_handlers_disconnect_by_func( tags->user, G_CALLBACK(inf_text_gtk_user_notify_hue_cb), tags->buffer ); g_object_unref(tags->colored_tag); } if(tags->colorless_tag) g_object_unref(tags->colorless_tag); g_slice_free(InfTextGtkBufferUserTags, tags); } static InfTextGtkBufferUserTags* inf_text_gtk_buffer_get_user_tags(InfTextGtkBuffer* buffer, guint user_id) { InfTextGtkBufferPrivate* priv; InfTextGtkBufferUserTags* tags; InfUser* user; priv = INF_TEXT_GTK_BUFFER_PRIVATE(buffer); if(user_id == 0) return NULL; tags = g_hash_table_lookup(priv->user_tags, GUINT_TO_POINTER(user_id)); if(tags != NULL) { return tags; } else { user = inf_user_table_lookup_user_by_id(priv->user_table, user_id); g_assert(INF_TEXT_IS_USER(user)); tags = g_slice_new(InfTextGtkBufferUserTags); tags->buffer = buffer; tags->user = INF_TEXT_USER(user); tags->colored_tag = NULL; tags->colorless_tag = NULL; g_hash_table_insert(priv->user_tags, GUINT_TO_POINTER(user_id), tags); return tags; } } static GtkTextTag* inf_text_gtk_buffer_get_user_tag(InfTextGtkBuffer* buffer, InfTextGtkBufferUserTags* user_tags, gboolean colored) { InfTextGtkBufferPrivate* priv; GtkTextTagTable* table; GtkTextTag** tag; gchar* tag_name; guint user_id; const gchar* colorstr; priv = INF_TEXT_GTK_BUFFER_PRIVATE(buffer); tag = colored ? &user_tags->colored_tag : &user_tags->colorless_tag; if(*tag != NULL) return *tag; user_id = 0; if(user_tags->user != NULL) user_id = inf_user_get_id(INF_USER(user_tags->user)); colorstr = colored ? "colored" : "colorless"; tag_name = g_strdup_printf("inftextgtk-user-%s-%u", colorstr, user_id); *tag = gtk_text_tag_new(tag_name); g_free(tag_name); table = gtk_text_buffer_get_tag_table(priv->buffer); gtk_text_tag_table_add(table, *tag); /* Set lowest priority for author tags, so GtkSourceView's bracket * matching highlight tags and highlight of FIXME and such in comments is * shown instead of the user color. */ gtk_text_tag_set_priority(*tag, 0); g_object_set_qdata( G_OBJECT(*tag), inf_text_gtk_buffer_tag_user_quark, user_tags->user ); if(colored) { g_signal_connect( G_OBJECT(user_tags->user), "notify::hue", G_CALLBACK(inf_text_gtk_user_notify_hue_cb), buffer ); inf_text_gtk_update_tag_color(buffer, *tag, user_tags->user); } return *tag; } static InfTextUser* inf_text_gtk_buffer_author_from_tag(GtkTextTag* tag) { gpointer author_ptr; author_ptr = g_object_get_qdata( G_OBJECT(tag), inf_text_gtk_buffer_tag_user_quark ); return INF_TEXT_USER(author_ptr); } static InfTextUser* inf_text_gtk_buffer_iter_list_contains_author_tag(GSList* tag_list) { GSList* item; InfTextUser* author; for(item = tag_list; item != NULL; item = g_slist_next(item)) { author = inf_text_gtk_buffer_author_from_tag(GTK_TEXT_TAG(item->data)); if(author != NULL) return author; } return NULL; } static InfTextUser* inf_text_gtk_buffer_iter_get_author(GtkTextIter* location) { GSList* tag_list; InfTextUser* author; tag_list = gtk_text_iter_get_tags(location); author = inf_text_gtk_buffer_iter_list_contains_author_tag(tag_list); g_slist_free(tag_list); return author; } static gboolean inf_text_gtk_buffer_iter_is_author_toggle(const GtkTextIter* iter, InfTextUser** toggled_on, InfTextUser** toggled_off) { GSList* tag_list; InfTextUser* author_on; InfTextUser* author_off; tag_list = gtk_text_iter_get_toggled_tags(iter, TRUE); author_on = inf_text_gtk_buffer_iter_list_contains_author_tag(tag_list); g_slist_free(tag_list); /* We need to check both the tags that are toggled on and the tags that * are toggled off at this point, because text that is not written by * anyone specific (author NULL) does not count as author tag. */ if(author_on == NULL || toggled_off != NULL) { tag_list = gtk_text_iter_get_toggled_tags(iter, FALSE); author_off = inf_text_gtk_buffer_iter_list_contains_author_tag(tag_list); g_slist_free(tag_list); } if(author_on == NULL && author_off == NULL) if(!gtk_text_iter_is_start(iter) && !gtk_text_iter_is_end(iter)) return FALSE; if(toggled_on) *toggled_on = author_on; if(toggled_off) *toggled_off = author_off; return TRUE; } static void inf_text_gtk_buffer_iter_next_author_toggle(GtkTextIter* iter, InfTextUser** user_on, InfTextUser** user_off) { gboolean is_author_toggle; do { gtk_text_iter_forward_to_tag_toggle(iter, NULL); is_author_toggle = inf_text_gtk_buffer_iter_is_author_toggle( iter, user_on, user_off ); } while(!is_author_toggle); } static void inf_text_gtk_buffer_iter_prev_author_toggle(GtkTextIter* iter, InfTextUser** user_on, InfTextUser** user_off) { gboolean is_author_toggle; do { gtk_text_iter_backward_to_tag_toggle(iter, NULL); is_author_toggle = inf_text_gtk_buffer_iter_is_author_toggle( iter, user_on, user_off ); } while(!is_author_toggle); } static void inf_text_gtk_buffer_ensure_author_tags_priority_foreach_func(GtkTextTag* tag, gpointer data) { InfTextUser* author; author = inf_text_gtk_buffer_author_from_tag(tag); if(author != NULL) gtk_text_tag_set_priority(tag, 0); } static void inf_text_gtk_buffer_update_user_color_tag_table_foreach_func(GtkTextTag* tag, gpointer data) { InfTextGtkBuffer* buffer; InfTextGtkBufferPrivate* priv; InfTextUser* author; buffer = INF_TEXT_GTK_BUFFER(data); priv = INF_TEXT_GTK_BUFFER_PRIVATE(buffer); author = inf_text_gtk_buffer_author_from_tag(tag); if(author != NULL) inf_text_gtk_update_tag_color(buffer, tag, author); } /* Required by inf_text_gtk_buffer_record_signal() and * inf_text_gtk_buffer_mark_set_cb() */ static void inf_text_gtk_buffer_active_user_selection_changed_cb(InfTextUser* user, guint position, gint length, gboolean by_request, gpointer user_data); /* Required by inf_text_gtk_buffer_record_signal() and * inf_text_gtk_buffer_mark_set_cb() */ static void inf_text_gtk_buffer_active_user_notify_status_cb(GObject* object, GParamSpec* pspec, gpointer user_data); static void inf_text_gtk_buffer_apply_tag_cb(GtkTextBuffer* gtk_buffer, GtkTextTag* tag, GtkTextIter* start, GtkTextIter* end, gpointer user_data) { /* Don't allow author tags to be applied by default. GTK+ seems to do this * when copy+pasting text from the text buffer itself, but we want to make * sure that a given segment of text has always a unique author set. */ if(inf_text_gtk_buffer_author_from_tag(tag) != NULL) g_signal_stop_emission_by_name(G_OBJECT(gtk_buffer), "apply-tag"); } static void inf_text_gtk_buffer_buffer_insert_text_tag_table_foreach_func(GtkTextTag* tag, gpointer data) { InfTextGtkBufferTagRemove* tag_remove; tag_remove = (InfTextGtkBufferTagRemove*)data; if(tag_remove->ignore_tags == NULL || (tag != tag_remove->ignore_tags->colored_tag && tag != tag_remove->ignore_tags->colorless_tag)) { gtk_text_buffer_remove_tag( tag_remove->buffer, tag, &tag_remove->begin_iter, &tag_remove->end_iter ); } } /* Record tracking: * This is to allow and correctly handle nested emissions of GtkTextBuffer's * insert-text/delete-range signals. The text-inserted and text-erased * signals of InfTextBuffer need to be emitted right after the operation was * applied to the buffer which is why we need some bookkeeping here. */ #ifndef G_DISABLE_ASSERT /* Check whether the top record has been applied correctly to the buffer */ static gboolean inf_text_gtk_buffer_record_check(InfTextGtkBuffer* buffer, InfTextGtkBufferRecord* record) { InfTextGtkBufferPrivate* priv; InfTextChunk* chunk; guint text_len; guint buf_len; gpointer buf_text; gpointer chunk_text; gsize buf_bytes; gsize chunk_bytes; int result; priv = INF_TEXT_GTK_BUFFER_PRIVATE(buffer); text_len = inf_text_chunk_get_length(record->chunk); buf_len = gtk_text_buffer_get_char_count(priv->buffer); /* We can only check insertions */ if(record->insert) { if(record->char_count + text_len != buf_len) return FALSE; if(record->position + text_len > buf_len) return FALSE; chunk = inf_text_buffer_get_slice( INF_TEXT_BUFFER(buffer), record->position, text_len ); buf_text = inf_text_chunk_get_text(record->chunk, &buf_bytes); chunk_text = inf_text_chunk_get_text(chunk, &chunk_bytes); inf_text_chunk_free(chunk); if(buf_bytes == chunk_bytes) result = memcmp(buf_text, chunk_text, buf_bytes); else result = -1; g_free(buf_text); g_free(chunk_text); if(result != 0) return FALSE; } else { if(text_len > record->char_count) return FALSE; if(record->char_count - text_len != buf_len) return FALSE; } return TRUE; } #endif static void inf_text_gtk_buffer_record_transform(InfTextGtkBufferRecord* record, InfTextGtkBufferRecord* against) { guint record_len; guint against_len; /* What we do here is common sense; in fact this depends on how * insert-text/delete-range signal handlers do revalidation of iters if * they insert/erase text themselves. We rely on them doing it exactly * this way currently, otherwise we cannot identify new/erased text to * emit text-inserted/text-erased for, resulting in new/erased text not * being transmitted to remote users, in turn resulting in lost session * consistency. This is why the inf_text_gtk_buffer_record_check() * check will fail if this happens. */ g_assert(record->applied == FALSE); g_assert(against->applied == TRUE); record_len = inf_text_chunk_get_length(record->chunk); against_len = inf_text_chunk_get_length(against->chunk); if(record->insert && against->insert) { if(record->position >= against->position) record->position += against_len; } else if(record->insert && !against->insert) { if(record->position >= against->position + against_len) record->position -= against_len; else if(record->position >= against->position) record->position = against->position; } else if(!record->insert && against->insert) { if(record->position >= against->position) { record->position += against->position; } else if(record->position < against->position && record->position + record_len > against->position) { /* Add text right into deletion range... */ inf_text_chunk_insert_chunk( record->chunk, against->position - record->position, against->chunk ); } } else if(!record->insert && !against->insert) { if(against->position + against_len <= record->position + record_len) { record->position -= against_len; } else if(against->position + against_len > record->position && against->position + against_len <= record->position + record_len) { record->position = against->position; inf_text_chunk_erase( record->chunk, 0, against->position + against_len - record->position ); } else if(against->position <= record->position && against->position + against_len >= record->position + record_len) { record->position = against->position; inf_text_chunk_erase( record->chunk, 0, inf_text_chunk_get_length(record->chunk) ); } else if(against->position >= record->position && against->position + against_len <= record->position + record_len) { inf_text_chunk_erase( record->chunk, against->position - record->position, inf_text_chunk_get_length(against->chunk) ); } else if(against->position >= record->position && against->position + against_len >= record->position + record_len) { inf_text_chunk_erase( record->chunk, against->position - record->position, record->position + record_len - against->position ); } } /* Revalidate char count */ if(against->insert) { record->char_count += against_len; } else { g_assert(record->char_count >= against_len); record->char_count -= against_len; } } static void inf_text_gtk_buffer_record_signal(InfTextGtkBuffer* buffer, InfTextGtkBufferRecord* record) { InfTextGtkBufferPrivate* priv; InfTextGtkBufferRecord* rec; InfTextGtkBufferTagRemove tag_remove; GtkTextTag* tag; priv = INF_TEXT_GTK_BUFFER_PRIVATE(buffer); g_assert(priv->active_user != NULL); g_assert(record->applied == FALSE); g_assert(inf_text_gtk_buffer_record_check(buffer, record)); record->applied = TRUE; for(rec = record->next; rec != NULL; rec = rec->next) if(!rec->applied) inf_text_gtk_buffer_record_transform(rec->next, record); if(record->insert) { /* Allow author tag changes within this function: */ inf_signal_handlers_block_by_func( G_OBJECT(priv->buffer), G_CALLBACK(inf_text_gtk_buffer_apply_tag_cb), buffer ); /* Tag the inserted text with the user's color */ tag_remove.buffer = priv->buffer; tag_remove.ignore_tags = inf_text_gtk_buffer_get_user_tags( buffer, inf_user_get_id(INF_USER(priv->active_user)) ); g_assert(tag_remove.ignore_tags != NULL); tag = inf_text_gtk_buffer_get_user_tag( buffer, tag_remove.ignore_tags, priv->show_user_colors ); /* Remove other user tags, if any */ gtk_text_buffer_get_iter_at_offset( priv->buffer, &tag_remove.begin_iter, record->position ); gtk_text_buffer_get_iter_at_offset( priv->buffer, &tag_remove.end_iter, record->position + inf_text_chunk_get_length(record->chunk) ); gtk_text_tag_table_foreach( gtk_text_buffer_get_tag_table(tag_remove.buffer), inf_text_gtk_buffer_buffer_insert_text_tag_table_foreach_func, &tag_remove ); /* Apply tag for this particular user */ gtk_text_buffer_apply_tag( priv->buffer, tag, &tag_remove.begin_iter, &tag_remove.end_iter ); /* Allow author tag changes within this function: */ inf_signal_handlers_unblock_by_func( G_OBJECT(priv->buffer), G_CALLBACK(inf_text_gtk_buffer_apply_tag_cb), buffer ); } /* Block the notify_status signal handler of the active user. That signal * handler syncs the cursor position of the user to the insertion mark of * the TextBuffer when the user becomes active again. However, when we * insert or erase text, then this will be updated anyway. */ inf_signal_handlers_block_by_func( G_OBJECT(priv->active_user), G_CALLBACK(inf_text_gtk_buffer_active_user_notify_status_cb), buffer ); /* Block selection-changed of active user. This would try to resync the * buffer markers, but GtkTextBuffer already did this for us. */ inf_signal_handlers_block_by_func( G_OBJECT(priv->active_user), G_CALLBACK(inf_text_gtk_buffer_active_user_selection_changed_cb), buffer ); if(record->insert) { inf_text_buffer_text_inserted( INF_TEXT_BUFFER(buffer), record->position, record->chunk, INF_USER(priv->active_user) ); } else { inf_text_buffer_text_erased( INF_TEXT_BUFFER(buffer), record->position, record->chunk, INF_USER(priv->active_user) ); } inf_signal_handlers_unblock_by_func( G_OBJECT(priv->active_user), G_CALLBACK(inf_text_gtk_buffer_active_user_notify_status_cb), buffer ); inf_signal_handlers_unblock_by_func( G_OBJECT(priv->active_user), G_CALLBACK(inf_text_gtk_buffer_active_user_selection_changed_cb), buffer ); } static void inf_text_gtk_buffer_push_record(InfTextGtkBuffer* buffer, gboolean insert, guint position, InfTextChunk* chunk) { InfTextGtkBufferPrivate* priv; InfTextGtkBufferRecord* rec; priv = INF_TEXT_GTK_BUFFER_PRIVATE(buffer); rec = priv->record; priv->record = g_slice_new(InfTextGtkBufferRecord); priv->record->insert = insert; priv->record->char_count = gtk_text_buffer_get_char_count(priv->buffer); priv->record->position = position; priv->record->chunk = chunk; priv->record->applied = FALSE; priv->record->next = rec; /* It is enough to check whether the top record was applied to the buffer, * since, for previous records we would have been notified in a previous * callback already. */ if(rec != NULL && rec->applied == FALSE) { /* If char count differs then the previous record has already been applied * (that is the default handler ran but not our after handler, so * probably another after handler inserted new text). */ /* TODO: This does not work if length of record is zero */ if(rec->char_count != (guint)gtk_text_buffer_get_char_count(priv->buffer)) { /* This record has been applied already, so signal. */ inf_text_gtk_buffer_record_signal(buffer, rec); #ifndef G_ASSERT_DISABLED /* Outer records would already have been signalled by previous signal * handler invocations if they were applied. */ for(; rec != NULL; rec = rec->next) { g_assert( rec->applied == TRUE || rec->char_count == (guint)gtk_text_buffer_get_char_count(priv->buffer) ); } #endif } } } static void inf_text_gtk_buffer_pop_record(InfTextGtkBuffer* buffer) { InfTextGtkBufferPrivate* priv; InfTextGtkBufferRecord* rec; guint char_count; guint length; priv = INF_TEXT_GTK_BUFFER_PRIVATE(buffer); g_assert(priv->record != NULL); if(!priv->record->applied) { length = inf_text_chunk_get_length(priv->record->chunk); char_count = gtk_text_buffer_get_char_count(priv->buffer); if(priv->record->insert) { g_assert(priv->record->char_count + length == char_count); } else { g_assert(priv->record->char_count >= length); g_assert(priv->record->char_count - length == char_count); } /* Signal application */ inf_text_gtk_buffer_record_signal(buffer, priv->record); } rec = priv->record; priv->record = rec->next; inf_text_chunk_free(rec->chunk); g_slice_free(InfTextGtkBufferRecord, rec); } static void inf_text_gtk_buffer_insert_text_cb_before(GtkTextBuffer* gtk_buffer, GtkTextIter* location, gchar* text, gint len, gpointer user_data) { InfTextGtkBuffer* buffer; InfTextGtkBufferPrivate* priv; InfTextChunk* chunk; buffer = INF_TEXT_GTK_BUFFER(user_data); priv = INF_TEXT_GTK_BUFFER_PRIVATE(buffer); g_assert(priv->active_user != NULL); chunk = inf_text_chunk_new("UTF-8"); inf_text_chunk_insert_text( chunk, 0, text, len, g_utf8_strlen(text, len), inf_user_get_id(INF_USER(priv->active_user)) ); inf_text_gtk_buffer_push_record( buffer, TRUE, gtk_text_iter_get_offset(location), chunk ); } static void inf_text_gtk_buffer_insert_text_cb_after(GtkTextBuffer* gtk_buffer, GtkTextIter* location, gchar* text, gint len, gpointer user_data) { InfTextGtkBuffer* buffer; InfTextGtkBufferPrivate* priv; gpointer rec_text; gsize bytes; buffer = INF_TEXT_GTK_BUFFER(user_data); priv = INF_TEXT_GTK_BUFFER_PRIVATE(buffer); g_assert(priv->record != NULL); g_assert(priv->record->insert == TRUE); #ifndef G_ASSERT_DISABLED if(priv->record->applied == FALSE) { g_assert( priv->record->position + inf_text_chunk_get_length(priv->record->chunk) == (guint)gtk_text_iter_get_offset(location) ); rec_text = inf_text_chunk_get_text(priv->record->chunk, &bytes); g_assert(bytes == (gsize)len); g_assert(memcmp(text, rec_text, bytes) == 0); g_free(rec_text); } #endif inf_text_gtk_buffer_pop_record(buffer); } static void inf_text_gtk_buffer_delete_range_cb_before(GtkTextBuffer* gtk_buffer, GtkTextIter* begin, GtkTextIter* end, gpointer user_data) { InfTextGtkBuffer* buffer; InfTextGtkBufferPrivate* priv; guint begin_offset; guint end_offset; InfTextChunk* chunk; buffer = INF_TEXT_GTK_BUFFER(user_data); priv = INF_TEXT_GTK_BUFFER_PRIVATE(buffer); begin_offset = gtk_text_iter_get_offset(begin); end_offset = gtk_text_iter_get_offset(end); chunk = inf_text_buffer_get_slice( INF_TEXT_BUFFER(buffer), begin_offset, end_offset - begin_offset ); inf_text_gtk_buffer_push_record(buffer, FALSE, begin_offset, chunk); } static void inf_text_gtk_buffer_delete_range_cb_after(GtkTextBuffer* gtk_buffer, GtkTextIter* begin, GtkTextIter* end, gpointer user_data) { InfTextGtkBuffer* buffer; InfTextGtkBufferPrivate* priv; buffer = INF_TEXT_GTK_BUFFER(user_data); priv = INF_TEXT_GTK_BUFFER_PRIVATE(buffer); g_assert(priv->record != NULL); g_assert(priv->record->insert == FALSE); g_assert(priv->record->applied == TRUE || priv->record->position == (guint)gtk_text_iter_get_offset(begin)); inf_text_gtk_buffer_pop_record(buffer); } static void inf_text_gtk_buffer_mark_set_cb(GtkTextBuffer* gtk_buffer, GtkTextIter* location, GtkTextMark* mark, gpointer user_data) { InfTextGtkBuffer* buffer; InfTextGtkBufferPrivate* priv; GtkTextMark* insert_mark; GtkTextMark* sel_mark; GtkTextIter insert_iter; GtkTextIter sel_iter; guint offset; int sel; buffer = INF_TEXT_GTK_BUFFER(user_data); priv = INF_TEXT_GTK_BUFFER_PRIVATE(buffer); insert_mark = gtk_text_buffer_get_insert(gtk_buffer); sel_mark = gtk_text_buffer_get_selection_bound(gtk_buffer); if( (mark == insert_mark || mark == sel_mark) && priv->active_user != NULL) { /* Don't send status updates for inactive users as these would make it * active. Instead, we send one update when the user becomes active * again. */ if(inf_user_get_status(INF_USER(priv->active_user)) == INF_USER_ACTIVE || priv->wake_on_cursor_movement == TRUE) { gtk_text_buffer_get_iter_at_mark(gtk_buffer, &insert_iter, insert_mark); gtk_text_buffer_get_iter_at_mark(gtk_buffer, &sel_iter, sel_mark); offset = gtk_text_iter_get_offset(&insert_iter); sel = gtk_text_iter_get_offset(&sel_iter) - offset; if(inf_text_user_get_caret_position(priv->active_user) != offset || inf_text_user_get_selection_length(priv->active_user) != sel) { /* Block the notify_status signal handler of the active user. That * signal handler syncs the cursor position of the user to the * insertion mark of the TextBuffer when the user becomes active * again. However, when we move the cursor, then this will be updated * anyway. */ inf_signal_handlers_block_by_func( G_OBJECT(priv->active_user), G_CALLBACK(inf_text_gtk_buffer_active_user_notify_status_cb), buffer ); inf_signal_handlers_block_by_func( G_OBJECT(priv->active_user), G_CALLBACK(inf_text_gtk_buffer_active_user_selection_changed_cb), buffer ); inf_text_user_set_selection(priv->active_user, offset, sel, TRUE); inf_signal_handlers_unblock_by_func( G_OBJECT(priv->active_user), G_CALLBACK(inf_text_gtk_buffer_active_user_notify_status_cb), buffer ); inf_signal_handlers_unblock_by_func( G_OBJECT(priv->active_user), G_CALLBACK(inf_text_gtk_buffer_active_user_selection_changed_cb), buffer ); } } } } static void inf_text_gtk_buffer_active_user_notify_status_cb(GObject* object, GParamSpec* pspec, gpointer user_data) { InfTextGtkBuffer* buffer; InfTextGtkBufferPrivate* priv; GtkTextMark* insert_mark; GtkTextMark* sel_mark; GtkTextIter insert_iter; GtkTextIter sel_iter; guint offset; int sel; buffer = INF_TEXT_GTK_BUFFER(user_data); priv = INF_TEXT_GTK_BUFFER_PRIVATE(buffer); g_assert(INF_TEXT_USER(object) == priv->active_user); switch(inf_user_get_status(INF_USER(object))) { case INF_USER_ACTIVE: /* User became active: Sync user selection and the insertion mark of the * TextBuffer. They can get out of sync while the user is inactive, and * wake-on-cursor-movement is FALSE. For example text can be selected in * an inactive document, and then the user decides to select something * else, erasing the previous selection. */ insert_mark = gtk_text_buffer_get_insert(priv->buffer); sel_mark = gtk_text_buffer_get_selection_bound(priv->buffer); gtk_text_buffer_get_iter_at_mark(priv->buffer, &insert_iter, insert_mark); gtk_text_buffer_get_iter_at_mark(priv->buffer, &sel_iter, sel_mark); offset = gtk_text_iter_get_offset(&insert_iter); sel = gtk_text_iter_get_offset(&sel_iter) - offset; if(inf_text_user_get_caret_position(priv->active_user) != offset || inf_text_user_get_selection_length(priv->active_user) != sel) { inf_signal_handlers_block_by_func( G_OBJECT(priv->active_user), G_CALLBACK(inf_text_gtk_buffer_active_user_selection_changed_cb), buffer ); inf_text_user_set_selection(priv->active_user, offset, sel, TRUE); inf_signal_handlers_unblock_by_func( G_OBJECT(priv->active_user), G_CALLBACK(inf_text_gtk_buffer_active_user_selection_changed_cb), buffer ); } break; case INF_USER_UNAVAILABLE: /* TODO: Do we want to unset the active-user automatically here? */ break; default: /* Not of interest. */ break; } } static void inf_text_gtk_buffer_active_user_selection_changed_cb(InfTextUser* user, guint position, gint selection_length, gboolean by_request, gpointer user_data) { InfTextGtkBuffer* buffer; InfTextGtkBufferPrivate* priv; GtkTextIter insert; GtkTextIter selection_bound; buffer = INF_TEXT_GTK_BUFFER(user_data); priv = INF_TEXT_GTK_BUFFER_PRIVATE(buffer); inf_signal_handlers_block_by_func( G_OBJECT(priv->buffer), G_CALLBACK(inf_text_gtk_buffer_mark_set_cb), buffer ); gtk_text_buffer_get_iter_at_offset(priv->buffer, &insert, position); gtk_text_buffer_get_iter_at_offset( priv->buffer, &selection_bound, position + selection_length ); gtk_text_buffer_select_range(priv->buffer, &insert, &selection_bound); inf_signal_handlers_unblock_by_func( G_OBJECT(priv->buffer), G_CALLBACK(inf_text_gtk_buffer_mark_set_cb), buffer ); } static void inf_text_gtk_buffer_modified_changed_cb(GtkTextBuffer* buffer, gpointer user_data) { g_object_notify(G_OBJECT(user_data), "modified"); } static void inf_text_gtk_buffer_set_modified(InfTextGtkBuffer* buffer, gboolean modified) { InfTextGtkBufferPrivate* priv; priv = INF_TEXT_GTK_BUFFER_PRIVATE(buffer); if(priv->buffer != NULL) { inf_signal_handlers_block_by_func( G_OBJECT(priv->buffer), G_CALLBACK(inf_text_gtk_buffer_modified_changed_cb), buffer ); gtk_text_buffer_set_modified(priv->buffer, modified); inf_signal_handlers_unblock_by_func( G_OBJECT(priv->buffer), G_CALLBACK(inf_text_gtk_buffer_modified_changed_cb), buffer ); g_object_notify(G_OBJECT(buffer), "modified"); } } static void inf_text_gtk_buffer_set_buffer(InfTextGtkBuffer* buffer, GtkTextBuffer* gtk_buffer) { InfTextGtkBufferPrivate* priv; priv = INF_TEXT_GTK_BUFFER_PRIVATE(buffer); if(priv->buffer != NULL) { inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->buffer), G_CALLBACK(inf_text_gtk_buffer_apply_tag_cb), buffer ); inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->buffer), G_CALLBACK(inf_text_gtk_buffer_insert_text_cb_before), buffer ); inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->buffer), G_CALLBACK(inf_text_gtk_buffer_insert_text_cb_after), buffer ); inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->buffer), G_CALLBACK(inf_text_gtk_buffer_delete_range_cb_before), buffer ); inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->buffer), G_CALLBACK(inf_text_gtk_buffer_delete_range_cb_after), buffer ); inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->buffer), G_CALLBACK(inf_text_gtk_buffer_mark_set_cb), buffer ); inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->buffer), G_CALLBACK(inf_text_gtk_buffer_modified_changed_cb), buffer ); g_object_unref(G_OBJECT(priv->buffer)); } priv->buffer = gtk_buffer; if(gtk_buffer != NULL) { g_object_ref(G_OBJECT(gtk_buffer)); g_signal_connect( G_OBJECT(gtk_buffer), "apply-tag", G_CALLBACK(inf_text_gtk_buffer_apply_tag_cb), buffer ); g_signal_connect( G_OBJECT(gtk_buffer), "insert-text", G_CALLBACK(inf_text_gtk_buffer_insert_text_cb_before), buffer ); g_signal_connect_after( G_OBJECT(gtk_buffer), "insert-text", G_CALLBACK(inf_text_gtk_buffer_insert_text_cb_after), buffer ); g_signal_connect( G_OBJECT(gtk_buffer), "delete-range", G_CALLBACK(inf_text_gtk_buffer_delete_range_cb_before), buffer ); g_signal_connect_after( G_OBJECT(gtk_buffer), "delete-range", G_CALLBACK(inf_text_gtk_buffer_delete_range_cb_after), buffer ); g_signal_connect_after( G_OBJECT(gtk_buffer), "mark-set", G_CALLBACK(inf_text_gtk_buffer_mark_set_cb), buffer ); g_signal_connect_after( G_OBJECT(gtk_buffer), "modified-changed", G_CALLBACK(inf_text_gtk_buffer_modified_changed_cb), buffer ); } g_object_notify(G_OBJECT(buffer), "buffer"); /* TODO: Notify modified, if it changed */ } static void inf_text_gtk_buffer_init(InfTextGtkBuffer* buffer) { InfTextGtkBufferPrivate* priv; priv = INF_TEXT_GTK_BUFFER_PRIVATE(buffer); priv->buffer = NULL; priv->user_table = NULL; priv->user_tags = g_hash_table_new_full( NULL, NULL, NULL, inf_text_gtk_buffer_user_tags_free ); priv->show_user_colors = TRUE; priv->active_user = NULL; priv->wake_on_cursor_movement = FALSE; priv->saturation = 0.35; priv->value = 1.0; priv->alpha = 1.0; } static void inf_text_gtk_buffer_dispose(GObject* object) { InfTextGtkBuffer* buffer; InfTextGtkBufferPrivate* priv; buffer = INF_TEXT_GTK_BUFFER(object); priv = INF_TEXT_GTK_BUFFER_PRIVATE(buffer); g_hash_table_remove_all(priv->user_tags); inf_text_gtk_buffer_set_buffer(buffer, NULL); inf_text_gtk_buffer_set_active_user(buffer, NULL); g_object_unref(priv->user_table); G_OBJECT_CLASS(inf_text_gtk_buffer_parent_class)->dispose(object); } static void inf_text_gtk_buffer_finalize(GObject* object) { InfTextGtkBuffer* buffer; InfTextGtkBufferPrivate* priv; buffer = INF_TEXT_GTK_BUFFER(object); priv = INF_TEXT_GTK_BUFFER_PRIVATE(buffer); g_hash_table_unref(priv->user_tags); G_OBJECT_CLASS(inf_text_gtk_buffer_parent_class)->finalize(object); } static void inf_text_gtk_buffer_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfTextGtkBuffer* buffer; InfTextGtkBufferPrivate* priv; buffer = INF_TEXT_GTK_BUFFER(object); priv = INF_TEXT_GTK_BUFFER_PRIVATE(buffer); switch(prop_id) { case PROP_BUFFER: g_assert(priv->buffer == NULL); /* construct only */ inf_text_gtk_buffer_set_buffer( buffer, GTK_TEXT_BUFFER(g_value_get_object(value)) ); break; case PROP_USER_TABLE: g_assert(priv->user_table == NULL); /* construct/only */ priv->user_table = INF_USER_TABLE(g_value_dup_object(value)); break; case PROP_ACTIVE_USER: inf_text_gtk_buffer_set_active_user( buffer, INF_TEXT_USER(g_value_get_object(value)) ); break; case PROP_WAKE_ON_CURSOR_MOVEMENT: priv->wake_on_cursor_movement = g_value_get_boolean(value); break; case PROP_SHOW_USER_COLORS: priv->show_user_colors = g_value_get_boolean(value); break; case PROP_MODIFIED: inf_text_gtk_buffer_set_modified(buffer, g_value_get_boolean(value)); break; case PROP_SATURATION: inf_text_gtk_buffer_set_saturation_value( buffer, g_value_get_double(value), priv->value ); break; case PROP_VALUE: inf_text_gtk_buffer_set_saturation_value( buffer, priv->saturation, g_value_get_double(value) ); break; case PROP_ALPHA: inf_text_gtk_buffer_set_fade(buffer, g_value_get_double(value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void inf_text_gtk_buffer_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfTextGtkBuffer* buffer; InfTextGtkBufferPrivate* priv; buffer = INF_TEXT_GTK_BUFFER(object); priv = INF_TEXT_GTK_BUFFER_PRIVATE(buffer); switch(prop_id) { case PROP_BUFFER: g_value_set_object(value, G_OBJECT(priv->buffer)); break; case PROP_USER_TABLE: g_value_set_object(value, G_OBJECT(priv->user_table)); break; case PROP_ACTIVE_USER: g_value_set_object(value, G_OBJECT(priv->active_user)); break; case PROP_WAKE_ON_CURSOR_MOVEMENT: g_value_set_boolean(value, priv->wake_on_cursor_movement); break; case PROP_SHOW_USER_COLORS: g_value_set_boolean(value, priv->show_user_colors); break; case PROP_MODIFIED: if(priv->buffer != NULL) g_value_set_boolean(value, gtk_text_buffer_get_modified(priv->buffer)); else g_value_set_boolean(value, FALSE); break; case PROP_SATURATION: g_value_set_double(value, priv->saturation); break; case PROP_VALUE: g_value_set_double(value, priv->value); break; case PROP_ALPHA: g_value_set_double(value, priv->alpha); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static gboolean inf_text_gtk_buffer_buffer_get_modified(InfBuffer* buffer) { InfTextGtkBuffer* gtk_buffer; InfTextGtkBufferPrivate* priv; gtk_buffer = INF_TEXT_GTK_BUFFER(buffer); priv = INF_TEXT_GTK_BUFFER_PRIVATE(gtk_buffer); if(priv->buffer != NULL) return gtk_text_buffer_get_modified(priv->buffer); else return FALSE; } static void inf_text_gtk_buffer_buffer_set_modified(InfBuffer* buffer, gboolean modified) { inf_text_gtk_buffer_set_modified(INF_TEXT_GTK_BUFFER(buffer), modified); } static const gchar* inf_text_gtk_buffer_buffer_get_encoding(InfTextBuffer* buffer) { return "UTF-8"; } static guint inf_text_gtk_buffer_get_length(InfTextBuffer* buffer) { InfTextGtkBufferPrivate* priv; priv = INF_TEXT_GTK_BUFFER_PRIVATE(buffer); return gtk_text_buffer_get_char_count(priv->buffer); } static InfTextChunk* inf_text_gtk_buffer_buffer_get_slice(InfTextBuffer* buffer, guint pos, guint len) { InfTextGtkBufferPrivate* priv; GtkTextIter begin; GtkTextIter iter; InfTextChunk* result; guint remaining; guint size; InfTextUser* author; gchar* text; priv = INF_TEXT_GTK_BUFFER_PRIVATE(buffer); gtk_text_buffer_get_iter_at_offset(priv->buffer, &iter, pos); result = inf_text_chunk_new("UTF-8"); remaining = len; while(remaining > 0) { /* This indicates invalid length */ g_assert(gtk_text_iter_is_end(&iter) == FALSE); begin = iter; inf_text_gtk_buffer_iter_next_author_toggle(&iter, NULL, &author); size = gtk_text_iter_get_offset(&iter) - gtk_text_iter_get_offset(&begin); /* Not the whole segment if region to slice ends before segment end */ if(size > remaining) { size = remaining; iter = begin; gtk_text_iter_forward_chars(&iter, size); } text = gtk_text_buffer_get_slice(priv->buffer, &begin, &iter, TRUE); /* TODO: Faster inf_text_chunk_append that optionally eats text */ inf_text_chunk_insert_text( result, len - remaining, text, strlen(text), /* I hate strlen. GTK+ should tell us how many bytes. */ size, (author == NULL) ? 0 : inf_user_get_id(INF_USER(author)) ); remaining -= size; g_free(text); } return result; } static void inf_text_gtk_buffer_buffer_insert_text(InfTextBuffer* buffer, guint pos, InfTextChunk* chunk, InfUser* user) { InfTextGtkBufferPrivate* priv; InfTextChunkIter chunk_iter; InfTextGtkBufferTagRemove tag_remove; GtkTextTag* tag; GtkTextMark* mark; GtkTextIter insert_iter; gboolean insert_at_cursor; gboolean insert_at_selection_bound; priv = INF_TEXT_GTK_BUFFER_PRIVATE(buffer); tag_remove.buffer = priv->buffer; /* This would have to be handled separately, but I think this is unlikely * to happen anyway. If it does happen then we would again need to rely on * iterator revalidation to happen in the way we expect it. */ g_assert(priv->record == NULL); /* Allow author tag changes within this function: */ inf_signal_handlers_block_by_func( G_OBJECT(priv->buffer), G_CALLBACK(inf_text_gtk_buffer_apply_tag_cb), buffer ); inf_signal_handlers_block_by_func( G_OBJECT(priv->buffer), G_CALLBACK(inf_text_gtk_buffer_insert_text_cb_before), buffer ); inf_signal_handlers_block_by_func( G_OBJECT(priv->buffer), G_CALLBACK(inf_text_gtk_buffer_insert_text_cb_after), buffer ); if(inf_text_chunk_iter_init_begin(chunk, &chunk_iter)) { gtk_text_buffer_get_iter_at_offset( priv->buffer, &tag_remove.end_iter, pos ); do { tag_remove.ignore_tags = inf_text_gtk_buffer_get_user_tags( INF_TEXT_GTK_BUFFER(buffer), inf_text_chunk_iter_get_author(&chunk_iter) ); if(tag_remove.ignore_tags) { tag = inf_text_gtk_buffer_get_user_tag( INF_TEXT_GTK_BUFFER(buffer), tag_remove.ignore_tags, priv->show_user_colors ); } else { tag = NULL; } gtk_text_buffer_insert_with_tags( tag_remove.buffer, &tag_remove.end_iter, inf_text_chunk_iter_get_text(&chunk_iter), inf_text_chunk_iter_get_bytes(&chunk_iter), tag, NULL ); /* Remove other user tags. If we inserted the new text within another * user's text, GtkTextBuffer automatically applies that tag to the * new text. */ /* TODO: We could probably look for the tag that we have to remove * before inserting text, to optimize this a bit. */ tag_remove.begin_iter = tag_remove.end_iter; gtk_text_iter_backward_chars( &tag_remove.begin_iter, inf_text_chunk_iter_get_length(&chunk_iter) ); gtk_text_tag_table_foreach( gtk_text_buffer_get_tag_table(tag_remove.buffer), inf_text_gtk_buffer_buffer_insert_text_tag_table_foreach_func, &tag_remove ); } while(inf_text_chunk_iter_next(&chunk_iter)); /* Fix left gravity of own cursor on remote insert */ /* TODO: We could also do this by simply resyncing the text buffer marks * to the active user's caret and selection properties. But then we * wouldn't have left gravtiy if no active user was present. */ if(user != INF_USER(priv->active_user) || user == NULL) { mark = gtk_text_buffer_get_insert(priv->buffer); gtk_text_buffer_get_iter_at_mark(priv->buffer, &insert_iter, mark); if(gtk_text_iter_equal(&insert_iter, &tag_remove.end_iter)) insert_at_cursor = TRUE; else insert_at_cursor = FALSE; mark = gtk_text_buffer_get_selection_bound(priv->buffer); gtk_text_buffer_get_iter_at_mark(priv->buffer, &insert_iter, mark); if(gtk_text_iter_equal(&insert_iter, &tag_remove.end_iter)) insert_at_selection_bound = TRUE; else insert_at_selection_bound = FALSE; if(insert_at_cursor || insert_at_selection_bound) { inf_signal_handlers_block_by_func( G_OBJECT(priv->buffer), G_CALLBACK(inf_text_gtk_buffer_mark_set_cb), buffer ); gtk_text_iter_backward_chars( &tag_remove.end_iter, inf_text_chunk_get_length(chunk) ); if(insert_at_cursor) { gtk_text_buffer_move_mark( priv->buffer, gtk_text_buffer_get_insert(priv->buffer), &tag_remove.end_iter ); } if(insert_at_selection_bound) { gtk_text_buffer_move_mark( priv->buffer, gtk_text_buffer_get_selection_bound(priv->buffer), &tag_remove.end_iter ); } inf_signal_handlers_unblock_by_func( G_OBJECT(priv->buffer), G_CALLBACK(inf_text_gtk_buffer_mark_set_cb), buffer ); } } } inf_signal_handlers_unblock_by_func( G_OBJECT(priv->buffer), G_CALLBACK(inf_text_gtk_buffer_apply_tag_cb), buffer ); inf_signal_handlers_unblock_by_func( G_OBJECT(priv->buffer), G_CALLBACK(inf_text_gtk_buffer_insert_text_cb_before), buffer ); inf_signal_handlers_unblock_by_func( G_OBJECT(priv->buffer), G_CALLBACK(inf_text_gtk_buffer_insert_text_cb_after), buffer ); inf_text_buffer_text_inserted(buffer, pos, chunk, user); } static void inf_text_gtk_buffer_buffer_erase_text(InfTextBuffer* buffer, guint pos, guint len, InfUser* user) { InfTextGtkBufferPrivate* priv; InfTextChunk* chunk; GtkTextIter begin; GtkTextIter end; priv = INF_TEXT_GTK_BUFFER_PRIVATE(buffer); /* This would have to be handled separately, but I think this is unlikely * to happen anyway. If it does happen then we would again need to rely on * iterator revalidation to happen in the way we expect it. */ g_assert(priv->record == NULL); chunk = inf_text_buffer_get_slice(buffer, pos, len); gtk_text_buffer_get_iter_at_offset(priv->buffer, &begin, pos); gtk_text_buffer_get_iter_at_offset(priv->buffer, &end, pos + len); inf_signal_handlers_block_by_func( G_OBJECT(priv->buffer), G_CALLBACK(inf_text_gtk_buffer_delete_range_cb_before), buffer ); inf_signal_handlers_block_by_func( G_OBJECT(priv->buffer), G_CALLBACK(inf_text_gtk_buffer_delete_range_cb_after), buffer ); gtk_text_buffer_delete(priv->buffer, &begin, &end); inf_signal_handlers_unblock_by_func( G_OBJECT(priv->buffer), G_CALLBACK(inf_text_gtk_buffer_delete_range_cb_before), buffer ); inf_signal_handlers_unblock_by_func( G_OBJECT(priv->buffer), G_CALLBACK(inf_text_gtk_buffer_delete_range_cb_after), buffer ); inf_text_buffer_text_erased(buffer, pos, chunk, user); inf_text_chunk_free(chunk); } static InfTextBufferIter* inf_text_gtk_buffer_buffer_create_begin_iter(InfTextBuffer* buffer) { InfTextGtkBufferPrivate* priv; InfTextBufferIter* iter; priv = INF_TEXT_GTK_BUFFER_PRIVATE(buffer); if(gtk_text_buffer_get_char_count(priv->buffer) == 0) { return NULL; } else { iter = g_slice_new(InfTextBufferIter); gtk_text_buffer_get_start_iter(priv->buffer, &iter->begin); iter->end = iter->begin; inf_text_gtk_buffer_iter_next_author_toggle( &iter->end, NULL, &iter->user ); return iter; } } static InfTextBufferIter* inf_text_gtk_buffer_buffer_create_end_iter(InfTextBuffer* buffer) { InfTextGtkBufferPrivate* priv; InfTextBufferIter* iter; priv = INF_TEXT_GTK_BUFFER_PRIVATE(buffer); if(gtk_text_buffer_get_char_count(priv->buffer) == 0) { return NULL; } else { iter = g_slice_new(InfTextBufferIter); gtk_text_buffer_get_end_iter(priv->buffer, &iter->end); iter->begin = iter->end; inf_text_gtk_buffer_iter_prev_author_toggle( &iter->begin, &iter->user, NULL ); return iter; } } static void inf_text_gtk_buffer_buffer_destroy_iter(InfTextBuffer* buffer, InfTextBufferIter* iter) { g_slice_free(InfTextBufferIter, iter); } static gboolean inf_text_gtk_buffer_buffer_iter_next(InfTextBuffer* buffer, InfTextBufferIter* iter) { if(gtk_text_iter_is_end(&iter->end)) return FALSE; iter->begin = iter->end; inf_text_gtk_buffer_iter_next_author_toggle(&iter->end, NULL, &iter->user); return TRUE; } static gboolean inf_text_gtk_buffer_buffer_iter_prev(InfTextBuffer* buffer, InfTextBufferIter* iter) { if(gtk_text_iter_is_start(&iter->begin)) return FALSE; iter->end = iter->begin; inf_text_gtk_buffer_iter_prev_author_toggle( &iter->begin, &iter->user, NULL ); return TRUE; } static gpointer inf_text_gtk_buffer_buffer_iter_get_text(InfTextBuffer* buffer, InfTextBufferIter* iter) { InfTextGtkBufferPrivate* priv; priv = INF_TEXT_GTK_BUFFER_PRIVATE(buffer); return gtk_text_buffer_get_slice( priv->buffer, &iter->begin, &iter->end, TRUE ); } static guint inf_text_gtk_buffer_buffer_iter_get_offset(InfTextBuffer* buffer, InfTextBufferIter* iter) { return gtk_text_iter_get_offset(&iter->begin); } static guint inf_text_gtk_buffer_buffer_iter_get_length(InfTextBuffer* buffer, InfTextBufferIter* iter) { return gtk_text_iter_get_offset(&iter->end) - gtk_text_iter_get_offset(&iter->begin); } static gsize inf_text_gtk_buffer_buffer_iter_get_bytes(InfTextBuffer* buffer, InfTextBufferIter* iter) { GtkTextIter walk; gsize bytes; guint remaining; guint end; guint line_chars; guint line_bytes; gboolean result; walk = iter->begin; bytes = 0; remaining = gtk_text_iter_get_offset(&iter->end) - gtk_text_iter_get_offset(&walk); end = gtk_text_iter_get_offset(&iter->end); while(remaining > 0) { line_chars = gtk_text_iter_get_chars_in_line(&walk) - gtk_text_iter_get_line_offset(&walk); if(line_chars + gtk_text_iter_get_offset(&walk) <= end) { /* Need whole line */ line_bytes = gtk_text_iter_get_bytes_in_line(&walk) - gtk_text_iter_get_line_index(&walk); remaining -= line_chars; bytes += line_bytes; result = gtk_text_iter_forward_line(&walk); /* We cannot be in last line, because the end iterator would have to * be past the last line then. */ g_assert(remaining == 0 || result == TRUE); } else { /* End iterator is in this line */ line_bytes = gtk_text_iter_get_line_index(&iter->end) - gtk_text_iter_get_line_index(&walk); remaining = 0; bytes += line_bytes; } } return bytes; } static guint inf_text_gtk_buffer_buffer_iter_get_author(InfTextBuffer* buffer, InfTextBufferIter* iter) { return (iter->user == NULL) ? 0 : inf_user_get_id(INF_USER(iter->user)); } static void inf_text_gtk_buffer_class_init(InfTextGtkBufferClass* text_gtk_buffer_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(text_gtk_buffer_class); object_class->dispose = inf_text_gtk_buffer_dispose; object_class->finalize = inf_text_gtk_buffer_finalize; object_class->set_property = inf_text_gtk_buffer_set_property; object_class->get_property = inf_text_gtk_buffer_get_property; inf_text_gtk_buffer_tag_user_quark = g_quark_from_static_string( "inf-text-gtk-buffer-tag-user" ); g_object_class_install_property( object_class, PROP_BUFFER, g_param_spec_object( "buffer", "Buffer", "The underlaying GtkTextBuffer", GTK_TYPE_TEXT_BUFFER, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_USER_TABLE, g_param_spec_object( "user-table", "User table", "A user table of the participating users", INF_TYPE_USER_TABLE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_ACTIVE_USER, g_param_spec_object( "active-user", "Active user", "The user currently inserting text locally", INF_TEXT_TYPE_USER, G_PARAM_READWRITE ) ); g_object_class_install_property( object_class, PROP_WAKE_ON_CURSOR_MOVEMENT, g_param_spec_boolean( "wake-on-cursor-movement", "Wake on cursor movement", "Whether to make inactive users active when the insertion mark in the " "TextBuffer moves", FALSE, G_PARAM_READWRITE ) ); g_object_class_install_property( object_class, PROP_SHOW_USER_COLORS, g_param_spec_boolean( "show-user-colors", "Show user colors", "Whether to show user colors initially for newly written text", TRUE, G_PARAM_READWRITE ) ); g_object_class_install_property( object_class, PROP_SATURATION, g_param_spec_double( "saturation", "Saturation", "Saturation of user colors in a HSV color model", 0.0, 1.0, 0.35, G_PARAM_READWRITE ) ); g_object_class_install_property( object_class, PROP_VALUE, g_param_spec_double( "value", "Value", "Value of user colors in a HSV color model", 0.0, 1.0, 1.0, G_PARAM_READWRITE ) ); g_object_class_install_property( object_class, PROP_VALUE, g_param_spec_double( "alpha", "Alpha", "The translucency of the user color", 0.0, 1.0, 1.0, G_PARAM_READWRITE ) ); g_object_class_override_property(object_class, PROP_MODIFIED, "modified"); } static void inf_text_gtk_buffer_buffer_iface_init(InfBufferInterface* iface) { iface->get_modified = inf_text_gtk_buffer_buffer_get_modified; iface->set_modified = inf_text_gtk_buffer_buffer_set_modified; } static void inf_text_gtk_buffer_text_buffer_iface_init(InfTextBufferInterface* iface) { iface->get_encoding = inf_text_gtk_buffer_buffer_get_encoding; iface->get_length = inf_text_gtk_buffer_get_length; iface->get_slice = inf_text_gtk_buffer_buffer_get_slice; iface->insert_text = inf_text_gtk_buffer_buffer_insert_text; iface->erase_text = inf_text_gtk_buffer_buffer_erase_text; iface->create_begin_iter = inf_text_gtk_buffer_buffer_create_begin_iter; iface->create_end_iter = inf_text_gtk_buffer_buffer_create_end_iter; iface->destroy_iter = inf_text_gtk_buffer_buffer_destroy_iter; iface->iter_next = inf_text_gtk_buffer_buffer_iter_next; iface->iter_prev = inf_text_gtk_buffer_buffer_iter_prev; iface->iter_get_text = inf_text_gtk_buffer_buffer_iter_get_text; iface->iter_get_offset = inf_text_gtk_buffer_buffer_iter_get_offset; iface->iter_get_length = inf_text_gtk_buffer_buffer_iter_get_length; iface->iter_get_bytes = inf_text_gtk_buffer_buffer_iter_get_bytes; iface->iter_get_author = inf_text_gtk_buffer_buffer_iter_get_author; iface->text_inserted = NULL; iface->text_erased = NULL; } /** * inf_text_gtk_buffer_new: (constructor) * @buffer: The underlaying #GtkTextBuffer. * @user_table: The #InfUserTable containing the participating users. * * Creates a new #InfTextGtkBuffer wrapping @buffer. It implements the * #InfTextBuffer interface by using @buffer to store the text. User colors * are read from the users from @user_table. * * Returns: (transfer full): A #InfTextGtkBuffer. **/ InfTextGtkBuffer* inf_text_gtk_buffer_new(GtkTextBuffer* buffer, InfUserTable* user_table) { GObject* object; g_return_val_if_fail(GTK_IS_TEXT_BUFFER(buffer), NULL); g_return_val_if_fail(INF_IS_USER_TABLE(user_table), NULL); object = g_object_new( INF_TEXT_GTK_TYPE_BUFFER, "buffer", buffer, "user-table", user_table, NULL ); return INF_TEXT_GTK_BUFFER(object); } /** * inf_text_gtk_buffer_get_text_buffer: * @buffer: A #InfTextGtkBuffer. * * Returns the underlaying #GtkTextBuffer. * * Returns: (transfer none): A #GtkTextBuffer. **/ GtkTextBuffer* inf_text_gtk_buffer_get_text_buffer(InfTextGtkBuffer* buffer) { g_return_val_if_fail(INF_TEXT_GTK_IS_BUFFER(buffer), NULL); return INF_TEXT_GTK_BUFFER_PRIVATE(buffer)->buffer; } /** * inf_text_gtk_buffer_set_active_user: * @buffer: A #InfTextGtkBuffer. * @user: (allow-none): A #InfTextUser, or %NULL. * * Sets the active user for @buffer. The active user is the user by which * edits not issued through the #InfTextBuffer interface are performed (for * example, edits by the user when the underlaying buffer is displayed in * a #GtkTextView). * * Note that such modifications should not be performed when no active user is * set. Note also the active user must be available and have the * %INF_USER_LOCAL flag set. **/ void inf_text_gtk_buffer_set_active_user(InfTextGtkBuffer* buffer, InfTextUser* user) { InfTextGtkBufferPrivate* priv; g_return_if_fail(INF_TEXT_GTK_IS_BUFFER(buffer)); g_return_if_fail(user == NULL || INF_TEXT_IS_USER(user)); g_return_if_fail( user == NULL || (inf_user_get_flags(INF_USER(user)) & INF_USER_LOCAL) != 0 ); g_return_if_fail( user == NULL || inf_user_get_status(INF_USER(user)) != INF_USER_UNAVAILABLE ); priv = INF_TEXT_GTK_BUFFER_PRIVATE(buffer); if(priv->active_user != NULL) { inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->active_user), G_CALLBACK(inf_text_gtk_buffer_active_user_notify_status_cb), buffer ); inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->active_user), G_CALLBACK(inf_text_gtk_buffer_active_user_selection_changed_cb), buffer ); g_object_unref(G_OBJECT(priv->active_user)); } priv->active_user = user; if(user != NULL) { /* TODO: Set cursor and selection of new user */ g_object_ref(G_OBJECT(user)); g_signal_connect( G_OBJECT(user), "notify::status", G_CALLBACK(inf_text_gtk_buffer_active_user_notify_status_cb), buffer ); g_signal_connect( G_OBJECT(user), "selection-changed", G_CALLBACK(inf_text_gtk_buffer_active_user_selection_changed_cb), buffer ); } g_object_notify(G_OBJECT(buffer), "active-user"); } /** * inf_text_gtk_buffer_get_active_user: * @buffer: A #InfTextGtkBuffer. * * Returns the current active user for @buffer. * * Returns: (transfer none) (allow-none): A #InfTextUser. **/ InfTextUser* inf_text_gtk_buffer_get_active_user(InfTextGtkBuffer* buffer) { g_return_val_if_fail(INF_TEXT_GTK_IS_BUFFER(buffer), NULL); return INF_TEXT_GTK_BUFFER_PRIVATE(buffer)->active_user; } /** * inf_text_gtk_buffer_get_author: * @buffer: A #InfTextGtkBuffer. * @location: A #GtkTextIter which is not the end iterator. * * Returns the #InfTextUser which wrote the character at @location. If there * is no such user, then %NULL is returned. * * Returns: (transfer none) (allow-none): A #InfTextUser, or %NULL. */ InfTextUser* inf_text_gtk_buffer_get_author(InfTextGtkBuffer* buffer, GtkTextIter* location) { InfTextGtkBufferPrivate* priv; g_return_val_if_fail(INF_TEXT_GTK_IS_BUFFER(buffer), NULL); g_return_val_if_fail( location != NULL && !gtk_text_iter_is_end(location), NULL ); priv = INF_TEXT_GTK_BUFFER_PRIVATE(buffer); return inf_text_gtk_buffer_iter_get_author(location); } /** * inf_text_gtk_buffer_get_user_for_tag: * @buffer: A #InfTextGtkBuffer. * @tag: A #GtkTextTag from @buffer's underlying #GtkTextBuffer's tag table. * * If @tag is an author tag, i.e. used by @buffer to mark text that a certain * user has written, then this function returns the #InfTextUser whose text is * marked by @tag. If @tag is not an author tag then the function returns * %NULL. * * Returns: (transfer none) (allow-none): A #InfTextUser, or %NULL. */ InfTextUser* inf_text_gtk_buffer_get_user_for_tag(InfTextGtkBuffer* buffer, GtkTextTag* tag) { g_return_val_if_fail(INF_TEXT_GTK_IS_BUFFER(buffer), NULL); g_return_val_if_fail(GTK_IS_TEXT_TAG(tag), NULL); return inf_text_gtk_buffer_author_from_tag(tag); } /** * inf_text_gtk_buffer_is_author_toggle: * @buffer: A #InfTextGtkBuffer. * @iter: A #GtkTextIter pointing into @buffer's underlying #GtkTextBuffer. * @user_on: (out) (allow-none): A location to store a #InfTextUser, or %NULL. * @user_off: (out) (allow-none): Another location to store a #InfTextUser, * or %NULL. * * This function returns %TRUE if the author of the text in @buffer changes * at @iter, or %FALSE otherwise. If it returns %TRUE, then the user who * authored the text to the right hand side of @iter is stored in @user_on (if * non-%NULL) and the author of the text to the left hand side of @iter is * stored in @user_off (if non-%NULL). Both can also be set to %NULL if there * is unowned text in the buffer or if @iter is at the start or end of the * buffer. * * Returns: Whether text attribution changes at @iter. */ gboolean inf_text_gtk_buffer_is_author_toggle(InfTextGtkBuffer* buffer, const GtkTextIter* iter, InfTextUser** user_on, InfTextUser** user_off) { g_return_val_if_fail(INF_TEXT_GTK_IS_BUFFER(buffer), FALSE); g_return_val_if_fail(iter != NULL, FALSE); return inf_text_gtk_buffer_iter_is_author_toggle( iter, user_on, user_off ); } /** * inf_text_gtk_buffer_forward_to_author_toggle: * @buffer: A #InfTextGtkBuffer. * @iter: A #GtkTextIter pointing into @buffer's underlying #GtkTextBuffer. * @user_on: (out) (allow-none): A location to store a #InfTextUser, or %NULL. * @user_off: (out) (allow-none): Another location to store a #InfTextUser, * or %NULL. * * Moves @iter to the next point in @buffer's underlying #GtkTextBuffer where * the text has been written by another user. If @iter points to the end of * the buffer, then the function does nothing and returns %FALSE. Otherwise * it returns %TRUE and sets @user_on to the user which has written the text * on the right hand side of the location @iter has been moved to (if * non-%NULL) and @user_off to the user which has written the left hand side * of the location @iter has been moved to. * * Returns: %TRUE if @iter was moved, or %FALSE otherwise. */ gboolean inf_text_gtk_buffer_forward_to_author_toggle(InfTextGtkBuffer* buffer, GtkTextIter* iter, InfTextUser** user_on, InfTextUser** user_off) { g_return_val_if_fail(INF_TEXT_GTK_IS_BUFFER(buffer), FALSE); g_return_val_if_fail(iter != NULL, FALSE); if(gtk_text_iter_is_end(iter)) return FALSE; inf_text_gtk_buffer_iter_next_author_toggle(iter, user_on, user_off); return TRUE; } /** * inf_text_gtk_buffer_backward_to_author_toggle: * @buffer: A #InfTextGtkBuffer. * @iter: A #GtkTextIter pointing into @buffer's underlying #GtkTextBuffer. * @user_on: (out) (allow-none): A location to store a #InfTextUser, or %NULL. * @user_off: (out) (allow-none): Another location to store a #InfTextUser, * or %NULL. * * Moves @iter to the previous point in @buffer's underlying #GtkTextBuffer * where the text has been written by another user. If @iter points to the * beginning of the buffer, then the function does nothing and returns %FALSE. * Otherwise it returns %TRUE and sets @user_on to the user which has written * the text on the right hand side of the location @iter has been moved to (if * non-%NULL) and @user_off to the user which has written the left hand side * of the location @iter has been moved to. * * Returns: %TRUE if @iter was moved, or %FALSE otherwise. */ gboolean inf_text_gtk_buffer_backward_to_author_toggle(InfTextGtkBuffer* buffer, GtkTextIter* iter, InfTextUser** user_on, InfTextUser** user_off) { g_return_val_if_fail(INF_TEXT_GTK_IS_BUFFER(buffer), FALSE); g_return_val_if_fail(iter != NULL, FALSE); if(gtk_text_iter_is_start(iter)) return FALSE; inf_text_gtk_buffer_iter_prev_author_toggle(iter, user_on, user_off); return TRUE; } /** * inf_text_gtk_buffer_set_wake_on_cursor_movement: * @buffer: A #InfTextGtkBuffer. * @wake: Whether to make inactive users active on cursor movement. * * This function spcecifies whether movement of the insertion point or * selection bound of the underlying text buffer causes the active user * (see inf_text_gtk_buffer_set_active_user()) to become active when its * status is %INF_USER_INACTIVE. * * If @wake is %TRUE, then the user status changes to %INF_USER_ACTIVE * in that case. If @wake is %FALSE, then the user status stays * %INF_USER_INACTIVE, and its caret-position and selection-length * properties will be no longer be synchronized to the buffer marks until * the user is set active again. */ void inf_text_gtk_buffer_set_wake_on_cursor_movement(InfTextGtkBuffer* buffer, gboolean wake) { g_return_if_fail(INF_TEXT_GTK_IS_BUFFER(buffer)); INF_TEXT_GTK_BUFFER_PRIVATE(buffer)->wake_on_cursor_movement = wake; g_object_notify(G_OBJECT(buffer), "wake-on-cursor-movement"); } /** * inf_text_gtk_buffer_get_wake_on_cursor_movement: * @buffer: A #InfTextGtkBuffer. * * Returns whether movement of the insertion point or selection bound of the * underlying text buffer causes whether the active user (see * inf_text_gtk_buffer_set_active_user()) to become active when its status * is %INF_USER_INACTIVE. See also * inf_text_gtk_buffer_set_wake_on_cursor_movement(). * * Returns: Whether to make inactive users active when the insertion mark * is moved. */ gboolean inf_text_gtk_buffer_get_wake_on_cursor_movement(InfTextGtkBuffer* buffer) { g_return_val_if_fail(INF_TEXT_GTK_IS_BUFFER(buffer), FALSE); return INF_TEXT_GTK_BUFFER_PRIVATE(buffer)->wake_on_cursor_movement; } /** * inf_text_gtk_buffer_ensure_author_tags_priority: * @buffer: A #InfTextGtkBuffer. * * Ensures that all author tags have the lowest priority of all tags in the * underlying #GtkTextBuffer's tag table. Normally you do not need to use * this function if you do not set the priority for your tags explicitely. * However, if you do (or are forced to do, because you are using a library * that does this, such as GtkSourceView), then you can call this function * afterwards to make sure all the user tags have the lowest priority. */ void inf_text_gtk_buffer_ensure_author_tags_priority(InfTextGtkBuffer* buffer) { InfTextGtkBufferPrivate* priv; GtkTextTagTable* tag_table; g_return_if_fail(INF_TEXT_GTK_IS_BUFFER(buffer)); priv = INF_TEXT_GTK_BUFFER_PRIVATE(buffer); tag_table = gtk_text_buffer_get_tag_table(priv->buffer); gtk_text_tag_table_foreach( tag_table, inf_text_gtk_buffer_ensure_author_tags_priority_foreach_func, buffer ); } /** * inf_text_gtk_buffer_set_saturation_value: * @buffer: A #InfTextGtkBuffer. * @saturation: Saturation to use for user colors. * @value: Value to use for user colors. * * Sets the saturation and value to use for user colors in a HSV color model. * The hue is defined by each user's individual color. The reason why S and V * are set locally the same for all users is that they can be adjusted * depending on one's theme: Dark themes want dark user colors, bright themes * want bright ones. */ void inf_text_gtk_buffer_set_saturation_value(InfTextGtkBuffer* buffer, gdouble saturation, gdouble value) { InfTextGtkBufferPrivate* priv; GtkTextTagTable* tag_table; g_return_if_fail(INF_TEXT_GTK_IS_BUFFER(buffer)); g_return_if_fail(saturation >= 0.0 && saturation <= 1.0); g_return_if_fail(value >= 0.0 && value <= 1.0); priv = INF_TEXT_GTK_BUFFER_PRIVATE(buffer); if(saturation == priv->saturation && value == priv->value) return; g_object_freeze_notify(G_OBJECT(buffer)); if(saturation != priv->saturation) { priv->saturation = saturation; g_object_notify(G_OBJECT(buffer), "saturation"); } if(value != priv->value) { priv->value = value; g_object_notify(G_OBJECT(buffer), "value"); } tag_table = gtk_text_buffer_get_tag_table(priv->buffer); gtk_text_tag_table_foreach( tag_table, inf_text_gtk_buffer_update_user_color_tag_table_foreach_func, buffer ); g_object_thaw_notify(G_OBJECT(buffer)); } /** * inf_text_gtk_buffer_set_fade: * @buffer: A #InfTextGtkBuffer. * @alpha: An alpha value between 0.0 and 1.0. * * This functions can be used to show the user background color with limited * intensity, such that the background of the #GtkTextView showing the buffer * partly shines through. * * An @alpha value of 1.0 means to fully show the user background color, a * value of 0.0 means to show the given background color. Values inbetween * interpolate linearly between the two colors in RGB color space. * * The default value for @alpha is 1.0. */ void inf_text_gtk_buffer_set_fade(InfTextGtkBuffer* buffer, gdouble alpha) { InfTextGtkBufferPrivate* priv; GtkTextTagTable* tag_table; g_return_if_fail(INF_TEXT_GTK_IS_BUFFER(buffer)); g_return_if_fail(alpha >= 0.0 && alpha <= 1.0); priv = INF_TEXT_GTK_BUFFER_PRIVATE(buffer); g_object_freeze_notify(G_OBJECT(buffer)); if(alpha != priv->alpha) { priv->alpha = alpha; g_object_notify(G_OBJECT(buffer), "alpha"); } tag_table = gtk_text_buffer_get_tag_table(priv->buffer); gtk_text_tag_table_foreach( tag_table, inf_text_gtk_buffer_update_user_color_tag_table_foreach_func, buffer ); g_object_thaw_notify(G_OBJECT(buffer)); } /** * inf_text_gtk_buffer_get_saturation: * @buffer: A #InfTextGtkBuffer. * * Returns the saturation part of the HSV user color. * * Returns: The saturation used for user colors. */ gdouble inf_text_gtk_buffer_get_saturation(InfTextGtkBuffer* buffer) { g_return_val_if_fail(INF_TEXT_GTK_IS_BUFFER(buffer), 0.0); return INF_TEXT_GTK_BUFFER_PRIVATE(buffer)->saturation; } /** * inf_text_gtk_buffer_get_value: * @buffer: A #InfTextGtkBuffer. * * Returns the value part of the HSV user color. * * Returns: The value used for user colors. */ gdouble inf_text_gtk_buffer_get_value(InfTextGtkBuffer* buffer) { g_return_val_if_fail(INF_TEXT_GTK_IS_BUFFER(buffer), 0.0); return INF_TEXT_GTK_BUFFER_PRIVATE(buffer)->value; } /** * inf_text_gtk_buffer_set_show_user_colors: * @buffer: A #InfTextGtkBuffer. * @show: Whether to show user colors or not. * * If @show is %TRUE (the default), then the user color is used as background * for newly written text by that user. Otherwise, newly written text has no * background color. * * Note that this setting is for newly written text only. If you want to show * or hide user colors for existing text use * inf_text_gtk_buffer_show_user_colors(). */ void inf_text_gtk_buffer_set_show_user_colors(InfTextGtkBuffer* buffer, gboolean show) { g_return_if_fail(INF_TEXT_GTK_IS_BUFFER(buffer)); INF_TEXT_GTK_BUFFER_PRIVATE(buffer)->show_user_colors = show; g_object_notify(G_OBJECT(buffer), "show-user-colors"); } /** * inf_text_gtk_buffer_get_show_user_colors: * @buffer: A #InfTextGtkBuffer. * * Returns whether newly written text is attributed with the author's user * color or not. * * Returns: %TRUE if user color is applied to newly written text, or %FALSE * otherwise. */ gboolean inf_text_gtk_buffer_get_show_user_colors(InfTextGtkBuffer* buffer) { g_return_val_if_fail(INF_TEXT_GTK_IS_BUFFER(buffer), FALSE); return INF_TEXT_GTK_BUFFER_PRIVATE(buffer)->show_user_colors; } /** * inf_text_gtk_buffer_show_user_colors: * @buffer: A #InfTextGtkBuffer. * @show: Whether to show or hide user colors. * @start: (in) (transfer none): Beginning of the range for which to show * or hide user colors. * @end: (in) (transfer none): End of the range for which to show or hide * user colors. * * If @show is %FALSE, then don't show user colors (which user wrote what * text) as the background of the text, in the range from @start to @end. * If @show is %TRUE, show user colors if they have previously been hidden * via a call to this function with @show being %FALSE. */ void inf_text_gtk_buffer_show_user_colors(InfTextGtkBuffer* buffer, gboolean show, GtkTextIter* start, GtkTextIter* end) { InfTextGtkBufferPrivate* priv; GtkTextIter iter; GtkTextIter prev; InfTextUser* user; InfTextGtkBufferUserTags* tags; GtkTextTag* hide_tag; GtkTextTag* show_tag; g_return_if_fail(INF_TEXT_GTK_IS_BUFFER(buffer)); g_return_if_fail(start != NULL); g_return_if_fail(end != NULL); priv = INF_TEXT_GTK_BUFFER_PRIVATE(buffer); iter = *start; prev = iter; while(!gtk_text_iter_equal(&iter, end)) { inf_text_gtk_buffer_iter_next_author_toggle(&iter, NULL, &user); if(gtk_text_iter_compare(&iter, end) > 0) iter = *end; if(user != NULL) { tags = g_hash_table_lookup( priv->user_tags, GUINT_TO_POINTER(inf_user_get_id(INF_USER(user))) ); g_assert(tags != NULL); if(show) { hide_tag = inf_text_gtk_buffer_get_user_tag(buffer, tags, FALSE); show_tag = inf_text_gtk_buffer_get_user_tag(buffer, tags, TRUE); } else { hide_tag = inf_text_gtk_buffer_get_user_tag(buffer, tags, TRUE); show_tag = inf_text_gtk_buffer_get_user_tag(buffer, tags, FALSE); } inf_signal_handlers_block_by_func( priv->buffer, G_CALLBACK(inf_text_gtk_buffer_apply_tag_cb), buffer ); gtk_text_buffer_remove_tag(priv->buffer, hide_tag, &prev, &iter); gtk_text_buffer_apply_tag(priv->buffer, show_tag, &prev, &iter); inf_signal_handlers_unblock_by_func( priv->buffer, G_CALLBACK(inf_text_gtk_buffer_apply_tag_cb), buffer ); } prev = iter; } } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinftextgtk/PaxHeaders.26529/Makefile.in0000644000000000000000000000013213051241010020511 xustar0030 mtime=1487225352.413150673 30 atime=1487225352.413150673 30 ctime=1488261589.396138199 libinfinity-0.7.1/libinftextgtk/Makefile.in0000644000175000017500000010402213051241010021242 0ustar00arminarmin00000000000000# Makefile.in generated by automake 1.15 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2014 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__is_gnu_make = { \ if test -z '$(MAKELEVEL)'; then \ false; \ elif test -n '$(MAKE_HOST)'; then \ true; \ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ true; \ else \ false; \ fi; \ } am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) 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@ subdir = libinftextgtk ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/gtk-doc.m4 \ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) DIST_COMMON = $(srcdir)/Makefile.am $(libinftextgtk_0_7_la_HEADERS) \ $(am__DIST_COMMON) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h \ $(top_builddir)/libinfinity/inf-config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(girdir)" \ "$(DESTDIR)$(typelibdir)" \ "$(DESTDIR)$(libinftextgtk_0_7_ladir)" LTLIBRARIES = $(lib_LTLIBRARIES) am__DEPENDENCIES_1 = am__DEPENDENCIES_2 = ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) libinftextgtk_0_7_la_DEPENDENCIES = $(am__DEPENDENCIES_2) am__objects_1 = libinftextgtk_0_7_la-inf-text-gtk-buffer.lo \ libinftextgtk_0_7_la-inf-text-gtk-hue-chooser.lo \ libinftextgtk_0_7_la-inf-text-gtk-view.lo \ libinftextgtk_0_7_la-inf-text-gtk-viewport.lo am_libinftextgtk_0_7_la_OBJECTS = $(am__objects_1) libinftextgtk_0_7_la_OBJECTS = $(am_libinftextgtk_0_7_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libinftextgtk_0_7_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(libinftextgtk_0_7_la_LDFLAGS) \ $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) -I$(top_builddir)/libinfinity 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_CC_1 = 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_CCLD_1 = SOURCES = $(libinftextgtk_0_7_la_SOURCES) DIST_SOURCES = $(libinftextgtk_0_7_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac DATA = $(gir_DATA) $(typelib_DATA) HEADERS = $(libinftextgtk_0_7_la_HEADERS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ 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@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DATADIRNAME = @DATADIRNAME@ 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@ GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ GMOFILES = @GMOFILES@ GMSGFMT = @GMSGFMT@ GREP = @GREP@ GTKDOC_CHECK = @GTKDOC_CHECK@ GTKDOC_CHECK_PATH = @GTKDOC_CHECK_PATH@ GTKDOC_DEPS_CFLAGS = @GTKDOC_DEPS_CFLAGS@ GTKDOC_DEPS_LIBS = @GTKDOC_DEPS_LIBS@ GTKDOC_MKPDF = @GTKDOC_MKPDF@ GTKDOC_REBASE = @GTKDOC_REBASE@ HTML_DIR = @HTML_DIR@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INSTOBJEXT = @INSTOBJEXT@ INTLLIBS = @INTLLIBS@ INTROSPECTION_CFLAGS = @INTROSPECTION_CFLAGS@ INTROSPECTION_COMPILER = @INTROSPECTION_COMPILER@ INTROSPECTION_GENERATE = @INTROSPECTION_GENERATE@ INTROSPECTION_GIRDIR = @INTROSPECTION_GIRDIR@ INTROSPECTION_LIBS = @INTROSPECTION_LIBS@ INTROSPECTION_MAKEFILE = @INTROSPECTION_MAKEFILE@ INTROSPECTION_SCANNER = @INTROSPECTION_SCANNER@ INTROSPECTION_TYPELIBDIR = @INTROSPECTION_TYPELIBDIR@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBINFINITY_API_VERSION = @LIBINFINITY_API_VERSION@ LIBINFINITY_LIBTOOL_VERSION = @LIBINFINITY_LIBTOOL_VERSION@ LIBINFINITY_VERSION = @LIBINFINITY_VERSION@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MKINSTALLDIRS = @MKINSTALLDIRS@ MSGFMT = @MSGFMT@ MSGFMT_OPTS = @MSGFMT_OPTS@ 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@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ 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@ avahi_CFLAGS = @avahi_CFLAGS@ avahi_LIBS = @avahi_LIBS@ 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@ gio_CFLAGS = @gio_CFLAGS@ gio_LIBS = @gio_LIBS@ gtk_requirement = @gtk_requirement@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infgtk_CFLAGS = @infgtk_CFLAGS@ infgtk_LIBS = @infgtk_LIBS@ infinity_CFLAGS = @infinity_CFLAGS@ infinity_LIBS = @infinity_LIBS@ infinoted_CFLAGS = @infinoted_CFLAGS@ infinoted_LIBS = @infinoted_LIBS@ infodir = @infodir@ inftext_CFLAGS = @inftext_CFLAGS@ inftext_LIBS = @inftext_LIBS@ inftextgtk_CFLAGS = @inftextgtk_CFLAGS@ inftextgtk_LIBS = @inftextgtk_LIBS@ install_sh = @install_sh@ libdaemon_CFLAGS = @libdaemon_CFLAGS@ libdaemon_LIBS = @libdaemon_LIBS@ 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@ runstatedir = @runstatedir@ 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@ # TODO: Find a way to have the version number set automatically. lib_LTLIBRARIES = libinftextgtk-0.7.la cppflags = \ -I$(top_srcdir) \ $(inftextgtk_CFLAGS) \ $(inftext_CFLAGS) \ $(infinity_CFLAGS) ldflags = \ -no-undefined \ -version-info $(LIBINFINITY_LIBTOOL_VERSION) libadd = \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(inftextgtk_LIBS) \ $(inftext_LIBS) \ $(infinity_LIBS) headers = \ inf-text-gtk-buffer.h \ inf-text-gtk-hue-chooser.h \ inf-text-gtk-view.h \ inf-text-gtk-viewport.h sources = \ inf-text-gtk-buffer.c \ inf-text-gtk-hue-chooser.c \ inf-text-gtk-view.c \ inf-text-gtk-viewport.c libinftextgtk_0_7_la_CPPFLAGS = $(cppflags) libinftextgtk_0_7_la_LDFLAGS = $(ldflags) libinftextgtk_0_7_la_LIBADD = $(libadd) libinftextgtk_0_7_la_HEADERS = $(headers) libinftextgtk_0_7_la_SOURCES = $(sources) libinftextgtk_0_7_ladir = \ $(includedir)/libinftextgtk-$(LIBINFINITY_API_VERSION)/libinftextgtk @HAVE_INTROSPECTION_TRUE@INTROSPECTION_GIRS = InfTextGtk-0.7.gir @HAVE_INTROSPECTION_TRUE@INTROSPECTION_SCANNER_ENV = CC="${CC}" @HAVE_INTROSPECTION_TRUE@INTROSPECTION_COMPILER_ARGS = \ @HAVE_INTROSPECTION_TRUE@ --includedir=${top_srcdir}/libinfinity \ @HAVE_INTROSPECTION_TRUE@ --includedir=${top_builddir}/libinfinity \ @HAVE_INTROSPECTION_TRUE@ --includedir=${top_builddir}/libinftext \ @HAVE_INTROSPECTION_TRUE@ --includedir=${top_builddir}/libinfgtk @HAVE_INTROSPECTION_TRUE@InfTextGtk_0_7_gir_SCANNERFLAGS = \ @HAVE_INTROSPECTION_TRUE@ -I${top_srcdir} \ @HAVE_INTROSPECTION_TRUE@ --add-include-path=$(top_srcdir)/libinfinity \ @HAVE_INTROSPECTION_TRUE@ --add-include-path=$(top_builddir)/libinfinity \ @HAVE_INTROSPECTION_TRUE@ --add-include-path=$(top_builddir)/libinftext \ @HAVE_INTROSPECTION_TRUE@ --add-include-path=$(top_builddir)/libinfgtk \ @HAVE_INTROSPECTION_TRUE@ -n InfTextGtk \ @HAVE_INTROSPECTION_TRUE@ --identifier-prefix=InfTextGtk @HAVE_INTROSPECTION_TRUE@InfTextGtk_0_7_gir_NAMESPACE = InfTextGtk @HAVE_INTROSPECTION_TRUE@InfTextGtk_0_7_gir_VERSION = 0.7 @HAVE_INTROSPECTION_TRUE@InfTextGtk_0_7_gir_CFLAGS = $(inftextgtk_CFLAGS) $(inftext_CFLAGS) $(infinity_CFLAGS) @HAVE_INTROSPECTION_TRUE@InfTextGtk_0_7_gir_LIBS = libinftextgtk-0.7.la @HAVE_INTROSPECTION_TRUE@InfTextGtk_0_7_gir_FILES = \ @HAVE_INTROSPECTION_TRUE@ $(libinftextgtk_0_7_la_SOURCES) \ @HAVE_INTROSPECTION_TRUE@ $(libinftextgtk_0_7_la_HEADERS) @HAVE_INTROSPECTION_TRUE@InfTextGtk_0_7_gir_INCLUDES = InfText-0.7 InfGtk-0.7 Gtk-3.0 @HAVE_INTROSPECTION_TRUE@InfTextGtk_0_7_gir_PACKAGES = gtk+-3.0 @HAVE_INTROSPECTION_TRUE@InfTextGtk_0_7_gir_EXPORT_PACKAGES = libinftextgtk-0.7 @HAVE_INTROSPECTION_TRUE@girdir = $(datadir)/gir-1.0 @HAVE_INTROSPECTION_TRUE@gir_DATA = InfTextGtk-0.7.gir @HAVE_INTROSPECTION_TRUE@typelibdir = $(libdir)/girepository-1.0 @HAVE_INTROSPECTION_TRUE@typelib_DATA = InfTextGtk-0.7.typelib @HAVE_INTROSPECTION_TRUE@CLEANFILES = \ @HAVE_INTROSPECTION_TRUE@ $(gir_DATA) \ @HAVE_INTROSPECTION_TRUE@ $(typelib_DATA) all: all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(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) --foreign libinftextgtk/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign libinftextgtk/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: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libinftextgtk-0.7.la: $(libinftextgtk_0_7_la_OBJECTS) $(libinftextgtk_0_7_la_DEPENDENCIES) $(EXTRA_libinftextgtk_0_7_la_DEPENDENCIES) $(AM_V_CCLD)$(libinftextgtk_0_7_la_LINK) -rpath $(libdir) $(libinftextgtk_0_7_la_OBJECTS) $(libinftextgtk_0_7_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libinftextgtk_0_7_la-inf-text-gtk-buffer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libinftextgtk_0_7_la-inf-text-gtk-hue-chooser.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libinftextgtk_0_7_la-inf-text-gtk-view.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libinftextgtk_0_7_la-inf-text-gtk-viewport.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.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 -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.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 -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.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 $@ $< libinftextgtk_0_7_la-inf-text-gtk-buffer.lo: inf-text-gtk-buffer.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinftextgtk_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libinftextgtk_0_7_la-inf-text-gtk-buffer.lo -MD -MP -MF $(DEPDIR)/libinftextgtk_0_7_la-inf-text-gtk-buffer.Tpo -c -o libinftextgtk_0_7_la-inf-text-gtk-buffer.lo `test -f 'inf-text-gtk-buffer.c' || echo '$(srcdir)/'`inf-text-gtk-buffer.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libinftextgtk_0_7_la-inf-text-gtk-buffer.Tpo $(DEPDIR)/libinftextgtk_0_7_la-inf-text-gtk-buffer.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='inf-text-gtk-buffer.c' object='libinftextgtk_0_7_la-inf-text-gtk-buffer.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) $(libinftextgtk_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libinftextgtk_0_7_la-inf-text-gtk-buffer.lo `test -f 'inf-text-gtk-buffer.c' || echo '$(srcdir)/'`inf-text-gtk-buffer.c libinftextgtk_0_7_la-inf-text-gtk-hue-chooser.lo: inf-text-gtk-hue-chooser.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinftextgtk_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libinftextgtk_0_7_la-inf-text-gtk-hue-chooser.lo -MD -MP -MF $(DEPDIR)/libinftextgtk_0_7_la-inf-text-gtk-hue-chooser.Tpo -c -o libinftextgtk_0_7_la-inf-text-gtk-hue-chooser.lo `test -f 'inf-text-gtk-hue-chooser.c' || echo '$(srcdir)/'`inf-text-gtk-hue-chooser.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libinftextgtk_0_7_la-inf-text-gtk-hue-chooser.Tpo $(DEPDIR)/libinftextgtk_0_7_la-inf-text-gtk-hue-chooser.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='inf-text-gtk-hue-chooser.c' object='libinftextgtk_0_7_la-inf-text-gtk-hue-chooser.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) $(libinftextgtk_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libinftextgtk_0_7_la-inf-text-gtk-hue-chooser.lo `test -f 'inf-text-gtk-hue-chooser.c' || echo '$(srcdir)/'`inf-text-gtk-hue-chooser.c libinftextgtk_0_7_la-inf-text-gtk-view.lo: inf-text-gtk-view.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinftextgtk_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libinftextgtk_0_7_la-inf-text-gtk-view.lo -MD -MP -MF $(DEPDIR)/libinftextgtk_0_7_la-inf-text-gtk-view.Tpo -c -o libinftextgtk_0_7_la-inf-text-gtk-view.lo `test -f 'inf-text-gtk-view.c' || echo '$(srcdir)/'`inf-text-gtk-view.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libinftextgtk_0_7_la-inf-text-gtk-view.Tpo $(DEPDIR)/libinftextgtk_0_7_la-inf-text-gtk-view.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='inf-text-gtk-view.c' object='libinftextgtk_0_7_la-inf-text-gtk-view.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) $(libinftextgtk_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libinftextgtk_0_7_la-inf-text-gtk-view.lo `test -f 'inf-text-gtk-view.c' || echo '$(srcdir)/'`inf-text-gtk-view.c libinftextgtk_0_7_la-inf-text-gtk-viewport.lo: inf-text-gtk-viewport.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libinftextgtk_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libinftextgtk_0_7_la-inf-text-gtk-viewport.lo -MD -MP -MF $(DEPDIR)/libinftextgtk_0_7_la-inf-text-gtk-viewport.Tpo -c -o libinftextgtk_0_7_la-inf-text-gtk-viewport.lo `test -f 'inf-text-gtk-viewport.c' || echo '$(srcdir)/'`inf-text-gtk-viewport.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libinftextgtk_0_7_la-inf-text-gtk-viewport.Tpo $(DEPDIR)/libinftextgtk_0_7_la-inf-text-gtk-viewport.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='inf-text-gtk-viewport.c' object='libinftextgtk_0_7_la-inf-text-gtk-viewport.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) $(libinftextgtk_0_7_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libinftextgtk_0_7_la-inf-text-gtk-viewport.lo `test -f 'inf-text-gtk-viewport.c' || echo '$(srcdir)/'`inf-text-gtk-viewport.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-girDATA: $(gir_DATA) @$(NORMAL_INSTALL) @list='$(gir_DATA)'; test -n "$(girdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(girdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(girdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(girdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(girdir)" || exit $$?; \ done uninstall-girDATA: @$(NORMAL_UNINSTALL) @list='$(gir_DATA)'; test -n "$(girdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(girdir)'; $(am__uninstall_files_from_dir) install-typelibDATA: $(typelib_DATA) @$(NORMAL_INSTALL) @list='$(typelib_DATA)'; test -n "$(typelibdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(typelibdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(typelibdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(typelibdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(typelibdir)" || exit $$?; \ done uninstall-typelibDATA: @$(NORMAL_UNINSTALL) @list='$(typelib_DATA)'; test -n "$(typelibdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(typelibdir)'; $(am__uninstall_files_from_dir) install-libinftextgtk_0_7_laHEADERS: $(libinftextgtk_0_7_la_HEADERS) @$(NORMAL_INSTALL) @list='$(libinftextgtk_0_7_la_HEADERS)'; test -n "$(libinftextgtk_0_7_ladir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(libinftextgtk_0_7_ladir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libinftextgtk_0_7_ladir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(libinftextgtk_0_7_ladir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(libinftextgtk_0_7_ladir)" || exit $$?; \ done uninstall-libinftextgtk_0_7_laHEADERS: @$(NORMAL_UNINSTALL) @list='$(libinftextgtk_0_7_la_HEADERS)'; test -n "$(libinftextgtk_0_7_ladir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(libinftextgtk_0_7_ladir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ 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-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ 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" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files 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: check-am all-am: Makefile $(LTLIBRARIES) $(DATA) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(girdir)" "$(DESTDIR)$(typelibdir)" "$(DESTDIR)$(libinftextgtk_0_7_ladir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: 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." clean: clean-am clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \ 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-girDATA install-libinftextgtk_0_7_laHEADERS \ install-typelibDATA install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-libLTLIBRARIES 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-girDATA uninstall-libLTLIBRARIES \ uninstall-libinftextgtk_0_7_laHEADERS uninstall-typelibDATA .MAKE: install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libLTLIBRARIES clean-libtool cscopelist-am ctags \ ctags-am 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-girDATA install-html install-html-am \ install-info install-info-am install-libLTLIBRARIES \ install-libinftextgtk_0_7_laHEADERS install-man install-pdf \ install-pdf-am install-ps install-ps-am install-strip \ install-typelibDATA installcheck installcheck-am installdirs \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \ uninstall-girDATA uninstall-libLTLIBRARIES \ uninstall-libinftextgtk_0_7_laHEADERS uninstall-typelibDATA .PRECIOUS: Makefile @HAVE_INTROSPECTION_TRUE@-include $(INTROSPECTION_MAKEFILE) @HAVE_INTROSPECTION_TRUE@InfTextGtk-0.7.gir: libinftextgtk-0.7.la # 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: libinfinity-0.7.1/libinftextgtk/PaxHeaders.26529/Makefile.am0000644000000000000000000000013213034544714020522 xustar0030 mtime=1483917772.686920573 30 atime=1483917772.686920573 30 ctime=1488261589.388138217 libinfinity-0.7.1/libinftextgtk/Makefile.am0000644000175000017500000000450013034544714021253 0ustar00arminarmin00000000000000# TODO: Find a way to have the version number set automatically. lib_LTLIBRARIES = libinftextgtk-0.7.la cppflags = \ -I$(top_srcdir) \ $(inftextgtk_CFLAGS) \ $(inftext_CFLAGS) \ $(infinity_CFLAGS) ldflags = \ -no-undefined \ -version-info $(LIBINFINITY_LIBTOOL_VERSION) libadd = \ ${top_builddir}/libinftext/libinftext-$(LIBINFINITY_API_VERSION).la \ ${top_builddir}/libinfinity/libinfinity-$(LIBINFINITY_API_VERSION).la \ $(inftextgtk_LIBS) \ $(inftext_LIBS) \ $(infinity_LIBS) headers = \ inf-text-gtk-buffer.h \ inf-text-gtk-hue-chooser.h \ inf-text-gtk-view.h \ inf-text-gtk-viewport.h sources = \ inf-text-gtk-buffer.c \ inf-text-gtk-hue-chooser.c \ inf-text-gtk-view.c \ inf-text-gtk-viewport.c libinftextgtk_0_7_la_CPPFLAGS = $(cppflags) libinftextgtk_0_7_la_LDFLAGS = $(ldflags) libinftextgtk_0_7_la_LIBADD = $(libadd) libinftextgtk_0_7_la_HEADERS = $(headers) libinftextgtk_0_7_la_SOURCES = $(sources) libinftextgtk_0_7_ladir = \ $(includedir)/libinftextgtk-$(LIBINFINITY_API_VERSION)/libinftextgtk if HAVE_INTROSPECTION -include $(INTROSPECTION_MAKEFILE) INTROSPECTION_GIRS = InfTextGtk-0.7.gir INTROSPECTION_SCANNER_ENV = CC="${CC}" INTROSPECTION_COMPILER_ARGS = \ --includedir=${top_srcdir}/libinfinity \ --includedir=${top_builddir}/libinfinity \ --includedir=${top_builddir}/libinftext \ --includedir=${top_builddir}/libinfgtk InfTextGtk-0.7.gir: libinftextgtk-0.7.la InfTextGtk_0_7_gir_SCANNERFLAGS = \ -I${top_srcdir} \ --add-include-path=$(top_srcdir)/libinfinity \ --add-include-path=$(top_builddir)/libinfinity \ --add-include-path=$(top_builddir)/libinftext \ --add-include-path=$(top_builddir)/libinfgtk \ -n InfTextGtk \ --identifier-prefix=InfTextGtk InfTextGtk_0_7_gir_NAMESPACE = InfTextGtk InfTextGtk_0_7_gir_VERSION = 0.7 InfTextGtk_0_7_gir_CFLAGS = $(inftextgtk_CFLAGS) $(inftext_CFLAGS) $(infinity_CFLAGS) InfTextGtk_0_7_gir_LIBS = libinftextgtk-0.7.la InfTextGtk_0_7_gir_FILES = \ $(libinftextgtk_0_7_la_SOURCES) \ $(libinftextgtk_0_7_la_HEADERS) InfTextGtk_0_7_gir_INCLUDES = InfText-0.7 InfGtk-0.7 Gtk-3.0 InfTextGtk_0_7_gir_PACKAGES = gtk+-3.0 InfTextGtk_0_7_gir_EXPORT_PACKAGES = libinftextgtk-0.7 girdir = $(datadir)/gir-1.0 gir_DATA = InfTextGtk-0.7.gir typelibdir = $(libdir)/girepository-1.0 typelib_DATA = InfTextGtk-0.7.typelib CLEANFILES = \ $(gir_DATA) \ $(typelib_DATA) endif libinfinity-0.7.1/libinftextgtk/PaxHeaders.26529/inf-text-gtk-viewport.h0000644000000000000000000000013213034342512023025 xustar0030 mtime=1483851082.049718536 30 atime=1483851082.049718536 30 ctime=1488261589.396138199 libinfinity-0.7.1/libinftextgtk/inf-text-gtk-viewport.h0000644000175000017500000000602713034342512023564 0ustar00arminarmin00000000000000/* infinote - Collaborative notetaking application * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef __INF_TEXT_GTK_VIEWPORT_H__ #define __INF_TEXT_GTK_VIEWPORT_H__ #include #include #include #include G_BEGIN_DECLS #define INF_TEXT_GTK_TYPE_VIEWPORT (inf_text_gtk_viewport_get_type()) #define INF_TEXT_GTK_VIEWPORT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_TEXT_GTK_TYPE_VIEWPORT, InfTextGtkViewport)) #define INF_TEXT_GTK_VIEWPORT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INF_TEXT_GTK_TYPE_VIEWPORT, InfTextGtkViewportClass)) #define INF_TEXT_GTK_IS_VIEWPORT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_TEXT_GTK_TYPE_VIEWPORT)) #define INF_TEXT_GTK_IS_VIEWPORT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INF_TEXT_GTK_TYPE_VIEWPORT)) #define INF_TEXT_GTK_VIEWPORT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INF_TEXT_GTK_TYPE_VIEWPORT, InfTextGtkViewportClass)) typedef struct _InfTextGtkViewport InfTextGtkViewport; typedef struct _InfTextGtkViewportClass InfTextGtkViewportClass; /** * InfTextGtkViewportClass: * * This structure does not contain any public fields. */ struct _InfTextGtkViewportClass { /*< private >*/ GObjectClass parent_class; }; /** * InfTextGtkViewport: * * #InfTextGtkViewport is an opaque data type. You should only access it via * the public API functions. */ struct _InfTextGtkViewport { /*< private >*/ GObject parent; }; GType inf_text_gtk_viewport_get_type(void) G_GNUC_CONST; InfTextGtkViewport* inf_text_gtk_viewport_new(GtkScrolledWindow* scroll, InfUserTable* user_table); GtkScrolledWindow* inf_text_gtk_viewport_get_scrolled_window(InfTextGtkViewport* viewport); InfUserTable* inf_text_gtk_viewport_get_user_table(InfTextGtkViewport* viewport); void inf_text_gtk_viewport_set_active_user(InfTextGtkViewport* viewport, InfTextUser* user); InfTextUser* inf_text_gtk_viewport_get_active_user(InfTextGtkViewport* viewport); void inf_text_gtk_viewport_set_show_user_markers(InfTextGtkViewport* viewport, gboolean show); G_END_DECLS #endif /* __INF_TEXT_GTK_VIEWPORT_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinftextgtk/PaxHeaders.26529/inf-text-gtk-hue-chooser.h0000644000000000000000000000013213034342512023367 xustar0030 mtime=1483851082.049718536 30 atime=1483851082.049718536 30 ctime=1488261589.392138208 libinfinity-0.7.1/libinftextgtk/inf-text-gtk-hue-chooser.h0000644000175000017500000000607013034342512024124 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_TEXT_GTK_HUE_CHOOSER_H__ #define __INF_TEXT_GTK_HUE_CHOOSER_H__ #include G_BEGIN_DECLS #define INF_TEXT_GTK_TYPE_HUE_CHOOSER (inf_text_gtk_hue_chooser_get_type()) #define INF_TEXT_GTK_HUE_CHOOSER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_TEXT_GTK_TYPE_HUE_CHOOSER, InfTextGtkHueChooser)) #define INF_TEXT_GTK_HUE_CHOOSER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INF_TEXT_GTK_TYPE_HUE_CHOOSER, InfTextGtkHueChooserClass)) #define INF_TEXT_GTK_IS_HUE_CHOOSER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_TEXT_GTK_TYPE_HUE_CHOOSER)) #define INF_TEXT_GTK_IS_HUE_CHOOSER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INF_TEXT_GTK_TYPE_HUE_CHOOSER)) #define INF_TEXT_GTK_HUE_CHOOSER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INF_TEXT_GTK_TYPE_HUE_CHOOSER, InfTextGtkHueChooserClass)) typedef struct _InfTextGtkHueChooser InfTextGtkHueChooser; typedef struct _InfTextGtkHueChooserClass InfTextGtkHueChooserClass; /** * InfTextGtkHueChooserClass: * @hue_change: Default signal handler for the * #InfTextGtkHueChooser::hue-change signal. * @move: Default signal handler for the #InfTextGtkHueChooser::move signal. * * This structure contains default signal handlers of the * #InfTextGtkHueChooser class. */ struct _InfTextGtkHueChooserClass { /*< private >*/ GtkWidgetClass parent_class; /*< public >*/ void(*hue_change)(InfTextGtkHueChooser* chooser, gdouble hue); void(*move)(InfTextGtkHueChooser* chooser, GtkDirectionType direction); }; /** * InfTextGtkHueChooser: * * #InfTextGtkHueChooser is an opaque data type. You should only access it * via the public API functions. */ struct _InfTextGtkHueChooser { /*< private >*/ GtkWidget parent; }; GType inf_text_gtk_hue_chooser_get_type(void) G_GNUC_CONST; GtkWidget* inf_text_gtk_hue_chooser_new(void); GtkWidget* inf_text_gtk_hue_chooser_new_with_hue(gdouble hue); void inf_text_gtk_hue_chooser_set_hue(InfTextGtkHueChooser* chooser, gdouble hue); gdouble inf_text_gtk_hue_chooser_get_hue(InfTextGtkHueChooser* chooser); G_END_DECLS #endif /* __INF_TEXT_GTK_HUE_CHOOSER_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinftextgtk/PaxHeaders.26529/inf-text-gtk-hue-chooser.c0000644000000000000000000000013213034342512023362 xustar0030 mtime=1483851082.049718536 30 atime=1483851082.049718536 30 ctime=1488261589.400138191 libinfinity-0.7.1/libinftextgtk/inf-text-gtk-hue-chooser.c0000644000175000017500000005702113034342512024121 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * SECTION:inf-text-gtk-hue-chooser * @title: InfTextGtkHueChooser * @short_description: A GTK+ widget for selecting a hue value * @include: libinftextgtk/inf-text-gtk-hue-chooser.h * @see_also: #InfTextGtkHueChooser * @stability: Unstable * * #InfTextGtkHueChooser is a widget which allows the user to select a hue * value without selecting also saturation and lightness at the same time. It * only presents the hue circle without the inner triangle. */ #include #include #include #include /* Based on gtkhsv.c from GTK+ */ typedef enum _InfTextGtkHueChooserDragMode { INF_TEXT_GTK_HUE_CHOOSER_DRAG_NONE, INF_TEXT_GTK_HUE_CHOOSER_DRAG_HUE } InfTextGtkHueChooserDragMode; typedef struct _InfTextGtkHueChooserPrivate InfTextGtkHueChooserPrivate; struct _InfTextGtkHueChooserPrivate { gdouble hue; GdkWindow* window; guint ring_width; guint size; InfTextGtkHueChooserDragMode mode; }; enum { PROP_0, PROP_HUE }; enum { HUE_CHANGE, MOVE, LAST_SIGNAL }; #define INF_TEXT_GTK_HUE_CHOOSER_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INF_TEXT_GTK_TYPE_HUE_CHOOSER, InfTextGtkHueChooserPrivate)) static guint hue_chooser_signals[LAST_SIGNAL]; G_DEFINE_TYPE_WITH_CODE(InfTextGtkHueChooser, inf_text_gtk_hue_chooser, GTK_TYPE_WIDGET, G_ADD_PRIVATE(InfTextGtkHueChooser)) static const double INF_TEXT_GTK_HUE_CHOOSER_HUE_MOVE_DELTA = 0.002; /* * Helper functions */ #define INTENSITY(r, g, b) ((r) * 0.30 + (g) * 0.59 + (b) * 0.11) static gboolean inf_text_gtk_hue_chooser_is_in_ring(InfTextGtkHueChooser* chooser, gdouble x, gdouble y) { InfTextGtkHueChooserPrivate* priv; GtkAllocation allocation; gdouble center_x; gdouble center_y; gdouble dx; gdouble dy; gdouble inner; gdouble outer; gdouble dist_sqr; gtk_widget_get_allocation(GTK_WIDGET(chooser), &allocation); priv = INF_TEXT_GTK_HUE_CHOOSER_PRIVATE(chooser); center_x = allocation.width / 2.0; center_y = allocation.height / 2.0; outer = priv->size / 2.0; inner = outer - priv->ring_width; dx = x - center_x; dy = center_y - y; dist_sqr = dx * dx + dy * dy; return (dist_sqr >= inner * inner && dist_sqr <= outer * outer); } static gdouble inf_text_gtk_hue_chooser_hue_by_coords(InfTextGtkHueChooser* chooser, gdouble x, gdouble y) { GtkAllocation allocation; double center_x; double center_y; double dx; double dy; double angle; gtk_widget_get_allocation(GTK_WIDGET(chooser), &allocation); center_x = allocation.width / 2.0; center_y = allocation.height / 2.0; dx = x - center_x; dy = center_y - y; angle = atan2(dy, dx); if(angle < 0.0) angle += 2.0 * G_PI; return angle / (2.0 * G_PI); } static void inf_text_gtk_hue_chooser_paint(InfTextGtkHueChooser* chooser, cairo_t* cr, gint x, gint y, gint width, gint height) { InfTextGtkHueChooserPrivate* priv; GtkAllocation allocation; int xx, yy; gdouble dx, dy, dist; gdouble center_x; gdouble center_y; gdouble inner, outer; guint32* buf; guint32* p; gdouble angle; gdouble hue; gdouble r; gdouble g; gdouble b; cairo_surface_t* source; cairo_t* source_cr; gint focus_width; gint focus_pad; gint r_, g_, b_; priv = INF_TEXT_GTK_HUE_CHOOSER_PRIVATE(chooser); gtk_widget_style_get( GTK_WIDGET(chooser), "focus-line-width", &focus_width, "focus-padding", &focus_pad, NULL ); gtk_widget_get_allocation(GTK_WIDGET(chooser), &allocation); center_x = allocation.width / 2.0; center_y = allocation.height / 2.0; outer = priv->size / 2.0; inner = outer - priv->ring_width; /* Create an image initialized with the ring colors */ buf = g_new(guint32, width * height); for(yy = 0; yy < height; yy++) { p = buf + yy * width; dy = -(yy + y - center_y); for (xx = 0; xx < width; xx++) { dx = xx + x - center_x; dist = dx * dx + dy * dy; if(dist < ((inner-1) * (inner-1)) || dist > ((outer+1) * (outer+1))) { *p++ = 0; continue; } angle = atan2 (dy, dx); if (angle < 0.0) angle += 2.0 * G_PI; hue = angle / (2.0 * G_PI); gtk_hsv_to_rgb(hue, 1.0, 1.0, &r, &g, &b); r_ = floor (r * 255 + 0.5); g_ = floor (g * 255 + 0.5); b_ = floor (b * 255 + 0.5); *p++ = ((r_ << 16) | (g_ << 8) | b_ ); } } source = cairo_image_surface_create_for_data( (unsigned char *)buf, CAIRO_FORMAT_RGB24, width, height, 4 * width ); /* Now draw the value marker onto the source image, so that it * will get properly clipped at the edges of the ring */ source_cr = cairo_create(source); gtk_hsv_to_rgb(priv->hue, 1.0, 1.0, &r, &g, &b); if(INTENSITY(r, g, b) > 0.5) cairo_set_source_rgb(source_cr, 0.0, 0.0, 0.0); else cairo_set_source_rgb(source_cr, 1.0, 1.0, 1.0); cairo_move_to(source_cr, -x + center_x, - y + center_y); cairo_line_to( source_cr, -x + center_x + cos(priv->hue * 2.0 * G_PI) * priv->size / 2, -y + center_y - sin(priv->hue * 2.0 * G_PI) * priv->size / 2 ); cairo_stroke(source_cr); cairo_destroy(source_cr); /* Draw the ring using the source image */ cairo_save(cr); cairo_set_source_surface(cr, source, x, y); cairo_surface_destroy(source); cairo_set_line_width(cr, priv->ring_width); cairo_new_path(cr); cairo_arc( cr, center_x, center_y, priv->size / 2.0 - priv->ring_width / 2.0, 0, 2 * G_PI ); cairo_stroke(cr); cairo_restore(cr); g_free (buf); } /* * GObject overrides */ static void inf_text_gtk_hue_chooser_init(InfTextGtkHueChooser* hue_chooser) { InfTextGtkHueChooserPrivate* priv; priv = INF_TEXT_GTK_HUE_CHOOSER_PRIVATE(hue_chooser); gtk_widget_set_has_window(GTK_WIDGET(hue_chooser), FALSE); gtk_widget_set_can_focus(GTK_WIDGET(hue_chooser), TRUE); priv->hue = 0.0; priv->window = NULL; priv->ring_width = 50; priv->size = 240; priv->mode = INF_TEXT_GTK_HUE_CHOOSER_DRAG_NONE; } static void inf_text_gtk_hue_chooser_dispose(GObject* object) { InfTextGtkHueChooser* hue_chooser; InfTextGtkHueChooserPrivate* priv; hue_chooser = INF_TEXT_GTK_HUE_CHOOSER(object); priv = INF_TEXT_GTK_HUE_CHOOSER_PRIVATE(hue_chooser); G_OBJECT_CLASS(inf_text_gtk_hue_chooser_parent_class)->dispose(object); } static void inf_text_gtk_hue_chooser_finalize(GObject* object) { InfTextGtkHueChooser* hue_chooser; InfTextGtkHueChooserPrivate* priv; hue_chooser = INF_TEXT_GTK_HUE_CHOOSER(object); priv = INF_TEXT_GTK_HUE_CHOOSER_PRIVATE(hue_chooser); G_OBJECT_CLASS(inf_text_gtk_hue_chooser_parent_class)->finalize(object); } static void inf_text_gtk_hue_chooser_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfTextGtkHueChooser* hue_chooser; InfTextGtkHueChooserPrivate* priv; hue_chooser = INF_TEXT_GTK_HUE_CHOOSER(object); priv = INF_TEXT_GTK_HUE_CHOOSER_PRIVATE(hue_chooser); switch(prop_id) { case PROP_HUE: inf_text_gtk_hue_chooser_set_hue(hue_chooser, g_value_get_double(value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void inf_text_gtk_hue_chooser_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfTextGtkHueChooser* hue_chooser; InfTextGtkHueChooserPrivate* priv; hue_chooser = INF_TEXT_GTK_HUE_CHOOSER(object); priv = INF_TEXT_GTK_HUE_CHOOSER_PRIVATE(hue_chooser); switch(prop_id) { case PROP_HUE: g_value_set_double(value, priv->hue); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } /* * GtkWidget overrides */ static void inf_text_gtk_hue_chooser_map(GtkWidget* widget) { InfTextGtkHueChooser* chooser; InfTextGtkHueChooserPrivate* priv; chooser = INF_TEXT_GTK_HUE_CHOOSER(widget); priv = INF_TEXT_GTK_HUE_CHOOSER_PRIVATE(chooser); GTK_WIDGET_CLASS(inf_text_gtk_hue_chooser_parent_class)->map(widget); gdk_window_show(priv->window); } static void inf_text_gtk_hue_chooser_unmap(GtkWidget* widget) { InfTextGtkHueChooser* chooser; InfTextGtkHueChooserPrivate* priv; chooser = INF_TEXT_GTK_HUE_CHOOSER(widget); priv = INF_TEXT_GTK_HUE_CHOOSER_PRIVATE(chooser); gdk_window_hide(priv->window); GTK_WIDGET_CLASS(inf_text_gtk_hue_chooser_parent_class)->unmap(widget); } static void inf_text_gtk_hue_chooser_realize(GtkWidget* widget) { InfTextGtkHueChooser* chooser; InfTextGtkHueChooserPrivate* priv; GtkAllocation allocation; GdkWindowAttr attr; GdkWindow* parent_window; chooser = INF_TEXT_GTK_HUE_CHOOSER(widget); priv = INF_TEXT_GTK_HUE_CHOOSER_PRIVATE(chooser); gtk_widget_set_realized(widget, TRUE); gtk_widget_get_allocation(widget, &allocation); attr.window_type = GDK_WINDOW_CHILD; attr.x = allocation.x; attr.y = allocation.y; attr.width = allocation.width; attr.height = allocation.height; attr.wclass = GDK_INPUT_ONLY; attr.event_mask = gtk_widget_get_events(widget); attr.event_mask |= ( GDK_KEY_PRESS_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK ); parent_window = gtk_widget_get_parent_window(widget); g_object_ref(parent_window); gtk_widget_set_window(widget, parent_window); priv->window = gdk_window_new(parent_window, &attr, GDK_WA_X | GDK_WA_Y); gdk_window_set_user_data(priv->window, chooser); gdk_window_show(priv->window); } static void inf_text_gtk_hue_chooser_unrealize(GtkWidget* widget) { InfTextGtkHueChooser* chooser; InfTextGtkHueChooserPrivate* priv; chooser = INF_TEXT_GTK_HUE_CHOOSER(widget); priv = INF_TEXT_GTK_HUE_CHOOSER_PRIVATE(chooser); gdk_window_set_user_data(priv->window, NULL); gdk_window_destroy(priv->window); priv->window = NULL; GTK_WIDGET_CLASS(inf_text_gtk_hue_chooser_parent_class)->unrealize(widget); } static gint inf_text_gtk_hue_chooser_calculate_width_and_height(GtkWidget *widget) { InfTextGtkHueChooser* chooser; InfTextGtkHueChooserPrivate* priv; gint focus_width; gint focus_pad; chooser = INF_TEXT_GTK_HUE_CHOOSER(widget); priv = INF_TEXT_GTK_HUE_CHOOSER_PRIVATE(chooser); gtk_widget_style_get( widget, "focus-line-width", &focus_width, "focus-padding", &focus_pad, NULL ); return priv->size + 2 * (focus_width + focus_pad); } static void inf_text_gtk_hue_chooser_get_preferred_width(GtkWidget *widget, gint *minimum, gint *natural) { *minimum = *natural = inf_text_gtk_hue_chooser_calculate_width_and_height(widget); } static void inf_text_gtk_hue_chooser_get_preferred_height(GtkWidget *widget, gint *minimum, gint *natural) { *minimum = *natural = inf_text_gtk_hue_chooser_calculate_width_and_height(widget); } static void inf_text_gtk_hue_chooser_size_allocate(GtkWidget* widget, GtkAllocation* allocation) { InfTextGtkHueChooser* chooser; InfTextGtkHueChooserPrivate* priv; chooser = INF_TEXT_GTK_HUE_CHOOSER(widget); priv = INF_TEXT_GTK_HUE_CHOOSER_PRIVATE(chooser); gtk_widget_set_allocation(widget, allocation); if(gtk_widget_get_realized(widget)) { /* TODO: Keep 1:1 aspect ratio, center within allocation, set size * accordingly, always request only ring_width * 2. */ gdk_window_move_resize( priv->window, allocation->x, allocation->y, allocation->width, allocation->height ); } } static gboolean inf_text_gtk_hue_chooser_button_press_event(GtkWidget* widget, GdkEventButton* event) { InfTextGtkHueChooser* chooser; InfTextGtkHueChooserPrivate* priv; GdkCursor* cursor; double hue; chooser = INF_TEXT_GTK_HUE_CHOOSER(widget); priv = INF_TEXT_GTK_HUE_CHOOSER_PRIVATE(chooser); gtk_widget_queue_draw(widget); if(priv->mode != INF_TEXT_GTK_HUE_CHOOSER_DRAG_NONE || event->button != 1) return FALSE; if(inf_text_gtk_hue_chooser_is_in_ring(chooser, event->x, event->y)) { /* Start drag */ priv->mode = INF_TEXT_GTK_HUE_CHOOSER_DRAG_HUE; hue = inf_text_gtk_hue_chooser_hue_by_coords(chooser, event->x, event->y); inf_text_gtk_hue_chooser_set_hue(chooser, hue); cursor = gdk_cursor_new_for_display( gtk_widget_get_display(widget), GDK_CROSSHAIR ); gdk_device_grab( gdk_event_get_device((GdkEvent*)event), priv->window, GDK_OWNERSHIP_NONE, FALSE, GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_RELEASE_MASK, cursor, event->time ); g_object_unref(cursor); gtk_widget_grab_focus(widget); } return TRUE; } static gboolean inf_text_gtk_hue_chooser_button_release_event(GtkWidget* widget, GdkEventButton* event) { InfTextGtkHueChooser* chooser; InfTextGtkHueChooserPrivate* priv; double hue; chooser = INF_TEXT_GTK_HUE_CHOOSER(widget); priv = INF_TEXT_GTK_HUE_CHOOSER_PRIVATE(chooser); if(priv->mode == INF_TEXT_GTK_HUE_CHOOSER_DRAG_NONE || event->button != 1) return FALSE; priv->mode = INF_TEXT_GTK_HUE_CHOOSER_DRAG_NONE; hue = inf_text_gtk_hue_chooser_hue_by_coords(chooser, event->x, event->y); inf_text_gtk_hue_chooser_set_hue(chooser, hue); gdk_device_ungrab( gdk_event_get_device((GdkEvent*)event), event->time ); return TRUE; } static gboolean inf_text_gtk_hue_chooser_motion_notify_event(GtkWidget* widget, GdkEventMotion* event) { InfTextGtkHueChooser* chooser; InfTextGtkHueChooserPrivate* priv; double hue; chooser = INF_TEXT_GTK_HUE_CHOOSER(widget); priv = INF_TEXT_GTK_HUE_CHOOSER_PRIVATE(chooser); if(priv->mode == INF_TEXT_GTK_HUE_CHOOSER_DRAG_NONE) return FALSE; gdk_event_request_motions(event); hue = inf_text_gtk_hue_chooser_hue_by_coords(chooser, event->x, event->y); inf_text_gtk_hue_chooser_set_hue(chooser, hue); return TRUE; } static gboolean inf_text_gtk_hue_chooser_draw(GtkWidget* widget, cairo_t* cr) { InfTextGtkHueChooser* chooser; InfTextGtkHueChooserPrivate* priv; chooser = INF_TEXT_GTK_HUE_CHOOSER(widget); priv = INF_TEXT_GTK_HUE_CHOOSER_PRIVATE(chooser); inf_text_gtk_hue_chooser_paint( chooser, cr, 0, 0, gtk_widget_get_allocated_width(widget), gtk_widget_get_allocated_height(widget) ); return FALSE; } static gboolean inf_text_gtk_hue_chooser_focus(GtkWidget* widget, GtkDirectionType dir) { InfTextGtkHueChooser* chooser; InfTextGtkHueChooserPrivate* priv; chooser = INF_TEXT_GTK_HUE_CHOOSER(widget); priv = INF_TEXT_GTK_HUE_CHOOSER_PRIVATE(chooser); if(!gtk_widget_has_focus(widget)) { gtk_widget_grab_focus(GTK_WIDGET(widget)); return TRUE; } return FALSE; } static gboolean inf_text_gtk_hue_chooser_grab_broken_event(GtkWidget* widget, GdkEventGrabBroken* event) { InfTextGtkHueChooser* chooser; InfTextGtkHueChooserPrivate* priv; chooser = INF_TEXT_GTK_HUE_CHOOSER(widget); priv = INF_TEXT_GTK_HUE_CHOOSER_PRIVATE(chooser); priv->mode = INF_TEXT_GTK_HUE_CHOOSER_DRAG_NONE; return TRUE; } /* * Default signal handlers */ static void inf_text_gtk_hue_chooser_hue_change(InfTextGtkHueChooser* chooser, gdouble hue) { InfTextGtkHueChooserPrivate* priv; priv = INF_TEXT_GTK_HUE_CHOOSER_PRIVATE(chooser); priv->hue = hue; g_object_notify(G_OBJECT(chooser), "hue"); gtk_widget_queue_draw(GTK_WIDGET(chooser)); } static void inf_text_gtk_hue_chooser_move(InfTextGtkHueChooser* chooser, GtkDirectionType direction) { InfTextGtkHueChooserPrivate* priv; gdouble hue; priv = INF_TEXT_GTK_HUE_CHOOSER_PRIVATE(chooser); hue = priv->hue; switch(direction) { case GTK_DIR_UP: case GTK_DIR_LEFT: hue += INF_TEXT_GTK_HUE_CHOOSER_HUE_MOVE_DELTA; break; case GTK_DIR_DOWN: case GTK_DIR_RIGHT: hue -= INF_TEXT_GTK_HUE_CHOOSER_HUE_MOVE_DELTA; break; default: /* we don't care about the tab directions */ break; } /* wrap */ if(hue < 0.0) hue += 1.0; if(hue > 1.0) hue -= 1.0; inf_text_gtk_hue_chooser_set_hue(chooser, hue); } /* * Type registration */ static void inf_text_gtk_hue_chooser_class_init( InfTextGtkHueChooserClass* hue_chooser_class) { GObjectClass* object_class; GtkWidgetClass* widget_class; GtkBindingSet* binding_set; object_class = G_OBJECT_CLASS(hue_chooser_class); widget_class = GTK_WIDGET_CLASS(hue_chooser_class); object_class->dispose = inf_text_gtk_hue_chooser_dispose; object_class->finalize = inf_text_gtk_hue_chooser_finalize; object_class->set_property = inf_text_gtk_hue_chooser_set_property; object_class->get_property = inf_text_gtk_hue_chooser_get_property; widget_class->map = inf_text_gtk_hue_chooser_map; widget_class->unmap = inf_text_gtk_hue_chooser_unmap; widget_class->realize = inf_text_gtk_hue_chooser_realize; widget_class->unrealize = inf_text_gtk_hue_chooser_unrealize; widget_class->get_preferred_height = inf_text_gtk_hue_chooser_get_preferred_height; widget_class->get_preferred_width = inf_text_gtk_hue_chooser_get_preferred_width; widget_class->size_allocate = inf_text_gtk_hue_chooser_size_allocate; widget_class->button_press_event = inf_text_gtk_hue_chooser_button_press_event; widget_class->button_release_event = inf_text_gtk_hue_chooser_button_release_event; widget_class->motion_notify_event = inf_text_gtk_hue_chooser_motion_notify_event; widget_class->draw = inf_text_gtk_hue_chooser_draw; widget_class->focus = inf_text_gtk_hue_chooser_focus; widget_class->grab_broken_event = inf_text_gtk_hue_chooser_grab_broken_event; hue_chooser_class->hue_change = inf_text_gtk_hue_chooser_hue_change; hue_chooser_class->move = inf_text_gtk_hue_chooser_move; /** * InfTextGtkHueChooser::hue-change: * @chooser: The #InfTextGtkHueChooser emitting the signal. * @hue: The new hue value. * * This signal is emitted whenever the hue value is changed. */ hue_chooser_signals[HUE_CHANGE] = g_signal_new( "hue-change", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET(InfTextGtkHueChooserClass, hue_change), NULL, NULL, g_cclosure_marshal_VOID__DOUBLE, G_TYPE_NONE, 1, G_TYPE_DOUBLE ); /** * InfTextGtkHueChooser::move: * @chooser: The #InfTextGtkHueChooser emitting the signal. * @direction: The direction in which the move was mode. * * This is an action signal emitted when the selection is moved by the user. */ hue_chooser_signals[MOVE] = g_signal_new( "move", G_OBJECT_CLASS_TYPE(object_class), G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET(InfTextGtkHueChooserClass, move), NULL, NULL, g_cclosure_marshal_VOID__ENUM, G_TYPE_NONE, 1, GTK_TYPE_DIRECTION_TYPE ); g_object_class_install_property( object_class, PROP_HUE, g_param_spec_double( "hue", "Hue", "The current hue value", 0.0, 1.0, 0.0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT ) ); binding_set = gtk_binding_set_by_class(object_class); gtk_binding_entry_add_signal( binding_set, GDK_KEY_Up, 0, "move", 1, G_TYPE_ENUM, GTK_DIR_UP ); gtk_binding_entry_add_signal( binding_set, GDK_KEY_KP_Up, 0, "move", 1, G_TYPE_ENUM, GTK_DIR_UP ); gtk_binding_entry_add_signal( binding_set, GDK_KEY_Down, 0, "move", 1, G_TYPE_ENUM, GTK_DIR_DOWN ); gtk_binding_entry_add_signal( binding_set, GDK_KEY_KP_Down, 0, "move", 1, G_TYPE_ENUM, GTK_DIR_DOWN ); gtk_binding_entry_add_signal( binding_set, GDK_KEY_Right, 0, "move", 1, G_TYPE_ENUM, GTK_DIR_RIGHT ); gtk_binding_entry_add_signal( binding_set, GDK_KEY_KP_Right, 0, "move", 1, G_TYPE_ENUM, GTK_DIR_RIGHT ); gtk_binding_entry_add_signal( binding_set, GDK_KEY_Left, 0, "move", 1, G_TYPE_ENUM, GTK_DIR_LEFT ); gtk_binding_entry_add_signal( binding_set, GDK_KEY_KP_Left, 0, "move", 1, G_TYPE_ENUM, GTK_DIR_LEFT ); } /* * Public API */ /** * inf_text_gtk_hue_chooser_new: (constructor) * * Creates a new #InfTextGtkHueChooser widget with the initial hue set to 0.0 * (red). * * Returns: (transfer floating): A newly created #InfTextGtkHueChooser. **/ GtkWidget* inf_text_gtk_hue_chooser_new(void) { GObject* object; object = g_object_new(INF_TEXT_GTK_TYPE_HUE_CHOOSER, NULL); return GTK_WIDGET(object); } /** * inf_text_gtk_hue_chooser_new_with_hue: (constructor) * @hue: Initial hue value * * Creates a new #InfTextGtkHueChooser widget with the given hue as initial * value. @hue must be between 0.0 and 1.0. * * Returns: (transfer floating): A newly created #InfTextGtkHueChooser. **/ GtkWidget* inf_text_gtk_hue_chooser_new_with_hue(gdouble hue) { GObject* object; g_return_val_if_fail(hue >= 0.0 && hue <= 1.0, NULL); object = g_object_new(INF_TEXT_GTK_TYPE_HUE_CHOOSER, "hue", hue, NULL); return GTK_WIDGET(object); } /** * inf_text_gtk_hue_chooser_set_hue: * @chooser: A #InfTextGtkHueChooser. * @hue: New hue value. * * Sets the current hue value of @chooser to @hue. @hue must be between 0.0 * and 1.0. */ void inf_text_gtk_hue_chooser_set_hue(InfTextGtkHueChooser* chooser, gdouble hue) { InfTextGtkHueChooserPrivate* priv; g_return_if_fail(INF_TEXT_GTK_IS_HUE_CHOOSER(chooser)); g_return_if_fail(hue >= 0.0 && hue <= 1.0); priv = INF_TEXT_GTK_HUE_CHOOSER_PRIVATE(chooser); g_signal_emit(G_OBJECT(chooser), hue_chooser_signals[HUE_CHANGE], 0, hue); } /** * inf_text_gtk_hue_chooser_get_hue: * @chooser: A #InfTextGtkHueChooser. * * Returns the currently selected hue value of @chooser. * * Returns: The current hue value, a number between 0.0 and 1.0. */ gdouble inf_text_gtk_hue_chooser_get_hue(InfTextGtkHueChooser* chooser) { g_return_val_if_fail(INF_TEXT_GTK_IS_HUE_CHOOSER(chooser), 0.0); return INF_TEXT_GTK_HUE_CHOOSER_PRIVATE(chooser)->hue; } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinftextgtk/PaxHeaders.26529/inf-text-gtk-viewport.c0000644000000000000000000000013213034342512023020 xustar0030 mtime=1483851082.049718536 30 atime=1483851082.049718536 30 ctime=1488261589.404138182 libinfinity-0.7.1/libinftextgtk/inf-text-gtk-viewport.c0000644000175000017500000007167213034342512023567 0ustar00arminarmin00000000000000/* infinote - Collaborative notetaking application * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /** * SECTION:inf-text-gtk-viewport * @title: InfTextGtkViewport * @short_description: Drawing position of remote users into the scrollbar * @include: libinftextgtk/inf-text-gtk-viewport.h * @see_also: #InfTextGtkView * @stability: Unstable * * #InfTextGtkViewport is a helper object which, as long as it is alive, * draws the location of the cursor of remote users into the scrollbar of * a #GtkScrolledWindow containing a #GtkTextView. * * The function inf_text_gtk_viewport_set_active_user() can be used to skip * drawing the location of the user working locally on the document, if there * is any. * * See #InfTextGtkView for drawing the cursor and selected region of remote * users into a #GtkTextView. */ #include #include #include typedef struct _InfTextGtkViewportUser InfTextGtkViewportUser; struct _InfTextGtkViewportUser { InfTextGtkViewport* viewport; InfTextUser* user; GdkRectangle rectangle; }; typedef struct _InfTextGtkViewportPrivate InfTextGtkViewportPrivate; struct _InfTextGtkViewportPrivate { GtkScrolledWindow* scroll; InfUserTable* user_table; InfTextUser* active_user; GSList* users; gboolean show_user_markers; }; enum { PROP_0, /* construct only */ PROP_SCROLLED_WINDOW, PROP_USER_TABLE, /* read/write */ PROP_ACTIVE_USER, PROP_SHOW_USER_MARKERS }; #define INF_TEXT_GTK_VIEWPORT_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INF_TEXT_GTK_TYPE_VIEWPORT, InfTextGtkViewportPrivate)) G_DEFINE_TYPE_WITH_CODE(InfTextGtkViewport, inf_text_gtk_viewport, G_TYPE_OBJECT, G_ADD_PRIVATE(InfTextGtkViewport)) static InfTextGtkViewportUser* inf_text_gtk_viewport_find_user(InfTextGtkViewport* viewport, InfTextUser* user) { InfTextGtkViewportPrivate* priv; GSList* item; priv = INF_TEXT_GTK_VIEWPORT_PRIVATE(viewport); for(item = priv->users; item != NULL; item = item->next) if( ((InfTextGtkViewportUser*)item->data)->user == user) return (InfTextGtkViewportUser*)item->data; return NULL; } static void inf_text_gtk_viewport_user_compute_user_area(InfTextGtkViewportUser* user) { InfTextGtkViewportPrivate* priv; GtkWidget* textview; GtkWidget* scrollbar; GtkTextIter iter; GdkRectangle rect; gint y; gint end_y; gint scroll_height; gint slider_size; gint stepper_size; gint stepper_spacing; gint border; GdkRectangle allocation; gint scroll_ox; gint scroll_oy; gint dy; priv = INF_TEXT_GTK_VIEWPORT_PRIVATE(user->viewport); /* TODO: We might want to skip this if show-user-markers is false. */ textview = gtk_bin_get_child(GTK_BIN(priv->scroll)); scrollbar = gtk_scrolled_window_get_vscrollbar(priv->scroll); if(GTK_IS_TEXT_VIEW(textview) && scrollbar != NULL && gtk_widget_get_realized(textview)) { gtk_text_buffer_get_iter_at_offset( gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview)), &iter, inf_text_user_get_caret_position(user->user) ); gtk_text_view_get_iter_location(GTK_TEXT_VIEW(textview), &iter, &rect); y = rect.y; gtk_text_buffer_get_end_iter( gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview)), &iter ); gtk_text_view_get_iter_location(GTK_TEXT_VIEW(textview), &iter, &rect); end_y = rect.y; g_assert(end_y > 0 || y == 0); gtk_widget_style_get( scrollbar, "slider-width", &slider_size, "stepper-size", &stepper_size, "stepper-spacing", &stepper_spacing, "trough-border", &border, NULL ); gtk_widget_get_allocation(scrollbar, &allocation); scroll_ox = border; scroll_oy = border + stepper_size + stepper_spacing; scroll_height = allocation.height - 2*scroll_oy; if(end_y > 0) y = y * scroll_height / end_y; user->rectangle.x = scroll_ox + allocation.x; user->rectangle.y = scroll_oy + allocation.y + y - slider_size/3; user->rectangle.width = slider_size; user->rectangle.height = slider_size*2/3; if(user->rectangle.y < scroll_oy + allocation.y) { dy = scroll_oy + allocation.y - user->rectangle.y; user->rectangle.y += dy; user->rectangle.height -= dy; } if(user->rectangle.y + user->rectangle.height > scroll_oy + allocation.y + scroll_height) { user->rectangle.height = scroll_oy + allocation.y + scroll_height - user->rectangle.y; } } else { user->rectangle.x = user->rectangle.y = 0; user->rectangle.width = user->rectangle.height = 0; } } static void inf_text_gtk_viewport_user_invalidate_user_area(InfTextGtkViewportUser* user) { InfTextGtkViewportPrivate* priv; GtkWidget* scrollbar; priv = INF_TEXT_GTK_VIEWPORT_PRIVATE(user->viewport); if(priv->show_user_markers && user->rectangle.width > 0 && user->rectangle.height > 0) { scrollbar = gtk_scrolled_window_get_vscrollbar(priv->scroll); /* During destruction of the widget it can happen that there is no * vertical scrollbar anymore, so check for it here. */ if(scrollbar != NULL) { gtk_widget_queue_draw_area( scrollbar, user->rectangle.x, user->rectangle.y, user->rectangle.width, user->rectangle.height ); } } } static gboolean inf_text_gtk_viewport_scrollbar_draw_cb(GtkWidget* scrollbar, cairo_t* cr, gpointer user_data) { InfTextGtkViewport* viewport; InfTextGtkViewportPrivate* priv; InfTextGtkViewportUser* viewport_user; GdkRectangle* rectangle; GtkStyleContext* style; GdkRGBA bg; double h,s,v; double r,g,b; GSList* item; double line_width; GdkRectangle clip_area; viewport = INF_TEXT_GTK_VIEWPORT(user_data); priv = INF_TEXT_GTK_VIEWPORT_PRIVATE(viewport); /* Can this happen? */ if(!gtk_cairo_should_draw_window(cr, gtk_widget_get_window(scrollbar))) return FALSE; if(priv->show_user_markers) { style = gtk_widget_get_style_context(GTK_WIDGET(scrollbar)); gtk_style_context_save(style); gtk_style_context_add_class(style, GTK_STYLE_CLASS_VIEW); gtk_style_context_get_background_color(style, GTK_STATE_FLAG_NORMAL, &bg); gtk_style_context_restore(style); gtk_rgb_to_hsv(bg.red, bg.green, bg.blue, &h, &s, &v); s = MIN(MAX(s, 0.5), 0.8); v = MAX(v, 0.5); gtk_cairo_transform_to_window( cr, GTK_WIDGET(scrollbar), gtk_widget_get_window(scrollbar) ); gdk_cairo_get_clip_rectangle(cr, &clip_area); line_width = cairo_get_line_width(cr); for(item = priv->users; item != NULL; item = item->next) { viewport_user = (InfTextGtkViewportUser*)item->data; rectangle = &viewport_user->rectangle; if(gdk_rectangle_intersect(&clip_area, rectangle, NULL)) { h = inf_text_user_get_hue(viewport_user->user); cairo_rectangle( cr, rectangle->x + line_width/2, rectangle->y + line_width/2, rectangle->width - line_width, rectangle->height - line_width ); gtk_hsv_to_rgb(h, s, v/2.0, &r, &g, &b); cairo_set_source_rgba(cr, r, g, b, 0.6); cairo_stroke_preserve(cr); gtk_hsv_to_rgb(h, s, v, &r, &g, &b); cairo_set_source_rgba(cr, r, g, b, 0.6); cairo_fill(cr); } } } return FALSE; } static void inf_text_gtk_viewport_scrollbar_size_allocate_cb(GtkWidget* scrollbar, GtkAllocation* allocation, gpointer user_data) { InfTextGtkViewport* viewport; InfTextGtkViewportPrivate* priv; GSList* item; InfTextGtkViewportUser* viewport_user; viewport = INF_TEXT_GTK_VIEWPORT(user_data); priv = INF_TEXT_GTK_VIEWPORT_PRIVATE(viewport); for(item = priv->users; item != NULL; item = item->next) { viewport_user = (InfTextGtkViewportUser*)item->data; inf_text_gtk_viewport_user_invalidate_user_area(viewport_user); inf_text_gtk_viewport_user_compute_user_area(viewport_user); inf_text_gtk_viewport_user_invalidate_user_area(viewport_user); } } static void inf_text_gtk_viewport_adjustment_changed_cb(GtkAdjustment* adjustment, gpointer user_data) { InfTextGtkViewport* viewport; InfTextGtkViewportPrivate* priv; GSList* item; InfTextGtkViewportUser* viewport_user; viewport = INF_TEXT_GTK_VIEWPORT(user_data); priv = INF_TEXT_GTK_VIEWPORT_PRIVATE(viewport); for(item = priv->users; item != NULL; item = item->next) { viewport_user = (InfTextGtkViewportUser*)item->data; inf_text_gtk_viewport_user_invalidate_user_area(viewport_user); inf_text_gtk_viewport_user_compute_user_area(viewport_user); inf_text_gtk_viewport_user_invalidate_user_area(viewport_user); } } static void inf_text_gtk_viewport_scrollbar_style_updated_cb(GtkWidget* scrollbar, gpointer user_data) { InfTextGtkViewport* viewport; InfTextGtkViewportPrivate* priv; GSList* item; InfTextGtkViewportUser* viewport_user; viewport = INF_TEXT_GTK_VIEWPORT(user_data); priv = INF_TEXT_GTK_VIEWPORT_PRIVATE(viewport); for(item = priv->users; item != NULL; item = item->next) { viewport_user = (InfTextGtkViewportUser*)item->data; inf_text_gtk_viewport_user_invalidate_user_area(viewport_user); inf_text_gtk_viewport_user_compute_user_area(viewport_user); inf_text_gtk_viewport_user_invalidate_user_area(viewport_user); } } static void inf_text_gtk_viewport_user_selection_changed_cb(InfTextUser* user, guint position, gint length, gboolean by_request, gpointer user_data) { InfTextGtkViewportUser* viewport_user; InfTextGtkViewportPrivate* priv; viewport_user = (InfTextGtkViewportUser*)user_data; priv = INF_TEXT_GTK_VIEWPORT_PRIVATE(viewport_user->viewport); /* TODO: Just invalidate the region that really changed, by comparing * old and new rectangle's coordinates */ inf_text_gtk_viewport_user_invalidate_user_area(viewport_user); /* Recompute and revalidate */ inf_text_gtk_viewport_user_compute_user_area(viewport_user); inf_text_gtk_viewport_user_invalidate_user_area(viewport_user); } static void inf_text_gtk_viewport_user_notify_hue_cb(GObject* object, GParamSpec* pspec, gpointer user_data) { InfTextGtkViewportUser* viewport_user; InfTextGtkViewportPrivate* priv; viewport_user = (InfTextGtkViewportUser*)user_data; priv = INF_TEXT_GTK_VIEWPORT_PRIVATE(viewport_user->viewport); inf_text_gtk_viewport_user_invalidate_user_area(viewport_user); } static void inf_text_gtk_viewport_add_user(InfTextGtkViewport* viewport, InfTextUser* user) { InfTextGtkViewportPrivate* priv; InfTextGtkViewportUser* viewport_user; priv = INF_TEXT_GTK_VIEWPORT_PRIVATE(viewport); viewport_user = g_slice_new(InfTextGtkViewportUser); viewport_user->viewport = viewport; viewport_user->user = INF_TEXT_USER(user); priv->users = g_slist_prepend(priv->users, viewport_user); inf_text_gtk_viewport_user_compute_user_area(viewport_user); g_signal_connect_after( user, "selection-changed", G_CALLBACK(inf_text_gtk_viewport_user_selection_changed_cb), viewport_user ); g_signal_connect( user, "notify::hue", G_CALLBACK(inf_text_gtk_viewport_user_notify_hue_cb), viewport_user ); inf_text_gtk_viewport_user_invalidate_user_area(viewport_user); } static void inf_text_gtk_viewport_remove_user(InfTextGtkViewportUser* viewport_user) { InfTextGtkViewportPrivate* priv; priv = INF_TEXT_GTK_VIEWPORT_PRIVATE(viewport_user->viewport); inf_text_gtk_viewport_user_invalidate_user_area(viewport_user); inf_signal_handlers_disconnect_by_func( viewport_user->user, G_CALLBACK(inf_text_gtk_viewport_user_selection_changed_cb), viewport_user ); inf_signal_handlers_disconnect_by_func( viewport_user->user, G_CALLBACK(inf_text_gtk_viewport_user_notify_hue_cb), viewport_user ); priv->users = g_slist_remove(priv->users, viewport_user); g_slice_free(InfTextGtkViewportUser, viewport_user); } static void inf_text_gtk_viewport_user_notify_status_cb(GObject* object, GParamSpec* pspec, gpointer user_data) { InfTextGtkViewport* viewport; InfTextGtkViewportPrivate* priv; InfTextUser* user; InfTextGtkViewportUser* viewport_user; viewport = INF_TEXT_GTK_VIEWPORT(user_data); priv = INF_TEXT_GTK_VIEWPORT_PRIVATE(viewport); user = INF_TEXT_USER(object); g_assert(user != priv->active_user); viewport_user = inf_text_gtk_viewport_find_user(viewport, user); if(inf_user_get_status(INF_USER(user)) == INF_USER_ACTIVE) { if(!viewport_user) inf_text_gtk_viewport_add_user(viewport, user); } else { if(viewport_user) inf_text_gtk_viewport_remove_user(viewport_user); } } static void inf_text_gtk_viewport_user_removed(InfTextGtkViewport* viewport, InfTextUser* user) { InfTextGtkViewportPrivate* priv; InfTextGtkViewportUser* viewport_user; priv = INF_TEXT_GTK_VIEWPORT_PRIVATE(viewport); if(user == priv->active_user) { priv->active_user = NULL; g_object_notify(G_OBJECT(viewport), "active-user"); } else { inf_signal_handlers_disconnect_by_func( user, G_CALLBACK(inf_text_gtk_viewport_user_notify_status_cb), viewport ); if(inf_user_get_status(INF_USER(user)) == INF_USER_ACTIVE) { viewport_user = inf_text_gtk_viewport_find_user(viewport, user); g_assert(viewport_user != NULL); inf_text_gtk_viewport_remove_user(viewport_user); } } } static void inf_text_gtk_viewport_user_added(InfTextGtkViewport* viewport, InfTextUser* user) { InfTextGtkViewportPrivate* priv; priv = INF_TEXT_GTK_VIEWPORT_PRIVATE(viewport); /* Active user is guaranteed to be contained in user table, so if user was * just added then it can't be set as active user already. */ g_assert(user != priv->active_user); g_signal_connect( user, "notify::status", G_CALLBACK(inf_text_gtk_viewport_user_notify_status_cb), viewport ); if(inf_user_get_status(INF_USER(user)) == INF_USER_ACTIVE) inf_text_gtk_viewport_add_user(viewport, user); } static void inf_text_gtk_viewport_add_user_cb(InfUserTable* user_table, InfUser* user, gpointer user_data) { InfTextGtkViewport* viewport = INF_TEXT_GTK_VIEWPORT(user_data); g_assert(INF_TEXT_IS_USER(user)); inf_text_gtk_viewport_user_added(viewport, INF_TEXT_USER(user)); } static void inf_text_gtk_viewport_remove_user_cb(InfUserTable* user_table, InfUser* user, gpointer user_data) { InfTextGtkViewport* viewport = INF_TEXT_GTK_VIEWPORT(user_data); g_assert(INF_TEXT_IS_USER(user)); inf_text_gtk_viewport_user_removed(viewport, INF_TEXT_USER(user)); } static void inf_text_gtk_viewport_set_user_table_foreach_new_user_func(InfUser* user, gpointer user_data) { InfTextGtkViewport* viewport = INF_TEXT_GTK_VIEWPORT(user_data); g_assert(INF_TEXT_IS_USER(user)); inf_text_gtk_viewport_user_added(viewport, INF_TEXT_USER(user)); } static void inf_text_gtk_viewport_set_user_table_foreach_old_user_func(InfUser* user, gpointer user_data) { InfTextGtkViewport* viewport = INF_TEXT_GTK_VIEWPORT(user_data); g_assert(INF_TEXT_IS_USER(user)); inf_text_gtk_viewport_user_removed(viewport, INF_TEXT_USER(user)); } static void inf_text_gtk_viewport_set_scrolled_window(InfTextGtkViewport* viewport, GtkScrolledWindow* scroll) { InfTextGtkViewportPrivate* priv; GtkWidget* scrollbar; GtkAdjustment* adjustment; priv = INF_TEXT_GTK_VIEWPORT_PRIVATE(viewport); if(priv->scroll != NULL) { scrollbar = gtk_scrolled_window_get_vscrollbar(priv->scroll); /* Can already be unset at this point */ /* TODO: Should we catch that and unregister our signals before? OTOH it * is most likely going to be freed anyway... */ if(scrollbar != NULL) { adjustment = gtk_range_get_adjustment(GTK_RANGE(scrollbar)); g_assert(adjustment != NULL); inf_signal_handlers_disconnect_by_func( G_OBJECT(adjustment), G_CALLBACK(inf_text_gtk_viewport_adjustment_changed_cb), viewport ); inf_signal_handlers_disconnect_by_func( G_OBJECT(scrollbar), G_CALLBACK(inf_text_gtk_viewport_scrollbar_size_allocate_cb), viewport ); inf_signal_handlers_disconnect_by_func( G_OBJECT(scrollbar), G_CALLBACK(inf_text_gtk_viewport_scrollbar_style_updated_cb), viewport ); inf_signal_handlers_disconnect_by_func( G_OBJECT(scrollbar), G_CALLBACK(inf_text_gtk_viewport_scrollbar_draw_cb), viewport ); } g_object_unref(priv->scroll); } priv->scroll = scroll; if(scroll != NULL) { scrollbar = gtk_scrolled_window_get_vscrollbar(priv->scroll); /* TODO: can this happen? maybe for GTK_POLICY_NEVER? */ g_assert(scrollbar != NULL); adjustment = gtk_range_get_adjustment(GTK_RANGE(scrollbar)); g_assert(adjustment != NULL); g_object_ref(scroll); g_signal_connect_after( G_OBJECT(adjustment), "changed", G_CALLBACK(inf_text_gtk_viewport_adjustment_changed_cb), viewport ); g_signal_connect_after( G_OBJECT(scrollbar), "size-allocate", G_CALLBACK(inf_text_gtk_viewport_scrollbar_size_allocate_cb), viewport ); g_signal_connect_after( G_OBJECT(scrollbar), "style-updated", G_CALLBACK(inf_text_gtk_viewport_scrollbar_style_updated_cb), viewport ); g_signal_connect_after( G_OBJECT(scrollbar), "draw", G_CALLBACK(inf_text_gtk_viewport_scrollbar_draw_cb), viewport ); } g_object_notify(G_OBJECT(viewport), "scrolled-window"); } static void inf_text_gtk_viewport_set_user_table(InfTextGtkViewport* viewport, InfUserTable* user_table) { InfTextGtkViewportPrivate* priv; priv = INF_TEXT_GTK_VIEWPORT_PRIVATE(viewport); if(priv->user_table != NULL) { inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->user_table), G_CALLBACK(inf_text_gtk_viewport_add_user_cb), viewport ); inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->user_table), G_CALLBACK(inf_text_gtk_viewport_remove_user_cb), viewport ); inf_user_table_foreach_user( priv->user_table, inf_text_gtk_viewport_set_user_table_foreach_old_user_func, viewport ); g_object_unref(priv->user_table); } priv->user_table = user_table; if(user_table != NULL) { g_object_ref(user_table); g_signal_connect( G_OBJECT(user_table), "add-user", G_CALLBACK(inf_text_gtk_viewport_add_user_cb), viewport ); g_signal_connect( G_OBJECT(user_table), "remove-user", G_CALLBACK(inf_text_gtk_viewport_remove_user_cb), viewport ); inf_user_table_foreach_user( user_table, inf_text_gtk_viewport_set_user_table_foreach_new_user_func, viewport ); } g_object_notify(G_OBJECT(viewport), "user-table"); } static void inf_text_gtk_viewport_init(InfTextGtkViewport* viewport) { InfTextGtkViewportPrivate* priv; priv = INF_TEXT_GTK_VIEWPORT_PRIVATE(viewport); priv->scroll = NULL; priv->user_table = NULL; priv->active_user = NULL; priv->users = NULL; priv->show_user_markers = TRUE; } static void inf_text_gtk_viewport_dispose(GObject* object) { InfTextGtkViewport* viewport; InfTextGtkViewportPrivate* priv; viewport = INF_TEXT_GTK_VIEWPORT(object); priv = INF_TEXT_GTK_VIEWPORT_PRIVATE(viewport); inf_text_gtk_viewport_set_user_table(viewport, NULL); inf_text_gtk_viewport_set_scrolled_window(viewport, NULL); g_assert(priv->active_user == NULL); g_assert(priv->users == NULL); G_OBJECT_CLASS(inf_text_gtk_viewport_parent_class)->dispose(object); } static void inf_text_gtk_viewport_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfTextGtkViewport* viewport; InfTextGtkViewportPrivate* priv; viewport = INF_TEXT_GTK_VIEWPORT(object); priv = INF_TEXT_GTK_VIEWPORT_PRIVATE(viewport); switch(prop_id) { case PROP_SCROLLED_WINDOW: g_assert(priv->scroll == NULL); /* construct only */ inf_text_gtk_viewport_set_scrolled_window( viewport, GTK_SCROLLED_WINDOW(g_value_get_object(value)) ); break; case PROP_USER_TABLE: g_assert(priv->user_table == NULL); /* construct/only */ inf_text_gtk_viewport_set_user_table( viewport, INF_USER_TABLE(g_value_get_object(value)) ); break; case PROP_ACTIVE_USER: inf_text_gtk_viewport_set_active_user( viewport, INF_TEXT_USER(g_value_get_object(value)) ); break; case PROP_SHOW_USER_MARKERS: inf_text_gtk_viewport_set_show_user_markers( viewport, g_value_get_boolean(value) ); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(value, prop_id, pspec); break; } } static void inf_text_gtk_viewport_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfTextGtkViewport* viewport; InfTextGtkViewportPrivate* priv; viewport = INF_TEXT_GTK_VIEWPORT(object); priv = INF_TEXT_GTK_VIEWPORT_PRIVATE(viewport); switch(prop_id) { case PROP_SCROLLED_WINDOW: g_value_set_object(value, G_OBJECT(priv->scroll)); break; case PROP_USER_TABLE: g_value_set_object(value, G_OBJECT(priv->user_table)); break; case PROP_ACTIVE_USER: g_value_set_object(value, G_OBJECT(priv->active_user)); break; case PROP_SHOW_USER_MARKERS: g_value_set_boolean(value, priv->show_user_markers); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void inf_text_gtk_viewport_class_init(InfTextGtkViewportClass* viewport_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(viewport_class); object_class->dispose = inf_text_gtk_viewport_dispose; object_class->set_property = inf_text_gtk_viewport_set_property; object_class->get_property = inf_text_gtk_viewport_get_property; g_object_class_install_property( object_class, PROP_SCROLLED_WINDOW, g_param_spec_object( "scrolled-window", "Scrolled Window", "The underlying GtkScrolledWindow", GTK_TYPE_SCROLLED_WINDOW, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_USER_TABLE, g_param_spec_object( "user-table", "User table", "The user table containing the users of the session shown in the " "viewport", INF_TYPE_USER_TABLE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_ACTIVE_USER, g_param_spec_object( "active-user", "Active user", "The user for which to show the viewport", INF_TEXT_TYPE_USER, G_PARAM_READWRITE ) ); g_object_class_install_property( object_class, PROP_SHOW_USER_MARKERS, g_param_spec_boolean( "show-user-markers", "Show user markers", "Whether to indicate the position of non-local user's cursors in the " "scrollbar", TRUE, G_PARAM_READWRITE ) ); } /** * inf_text_gtk_viewport_new: (constructor) * @scroll: A #GtkScrolledWindow. * @user_table: The #InfUserTable for the text session displayed in @viewport. * * Creates a new #InfTextGtkViewport for @scroll. This draws the position of * remote user's cursors into the scrollbars of @scroll. * * Returns: (transfer full): A new #InfTextGtkViewport. */ InfTextGtkViewport* inf_text_gtk_viewport_new(GtkScrolledWindow* scroll, InfUserTable* user_table) { GObject* object; g_return_val_if_fail(GTK_IS_SCROLLED_WINDOW(scroll), NULL); g_return_val_if_fail(INF_IS_USER_TABLE(user_table), NULL); object = g_object_new( INF_TEXT_GTK_TYPE_VIEWPORT, "scrolled-window", scroll, "user-table", user_table, NULL ); return INF_TEXT_GTK_VIEWPORT(object); } /** * inf_text_gtk_viewport_get_scrolled_window: * @viewport: A #InfTextGtkViewport. * * Returns the underlying #GtkScrolledWindow. * * Returns: (transfer none): The #InfTextGtkViewport's #GtkScrolledWindow. **/ GtkScrolledWindow* inf_text_gtk_viewport_get_scrolled_window(InfTextGtkViewport* viewport) { g_return_val_if_fail(INF_TEXT_GTK_IS_VIEWPORT(viewport), NULL); return INF_TEXT_GTK_VIEWPORT_PRIVATE(viewport)->scroll; } /** * inf_text_gtk_viewport_get_user_table: * @viewport: A #InfTextGtkViewport. * * Returns the #InfUserTable containing the users of the session the * #InfTextGtkViewport's #GtkScrolledWindow is displaying. * * Returns: (transfer none): The #InfTextGtkViewport's #InfUserTable. */ InfUserTable* inf_text_gtk_viewport_get_user_table(InfTextGtkViewport* viewport) { g_return_val_if_fail(INF_TEXT_GTK_IS_VIEWPORT(viewport), NULL); return INF_TEXT_GTK_VIEWPORT_PRIVATE(viewport)->user_table; } /** * inf_text_gtk_viewport_set_active_user: * @viewport: A #InfTextGtkViewport. * @user: (allow-none): A user from @viewport's user table, or %NULL. * * Sets the user for which perspective to draw the viewport. The cursor * position for teh active user is not draws since it is assumed that the * viewport's "real" scrollbars match the active user's position. */ void inf_text_gtk_viewport_set_active_user(InfTextGtkViewport* viewport, InfTextUser* user) { InfTextGtkViewportPrivate* priv; InfTextUser* active_user; g_return_if_fail(INF_TEXT_GTK_IS_VIEWPORT(viewport)); g_return_if_fail(user == NULL || INF_TEXT_IS_USER(user)); priv = INF_TEXT_GTK_VIEWPORT_PRIVATE(viewport); g_return_if_fail( user == NULL || inf_user_table_lookup_user_by_id( priv->user_table, inf_user_get_id(INF_USER(user)) ) == INF_USER(user) ); if(priv->active_user != NULL) { active_user = priv->active_user; priv->active_user = NULL; inf_text_gtk_viewport_user_added(viewport, active_user); } if(user != NULL) { inf_text_gtk_viewport_user_removed(viewport, user); } priv->active_user = user; g_object_notify(G_OBJECT(viewport), "active-user"); } /** * inf_text_gtk_viewport_get_active_user: * @viewport: A #InfTextGtkViewport. * * Returns the active user of @viewport. See * inf_text_gtk_viewport_set_active_user(). * * Returns: (transfer none) (allow-none): The active user of @viewport. */ InfTextUser* inf_text_gtk_viewport_get_active_user(InfTextGtkViewport* viewport) { g_return_val_if_fail(INF_TEXT_GTK_IS_VIEWPORT(viewport), NULL); return INF_TEXT_GTK_VIEWPORT_PRIVATE(viewport)->active_user; } /** * inf_text_gtk_viewport_set_show_user_markers: * @viewport: A #InfTextGtkViewport. * @show: Whether to show the position of non-local users. * * If @show is %TRUE then draw a marker indicating the cursor position of all * non-local users with status %INF_USER_ACTIVE in the scrollbar of the * scrolled window. If @show is %FALSE then do not draw user markers into the * scrollbar. */ void inf_text_gtk_viewport_set_show_user_markers(InfTextGtkViewport* viewport, gboolean show) { InfTextGtkViewportPrivate* priv; g_return_if_fail(INF_TEXT_GTK_IS_VIEWPORT(viewport)); priv = INF_TEXT_GTK_VIEWPORT_PRIVATE(viewport); if(priv->show_user_markers != show) { gtk_widget_queue_draw(gtk_scrolled_window_get_vscrollbar(priv->scroll)); priv->show_user_markers = show; g_object_notify(G_OBJECT(viewport), "show-user-markers"); } } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinftextgtk/PaxHeaders.26529/inf-text-gtk-view.c0000644000000000000000000000013213034342512022113 xustar0030 mtime=1483851082.049718536 30 atime=1483851082.049718536 30 ctime=1488261589.400138191 libinfinity-0.7.1/libinftextgtk/inf-text-gtk-view.c0000644000175000017500000016221713034342512022656 0ustar00arminarmin00000000000000/* infinote - Collaborative notetaking application * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /** * SECTION:inf-text-gtk-view * @title: InfTextGtkView * @short_description: Drawing remote cursors and selections in a #GtkTextView * @include: libinftextgtk/inf-text-gtk-view.h * @see_also: #InfTextGtkBuffer, #InfTextGtkViewport * @stability: Unstable * * #InfTextGtkView is a helper object which, as long as it is alive, draws * the cursor position, selected text of remote users into a #GtkTextView * widget. It can also highlight the current line of a remote user in a * similar way the #GtkSourceView widget can highlight the current line of * the local user. * * This functionality was not implemented by subclassing #GtkTextView such * that it can also be used with existing subclasses, such as #GtkSourceView. * * With the function inf_text_gtk_view_set_active_user() the local * #InfTextUser who is editing the text can be set, if there is any. The * insertion position, seleceted text or current line are not drawn for this * user, since the normal #GtkTextView takes care of that already. This * assumes the local user cursor position and selection is synchronized to the * corresponding #InfTextUser properties, which is automatically the case when * a #InfTextGtkBuffer is used for the buffer the #GtkTextView is displaying. * * See #InfTextGtkViewport for drawing a marker at remote users' location into * the scrollbar. */ #include #include #include typedef struct _InfTextGtkViewUser InfTextGtkViewUser; struct _InfTextGtkViewUser { InfTextGtkView* view; InfTextUser* user; gboolean cursor_visible; InfIoTimeout* timeout; /* TODO: Use glib for that; remove InfIo property */ guint revalidate_idle; /* All in buffer coordinates: */ /* The rectangular area occupied by the cursor */ GdkRectangle cursor_rect; /* The position and height of the selection bound. width is ignored. */ GdkRectangle selection_bound_rect; /* Current line */ gint line_y; gint line_height; }; /* Helper struct for redrawing selection area */ typedef struct _InfTextGtkViewUserToggle InfTextGtkViewUserToggle; struct _InfTextGtkViewUserToggle { /* User toggled on or off at this point */ InfTextGtkViewUser* user; /* Position of the toggle */ guint pos; /* NULL if this toggles on, or the corresponding on * toggle if it toggles off. */ InfTextGtkViewUserToggle* on_toggle; /* Position in textview, in window coordinates */ gint x; gint y; }; typedef struct _InfTextGtkViewPrivate InfTextGtkViewPrivate; struct _InfTextGtkViewPrivate { InfIo* io; GtkTextView* textview; InfUserTable* user_table; InfTextUser* active_user; GSList* users; gboolean show_remote_cursors; gboolean show_remote_selections; gboolean show_remote_current_lines; }; enum { PROP_0, /* construct only */ PROP_IO, PROP_VIEW, PROP_USER_TABLE, /* read/write */ PROP_ACTIVE_USER, PROP_SHOW_REMOTE_CURSORS, PROP_SHOW_REMOTE_SELECTIONS, PROP_SHOW_REMOTE_CURRENT_LINES }; #define INF_TEXT_GTK_VIEW_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), INF_TEXT_GTK_TYPE_VIEW, InfTextGtkViewPrivate)) G_DEFINE_TYPE_WITH_CODE(InfTextGtkView, inf_text_gtk_view, G_TYPE_OBJECT, G_ADD_PRIVATE(InfTextGtkView)) static InfTextGtkViewUser* inf_text_gtk_view_find_user(InfTextGtkView* view, InfTextUser* user) { InfTextGtkViewPrivate* priv; GSList* item; priv = INF_TEXT_GTK_VIEW_PRIVATE(view); for(item = priv->users; item != NULL; item = item->next) if( ((InfTextGtkViewUser*)item->data)->user == user) return (InfTextGtkViewUser*)item->data; return NULL; } /* Compute cursor_rect, selection_bound_rect */ static void inf_text_gtk_view_user_compute_user_area(InfTextGtkViewUser* view_user) { InfTextGtkViewPrivate* priv; GtkTextIter iter; gfloat cursor_aspect_ratio; priv = INF_TEXT_GTK_VIEW_PRIVATE(view_user->view); gtk_widget_style_get( GTK_WIDGET(priv->textview), "cursor-aspect-ratio", &cursor_aspect_ratio, NULL ); gtk_text_buffer_get_iter_at_offset( gtk_text_view_get_buffer(priv->textview), &iter, inf_text_user_get_caret_position(view_user->user) ); /* Find current line */ gtk_text_view_get_line_yrange( priv->textview, &iter, &view_user->line_y, &view_user->line_height ); /* TODO: We don't need the cursor rect for show-remote-current-lines, and * we don't need the selection rect for show-remote-cursors and * show-remote-current-lines. So we might not even want to compute them in * if those are disabled. */ /* Find cursor position */ gtk_text_view_get_iter_location( priv->textview, &iter, &view_user->cursor_rect ); view_user->cursor_rect.width = MAX( (int)(view_user->cursor_rect.height * cursor_aspect_ratio), 1 ); /* Find selection bound */ gtk_text_iter_forward_chars( &iter, inf_text_user_get_selection_length(view_user->user) ); gtk_text_view_get_iter_location( priv->textview, &iter, &view_user->selection_bound_rect ); view_user->selection_bound_rect.width = MAX( (int)(view_user->selection_bound_rect.height * cursor_aspect_ratio), 1 ); } static guint inf_text_gtk_view_get_left_margin(GtkTextView* view) { GtkAdjustment* hadjustment; gint margin; gint hadj; hadjustment = gtk_scrollable_get_hadjustment(GTK_SCROLLABLE(view)); margin = gtk_text_view_get_left_margin(view); if(!hadjustment) return margin; hadj = gtk_adjustment_get_value(hadjustment); if(hadj < margin) return margin - hadj; return 0; } static guint inf_text_gtk_view_get_right_margin(GtkTextView* view) { GtkAdjustment* hadjustment; gint margin; gdouble hadj; gdouble hupper; gdouble hpage; hadjustment = gtk_scrollable_get_hadjustment(GTK_SCROLLABLE(view)); margin = gtk_text_view_get_right_margin(view); if(!hadjustment) return margin; /* TODO: I am not exactly sure where this +1 comes from, but it is required * so that the selection is aligned with the local selection at the right * margin. */ hadj = gtk_adjustment_get_value(hadjustment) + 1; g_object_get( G_OBJECT(hadjustment), "upper", &hupper, "page-size", &hpage, NULL ); if(hadj > hupper - hpage - margin) return margin - (gint)(hupper - hpage - hadj); return 0; } /* Invalidate the whole area of the textview covered by the given user: * cursor, selection, current line */ static void inf_text_gtk_view_user_invalidate_user_area(InfTextGtkViewUser* view_user) { InfTextGtkViewPrivate* priv; GdkWindow* window; GdkRectangle invalidate_rect; gint selection_bound_x; gint selection_bound_y; gint window_width; priv = INF_TEXT_GTK_VIEW_PRIVATE(view_user->view); if(gtk_widget_get_realized(GTK_WIDGET(priv->textview))) { /* Invalidate cursors/selections */ if(priv->show_remote_cursors || priv->show_remote_selections || priv->show_remote_current_lines) { window = gtk_text_view_get_window(priv->textview, GTK_TEXT_WINDOW_TEXT); window_width = gdk_window_get_width(window); gtk_text_view_buffer_to_window_coords( priv->textview, GTK_TEXT_WINDOW_TEXT, view_user->cursor_rect.x, view_user->cursor_rect.y, &invalidate_rect.x, &invalidate_rect.y ); invalidate_rect.width = view_user->cursor_rect.width; invalidate_rect.height = view_user->cursor_rect.height; /* Don't check for InfTextUser's selection length here so that clearing * a previous selection works. */ if(priv->show_remote_selections && (view_user->selection_bound_rect.x != view_user->cursor_rect.x || view_user->selection_bound_rect.y != view_user->cursor_rect.y)) { gtk_text_view_buffer_to_window_coords( priv->textview, GTK_TEXT_WINDOW_TEXT, view_user->selection_bound_rect.x, view_user->selection_bound_rect.y, &selection_bound_x, &selection_bound_y ); /* Invalidate the whole area between cursor and selection bound */ if(selection_bound_y == invalidate_rect.y) { /* Cursor and selection bound are on the same line */ if(selection_bound_x > invalidate_rect.x) { /* Selection bound is to the right of cursor */ invalidate_rect.width = MAX( selection_bound_x - invalidate_rect.x, invalidate_rect.width ); } else { /* Selection bound is to the left of cursor */ invalidate_rect.width += (invalidate_rect.x - selection_bound_x); invalidate_rect.x = selection_bound_x; } } else { /* Cursor and selection bound are on different lines. Could split * the actual area to be invalidated into three rectangles here, * but let's just do the union for simplicity reasons. */ invalidate_rect.width = window_width; invalidate_rect.height = MAX( invalidate_rect.y + invalidate_rect.height, selection_bound_y + view_user->selection_bound_rect.height ) - MIN(invalidate_rect.y, selection_bound_y); invalidate_rect.x = inf_text_gtk_view_get_left_margin(priv->textview); invalidate_rect.y = MIN(invalidate_rect.y, selection_bound_y); invalidate_rect.width -= inf_text_gtk_view_get_left_margin(priv->textview) + inf_text_gtk_view_get_right_margin(priv->textview); } gdk_window_invalidate_rect(window, &invalidate_rect, FALSE); } /* Invalidate current lines */ if(priv->show_remote_current_lines) { gtk_text_view_buffer_to_window_coords( priv->textview, GTK_TEXT_WINDOW_TEXT, 0, view_user->line_y, NULL, &invalidate_rect.y ); /* -1 to stay consistent with GtkSourceView */ invalidate_rect.x = inf_text_gtk_view_get_left_margin(priv->textview) - 1; invalidate_rect.width = window_width - invalidate_rect.x; invalidate_rect.height = view_user->line_height; } gdk_window_invalidate_rect(window, &invalidate_rect, FALSE); } } } static gint inf_text_gtk_view_user_line_position_cmp(gconstpointer first, gconstpointer second) { const InfTextGtkViewUser* first_user; const InfTextGtkViewUser* second_user; first_user = (const InfTextGtkViewUser*)first; second_user = (const InfTextGtkViewUser*)second; if(second_user->line_y < first_user->line_y) return 1; else if(second_user->line_y > first_user->line_y) return -1; return 0; } static gint inf_text_gtk_view_user_toggle_position_cmp(gconstpointer first, gconstpointer second, gpointer user_data) { const InfTextGtkViewUserToggle* first_toggle; const InfTextGtkViewUserToggle* second_toggle; first_toggle = (const InfTextGtkViewUserToggle*)first; second_toggle = (const InfTextGtkViewUserToggle*)second; if(second_toggle->pos < first_toggle->pos) return 1; else if(second_toggle->pos > first_toggle->pos) return -1; return 0; } static gint inf_text_gtk_view_user_toggle_user_cmp(gconstpointer first, gconstpointer second) { const InfTextGtkViewUserToggle* first_toggle; const InfTextGtkViewUserToggle* second_toggle; guint first_id; guint second_id; first_toggle = (const InfTextGtkViewUserToggle*)first; second_toggle = (const InfTextGtkViewUserToggle*)second; first_id = inf_user_get_id(INF_USER(first_toggle->user->user)); second_id = inf_user_get_id(INF_USER(second_toggle->user->user)); if(second_id < first_id) return 1; else if(second_id > first_id) return -1; return 0; } static void inf_text_gtk_view_user_toggle_free(gpointer data) { g_slice_free(InfTextGtkViewUserToggle, data); } static InfTextGtkViewUserToggle* inf_text_gtk_view_add_user_toggle(GSequence* sequence, guint position, InfTextGtkViewUser* user, InfTextGtkViewUserToggle* on_toggle, gint x, gint y) { InfTextGtkViewUserToggle* toggle; toggle = g_slice_new(InfTextGtkViewUserToggle); toggle->user = user; toggle->pos = position; toggle->on_toggle = on_toggle; toggle->x = x; toggle->y = y; g_sequence_insert_sorted( sequence, toggle, inf_text_gtk_view_user_toggle_position_cmp, NULL ); return toggle; } static void inf_text_gtk_view_add_user_toggle_pair(GSequence* sequence, guint begin, guint end, InfTextGtkViewUser* user, gint begin_x, gint begin_y, gint end_x, gint end_y) { InfTextGtkViewUserToggle* begin_toggle; g_assert(end > begin); begin_toggle = inf_text_gtk_view_add_user_toggle( sequence, begin, user, NULL, begin_x, begin_y ); inf_text_gtk_view_add_user_toggle( sequence, end, user, begin_toggle, end_x, end_y ); } static gboolean inf_text_gtk_view_draw_before_cb(GtkWidget* widget, cairo_t* cr, gpointer user_data) { InfTextGtkView* view; InfTextGtkViewPrivate* priv; GSList* item; GSList* prev_item; InfTextGtkViewUser* prev_user; InfTextGtkViewUser* view_user; GtkAdjustment* hadjustment; GtkAdjustment* vadjustment; GdkWindow *text_window; GtkStyleContext* style; GdkRGBA bg; double h, s, v; double r, g, b; GSList* sort_users; GdkRectangle rect; gint window_width; gint rx, ry; GdkRectangle clip_area; cairo_pattern_t* pattern; double n, n_users; cairo_matrix_t matrix; view = INF_TEXT_GTK_VIEW(user_data); priv = INF_TEXT_GTK_VIEW_PRIVATE(view); text_window = gtk_text_view_get_window(priv->textview, GTK_TEXT_WINDOW_TEXT); if(!gtk_cairo_should_draw_window(cr, text_window)) { return FALSE; } if(priv->show_remote_current_lines) { gtk_cairo_transform_to_window(cr, GTK_WIDGET(priv->textview), text_window); gdk_cairo_get_clip_rectangle(cr, &clip_area); window_width = gdk_window_get_width(text_window); /* Make current line color depend on background. */ style = gtk_widget_get_style_context(GTK_WIDGET(priv->textview)); gtk_style_context_save(style); gtk_style_context_add_class(style, GTK_STYLE_CLASS_VIEW); gtk_style_context_get_background_color(style, GTK_STATE_FLAG_NORMAL, &bg); gtk_style_context_restore(style); gtk_rgb_to_hsv(bg.red, bg.green, bg.blue, &h, &s, &v); v = MAX(v, 0.3); s = MAX(s, 0.1 + 0.3*(1 - v)); sort_users = g_slist_copy(priv->users); sort_users = g_slist_sort(sort_users, inf_text_gtk_view_user_line_position_cmp); prev_item = sort_users; if(prev_item) prev_user = (InfTextGtkViewUser*)prev_item->data; n_users = 1.0; for(item = sort_users; item != NULL; item = item->next, n_users += 1.0) { if(item->next == NULL || ((InfTextGtkViewUser*)item->next->data)->line_y != prev_user->line_y) { gtk_text_view_buffer_to_window_coords( priv->textview, GTK_TEXT_WINDOW_TEXT, 0, prev_user->line_y, NULL, &rect.y ); /* -1 to stay consistent with GtkSourceView */ rect.x = inf_text_gtk_view_get_left_margin(priv->textview) - 1; rect.width = window_width - rect.x; rect.height = prev_user->line_height; if(gdk_rectangle_intersect(&clip_area, &rect, NULL)) { hadjustment = gtk_scrollable_get_hadjustment(GTK_SCROLLABLE(priv->textview)); vadjustment = gtk_scrollable_get_vadjustment(GTK_SCROLLABLE(priv->textview)); /* Construct pattern */ rx = gtk_adjustment_get_value(vadjustment); ry = gtk_adjustment_get_value(hadjustment); pattern = cairo_pattern_create_linear(0, 0, 3.5*n_users, 3.5*n_users); cairo_matrix_init_translate(&matrix, rx, ry); cairo_pattern_set_matrix(pattern, &matrix); cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT); for(n = 0.0; prev_item != item->next; prev_item = prev_item->next, n += 1.0) { view_user = (InfTextGtkViewUser*)prev_item->data; h = inf_text_user_get_hue(view_user->user); gtk_hsv_to_rgb(h, s, v, &r, &g, &b); cairo_pattern_add_color_stop_rgb( pattern, n/n_users, r, g, b ); cairo_pattern_add_color_stop_rgb( pattern, (n+1.0)/n_users, r, g, b ); } cairo_set_source(cr, pattern); gdk_cairo_rectangle(cr, &rect); cairo_fill(cr); cairo_pattern_destroy(pattern); } prev_item = item->next; if(prev_item) prev_user = (InfTextGtkViewUser*)prev_item->data; n_users = 0.0; } } g_slist_free(sort_users); } return FALSE; } static gboolean inf_text_gtk_view_draw_after_cb(GtkWidget* widget, cairo_t* cr, gpointer user_data) { InfTextGtkView* view; InfTextGtkViewPrivate* priv; gint window_width; GtkStyleContext* style; GdkColor* cursor_color; GdkRGBA fg; double hc,sc,vc; double hs,ss,vs; GSList* item; InfTextGtkViewUser* view_user; double rc,gc,bc; double rs,gs,bs; GdkRectangle clip_area; gint ax, ay; GtkTextIter begin_iter; GtkTextIter end_iter; guint area_begin; guint area_end; guint own_sel_begin; guint own_sel_end; gint osbx, osby; gint osex, osey; gint sel; guint begin; guint end; GSequence* toggles; GSequenceIter* tog_iter; InfTextGtkViewUserToggle* cur_toggle; InfTextGtkViewUserToggle* prev_toggle; guint n_users; GSList* users; cairo_pattern_t* pattern; GtkAdjustment* hadjustment; GtkAdjustment* vadjustment; double n; cairo_matrix_t matrix; GdkRectangle rct; gint rx, ry; GdkWindow *text_window; view = INF_TEXT_GTK_VIEW(user_data); priv = INF_TEXT_GTK_VIEW_PRIVATE(view); text_window = gtk_text_view_get_window(priv->textview, GTK_TEXT_WINDOW_TEXT); if(!gtk_cairo_should_draw_window(cr, text_window)) { return FALSE; } gtk_cairo_transform_to_window(cr, GTK_WIDGET(priv->textview), text_window); gdk_cairo_get_clip_rectangle(cr, &clip_area); style = gtk_widget_get_style_context(GTK_WIDGET(priv->textview)); gtk_style_context_save(style); gtk_style_context_add_class(style, GTK_STYLE_CLASS_VIEW); gtk_style_context_get_color(style, GTK_STATE_FLAG_NORMAL, &fg); gtk_style_context_restore(style); if(priv->show_remote_selections) { window_width = gdk_window_get_width(text_window); /* Make selection color based on text color: If text is dark, selection * is dark, if text is bright selection is bright. Note that we draw with * 50% alpha only, so text remains readable. */ gtk_rgb_to_hsv(fg.red, fg.green, fg.blue, &hs, &ss, &vs); vs = MAX(vs, 0.5); ss = 1.0 - 0.4*(vs); /* Find range of text to be updated */ gtk_text_view_window_to_buffer_coords( priv->textview, GTK_TEXT_WINDOW_TEXT, clip_area.x, clip_area.y, &ax, &ay ); gtk_text_view_get_iter_at_location( priv->textview, &begin_iter, ax, ay ); gtk_text_view_get_iter_at_location( priv->textview, &end_iter, ax + clip_area.width, ay + clip_area.height ); area_begin = gtk_text_iter_get_offset(&begin_iter); area_end = gtk_text_iter_get_offset(&end_iter); g_assert(area_end >= area_begin); /* Find own selection (we don't draw remote * selections over own selection). */ gtk_text_buffer_get_selection_bounds( gtk_text_view_get_buffer(priv->textview), &begin_iter, &end_iter ); own_sel_begin = gtk_text_iter_get_offset(&begin_iter); own_sel_end = gtk_text_iter_get_offset(&end_iter); if(own_sel_begin != own_sel_end) { gtk_text_view_get_iter_location(priv->textview, &begin_iter, &rct); gtk_text_view_buffer_to_window_coords( priv->textview, GTK_TEXT_WINDOW_TEXT, rct.x, rct.y, &osbx, &osby ); gtk_text_view_get_iter_location(priv->textview, &end_iter, &rct); gtk_text_view_buffer_to_window_coords( priv->textview, GTK_TEXT_WINDOW_TEXT, rct.x, rct.y, &osex, &osey ); } /* Build toggle list */ toggles = g_sequence_new(inf_text_gtk_view_user_toggle_free); for(item = priv->users; item != NULL; item = item->next) { view_user = (InfTextGtkViewUser*)item->data; if(inf_text_user_get_selection_length(view_user->user) != 0) { begin = inf_text_user_get_caret_position(view_user->user); sel = inf_text_user_get_selection_length(view_user->user); if(sel > 0) { end = begin + sel; } else { g_assert(begin >= (unsigned int)-sel); end = begin; begin += sel; } /* This can happen if the document is not yet fully loaded, i.e. synchronization * is still in progress. */ if(begin > gtk_text_buffer_get_char_count(gtk_text_view_get_buffer(priv->textview))) begin = gtk_text_buffer_get_char_count(gtk_text_view_get_buffer(priv->textview)); if(end > gtk_text_buffer_get_char_count(gtk_text_view_get_buffer(priv->textview))) end = gtk_text_buffer_get_char_count(gtk_text_view_get_buffer(priv->textview)); begin = MIN(MAX(begin, area_begin), area_end); end = MIN(MAX(end, area_begin), area_end); g_assert(end >= begin); if(begin != end) { if(sel > 0) { gtk_text_view_buffer_to_window_coords( priv->textview, GTK_TEXT_WINDOW_TEXT, view_user->cursor_rect.x, view_user->cursor_rect.y, &rx, &ry ); gtk_text_view_buffer_to_window_coords( priv->textview, GTK_TEXT_WINDOW_TEXT, view_user->selection_bound_rect.x, view_user->selection_bound_rect.y, &ax, &ay ); } else { gtk_text_view_buffer_to_window_coords( priv->textview, GTK_TEXT_WINDOW_TEXT, view_user->selection_bound_rect.x, view_user->selection_bound_rect.y, &rx, &ry ); gtk_text_view_buffer_to_window_coords( priv->textview, GTK_TEXT_WINDOW_TEXT, view_user->cursor_rect.x, view_user->cursor_rect.y, &ax, &ay ); } if(own_sel_begin == own_sel_end || own_sel_end <= begin || own_sel_begin >= end) { /* Local selection and remote selection do not overlap */ inf_text_gtk_view_add_user_toggle_pair( toggles, begin, end, view_user, rx, ry, ax, ay ); } else if(own_sel_begin <= begin && own_sel_end >= end) { /* Whole remote selection is covered by local selection */ } else if(own_sel_begin > begin && own_sel_end >= end) { /* Last part of remote selection is covered by local selection */ inf_text_gtk_view_add_user_toggle_pair( toggles, begin, own_sel_begin, view_user, rx, ry, osbx, osby ); } else if(own_sel_begin <= begin && own_sel_end < end) { /* First part of remote selection is covered by local selection */ inf_text_gtk_view_add_user_toggle_pair( toggles, own_sel_end, end, view_user, osex, osey, ax, ay ); } else if(own_sel_begin > begin && own_sel_end < end) { /* Local selection is in middle of remote selection */ inf_text_gtk_view_add_user_toggle_pair( toggles, begin, own_sel_begin, view_user, rx, ry, osbx, osby ); inf_text_gtk_view_add_user_toggle_pair( toggles, own_sel_end, end, view_user, osex, osey, ax, ay ); } else { g_assert_not_reached(); } } } } /* Walk toggle list, draw selections */ tog_iter = g_sequence_get_begin_iter(toggles); cur_toggle = NULL; prev_toggle = NULL; users = NULL; n_users = 0; tog_iter = g_sequence_get_begin_iter(toggles); while(!g_sequence_iter_is_end(tog_iter)) { cur_toggle = (InfTextGtkViewUserToggle*)g_sequence_get(tog_iter); /* Draw users from prev_toggle to cur_toggle */ if(users != NULL) { g_assert(prev_toggle != NULL); g_assert(n_users > 0); hadjustment = gtk_scrollable_get_hadjustment(GTK_SCROLLABLE(priv->textview)); vadjustment = gtk_scrollable_get_vadjustment(GTK_SCROLLABLE(priv->textview)); /* Construct pattern */ rx = gtk_adjustment_get_value(hadjustment); ry = gtk_adjustment_get_value(vadjustment); pattern = cairo_pattern_create_linear(0, 0, 3.5*n_users, 3.5*n_users); cairo_matrix_init_translate(&matrix, rx, ry); cairo_pattern_set_matrix(pattern, &matrix); cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT); for(item = users, n = 0.0; item != NULL; item = item->next, n += 1.0) { view_user = ((InfTextGtkViewUserToggle*)item->data)->user; hs = inf_text_user_get_hue(view_user->user); gtk_hsv_to_rgb(hs, ss, vs, &rs, &gs, &bs); cairo_pattern_add_color_stop_rgba( pattern, n/n_users, rs, gs, bs, 0.5 ); cairo_pattern_add_color_stop_rgba( pattern, (n+1.0)/n_users, rs, gs, bs, 0.5 ); } cairo_set_source(cr, pattern); if(prev_toggle->y == cur_toggle->y) { /* same line */ g_assert(prev_toggle->x < cur_toggle->x); rct.x = prev_toggle->x; rct.y = prev_toggle->y; rct.width = cur_toggle->x - prev_toggle->x; rct.height = cur_toggle->user->selection_bound_rect.height; gdk_cairo_rectangle(cr, &rct); } else { g_assert( cur_toggle->y - prev_toggle->y >= cur_toggle->user->selection_bound_rect.height ); /* multiple lines */ if(window_width > prev_toggle->x) { /* first line */ rct.x = prev_toggle->x; rct.y = prev_toggle->y; rct.width = window_width - prev_toggle->x - inf_text_gtk_view_get_right_margin(priv->textview); rct.height = prev_toggle->user->selection_bound_rect.height; gdk_cairo_rectangle(cr, &rct); } if(cur_toggle->x > 0) { /* last line */ rct.x = inf_text_gtk_view_get_left_margin(priv->textview); rct.y = cur_toggle->y; rct.width = cur_toggle->x - rct.x; rct.height = cur_toggle->user->selection_bound_rect.height; gdk_cairo_rectangle(cr, &rct); } if(cur_toggle->y - prev_toggle->y > cur_toggle->user->selection_bound_rect.height) { /* intermediate */ rct.x = inf_text_gtk_view_get_left_margin(priv->textview); rct.y = prev_toggle->y + prev_toggle->user->selection_bound_rect.height; rct.width = window_width - rct.x - inf_text_gtk_view_get_right_margin(priv->textview); rct.height = cur_toggle->y - prev_toggle->y - cur_toggle->user->selection_bound_rect.height; gdk_cairo_rectangle(cr, &rct); } } cairo_fill(cr); cairo_pattern_destroy(pattern); } prev_toggle = cur_toggle; /* advance to next position, toggle users on/off while doing so */ do { if(cur_toggle->on_toggle == NULL) { /* Keep toggles in user list sorted by user ID, so that the same * users generate the same pattern */ users = g_slist_insert_sorted( users, cur_toggle, inf_text_gtk_view_user_toggle_user_cmp ); ++n_users; } else { g_assert(n_users > 0); users = g_slist_remove(users, cur_toggle->on_toggle); --n_users; } tog_iter = g_sequence_iter_next(tog_iter); if(g_sequence_iter_is_end(tog_iter)) break; cur_toggle = (InfTextGtkViewUserToggle*)g_sequence_get(tog_iter); } while(cur_toggle->pos == prev_toggle->pos); } g_assert(n_users == 0); g_assert(users == NULL); g_sequence_free(toggles); } if(priv->show_remote_cursors) { gtk_widget_style_get (widget, "cursor-color", &cursor_color, NULL); if(cursor_color != NULL) { rc = cursor_color->red / 65535.0; bc = cursor_color->green / 65535.0; gc = cursor_color->blue / 65535.0; gdk_color_free(cursor_color); } else { rc = fg.red; bc = fg.green; gc = fg.blue; } gtk_rgb_to_hsv(rc, bc, gc, &hc, &sc, &vc); sc = MIN(MAX(sc, 0.3), 0.8); vc = MAX(vc, 0.7); for(item = priv->users; item != NULL; item = item->next) { view_user = (InfTextGtkViewUser*)item->data; if(view_user->cursor_visible) { gtk_text_view_buffer_to_window_coords( priv->textview, GTK_TEXT_WINDOW_TEXT, view_user->cursor_rect.x, view_user->cursor_rect.y, &rct.x, &rct.y ); rct.width = view_user->cursor_rect.width; rct.height = view_user->cursor_rect.height; if(gdk_rectangle_intersect(&clip_area, &rct, NULL)) { hc = inf_text_user_get_hue(view_user->user); gtk_hsv_to_rgb(hc, sc, vc, &rc, &gc, &bc); cairo_set_source_rgb(cr, rc, gc, bc); gdk_cairo_rectangle(cr, &rct); cairo_fill(cr); } } } } return FALSE; } static void inf_text_gtk_view_style_updated_cb(GtkWidget* widget, gpointer user_data) { InfTextGtkView* view; InfTextGtkViewPrivate* priv; GSList* item; InfTextGtkViewUser* view_user; view = INF_TEXT_GTK_VIEW(user_data); priv = INF_TEXT_GTK_VIEW_PRIVATE(view); for(item = priv->users; item != NULL; item = item->next) { view_user = (InfTextGtkViewUser*)item->data; inf_text_gtk_view_user_compute_user_area(view_user); } } static void inf_text_gtk_view_size_allocate_cb(GtkWidget* widget, GtkAllocation* allocation, gpointer user_data) { InfTextGtkView* view; InfTextGtkViewPrivate* priv; GSList* item; InfTextGtkViewUser* view_user; view = INF_TEXT_GTK_VIEW(user_data); priv = INF_TEXT_GTK_VIEW_PRIVATE(view); for(item = priv->users; item != NULL; item = item->next) { view_user = (InfTextGtkViewUser*)item->data; inf_text_gtk_view_user_compute_user_area(view_user); } } static void inf_text_gtk_view_user_cursor_blink_timeout_func(gpointer user_data) { InfTextGtkViewUser* view_user; InfTextGtkViewPrivate* priv; GtkSettings* settings; gboolean cursor_blink; gint cursor_blink_time; view_user = (InfTextGtkViewUser*)user_data; priv = INF_TEXT_GTK_VIEW_PRIVATE(view_user->view); view_user->cursor_visible = !view_user->cursor_visible; inf_text_gtk_view_user_invalidate_user_area(view_user); /* Schedule next cursor blink */ settings = gtk_widget_get_settings(GTK_WIDGET(priv->textview)); /* TODO: Handle gtk-cursor-blink-timeout */ g_object_get( G_OBJECT(settings), "gtk-cursor-blink", &cursor_blink, "gtk-cursor-blink-time", &cursor_blink_time, NULL ); if(cursor_blink) { if(!view_user->cursor_visible) cursor_blink_time = cursor_blink_time * 1 / 3; else cursor_blink_time = cursor_blink_time * 2 / 3; view_user->timeout = inf_io_add_timeout( priv->io, cursor_blink_time, inf_text_gtk_view_user_cursor_blink_timeout_func, view_user, NULL ); } else { view_user->timeout = NULL; } } static void inf_text_gtk_view_user_reset_timeout(InfTextGtkViewUser* view_user) { InfTextGtkViewPrivate* priv; GtkSettings* settings; gboolean cursor_blink; gint cursor_blink_time; priv = INF_TEXT_GTK_VIEW_PRIVATE(view_user->view); if(view_user->timeout) { inf_io_remove_timeout(priv->io, view_user->timeout); view_user->timeout = NULL; } if(!view_user->cursor_visible) { view_user->cursor_visible = TRUE; /* TODO: Only need to invalidate cursor rect, not whole user area */ inf_text_gtk_view_user_invalidate_user_area(view_user); } settings = gtk_widget_get_settings(GTK_WIDGET(priv->textview)); /* TODO: Reschedule timeout if these settings change */ g_object_get( G_OBJECT(settings), "gtk-cursor-blink", &cursor_blink, "gtk-cursor-blink-time", &cursor_blink_time, NULL ); if(cursor_blink) { view_user->timeout = inf_io_add_timeout( priv->io, cursor_blink_time, inf_text_gtk_view_user_cursor_blink_timeout_func, view_user, NULL ); } } static gboolean inf_text_gtk_view_user_selection_changed_cb_idle_func(gpointer user_data) { InfTextGtkViewUser* view_user; view_user = (InfTextGtkViewUser*)user_data; g_assert(view_user->revalidate_idle != 0); view_user->revalidate_idle = 0; /* Revalidate */ inf_text_gtk_view_user_invalidate_user_area(view_user); return FALSE; } static void inf_text_gtk_view_user_selection_changed_cb(InfTextUser* user, guint position, gint length, gboolean by_request, gpointer user_data) { InfTextGtkViewUser* view_user; InfTextGtkViewPrivate* priv; view_user = (InfTextGtkViewUser*)user_data; priv = INF_TEXT_GTK_VIEW_PRIVATE(view_user->view); /* We don't need to invalidate areas if the change was not made by a user * request. So for example if someone's cursor moved because another user * has inserted text somewhere before it, then we don't need to redraw that * cursor since it either: * a) was shifted to the right, in which case the underlying text was also * shifted and is therefore invalidated anyway. * b) Both text and cursor have not been shifted, no redraw necessary. * Note that we need to recompute the user area though because it might * have moved. */ if(by_request) { /* Invalidate current user area, e.g. to get rid of cursor at previous * location if it moved, or if the selection area was shrinked. */ /* TODO: Not sure whether this also needs to go to the idle handler... * if so make sure it is executed even if the viewuser is deleted in the * meanwhile. */ inf_text_gtk_view_user_invalidate_user_area(view_user); } inf_text_gtk_view_user_compute_user_area(view_user); if(by_request) { inf_text_gtk_view_user_reset_timeout(view_user); /* We can't invalidate here because * gtk_text_view_buffer_to_window_coords() does not give correct * coordinates at this point. We need to wait for the textview to * revalidate onscreen lines first (which it does in an idle handler, * note higher numbers indicate less priority). */ if(view_user->revalidate_idle == 0) { view_user->revalidate_idle = g_idle_add_full( GTK_TEXT_VIEW_PRIORITY_VALIDATE + 1, inf_text_gtk_view_user_selection_changed_cb_idle_func, view_user, NULL ); } } } static void inf_text_gtk_view_user_notify_hue_cb(GObject* object, GParamSpec* pspec, gpointer user_data) { InfTextGtkViewUser* view_user; InfTextGtkViewPrivate* priv; view_user = (InfTextGtkViewUser*)user_data; priv = INF_TEXT_GTK_VIEW_PRIVATE(view_user->view); /* TODO: Might restrict this on current lines, * cursor rects and selection rects */ gtk_widget_queue_draw(GTK_WIDGET(priv->textview)); } static void inf_text_gtk_view_add_user(InfTextGtkView* view, InfTextUser* user) { InfTextGtkViewPrivate* priv; InfTextGtkViewUser* view_user; priv = INF_TEXT_GTK_VIEW_PRIVATE(view); view_user = g_slice_new(InfTextGtkViewUser); view_user->view = view; view_user->user = INF_TEXT_USER(user); view_user->cursor_visible = TRUE; view_user->timeout = NULL; view_user->revalidate_idle = 0; inf_text_gtk_view_user_compute_user_area(view_user); inf_text_gtk_view_user_reset_timeout(view_user); priv->users = g_slist_prepend(priv->users, view_user); g_signal_connect_after( user, "selection-changed", G_CALLBACK(inf_text_gtk_view_user_selection_changed_cb), view_user ); g_signal_connect( user, "notify::hue", G_CALLBACK(inf_text_gtk_view_user_notify_hue_cb), view_user ); inf_text_gtk_view_user_invalidate_user_area(view_user); } static void inf_text_gtk_view_remove_user(InfTextGtkViewUser* view_user) { InfTextGtkViewPrivate* priv; priv = INF_TEXT_GTK_VIEW_PRIVATE(view_user->view); inf_signal_handlers_disconnect_by_func( view_user->user, G_CALLBACK(inf_text_gtk_view_user_selection_changed_cb), view_user ); inf_signal_handlers_disconnect_by_func( view_user->user, G_CALLBACK(inf_text_gtk_view_user_notify_hue_cb), view_user ); if(view_user->timeout != NULL) inf_io_remove_timeout(priv->io, view_user->timeout); if(view_user->revalidate_idle != 0) g_source_remove(view_user->revalidate_idle); inf_text_gtk_view_user_invalidate_user_area(view_user); priv->users = g_slist_remove(priv->users, view_user); g_slice_free(InfTextGtkViewUser, view_user); } static void inf_text_gtk_view_user_notify_status_cb(GObject* object, GParamSpec* pspec, gpointer user_data) { InfTextGtkView* view; InfTextGtkViewPrivate* priv; InfTextUser* user; InfTextGtkViewUser* view_user; view = INF_TEXT_GTK_VIEW(user_data); priv = INF_TEXT_GTK_VIEW_PRIVATE(view); user = INF_TEXT_USER(object); g_assert(user != priv->active_user); view_user = inf_text_gtk_view_find_user(view, user); if(inf_user_get_status(INF_USER(user)) == INF_USER_ACTIVE) { if(!view_user) inf_text_gtk_view_add_user(view, user); } else { if(view_user) inf_text_gtk_view_remove_user(view_user); } } static void inf_text_gtk_view_user_removed(InfTextGtkView* view, InfTextUser* user) { InfTextGtkViewPrivate* priv; InfTextGtkViewUser* view_user; priv = INF_TEXT_GTK_VIEW_PRIVATE(view); if(user == priv->active_user) { priv->active_user = NULL; g_object_notify(G_OBJECT(view), "active-user"); } else { inf_signal_handlers_disconnect_by_func( user, G_CALLBACK(inf_text_gtk_view_user_notify_status_cb), view ); if(inf_user_get_status(INF_USER(user)) == INF_USER_ACTIVE) { view_user = inf_text_gtk_view_find_user(view, user); g_assert(view_user != NULL); inf_text_gtk_view_remove_user(view_user); } } } static void inf_text_gtk_view_user_added(InfTextGtkView* view, InfTextUser* user) { InfTextGtkViewPrivate* priv; priv = INF_TEXT_GTK_VIEW_PRIVATE(view); /* Active user is guaranteed to be contained in user table, so if user was * just added then it can't be set as active user already. */ g_assert(user != priv->active_user); g_signal_connect( user, "notify::status", G_CALLBACK(inf_text_gtk_view_user_notify_status_cb), view ); if(inf_user_get_status(INF_USER(user)) == INF_USER_ACTIVE) inf_text_gtk_view_add_user(view, user); } static void inf_text_gtk_view_add_user_cb(InfUserTable* user_table, InfUser* user, gpointer user_data) { InfTextGtkView* view = INF_TEXT_GTK_VIEW(user_data); g_assert(INF_TEXT_IS_USER(user)); inf_text_gtk_view_user_added(view, INF_TEXT_USER(user)); } static void inf_text_gtk_view_remove_user_cb(InfUserTable* user_table, InfUser* user, gpointer user_data) { InfTextGtkView* view = INF_TEXT_GTK_VIEW(user_data); g_assert(INF_TEXT_IS_USER(user)); inf_text_gtk_view_user_removed(view, INF_TEXT_USER(user)); } static void inf_text_gtk_view_set_user_table_foreach_new_user_func(InfUser* user, gpointer user_data) { InfTextGtkView* view = INF_TEXT_GTK_VIEW(user_data); g_assert(INF_TEXT_IS_USER(user)); inf_text_gtk_view_user_added(view, INF_TEXT_USER(user)); } static void inf_text_gtk_view_set_user_table_foreach_old_user_func(InfUser* user, gpointer user_data) { InfTextGtkView* view = INF_TEXT_GTK_VIEW(user_data); g_assert(INF_TEXT_IS_USER(user)); inf_text_gtk_view_user_removed(view, INF_TEXT_USER(user)); } static void inf_text_gtk_view_set_view(InfTextGtkView* view, GtkTextView* gtk_view) { InfTextGtkViewPrivate* priv; priv = INF_TEXT_GTK_VIEW_PRIVATE(view); if(priv->textview != NULL) { inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->textview), G_CALLBACK(inf_text_gtk_view_draw_before_cb), view ); inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->textview), G_CALLBACK(inf_text_gtk_view_draw_after_cb), view ); inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->textview), G_CALLBACK(inf_text_gtk_view_style_updated_cb), view ); inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->textview), G_CALLBACK(inf_text_gtk_view_size_allocate_cb), view ); g_object_unref(priv->textview); } priv->textview = gtk_view; if(gtk_view != NULL) { g_object_ref(gtk_view); g_signal_connect( G_OBJECT(gtk_view), "draw", G_CALLBACK(inf_text_gtk_view_draw_before_cb), view ); g_signal_connect_after( G_OBJECT(gtk_view), "draw", G_CALLBACK(inf_text_gtk_view_draw_after_cb), view ); g_signal_connect_after( G_OBJECT(gtk_view), "style-updated", G_CALLBACK(inf_text_gtk_view_style_updated_cb), view ); /* This is required for the remote cursors showing up at the correct * position initially. Maybe gtk_text_view_get_iter_location() seems to * return junk before. Note that also style-updated is not enough. */ g_signal_connect_after( G_OBJECT(gtk_view), "size-allocate", G_CALLBACK(inf_text_gtk_view_size_allocate_cb), view ); } g_object_notify(G_OBJECT(view), "view"); } static void inf_text_gtk_view_set_user_table(InfTextGtkView* view, InfUserTable* user_table) { InfTextGtkViewPrivate* priv; priv = INF_TEXT_GTK_VIEW_PRIVATE(view); if(priv->user_table != NULL) { inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->user_table), G_CALLBACK(inf_text_gtk_view_add_user_cb), view ); inf_signal_handlers_disconnect_by_func( G_OBJECT(priv->user_table), G_CALLBACK(inf_text_gtk_view_remove_user_cb), view ); inf_user_table_foreach_user( priv->user_table, inf_text_gtk_view_set_user_table_foreach_old_user_func, view ); g_object_unref(priv->user_table); } priv->user_table = user_table; if(user_table != NULL) { g_object_ref(user_table); g_signal_connect( G_OBJECT(user_table), "add-user", G_CALLBACK(inf_text_gtk_view_add_user_cb), view ); g_signal_connect( G_OBJECT(user_table), "remove-user", G_CALLBACK(inf_text_gtk_view_remove_user_cb), view ); inf_user_table_foreach_user( user_table, inf_text_gtk_view_set_user_table_foreach_new_user_func, view ); } g_object_notify(G_OBJECT(view), "user-table"); } static void inf_text_gtk_view_init(InfTextGtkView* view) { InfTextGtkViewPrivate* priv; priv = INF_TEXT_GTK_VIEW_PRIVATE(view); priv->io = NULL; priv->textview = NULL; priv->user_table = NULL; priv->active_user = NULL; priv->users = NULL; priv->show_remote_cursors = TRUE; priv->show_remote_selections = TRUE; priv->show_remote_current_lines = TRUE; } static void inf_text_gtk_view_dispose(GObject* object) { InfTextGtkView* view; InfTextGtkViewPrivate* priv; view = INF_TEXT_GTK_VIEW(object); priv = INF_TEXT_GTK_VIEW_PRIVATE(view); inf_text_gtk_view_set_user_table(view, NULL); inf_text_gtk_view_set_view(view, NULL); g_assert(priv->active_user == NULL); g_assert(priv->users == NULL); if(priv->io != NULL) { g_object_unref(priv->io); priv->io = NULL; } G_OBJECT_CLASS(inf_text_gtk_view_parent_class)->dispose(object); } static void inf_text_gtk_view_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) { InfTextGtkView* view; InfTextGtkViewPrivate* priv; view = INF_TEXT_GTK_VIEW(object); priv = INF_TEXT_GTK_VIEW_PRIVATE(view); switch(prop_id) { case PROP_IO: g_assert(priv->io == NULL); /* construct only */ priv->io = INF_IO(g_value_dup_object(value)); break; case PROP_VIEW: g_assert(priv->textview == NULL); /* construct only */ inf_text_gtk_view_set_view( view, GTK_TEXT_VIEW(g_value_get_object(value)) ); break; case PROP_USER_TABLE: g_assert(priv->user_table == NULL); /* construct/only */ inf_text_gtk_view_set_user_table( view, INF_USER_TABLE(g_value_get_object(value)) ); break; case PROP_ACTIVE_USER: inf_text_gtk_view_set_active_user( view, INF_TEXT_USER(g_value_get_object(value)) ); break; case PROP_SHOW_REMOTE_CURSORS: inf_text_gtk_view_set_show_remote_cursors( view, g_value_get_boolean(value) ); break; case PROP_SHOW_REMOTE_SELECTIONS: inf_text_gtk_view_set_show_remote_selections( view, g_value_get_boolean(value) ); break; case PROP_SHOW_REMOTE_CURRENT_LINES: inf_text_gtk_view_set_show_remote_current_lines( view, g_value_get_boolean(value) ); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(value, prop_id, pspec); break; } } static void inf_text_gtk_view_get_property(GObject* object, guint prop_id, GValue* value, GParamSpec* pspec) { InfTextGtkView* view; InfTextGtkViewPrivate* priv; view = INF_TEXT_GTK_VIEW(object); priv = INF_TEXT_GTK_VIEW_PRIVATE(view); switch(prop_id) { case PROP_IO: g_value_set_object(value, G_OBJECT(priv->io)); break; case PROP_VIEW: g_value_set_object(value, G_OBJECT(priv->textview)); break; case PROP_USER_TABLE: g_value_set_object(value, G_OBJECT(priv->user_table)); break; case PROP_ACTIVE_USER: g_value_set_object(value, G_OBJECT(priv->active_user)); break; case PROP_SHOW_REMOTE_CURSORS: g_value_set_boolean(value, priv->show_remote_cursors); break; case PROP_SHOW_REMOTE_SELECTIONS: g_value_set_boolean(value, priv->show_remote_selections); break; case PROP_SHOW_REMOTE_CURRENT_LINES: g_value_set_boolean(value, priv->show_remote_current_lines); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void inf_text_gtk_view_class_init(InfTextGtkViewClass* view_class) { GObjectClass* object_class; object_class = G_OBJECT_CLASS(view_class); object_class->dispose = inf_text_gtk_view_dispose; object_class->set_property = inf_text_gtk_view_set_property; object_class->get_property = inf_text_gtk_view_get_property; g_object_class_install_property( object_class, PROP_IO, g_param_spec_object( "io", "IO", "The IO object to schedule timeouts", INF_TYPE_IO, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_VIEW, g_param_spec_object( "view", "View", "The underlying GtkTextView", GTK_TYPE_TEXT_VIEW, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_USER_TABLE, g_param_spec_object( "user-table", "User table", "The user table containing the users of the session shown in the view", INF_TYPE_USER_TABLE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY ) ); g_object_class_install_property( object_class, PROP_ACTIVE_USER, g_param_spec_object( "active-user", "Active user", "The user for which to show the view", INF_TEXT_TYPE_USER, G_PARAM_READWRITE ) ); g_object_class_install_property( object_class, PROP_SHOW_REMOTE_CURSORS, g_param_spec_boolean( "show-remote-cursors", "Show remote cursors", "Whether to show cursors of non-local users", TRUE, G_PARAM_READWRITE ) ); g_object_class_install_property( object_class, PROP_SHOW_REMOTE_SELECTIONS, g_param_spec_boolean( "show-remote-selections", "Show remote selections", "Whether to highlight text selected by non-local users", TRUE, G_PARAM_READWRITE ) ); g_object_class_install_property( object_class, PROP_SHOW_REMOTE_CURRENT_LINES, g_param_spec_boolean( "show-remote-current-lines", "Show remote current lines", "Whether to highlight the line in which the cursor of non-local users is", TRUE, G_PARAM_READWRITE ) ); } /** * inf_text_gtk_view_new: (constructor) * @io: A #InfIo. * @view: A #GtkTextView. * @user_table: The #InfUserTable for the text session displayed in @view. * * Creates a new #InfTextGtkView for @view. This draws remote user's cursors * and selections into the text view. * * Returns: (transfer full): A new #InfTextGtkView. */ InfTextGtkView* inf_text_gtk_view_new(InfIo* io, GtkTextView* view, InfUserTable* user_table) { GObject* object; g_return_val_if_fail(INF_IS_IO(io), NULL); g_return_val_if_fail(GTK_IS_TEXT_VIEW(view), NULL); g_return_val_if_fail(INF_IS_USER_TABLE(user_table), NULL); object = g_object_new( INF_TEXT_GTK_TYPE_VIEW, "io", io, "view", view, "user-table", user_table, NULL ); return INF_TEXT_GTK_VIEW(object); } /** * inf_text_gtk_view_get_text_view: * @view: A #InfTextGtkView. * * Returns the underlying #GtkTextView. * * Returns: (transfer none): The #InfTextGtkView's #GtkTextView. **/ GtkTextView* inf_text_gtk_view_get_text_view(InfTextGtkView* view) { g_return_val_if_fail(INF_TEXT_GTK_IS_VIEW(view), NULL); return INF_TEXT_GTK_VIEW_PRIVATE(view)->textview; } /** * inf_text_gtk_view_get_user_table: * @view: A #InfTextGtkView. * * Returns the #InfUserTable containing the users of the session the * #InfTextGtkView's #GtkTextView is displaying. * * Returns: (transfer none): The #InfTextGtkView's #InfUserTable. */ InfUserTable* inf_text_gtk_view_get_user_table(InfTextGtkView* view) { g_return_val_if_fail(INF_TEXT_GTK_IS_VIEW(view), NULL); return INF_TEXT_GTK_VIEW_PRIVATE(view)->user_table; } /** * inf_text_gtk_view_set_active_user: * @view: A #InfTextGtkView. * @user: (allow-none): A user from @view's user table, or %NULL. * * Sets the user for which perspective to draw the view. The selection and * cursor position is not drawn for this user since it is assumed that the * view's buffer cursor position and selection match the active user ones * (which is automatically the case if the buffer is managed by a * #InfTextGtkBuffer). */ void inf_text_gtk_view_set_active_user(InfTextGtkView* view, InfTextUser* user) { InfTextGtkViewPrivate* priv; InfTextUser* active_user; g_return_if_fail(INF_TEXT_GTK_IS_VIEW(view)); g_return_if_fail(user == NULL || INF_TEXT_IS_USER(user)); priv = INF_TEXT_GTK_VIEW_PRIVATE(view); g_return_if_fail( user == NULL || inf_user_table_lookup_user_by_id( priv->user_table, inf_user_get_id(INF_USER(user)) ) == INF_USER(user) ); if(priv->active_user != NULL) { active_user = priv->active_user; priv->active_user = NULL; inf_text_gtk_view_user_added(view, active_user); } if(user != NULL) { inf_text_gtk_view_user_removed(view, user); } priv->active_user = user; g_object_notify(G_OBJECT(view), "active-user"); } /** * inf_text_gtk_view_get_active_user: * @view: A #InfTextGtkView. * * Returns the active user of @view. See inf_text_gtk_view_set_active_user(). * * Returns: (transfer none) (allow-none): The active user of @view. */ InfTextUser* inf_text_gtk_view_get_active_user(InfTextGtkView* view) { g_return_val_if_fail(INF_TEXT_GTK_IS_VIEW(view), NULL); return INF_TEXT_GTK_VIEW_PRIVATE(view)->active_user; } /** * inf_text_gtk_view_set_show_remote_cursors: * @view: A #InfTextGtkView. * @show: Whether to show cursors of non-local users. * * If @show is %TRUE then @view draws a cursor for each non-local user in * %INF_USER_ACTIVE status in that user's color into its underlying * #GtkTextView. If it is %FALSE then remote cursors are not drawn. */ void inf_text_gtk_view_set_show_remote_cursors(InfTextGtkView* view, gboolean show) { InfTextGtkViewPrivate* priv; g_return_if_fail(INF_TEXT_GTK_IS_VIEW(view)); priv = INF_TEXT_GTK_VIEW_PRIVATE(view); if(priv->show_remote_cursors != show) { gtk_widget_queue_draw(GTK_WIDGET(priv->textview)); priv->show_remote_cursors = show; g_object_notify(G_OBJECT(view), "show-remote-cursors"); } } /** * inf_text_gtk_view_set_show_remote_selections: * @view: A #InfTextGtkView. * @show: Whether to show selections of non-local users. * * If @show is %TRUE then @view draws the selection ranges for each non-local * user in %INF_USER_ACTIVE status. The selection range is drawn shaded in * that user's color on top of the author color which indicates who wrote the * selected text. If more than one user has a given piece of text selected * then an alternating stripe pattern with each of the user's colors is drawn. * If @show is %FALSE then selection ranges of remote users are not drawn. */ void inf_text_gtk_view_set_show_remote_selections(InfTextGtkView* view, gboolean show) { InfTextGtkViewPrivate* priv; g_return_if_fail(INF_TEXT_GTK_IS_VIEW(view)); priv = INF_TEXT_GTK_VIEW_PRIVATE(view); if(priv->show_remote_selections != show) { gtk_widget_queue_draw(GTK_WIDGET(priv->textview)); priv->show_remote_selections = show; g_object_notify(G_OBJECT(view), "show-remote-selections"); } } /** * inf_text_gtk_view_set_show_remote_current_lines: * @view: A #InfTextGtkView. * @show: Whether to highlight the current line of non-local users. * * If @show is %TRUE then all lines in which the cursor of a non-local user * in %INF_USER_ACTIVE status is is highlighted with that user's color, similar * to GtkSourceView's "highlight current line" functionality. If it is %FALSE * then the current line of non-local users is not highlighted. */ void inf_text_gtk_view_set_show_remote_current_lines(InfTextGtkView* view, gboolean show) { InfTextGtkViewPrivate* priv; g_return_if_fail(INF_TEXT_GTK_IS_VIEW(view)); priv = INF_TEXT_GTK_VIEW_PRIVATE(view); if(priv->show_remote_current_lines != show) { gtk_widget_queue_draw(GTK_WIDGET(priv->textview)); priv->show_remote_current_lines = show; g_object_notify(G_OBJECT(view), "show-remote-current-lines"); } } /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinftextgtk/PaxHeaders.26529/inf-text-gtk-view.h0000644000000000000000000000013213034342512022120 xustar0030 mtime=1483851082.049718536 30 atime=1483851082.049718536 30 ctime=1488261589.392138208 libinfinity-0.7.1/libinftextgtk/inf-text-gtk-view.h0000644000175000017500000000624113034342512022655 0ustar00arminarmin00000000000000/* infinote - Collaborative notetaking application * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef __INF_TEXT_GTK_VIEW_H__ #define __INF_TEXT_GTK_VIEW_H__ #include #include #include #include #include G_BEGIN_DECLS #define INF_TEXT_GTK_TYPE_VIEW (inf_text_gtk_view_get_type()) #define INF_TEXT_GTK_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_TEXT_GTK_TYPE_VIEW, InfTextGtkView)) #define INF_TEXT_GTK_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INF_TEXT_GTK_TYPE_VIEW, InfTextGtkViewClass)) #define INF_TEXT_GTK_IS_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_TEXT_GTK_TYPE_VIEW)) #define INF_TEXT_GTK_IS_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INF_TEXT_GTK_TYPE_VIEW)) #define INF_TEXT_GTK_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INF_TEXT_GTK_TYPE_VIEW, InfTextGtkViewClass)) typedef struct _InfTextGtkView InfTextGtkView; typedef struct _InfTextGtkViewClass InfTextGtkViewClass; /** * InfTextGtkViewClass: * * This structure does not contain any public fields. */ struct _InfTextGtkViewClass { /*< private >*/ GObjectClass parent_class; }; /** * InfTextGtkView: * * #InfTextGtkView is an opaque data type. You should only access it via the * public API functions. */ struct _InfTextGtkView { /*< private >*/ GObject parent; }; GType inf_text_gtk_view_get_type(void) G_GNUC_CONST; InfTextGtkView* inf_text_gtk_view_new(InfIo* io, GtkTextView* view, InfUserTable* user_table); GtkTextView* inf_text_gtk_view_get_text_view(InfTextGtkView* view); InfUserTable* inf_text_gtk_view_get_user_table(InfTextGtkView* view); void inf_text_gtk_view_set_active_user(InfTextGtkView* view, InfTextUser* user); InfTextUser* inf_text_gtk_view_get_active_user(InfTextGtkView* view); void inf_text_gtk_view_set_show_remote_cursors(InfTextGtkView* view, gboolean show); void inf_text_gtk_view_set_show_remote_selections(InfTextGtkView* view, gboolean show); void inf_text_gtk_view_set_show_remote_current_lines(InfTextGtkView* view, gboolean show); G_END_DECLS #endif /* __INF_TEXT_GTK_VIEW_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/libinftextgtk/PaxHeaders.26529/inf-text-gtk-buffer.h0000644000000000000000000000013213034342512022417 xustar0030 mtime=1483851082.049718536 30 atime=1483851082.049718536 30 ctime=1488261589.392138208 libinfinity-0.7.1/libinftextgtk/inf-text-gtk-buffer.h0000644000175000017500000001177413034342512023163 0ustar00arminarmin00000000000000/* libinfinity - a GObject-based infinote implementation * Copyright (C) 2007-2015 Armin Burgmeier * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef __INF_TEXT_GTK_BUFFER_H__ #define __INF_TEXT_GTK_BUFFER_H__ #include #include #include #include #include G_BEGIN_DECLS #define INF_TEXT_GTK_TYPE_BUFFER (inf_text_gtk_buffer_get_type()) #define INF_TEXT_GTK_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), INF_TEXT_GTK_TYPE_BUFFER, InfTextGtkBuffer)) #define INF_TEXT_GTK_BUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), INF_TEXT_GTK_TYPE_BUFFER, InfTextGtkBufferClass)) #define INF_TEXT_GTK_IS_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), INF_TEXT_GTK_TYPE_BUFFER)) #define INF_TEXT_GTK_IS_BUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), INF_TEXT_GTK_TYPE_BUFFER)) #define INF_TEXT_GTK_BUFFER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), INF_TEXT_GTK_TYPE_BUFFER, InfTextGtkBufferClass)) typedef struct _InfTextGtkBuffer InfTextGtkBuffer; typedef struct _InfTextGtkBufferClass InfTextGtkBufferClass; /** * InfTextGtkBufferClass: * * This structure does not contain any public fields. */ struct _InfTextGtkBufferClass { /*< private >*/ GObjectClass parent_class; }; /** * InfTextGtkBuffer: * * #InfTextGtkBuffer is an opaque data type. You should only access it via the * public API functions. */ struct _InfTextGtkBuffer { /*< private >*/ GObject parent; }; GType inf_text_gtk_buffer_get_type(void) G_GNUC_CONST; InfTextGtkBuffer* inf_text_gtk_buffer_new(GtkTextBuffer* buffer, InfUserTable* user_table); GtkTextBuffer* inf_text_gtk_buffer_get_text_buffer(InfTextGtkBuffer* buffer); void inf_text_gtk_buffer_set_active_user(InfTextGtkBuffer* buffer, InfTextUser* user); InfTextUser* inf_text_gtk_buffer_get_active_user(InfTextGtkBuffer* buffer); InfTextUser* inf_text_gtk_buffer_get_author(InfTextGtkBuffer* buffer, GtkTextIter* location); InfTextUser* inf_text_gtk_buffer_get_user_for_tag(InfTextGtkBuffer* buffer, GtkTextTag* tag); gboolean inf_text_gtk_buffer_is_author_toggle(InfTextGtkBuffer* buffer, const GtkTextIter* iter, InfTextUser** user_on, InfTextUser** user_off); gboolean inf_text_gtk_buffer_forward_to_author_toggle(InfTextGtkBuffer* buffer, GtkTextIter* iter, InfTextUser** user_on, InfTextUser** user_off); gboolean inf_text_gtk_buffer_backward_to_author_toggle(InfTextGtkBuffer* buffer, GtkTextIter* iter, InfTextUser** user_on, InfTextUser** user_off); void inf_text_gtk_buffer_set_wake_on_cursor_movement(InfTextGtkBuffer* buffer, gboolean wake); gboolean inf_text_gtk_buffer_get_wake_on_cursor_movement(InfTextGtkBuffer* buffer); void inf_text_gtk_buffer_ensure_author_tags_priority(InfTextGtkBuffer* buffer); void inf_text_gtk_buffer_set_saturation_value(InfTextGtkBuffer* buffer, gdouble saturation, gdouble value); void inf_text_gtk_buffer_set_fade(InfTextGtkBuffer* buffer, gdouble alpha); gdouble inf_text_gtk_buffer_get_saturation(InfTextGtkBuffer* buffer); gdouble inf_text_gtk_buffer_get_value(InfTextGtkBuffer* buffer); void inf_text_gtk_buffer_set_show_user_colors(InfTextGtkBuffer* buffer, gboolean show); gboolean inf_text_gtk_buffer_get_show_user_colors(InfTextGtkBuffer* buffer); void inf_text_gtk_buffer_show_user_colors(InfTextGtkBuffer* buffer, gboolean show, GtkTextIter* start, GtkTextIter* end); G_END_DECLS #endif /* __INF_TEXT_GTK_BUFFER_H__ */ /* vim:set et sw=2 ts=2: */ libinfinity-0.7.1/PaxHeaders.26529/config.guess0000644000000000000000000000013213036062707016124 xustar0030 mtime=1484285383.711895803 30 atime=1484285383.711895803 30 ctime=1488261588.776139555 libinfinity-0.7.1/config.guess0000755000175000017500000012564413036062707016675 0ustar00arminarmin00000000000000#! /bin/sh # Attempt to guess a canonical system name. # Copyright 1992-2016 Free Software Foundation, Inc. timestamp='2016-10-02' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # # Originally written by Per Bothner; maintained since 2000 by Ben Elliston. # # You can get the latest version of this script from: # http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess # # Please send patches to . me=`echo "$0" | sed -e 's,.*/,,'` usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Operation modes: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright 1992-2016 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi trap 'exit 1' 1 2 15 # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. # Portable tmp directory creation inspired by the Autoconf team. set_cc_for_build=' trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; : ${TMPDIR=/tmp} ; { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; dummy=$tmp/dummy ; tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; case $CC_FOR_BUILD,$HOST_CC,$CC in ,,) echo "int x;" > $dummy.c ; for c in cc gcc c89 c99 ; do if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found ; fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac ; set_cc_for_build= ;' # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) if (test -f /.attbin/uname) >/dev/null 2>&1 ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown case "${UNAME_SYSTEM}" in Linux|GNU|GNU/*) # If the system lacks a compiler, then just pick glibc. # We could probably try harder. LIBC=gnu eval $set_cc_for_build cat <<-EOF > $dummy.c #include #if defined(__UCLIBC__) LIBC=uclibc #elif defined(__dietlibc__) LIBC=dietlibc #else LIBC=gnu #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'` ;; esac # Note: order is significant - the case branches are not exclusive. case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ /sbin/$sysctl 2>/dev/null || \ /usr/sbin/$sysctl 2>/dev/null || \ echo unknown)` case "${UNAME_MACHINE_ARCH}" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; earmv*) arch=`echo ${UNAME_MACHINE_ARCH} | sed -e 's,^e\(armv[0-9]\).*$,\1,'` endian=`echo ${UNAME_MACHINE_ARCH} | sed -ne 's,^.*\(eb\)$,\1,p'` machine=${arch}${endian}-unknown ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently (or will in the future) and ABI. case "${UNAME_MACHINE_ARCH}" in earm*) os=netbsdelf ;; arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) os=netbsd ;; esac # Determine ABI tags. case "${UNAME_MACHINE_ARCH}" in earm*) expr='s/^earmv[0-9]/-eabi/;s/eb$//' abi=`echo ${UNAME_MACHINE_ARCH} | sed -e "$expr"` ;; esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. case "${UNAME_VERSION}" in Debian*) release='-gnu' ;; *) release=`echo ${UNAME_RELEASE} | sed -e 's/[-_].*//' | cut -d. -f1,2` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}${abi}" exit ;; *:Bitrig:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} exit ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} exit ;; *:LibertyBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` echo ${UNAME_MACHINE_ARCH}-unknown-libertybsd${UNAME_RELEASE} exit ;; *:ekkoBSD:*:*) echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} exit ;; *:SolidBSD:*:*) echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} exit ;; macppc:MirBSD:*:*) echo powerpc-unknown-mirbsd${UNAME_RELEASE} exit ;; *:MirBSD:*:*) echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} exit ;; *:Sortix:*:*) echo ${UNAME_MACHINE}-unknown-sortix exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` ;; *5.*) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` ;; esac # According to Compaq, /usr/sbin/psrinfo has been available on # OSF/1 and Tru64 systems produced since 1995. I hope that # covers most systems running today. This code pipes the CPU # types through head -n 1, so we only detect the type of CPU 0. ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") UNAME_MACHINE=alpha ;; "EV4.5 (21064)") UNAME_MACHINE=alpha ;; "LCA4 (21066/21068)") UNAME_MACHINE=alpha ;; "EV5 (21164)") UNAME_MACHINE=alphaev5 ;; "EV5.6 (21164A)") UNAME_MACHINE=alphaev56 ;; "EV5.6 (21164PC)") UNAME_MACHINE=alphapca56 ;; "EV5.7 (21164PC)") UNAME_MACHINE=alphapca57 ;; "EV6 (21264)") UNAME_MACHINE=alphaev6 ;; "EV6.7 (21264A)") UNAME_MACHINE=alphaev67 ;; "EV6.8CB (21264C)") UNAME_MACHINE=alphaev68 ;; "EV6.8AL (21264B)") UNAME_MACHINE=alphaev68 ;; "EV6.8CX (21264D)") UNAME_MACHINE=alphaev68 ;; "EV6.9A (21264/EV69A)") UNAME_MACHINE=alphaev69 ;; "EV7 (21364)") UNAME_MACHINE=alphaev7 ;; "EV7.9 (21364A)") UNAME_MACHINE=alphaev79 ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` # Reset EXIT trap before exiting to avoid spurious non-zero exit code. exitcode=$? trap '' 0 exit $exitcode ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead # of the specific Alpha model? echo alpha-pc-interix exit ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 exit ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit ;; *:[Aa]miga[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-amigaos exit ;; *:[Mm]orph[Oo][Ss]:*:*) echo ${UNAME_MACHINE}-unknown-morphos exit ;; *:OS/390:*:*) echo i370-ibm-openedition exit ;; *:z/VM:*:*) echo s390-ibm-zvmoe exit ;; *:OS400:*:*) echo powerpc-ibm-os400 exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} exit ;; arm*:riscos:*:*|arm*:RISCOS:*:*) echo arm-unknown-riscos exit ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then echo pyramid-pyramid-sysv3 else echo pyramid-pyramid-bsd fi exit ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit ;; DRS?6000:unix:4.0:6*) echo sparc-icl-nx6 exit ;; DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7; exit ;; esac ;; s390x:SunOS:*:*) echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) echo i386-pc-auroraux${UNAME_RELEASE} exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) eval $set_cc_for_build SUN_ARCH=i386 # If there is a compiler, see if it is configured for 64-bit objects. # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. # This test works for both compilers. if [ "$CC_FOR_BUILD" != no_compiler_found ]; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then SUN_ARCH=x86_64 fi fi echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in Series*|S4*) UNAME_RELEASE=`uname -v` ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` exit ;; sun3*:SunOS:*:*) echo m68k-sun-sunos${UNAME_RELEASE} exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` test "x${UNAME_RELEASE}" = x && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) echo m68k-sun-sunos${UNAME_RELEASE} ;; sun4) echo sparc-sun-sunos${UNAME_RELEASE} ;; esac exit ;; aushp:SunOS:*:*) echo sparc-auspex-sunos${UNAME_RELEASE} exit ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) echo m68k-milan-mint${UNAME_RELEASE} exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) echo m68k-hades-mint${UNAME_RELEASE} exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint${UNAME_RELEASE} exit ;; m68k:machten:*:*) echo m68k-apple-machten${UNAME_RELEASE} exit ;; powerpc:machten:*:*) echo powerpc-apple-machten${UNAME_RELEASE} exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix${UNAME_RELEASE} exit ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix${UNAME_RELEASE} exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix${UNAME_RELEASE} exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && SYSTEM_NAME=`$dummy $dummyarg` && { echo "$SYSTEM_NAME"; exit; } echo mips-mips-riscos${UNAME_RELEASE} exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit ;; Motorola:*:4.3:PL8-*) echo powerpc-harris-powermax exit ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) echo powerpc-harris-powermax exit ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 exit ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 exit ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 exit ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=`/usr/bin/uname -p` if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ [ ${TARGET_BINARY_INTERFACE}x = x ] then echo m88k-dg-dgux${UNAME_RELEASE} else echo m88k-dg-dguxbcs${UNAME_RELEASE} fi else echo i586-dg-dgux${UNAME_RELEASE} fi exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 exit ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 exit ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd exit ;; *:IRIX*:*:*) echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix exit ;; ia64:AIX:*:*) if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` then echo "$SYSTEM_NAME" else echo rs6000-ibm-aix3.2.5 fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi exit ;; *:AIX:*:[4567]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if [ -x /usr/bin/lslpp ] ; then IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` else IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} fi echo ${IBM_ARCH}-ibm-aix${IBM_REV} exit ;; *:AIX:*:*) echo rs6000-ibm-aix exit ;; ibmrt:4.4BSD:*|romp-ibm:BSD:*) echo romp-ibm-bsd4.4 exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx exit ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 exit ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd exit ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 exit ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` case "${UNAME_MACHINE}" in 9000/31? ) HP_ARCH=m68000 ;; 9000/[34]?? ) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` case "${sc_cpu_version}" in 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case "${sc_kernel_bits}" in 32) HP_ARCH=hppa2.0n ;; 64) HP_ARCH=hppa2.0w ;; '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 esac ;; esac fi if [ "${HP_ARCH}" = "" ]; then eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #define _HPUX_SOURCE #include #include int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS="" $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac if [ ${HP_ARCH} = hppa2.0w ] then eval $set_cc_for_build # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler # generating 64-bit code. GNU and HP use different nomenclature: # # $ CC_FOR_BUILD=cc ./config.guess # => hppa2.0w-hp-hpux11.23 # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | grep -q __LP64__ then HP_ARCH=hppa2.0w else HP_ARCH=hppa64 fi fi echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit ;; ia64:HP-UX:*:*) HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ia64-hp-hpux${HPUX_REV} exit ;; 3050*:HI-UX:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #include int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 exit ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) echo hppa1.1-hp-bsd exit ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf exit ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then echo ${UNAME_MACHINE}-unknown-osf1mk else echo ${UNAME_MACHINE}-unknown-osf1 fi exit ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd exit ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd exit ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*[A-Z]90:*:*:*) echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; *:UNICOS/mp:*:*) echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; 5000:UNIX_System_V:4.*:*) FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi${UNAME_RELEASE} exit ;; *:BSD/OS:*:*) echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit ;; *:FreeBSD:*:*) UNAME_PROCESSOR=`/usr/bin/uname -p` case ${UNAME_PROCESSOR} in amd64) echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; *) echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; esac exit ;; i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit ;; *:MINGW64*:*) echo ${UNAME_MACHINE}-pc-mingw64 exit ;; *:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit ;; *:MSYS*:*) echo ${UNAME_MACHINE}-pc-msys exit ;; i*:windows32*:*) # uname -m includes "-pc" on this system. echo ${UNAME_MACHINE}-mingw32 exit ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit ;; *:Interix*:*) case ${UNAME_MACHINE} in x86) echo i586-pc-interix${UNAME_RELEASE} exit ;; authenticamd | genuineintel | EM64T) echo x86_64-unknown-interix${UNAME_RELEASE} exit ;; IA64) echo ia64-unknown-interix${UNAME_RELEASE} exit ;; esac ;; [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) echo i${UNAME_MACHINE}-pc-mks exit ;; 8664:Windows_NT:*) echo x86_64-pc-mks exit ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we # UNAME_MACHINE based on the output of uname instead of i386? echo i586-pc-interix exit ;; i*:UWIN*:*) echo ${UNAME_MACHINE}-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) echo x86_64-unknown-cygwin exit ;; p*:CYGWIN*:*) echo powerpcle-unknown-cygwin exit ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; *:GNU:*:*) # the GNU system echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC} exit ;; i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit ;; aarch64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep -q ld.so.1 if test "$?" = 0 ; then LIBC=gnulibc1 ; fi echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; arc:Linux:*:* | arceb:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; arm*:Linux:*:*) eval $set_cc_for_build if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then echo ${UNAME_MACHINE}-unknown-linux-${LIBC} else if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi else echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf fi fi exit ;; avr32*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; cris:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-${LIBC} exit ;; crisv32:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-${LIBC} exit ;; e2k:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; frv:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; hexagon:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; i*86:Linux:*:*) echo ${UNAME_MACHINE}-pc-linux-${LIBC} exit ;; ia64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; k1om:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; m32r*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; m68*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; mips:Linux:*:* | mips64:Linux:*:*) eval $set_cc_for_build sed 's/^ //' << EOF >$dummy.c #undef CPU #undef ${UNAME_MACHINE} #undef ${UNAME_MACHINE}el #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) CPU=${UNAME_MACHINE}el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) CPU=${UNAME_MACHINE} #else CPU= #endif #endif EOF eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; } ;; mips64el:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; openrisc*:Linux:*:*) echo or1k-unknown-linux-${LIBC} exit ;; or32:Linux:*:* | or1k*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; padre:Linux:*:*) echo sparc-unknown-linux-${LIBC} exit ;; parisc64:Linux:*:* | hppa64:Linux:*:*) echo hppa64-unknown-linux-${LIBC} exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in PA7*) echo hppa1.1-unknown-linux-${LIBC} ;; PA8*) echo hppa2.0-unknown-linux-${LIBC} ;; *) echo hppa-unknown-linux-${LIBC} ;; esac exit ;; ppc64:Linux:*:*) echo powerpc64-unknown-linux-${LIBC} exit ;; ppc:Linux:*:*) echo powerpc-unknown-linux-${LIBC} exit ;; ppc64le:Linux:*:*) echo powerpc64le-unknown-linux-${LIBC} exit ;; ppcle:Linux:*:*) echo powerpcle-unknown-linux-${LIBC} exit ;; riscv32:Linux:*:* | riscv64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux-${LIBC} exit ;; sh64*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; tile*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; vax:Linux:*:*) echo ${UNAME_MACHINE}-dec-linux-${LIBC} exit ;; x86_64:Linux:*:*) echo ${UNAME_MACHINE}-pc-linux-${LIBC} exit ;; xtensa*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. echo i386-sequent-sysv4 exit ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. echo ${UNAME_MACHINE}-pc-os2-emx exit ;; i*86:XTS-300:*:STOP) echo ${UNAME_MACHINE}-unknown-stop exit ;; i*86:atheos:*:*) echo ${UNAME_MACHINE}-unknown-atheos exit ;; i*86:syllable:*:*) echo ${UNAME_MACHINE}-pc-syllable exit ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) echo i386-unknown-lynxos${UNAME_RELEASE} exit ;; i*86:*DOS:*:*) echo ${UNAME_MACHINE}-pc-msdosdjgpp exit ;; i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} else echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} fi exit ;; i*86:*:5:[678]*) # UnixWare 7.x, OpenUNIX and OpenServer 6. case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 fi exit ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i586. # Note: whatever this is, it MUST be the same as what config.sub # prints for the "djgpp" host, or else GDB configure will decide that # this is a cross-build. echo i586-pc-msdosdjgpp exit ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit ;; paragon:*:*:*) echo i860-intel-osf1 exit ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 fi exit ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv exit ;; mc68k:UNIX:SYSTEM5:3.51m) echo m68k-convergent-sysv exit ;; M680?0:D-NIX:5.3:*) echo m68k-diab-dnix exit ;; M68*:*:R3V[5678]*:*) test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4; exit; } ;; NCR*:*:4.2:* | MPRAS*:*:4.2:*) OS_REL='.3' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos${UNAME_RELEASE} exit ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} exit ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} exit ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 exit ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` echo ${UNAME_MACHINE}-sni-sysv4 else echo ns32k-sni-sysv fi exit ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says echo i586-unisys-sysv4 exit ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 exit ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 exit ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. echo ${UNAME_MACHINE}-stratus-vos exit ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit ;; mc68*:A/UX:*:*) echo m68k-apple-aux${UNAME_RELEASE} exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then echo mips-nec-sysv${UNAME_RELEASE} else echo mips-unknown-sysv${UNAME_RELEASE} fi exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos exit ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit ;; BePC:Haiku:*:*) # Haiku running on Intel PC compatible. echo i586-pc-haiku exit ;; x86_64:Haiku:*:*) echo x86_64-unknown-haiku exit ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux${UNAME_RELEASE} exit ;; SX-6:SUPER-UX:*:*) echo sx6-nec-superux${UNAME_RELEASE} exit ;; SX-7:SUPER-UX:*:*) echo sx7-nec-superux${UNAME_RELEASE} exit ;; SX-8:SUPER-UX:*:*) echo sx8-nec-superux${UNAME_RELEASE} exit ;; SX-8R:SUPER-UX:*:*) echo sx8r-nec-superux${UNAME_RELEASE} exit ;; SX-ACE:SUPER-UX:*:*) echo sxace-nec-superux${UNAME_RELEASE} exit ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody${UNAME_RELEASE} exit ;; *:Rhapsody:*:*) echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown eval $set_cc_for_build if test "$UNAME_PROCESSOR" = unknown ; then UNAME_PROCESSOR=powerpc fi if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then if [ "$CC_FOR_BUILD" != no_compiler_found ]; then if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then case $UNAME_PROCESSOR in i386) UNAME_PROCESSOR=x86_64 ;; powerpc) UNAME_PROCESSOR=powerpc64 ;; esac fi fi elif test "$UNAME_PROCESSOR" = i386 ; then # Avoid executing cc on OS X 10.9, as it ships with a stub # that puts up a graphical alert prompting to install # developer tools. Any system running Mac OS X 10.7 or # later (Darwin 11 and later) is required to have a 64-bit # processor. This is not true of the ARM version of Darwin # that Apple uses in portable devices. UNAME_PROCESSOR=x86_64 fi echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` if test "$UNAME_PROCESSOR" = x86; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} exit ;; *:QNX:*:4*) echo i386-pc-qnx exit ;; NEO-?:NONSTOP_KERNEL:*:*) echo neo-tandem-nsk${UNAME_RELEASE} exit ;; NSE-*:NONSTOP_KERNEL:*:*) echo nse-tandem-nsk${UNAME_RELEASE} exit ;; NSR-?:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk${UNAME_RELEASE} exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv exit ;; DS/*:UNIX_System_V:*:*) echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} exit ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. if test "$cputype" = 386; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi echo ${UNAME_MACHINE}-unknown-plan9 exit ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 exit ;; *:TENEX:*:*) echo pdp10-unknown-tenex exit ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 exit ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 exit ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 exit ;; *:ITS:*:*) echo pdp10-unknown-its exit ;; SEI:*:*:SEIUX) echo mips-sei-seiux${UNAME_RELEASE} exit ;; *:DragonFly:*:*) echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit ;; *:*VMS:*:*) UNAME_MACHINE=`(uname -p) 2>/dev/null` case "${UNAME_MACHINE}" in A*) echo alpha-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;; V*) echo vax-dec-vms ; exit ;; esac ;; *:XENIX:*:SysV) echo i386-pc-xenix exit ;; i*86:skyos:*:*) echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE} | sed -e 's/ .*$//'` exit ;; i*86:rdos:*:*) echo ${UNAME_MACHINE}-pc-rdos exit ;; i*86:AROS:*:*) echo ${UNAME_MACHINE}-pc-aros exit ;; x86_64:VMkernel:*:*) echo ${UNAME_MACHINE}-unknown-esx exit ;; amd64:Isilon\ OneFS:*:*) echo x86_64-unknown-onefs exit ;; esac cat >&2 </dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` /bin/uname -X = `(/bin/uname -X) 2>/dev/null` hostinfo = `(hostinfo) 2>/dev/null` /bin/universe = `(/bin/universe) 2>/dev/null` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` /bin/arch = `(/bin/arch) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` UNAME_MACHINE = ${UNAME_MACHINE} UNAME_RELEASE = ${UNAME_RELEASE} UNAME_SYSTEM = ${UNAME_SYSTEM} UNAME_VERSION = ${UNAME_VERSION} EOF exit 1 # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: libinfinity-0.7.1/PaxHeaders.26529/ar-lib0000644000000000000000000000013213036062707014700 xustar0030 mtime=1484285383.703895797 30 atime=1484285383.703895797 30 ctime=1488261588.776139555 libinfinity-0.7.1/ar-lib0000755000175000017500000001330213036062707015434 0ustar00arminarmin00000000000000#! /bin/sh # Wrapper for Microsoft lib.exe me=ar-lib scriptversion=2012-03-01.08; # UTC # Copyright (C) 2010-2014 Free Software Foundation, Inc. # Written by Peter Rosin . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # This file is maintained in Automake, please report # bugs to or send patches to # . # func_error message func_error () { echo "$me: $1" 1>&2 exit 1 } file_conv= # func_file_conv build_file # Convert a $build file to $host form and store it in $file # Currently only supports Windows hosts. func_file_conv () { file=$1 case $file in / | /[!/]*) # absolute file, and not a UNC file if test -z "$file_conv"; then # lazily determine how to convert abs files case `uname -s` in MINGW*) file_conv=mingw ;; CYGWIN*) file_conv=cygwin ;; *) file_conv=wine ;; esac fi case $file_conv in mingw) file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` ;; cygwin) file=`cygpath -m "$file" || echo "$file"` ;; wine) file=`winepath -w "$file" || echo "$file"` ;; esac ;; esac } # func_at_file at_file operation archive # Iterate over all members in AT_FILE performing OPERATION on ARCHIVE # for each of them. # When interpreting the content of the @FILE, do NOT use func_file_conv, # since the user would need to supply preconverted file names to # binutils ar, at least for MinGW. func_at_file () { operation=$2 archive=$3 at_file_contents=`cat "$1"` eval set x "$at_file_contents" shift for member do $AR -NOLOGO $operation:"$member" "$archive" || exit $? done } case $1 in '') func_error "no command. Try '$0 --help' for more information." ;; -h | --h*) cat <